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