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/public/browser/draw_sw.h"
10 #include "base/debug/trace_event.h"
11 #include "jni/JavaBrowserViewRendererHelper_jni.h"
12 #include "third_party/skia/include/core/SkBitmap.h"
13 #include "third_party/skia/include/core/SkBitmapDevice.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
)
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::Rect
& clip
,
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
->getTotalClip().isRect() ||
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(
98 env
, java_canvas
, scroll_correction
, clip
, render_source
);
101 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmap(
104 const gfx::Vector2d
& scroll_correction
,
105 const gfx::Rect
& clip
,
106 const RenderMethod
& render_source
) {
107 // Render into an auxiliary bitmap if pixel info is not available.
108 ScopedJavaLocalRef
<jobject
> jcanvas(env
, java_canvas
);
109 TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
111 if (clip
.width() <= 0 || clip
.height() <= 0)
114 ScopedJavaLocalRef
<jobject
> jbitmap(
115 Java_JavaBrowserViewRendererHelper_createBitmap(
116 env
, clip
.width(), clip
.height(), jcanvas
.obj()));
120 if (!RasterizeIntoBitmap(env
,
122 clip
.x() - scroll_correction
.x(),
123 clip
.y() - scroll_correction
.y(),
128 Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
129 env
, jbitmap
.obj(), jcanvas
.obj(), clip
.x(), clip
.y());
133 bool RegisterJavaBrowserViewRendererHelper(JNIEnv
* env
) {
134 return RegisterNativesImpl(env
) >= 0;
137 bool JavaBrowserViewRendererHelper::RasterizeIntoBitmap(
139 const JavaRef
<jobject
>& jbitmap
,
142 const JavaBrowserViewRendererHelper::RenderMethod
& renderer
) {
143 DCHECK(jbitmap
.obj());
145 AndroidBitmapInfo bitmap_info
;
146 if (AndroidBitmap_getInfo(env
, jbitmap
.obj(), &bitmap_info
) < 0) {
147 LOG(ERROR
) << "Error getting java bitmap info.";
152 if (AndroidBitmap_lockPixels(env
, jbitmap
.obj(), &pixels
) < 0) {
153 LOG(ERROR
) << "Error locking java bitmap pixels.";
160 bitmap
.setConfig(SkBitmap::kARGB_8888_Config
,
164 bitmap
.setPixels(pixels
);
166 SkBitmapDevice
device(bitmap
);
167 SkCanvas
canvas(&device
);
168 canvas
.translate(-scroll_x
, -scroll_y
);
169 succeeded
= renderer
.Run(&canvas
);
172 if (AndroidBitmap_unlockPixels(env
, jbitmap
.obj()) < 0) {
173 LOG(ERROR
) << "Error unlocking java bitmap pixels.";
180 } // namespace android_webview