1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "android_webview/native/java_browser_view_renderer_helper.h"
7 #include <android/bitmap.h>
9 #include "android_webview/common/aw_switches.h"
10 #include "android_webview/public/browser/draw_sw.h"
11 #include "base/debug/trace_event.h"
12 #include "jni/JavaBrowserViewRendererHelper_jni.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
14 #include "third_party/skia/include/utils/SkCanvasStateUtils.h"
16 using base::android::JavaRef
;
17 using base::android::ScopedJavaLocalRef
;
19 namespace android_webview
{
23 // Provides software rendering functions from the Android glue layer.
24 // Allows preventing extra copies of data when rendering.
25 AwDrawSWFunctionTable
* g_sw_draw_functions
= NULL
;
27 class ScopedPixelAccess
{
29 ScopedPixelAccess(JNIEnv
* env
, jobject java_canvas
) : pixels_(NULL
) {
30 if (g_sw_draw_functions
&& !switches::ForceAuxiliaryBitmap())
31 pixels_
= g_sw_draw_functions
->access_pixels(env
, java_canvas
);
34 ~ScopedPixelAccess() {
36 g_sw_draw_functions
->release_pixels(pixels_
);
39 AwPixelInfo
* pixels() { return pixels_
; }
44 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess
);
50 void JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
51 AwDrawSWFunctionTable
* table
) {
52 g_sw_draw_functions
= table
;
56 JavaBrowserViewRendererHelper
* JavaBrowserViewRendererHelper::GetInstance() {
57 static JavaBrowserViewRendererHelper
* g_instance
=
58 new JavaBrowserViewRendererHelper
;
63 BrowserViewRendererJavaHelper
* BrowserViewRendererJavaHelper::GetInstance() {
64 return JavaBrowserViewRendererHelper::GetInstance();
67 JavaBrowserViewRendererHelper::JavaBrowserViewRendererHelper() {}
69 JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {}
71 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmapIfNeeded(
73 const gfx::Vector2d
& scroll_correction
,
74 const gfx::Size
& auxiliary_bitmap_size
,
75 RenderMethod render_source
) {
76 TRACE_EVENT0("android_webview", "RenderViaAuxilaryBitmapIfNeeded");
78 JNIEnv
* env
= base::android::AttachCurrentThread();
79 ScopedPixelAccess
auto_release_pixels(env
, java_canvas
);
80 AwPixelInfo
* pixels
= auto_release_pixels
.pixels();
81 if (pixels
&& pixels
->state
) {
82 skia::RefPtr
<SkCanvas
> canvas
= skia::AdoptRef(
83 SkCanvasStateUtils::CreateFromCanvasState(pixels
->state
));
85 // Workarounds for http://crbug.com/271096: SW draw only supports
86 // translate & scale transforms, and a simple rectangular clip.
87 if (canvas
&& (!canvas
->isClipRect() ||
88 (canvas
->getTotalMatrix().getType() &
89 ~(SkMatrix::kTranslate_Mask
| SkMatrix::kScale_Mask
)))) {
93 canvas
->translate(scroll_correction
.x(), scroll_correction
.y());
94 return render_source
.Run(canvas
.get());
97 return RenderViaAuxilaryBitmap(env
,
100 auxiliary_bitmap_size
,
104 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmap(
107 const gfx::Vector2d
& scroll_correction
,
108 const gfx::Size
& auxiliary_bitmap_size
,
109 const RenderMethod
& render_source
) {
110 // Render into an auxiliary bitmap if pixel info is not available.
111 ScopedJavaLocalRef
<jobject
> jcanvas(env
, java_canvas
);
112 TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
114 if (auxiliary_bitmap_size
.width() <= 0 || auxiliary_bitmap_size
.height() <= 0)
117 ScopedJavaLocalRef
<jobject
> jbitmap(
118 Java_JavaBrowserViewRendererHelper_createBitmap(
120 auxiliary_bitmap_size
.width(),
121 auxiliary_bitmap_size
.height(),
126 if (!RasterizeIntoBitmap(env
,
132 Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
136 scroll_correction
.x(),
137 scroll_correction
.y());
141 bool RegisterJavaBrowserViewRendererHelper(JNIEnv
* env
) {
142 return RegisterNativesImpl(env
);
145 bool JavaBrowserViewRendererHelper::RasterizeIntoBitmap(
147 const JavaRef
<jobject
>& jbitmap
,
148 const JavaBrowserViewRendererHelper::RenderMethod
& renderer
) {
149 DCHECK(jbitmap
.obj());
151 AndroidBitmapInfo bitmap_info
;
152 if (AndroidBitmap_getInfo(env
, jbitmap
.obj(), &bitmap_info
) < 0) {
153 LOG(ERROR
) << "Error getting java bitmap info.";
158 if (AndroidBitmap_lockPixels(env
, jbitmap
.obj(), &pixels
) < 0) {
159 LOG(ERROR
) << "Error locking java bitmap pixels.";
166 SkImageInfo::MakeN32Premul(bitmap_info
.width
, bitmap_info
.height
);
168 bitmap
.installPixels(info
, pixels
, bitmap_info
.stride
);
170 SkCanvas
canvas(bitmap
);
171 succeeded
= renderer
.Run(&canvas
);
174 if (AndroidBitmap_unlockPixels(env
, jbitmap
.obj()) < 0) {
175 LOG(ERROR
) << "Error unlocking java bitmap pixels.";
182 } // namespace android_webview