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/utils/SkCanvasStateUtils.h"
15 using base::android::JavaRef;
16 using base::android::ScopedJavaLocalRef;
18 namespace android_webview {
22 // Provides software rendering functions from the Android glue layer.
23 // Allows preventing extra copies of data when rendering.
24 AwDrawSWFunctionTable* g_sw_draw_functions = NULL;
26 class ScopedPixelAccess {
28 ScopedPixelAccess(JNIEnv* env, jobject java_canvas) : pixels_(NULL) {
29 if (g_sw_draw_functions)
30 pixels_ = g_sw_draw_functions->access_pixels(env, java_canvas);
33 ~ScopedPixelAccess() {
35 g_sw_draw_functions->release_pixels(pixels_);
38 AwPixelInfo* pixels() { return pixels_; }
43 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
49 void JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
50 AwDrawSWFunctionTable* table) {
51 g_sw_draw_functions = table;
55 JavaBrowserViewRendererHelper* JavaBrowserViewRendererHelper::GetInstance() {
56 static JavaBrowserViewRendererHelper* g_instance =
57 new JavaBrowserViewRendererHelper;
62 BrowserViewRendererJavaHelper* BrowserViewRendererJavaHelper::GetInstance() {
63 return JavaBrowserViewRendererHelper::GetInstance();
66 JavaBrowserViewRendererHelper::JavaBrowserViewRendererHelper() {}
68 JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {}
70 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmapIfNeeded(
72 const gfx::Vector2d& scroll_correction,
73 const gfx::Rect& clip,
74 RenderMethod render_source) {
75 TRACE_EVENT0("android_webview", "RenderViaAuxilaryBitmapIfNeeded");
77 JNIEnv* env = base::android::AttachCurrentThread();
78 ScopedPixelAccess auto_release_pixels(env, java_canvas);
79 AwPixelInfo* pixels = auto_release_pixels.pixels();
80 if (pixels && pixels->state) {
81 skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(
82 SkCanvasStateUtils::CreateFromCanvasState(pixels->state));
84 // Workarounds for http://crbug.com/271096: SW draw only supports
85 // translate & scale transforms, and a simple rectangular clip.
86 if (canvas && (!canvas->isClipRect() ||
87 (canvas->getTotalMatrix().getType() &
88 ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask)))) {
92 canvas->translate(scroll_correction.x(), scroll_correction.y());
93 return render_source.Run(canvas.get());
96 return RenderViaAuxilaryBitmap(
97 env, java_canvas, scroll_correction, clip, render_source);
100 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmap(
103 const gfx::Vector2d& scroll_correction,
104 const gfx::Rect& clip,
105 const RenderMethod& render_source) {
106 // Render into an auxiliary bitmap if pixel info is not available.
107 ScopedJavaLocalRef<jobject> jcanvas(env, java_canvas);
108 TRACE_EVENT0("android_webview", "RenderToAuxBitmap");
110 if (clip.width() <= 0 || clip.height() <= 0)
113 ScopedJavaLocalRef<jobject> jbitmap(
114 Java_JavaBrowserViewRendererHelper_createBitmap(
115 env, clip.width(), clip.height(), jcanvas.obj()));
119 if (!RasterizeIntoBitmap(env,
121 clip.x() - scroll_correction.x(),
122 clip.y() - scroll_correction.y(),
127 Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
128 env, jbitmap.obj(), jcanvas.obj(), clip.x(), clip.y());
132 bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env) {
133 return RegisterNativesImpl(env);
136 bool JavaBrowserViewRendererHelper::RasterizeIntoBitmap(
138 const JavaRef<jobject>& jbitmap,
141 const JavaBrowserViewRendererHelper::RenderMethod& renderer) {
142 DCHECK(jbitmap.obj());
144 AndroidBitmapInfo bitmap_info;
145 if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) {
146 LOG(ERROR) << "Error getting java bitmap info.";
151 if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) {
152 LOG(ERROR) << "Error locking java bitmap pixels.";
159 SkImageInfo::MakeN32Premul(bitmap_info.width, bitmap_info.height);
161 bitmap.installPixels(info, pixels, bitmap_info.stride);
163 SkCanvas canvas(bitmap);
164 canvas.translate(-scroll_x, -scroll_y);
165 succeeded = renderer.Run(&canvas);
168 if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) {
169 LOG(ERROR) << "Error unlocking java bitmap pixels.";
176 } // namespace android_webview