Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / android_webview / native / java_browser_view_renderer_helper.cc
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.
4
5 #include "android_webview/native/java_browser_view_renderer_helper.h"
6
7 #include <android/bitmap.h>
8
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"
15
16 using base::android::JavaRef;
17 using base::android::ScopedJavaLocalRef;
18
19 namespace android_webview {
20
21 namespace {
22
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;
26
27 class ScopedPixelAccess {
28  public:
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);
32   }
33
34   ~ScopedPixelAccess() {
35     if (pixels_)
36       g_sw_draw_functions->release_pixels(pixels_);
37   }
38
39   AwPixelInfo* pixels() { return pixels_; }
40
41  private:
42   AwPixelInfo* pixels_;
43
44   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPixelAccess);
45 };
46
47 }  // namespace
48
49 // static
50 void JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
51     AwDrawSWFunctionTable* table) {
52   g_sw_draw_functions = table;
53 }
54
55 // static
56 JavaBrowserViewRendererHelper* JavaBrowserViewRendererHelper::GetInstance() {
57   static JavaBrowserViewRendererHelper* g_instance =
58       new JavaBrowserViewRendererHelper;
59   return g_instance;
60 }
61
62 // static
63 BrowserViewRendererJavaHelper* BrowserViewRendererJavaHelper::GetInstance() {
64   return JavaBrowserViewRendererHelper::GetInstance();
65 }
66
67 JavaBrowserViewRendererHelper::JavaBrowserViewRendererHelper() {}
68
69 JavaBrowserViewRendererHelper::~JavaBrowserViewRendererHelper() {}
70
71 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmapIfNeeded(
72     jobject java_canvas,
73     const gfx::Vector2d& scroll_correction,
74     const gfx::Size& auxiliary_bitmap_size,
75     RenderMethod render_source) {
76   TRACE_EVENT0("android_webview", "RenderViaAuxilaryBitmapIfNeeded");
77
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));
84
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)))) {
90       canvas.clear();
91     }
92     if (canvas) {
93       canvas->translate(scroll_correction.x(), scroll_correction.y());
94       return render_source.Run(canvas.get());
95     }
96   }
97   return RenderViaAuxilaryBitmap(env,
98                                  java_canvas,
99                                  scroll_correction,
100                                  auxiliary_bitmap_size,
101                                  render_source);
102 }
103
104 bool JavaBrowserViewRendererHelper::RenderViaAuxilaryBitmap(
105     JNIEnv* env,
106     jobject java_canvas,
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");
113
114   if (auxiliary_bitmap_size.width() <= 0 || auxiliary_bitmap_size.height() <= 0)
115     return false;
116
117   ScopedJavaLocalRef<jobject> jbitmap(
118       Java_JavaBrowserViewRendererHelper_createBitmap(
119           env,
120           auxiliary_bitmap_size.width(),
121           auxiliary_bitmap_size.height(),
122           jcanvas.obj()));
123   if (!jbitmap.obj())
124     return false;
125
126   if (!RasterizeIntoBitmap(env,
127                            jbitmap,
128                            render_source)) {
129     return false;
130   }
131
132   Java_JavaBrowserViewRendererHelper_drawBitmapIntoCanvas(
133       env,
134       jbitmap.obj(),
135       jcanvas.obj(),
136       scroll_correction.x(),
137       scroll_correction.y());
138   return true;
139 }
140
141 bool RegisterJavaBrowserViewRendererHelper(JNIEnv* env) {
142   return RegisterNativesImpl(env);
143 }
144
145 bool JavaBrowserViewRendererHelper::RasterizeIntoBitmap(
146     JNIEnv* env,
147     const JavaRef<jobject>& jbitmap,
148     const JavaBrowserViewRendererHelper::RenderMethod& renderer) {
149   DCHECK(jbitmap.obj());
150
151   AndroidBitmapInfo bitmap_info;
152   if (AndroidBitmap_getInfo(env, jbitmap.obj(), &bitmap_info) < 0) {
153     LOG(ERROR) << "Error getting java bitmap info.";
154     return false;
155   }
156
157   void* pixels = NULL;
158   if (AndroidBitmap_lockPixels(env, jbitmap.obj(), &pixels) < 0) {
159     LOG(ERROR) << "Error locking java bitmap pixels.";
160     return false;
161   }
162
163   bool succeeded;
164   {
165     SkImageInfo info =
166         SkImageInfo::MakeN32Premul(bitmap_info.width, bitmap_info.height);
167     SkBitmap bitmap;
168     bitmap.installPixels(info, pixels, bitmap_info.stride);
169
170     SkCanvas canvas(bitmap);
171     succeeded = renderer.Run(&canvas);
172   }
173
174   if (AndroidBitmap_unlockPixels(env, jbitmap.obj()) < 0) {
175     LOG(ERROR) << "Error unlocking java bitmap pixels.";
176     return false;
177   }
178
179   return succeeded;
180 }
181
182 }  // namespace android_webview