• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006-2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "jni.h"
18 #include "GraphicsJNI.h"
19 #include <android_runtime/AndroidRuntime.h>
20 
21 #include "SkCanvas.h"
22 #include "SkDevice.h"
23 #include "SkGraphics.h"
24 #include "SkImageRef_GlobalPool.h"
25 #include "SkPorterDuff.h"
26 #include "SkShader.h"
27 #include "SkTemplates.h"
28 
29 #include "TextLayout.h"
30 #include "TextLayoutCache.h"
31 
32 #include "unicode/ubidi.h"
33 #include "unicode/ushape.h"
34 
35 #include <utils/Log.h>
36 
37 #define TIME_DRAWx
38 
get_thread_msec()39 static uint32_t get_thread_msec() {
40 #if defined(HAVE_POSIX_CLOCKS)
41     struct timespec tm;
42 
43     clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
44 
45     return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
46 #else
47     struct timeval tv;
48 
49     gettimeofday(&tv, NULL);
50     return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
51 #endif
52 }
53 
54 namespace android {
55 
56 class SkCanvasGlue {
57 public:
58 
finalizer(JNIEnv * env,jobject clazz,SkCanvas * canvas)59     static void finalizer(JNIEnv* env, jobject clazz, SkCanvas* canvas) {
60         canvas->unref();
61     }
62 
initRaster(JNIEnv * env,jobject,SkBitmap * bitmap)63     static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {
64         return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;
65     }
66 
freeCaches(JNIEnv * env,jobject)67     static void freeCaches(JNIEnv* env, jobject) {
68         // these are called in no particular order
69         SkImageRef_GlobalPool::SetRAMUsed(0);
70         SkGraphics::SetFontCacheUsed(0);
71     }
72 
isOpaque(JNIEnv * env,jobject jcanvas)73     static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
74         NPE_CHECK_RETURN_ZERO(env, jcanvas);
75         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
76         return canvas->getDevice()->accessBitmap(false).isOpaque();
77     }
78 
getWidth(JNIEnv * env,jobject jcanvas)79     static int getWidth(JNIEnv* env, jobject jcanvas) {
80         NPE_CHECK_RETURN_ZERO(env, jcanvas);
81         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
82         return canvas->getDevice()->accessBitmap(false).width();
83     }
84 
getHeight(JNIEnv * env,jobject jcanvas)85     static int getHeight(JNIEnv* env, jobject jcanvas) {
86         NPE_CHECK_RETURN_ZERO(env, jcanvas);
87         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
88         return canvas->getDevice()->accessBitmap(false).height();
89     }
90 
setBitmap(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap)91     static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas, SkBitmap* bitmap) {
92         if (bitmap) {
93             canvas->setBitmapDevice(*bitmap);
94         } else {
95             canvas->setDevice(NULL);
96         }
97     }
98 
saveAll(JNIEnv * env,jobject jcanvas)99     static int saveAll(JNIEnv* env, jobject jcanvas) {
100         NPE_CHECK_RETURN_ZERO(env, jcanvas);
101         return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
102     }
103 
save(JNIEnv * env,jobject jcanvas,SkCanvas::SaveFlags flags)104     static int save(JNIEnv* env, jobject jcanvas, SkCanvas::SaveFlags flags) {
105         NPE_CHECK_RETURN_ZERO(env, jcanvas);
106         return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
107     }
108 
saveLayer(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds,SkPaint * paint,int flags)109     static int saveLayer(JNIEnv* env, jobject, SkCanvas* canvas, jobject bounds,
110                          SkPaint* paint, int flags) {
111         SkRect* bounds_ = NULL;
112         SkRect  storage;
113         if (bounds != NULL) {
114             GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
115             bounds_ = &storage;
116         }
117         return canvas->saveLayer(bounds_, paint, (SkCanvas::SaveFlags)flags);
118     }
119 
saveLayer4F(JNIEnv * env,jobject,SkCanvas * canvas,jfloat l,jfloat t,jfloat r,jfloat b,SkPaint * paint,int flags)120     static int saveLayer4F(JNIEnv* env, jobject, SkCanvas* canvas,
121                            jfloat l, jfloat t, jfloat r, jfloat b,
122                            SkPaint* paint, int flags) {
123         SkRect bounds;
124         bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
125                    SkFloatToScalar(b));
126         return canvas->saveLayer(&bounds, paint, (SkCanvas::SaveFlags)flags);
127     }
128 
saveLayerAlpha(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds,int alpha,int flags)129     static int saveLayerAlpha(JNIEnv* env, jobject, SkCanvas* canvas,
130                               jobject bounds, int alpha, int flags) {
131         SkRect* bounds_ = NULL;
132         SkRect  storage;
133         if (bounds != NULL) {
134             GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
135             bounds_ = &storage;
136         }
137         return canvas->saveLayerAlpha(bounds_, alpha,
138                                       (SkCanvas::SaveFlags)flags);
139     }
140 
saveLayerAlpha4F(JNIEnv * env,jobject,SkCanvas * canvas,jfloat l,jfloat t,jfloat r,jfloat b,int alpha,int flags)141     static int saveLayerAlpha4F(JNIEnv* env, jobject, SkCanvas* canvas,
142                                 jfloat l, jfloat t, jfloat r, jfloat b,
143                                 int alpha, int flags) {
144         SkRect  bounds;
145         bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
146                    SkFloatToScalar(b));
147         return canvas->saveLayerAlpha(&bounds, alpha,
148                                       (SkCanvas::SaveFlags)flags);
149     }
150 
restore(JNIEnv * env,jobject jcanvas)151     static void restore(JNIEnv* env, jobject jcanvas) {
152         NPE_CHECK_RETURN_VOID(env, jcanvas);
153         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
154         if (canvas->getSaveCount() <= 1) {  // cannot restore anymore
155             doThrowISE(env, "Underflow in restore");
156             return;
157         }
158         canvas->restore();
159     }
160 
getSaveCount(JNIEnv * env,jobject jcanvas)161     static int getSaveCount(JNIEnv* env, jobject jcanvas) {
162         NPE_CHECK_RETURN_ZERO(env, jcanvas);
163         return GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
164     }
165 
restoreToCount(JNIEnv * env,jobject jcanvas,int restoreCount)166     static void restoreToCount(JNIEnv* env, jobject jcanvas, int restoreCount) {
167         NPE_CHECK_RETURN_VOID(env, jcanvas);
168         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
169         if (restoreCount < 1) {
170             doThrowIAE(env, "Underflow in restoreToCount");
171             return;
172         }
173         canvas->restoreToCount(restoreCount);
174     }
175 
translate(JNIEnv * env,jobject jcanvas,jfloat dx,jfloat dy)176     static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
177         NPE_CHECK_RETURN_VOID(env, jcanvas);
178         SkScalar dx_ = SkFloatToScalar(dx);
179         SkScalar dy_ = SkFloatToScalar(dy);
180         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
181     }
182 
scale__FF(JNIEnv * env,jobject jcanvas,jfloat sx,jfloat sy)183     static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
184         NPE_CHECK_RETURN_VOID(env, jcanvas);
185         SkScalar sx_ = SkFloatToScalar(sx);
186         SkScalar sy_ = SkFloatToScalar(sy);
187         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
188     }
189 
rotate__F(JNIEnv * env,jobject jcanvas,jfloat degrees)190     static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
191         NPE_CHECK_RETURN_VOID(env, jcanvas);
192         SkScalar degrees_ = SkFloatToScalar(degrees);
193         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
194     }
195 
skew__FF(JNIEnv * env,jobject jcanvas,jfloat sx,jfloat sy)196     static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
197         NPE_CHECK_RETURN_VOID(env, jcanvas);
198         SkScalar sx_ = SkFloatToScalar(sx);
199         SkScalar sy_ = SkFloatToScalar(sy);
200         (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
201     }
202 
concat(JNIEnv * env,jobject,SkCanvas * canvas,const SkMatrix * matrix)203     static void concat(JNIEnv* env, jobject, SkCanvas* canvas,
204                        const SkMatrix* matrix) {
205         canvas->concat(*matrix);
206     }
207 
setMatrix(JNIEnv * env,jobject,SkCanvas * canvas,const SkMatrix * matrix)208     static void setMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
209                           const SkMatrix* matrix) {
210         if (NULL == matrix) {
211             canvas->resetMatrix();
212         } else {
213             canvas->setMatrix(*matrix);
214         }
215     }
216 
clipRect_FFFF(JNIEnv * env,jobject jcanvas,jfloat left,jfloat top,jfloat right,jfloat bottom)217     static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
218                                   jfloat top, jfloat right, jfloat bottom) {
219         NPE_CHECK_RETURN_ZERO(env, jcanvas);
220         SkRect  r;
221         r.set(SkFloatToScalar(left), SkFloatToScalar(top),
222               SkFloatToScalar(right), SkFloatToScalar(bottom));
223         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
224         return c->clipRect(r);
225     }
226 
clipRect_IIII(JNIEnv * env,jobject jcanvas,jint left,jint top,jint right,jint bottom)227     static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
228                                   jint top, jint right, jint bottom) {
229         NPE_CHECK_RETURN_ZERO(env, jcanvas);
230         SkRect  r;
231         r.set(SkIntToScalar(left), SkIntToScalar(top),
232               SkIntToScalar(right), SkIntToScalar(bottom));
233         return GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
234     }
235 
clipRect_RectF(JNIEnv * env,jobject jcanvas,jobject rectf)236     static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
237         NPE_CHECK_RETURN_ZERO(env, jcanvas);
238         NPE_CHECK_RETURN_ZERO(env, rectf);
239         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
240         SkRect tmp;
241         return c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
242     }
243 
clipRect_Rect(JNIEnv * env,jobject jcanvas,jobject rect)244     static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
245         NPE_CHECK_RETURN_ZERO(env, jcanvas);
246         NPE_CHECK_RETURN_ZERO(env, rect);
247         SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
248         SkRect tmp;
249         return c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
250     }
251 
clipRect(JNIEnv * env,jobject,SkCanvas * canvas,float left,float top,float right,float bottom,int op)252     static jboolean clipRect(JNIEnv* env, jobject, SkCanvas* canvas,
253                              float left, float top, float right, float bottom,
254                              int op) {
255         SkRect rect;
256         rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
257                  SkFloatToScalar(right), SkFloatToScalar(bottom));
258         return canvas->clipRect(rect, (SkRegion::Op)op);
259     }
260 
clipPath(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,int op)261     static jboolean clipPath(JNIEnv* env, jobject, SkCanvas* canvas,
262                              SkPath* path, int op) {
263         return canvas->clipPath(*path, (SkRegion::Op)op);
264     }
265 
clipRegion(JNIEnv * env,jobject,SkCanvas * canvas,SkRegion * deviceRgn,int op)266     static jboolean clipRegion(JNIEnv* env, jobject, SkCanvas* canvas,
267                                SkRegion* deviceRgn, int op) {
268         return canvas->clipRegion(*deviceRgn, (SkRegion::Op)op);
269     }
270 
setDrawFilter(JNIEnv * env,jobject,SkCanvas * canvas,SkDrawFilter * filter)271     static void setDrawFilter(JNIEnv* env, jobject, SkCanvas* canvas,
272                               SkDrawFilter* filter) {
273         canvas->setDrawFilter(filter);
274     }
275 
quickReject__RectFI(JNIEnv * env,jobject,SkCanvas * canvas,jobject rect,int edgetype)276     static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
277                                         jobject rect, int edgetype) {
278         SkRect rect_;
279         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
280         return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
281     }
282 
quickReject__PathI(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,int edgetype)283     static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
284                                        SkPath* path, int edgetype) {
285         return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
286     }
287 
quickReject__FFFFI(JNIEnv * env,jobject,SkCanvas * canvas,jfloat left,jfloat top,jfloat right,jfloat bottom,int edgetype)288     static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
289                                        jfloat left, jfloat top, jfloat right,
290                                        jfloat bottom, int edgetype) {
291         SkRect r;
292         r.set(SkFloatToScalar(left), SkFloatToScalar(top),
293               SkFloatToScalar(right), SkFloatToScalar(bottom));
294         return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
295     }
296 
drawRGB(JNIEnv * env,jobject,SkCanvas * canvas,jint r,jint g,jint b)297     static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
298                         jint r, jint g, jint b) {
299         canvas->drawARGB(0xFF, r, g, b);
300     }
301 
drawARGB(JNIEnv * env,jobject,SkCanvas * canvas,jint a,jint r,jint g,jint b)302     static void drawARGB(JNIEnv* env, jobject, SkCanvas* canvas,
303                          jint a, jint r, jint g, jint b) {
304         canvas->drawARGB(a, r, g, b);
305     }
306 
drawColor__I(JNIEnv * env,jobject,SkCanvas * canvas,jint color)307     static void drawColor__I(JNIEnv* env, jobject, SkCanvas* canvas,
308                              jint color) {
309         canvas->drawColor(color);
310     }
311 
drawColor__II(JNIEnv * env,jobject,SkCanvas * canvas,jint color,SkPorterDuff::Mode mode)312     static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
313                               jint color, SkPorterDuff::Mode mode) {
314         canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
315     }
316 
drawPaint(JNIEnv * env,jobject,SkCanvas * canvas,SkPaint * paint)317     static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
318                           SkPaint* paint) {
319         canvas->drawPaint(*paint);
320     }
321 
doPoints(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint,SkCanvas::PointMode mode)322     static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
323                          jint offset, jint count, jobject jpaint,
324                          SkCanvas::PointMode mode) {
325         NPE_CHECK_RETURN_VOID(env, jcanvas);
326         NPE_CHECK_RETURN_VOID(env, jptsArray);
327         NPE_CHECK_RETURN_VOID(env, jpaint);
328         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
329         const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
330 
331         AutoJavaFloatArray autoPts(env, jptsArray);
332         float* floats = autoPts.ptr();
333         const int length = autoPts.length();
334 
335         if ((offset | count) < 0 || offset + count > length) {
336             doThrowAIOOBE(env);
337             return;
338         }
339 
340         // now convert the floats into SkPoints
341         count >>= 1;    // now it is the number of points
342         SkAutoSTMalloc<32, SkPoint> storage(count);
343         SkPoint* pts = storage.get();
344         const float* src = floats + offset;
345         for (int i = 0; i < count; i++) {
346             pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
347             src += 2;
348         }
349         canvas->drawPoints(mode, count, pts, paint);
350     }
351 
drawPoints(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint)352     static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
353                            jint offset, jint count, jobject jpaint) {
354         doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
355                  SkCanvas::kPoints_PointMode);
356     }
357 
drawLines(JNIEnv * env,jobject jcanvas,jfloatArray jptsArray,jint offset,jint count,jobject jpaint)358     static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
359                            jint offset, jint count, jobject jpaint) {
360         doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
361                  SkCanvas::kLines_PointMode);
362     }
363 
drawPoint(JNIEnv * env,jobject jcanvas,float x,float y,jobject jpaint)364     static void drawPoint(JNIEnv* env, jobject jcanvas, float x, float y,
365                           jobject jpaint) {
366         NPE_CHECK_RETURN_VOID(env, jcanvas);
367         NPE_CHECK_RETURN_VOID(env, jpaint);
368         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
369         const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
370 
371         canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
372     }
373 
drawLine__FFFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jfloat startX,jfloat startY,jfloat stopX,jfloat stopY,SkPaint * paint)374     static void drawLine__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
375                                     jfloat startX, jfloat startY, jfloat stopX,
376                                     jfloat stopY, SkPaint* paint) {
377         canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
378                          SkFloatToScalar(stopX), SkFloatToScalar(stopY),
379                          *paint);
380     }
381 
drawRect__RectFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jobject rect,SkPaint * paint)382     static void drawRect__RectFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
383                                      jobject rect, SkPaint* paint) {
384         SkRect rect_;
385         GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
386         canvas->drawRect(rect_, *paint);
387     }
388 
drawRect__FFFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jfloat left,jfloat top,jfloat right,jfloat bottom,SkPaint * paint)389     static void drawRect__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
390                                     jfloat left, jfloat top, jfloat right,
391                                     jfloat bottom, SkPaint* paint) {
392         SkScalar left_ = SkFloatToScalar(left);
393         SkScalar top_ = SkFloatToScalar(top);
394         SkScalar right_ = SkFloatToScalar(right);
395         SkScalar bottom_ = SkFloatToScalar(bottom);
396         canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
397     }
398 
drawOval(JNIEnv * env,jobject,SkCanvas * canvas,jobject joval,SkPaint * paint)399     static void drawOval(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
400                          SkPaint* paint) {
401         SkRect oval;
402         GraphicsJNI::jrectf_to_rect(env, joval, &oval);
403         canvas->drawOval(oval, *paint);
404     }
405 
drawCircle(JNIEnv * env,jobject,SkCanvas * canvas,jfloat cx,jfloat cy,jfloat radius,SkPaint * paint)406     static void drawCircle(JNIEnv* env, jobject, SkCanvas* canvas, jfloat cx,
407                            jfloat cy, jfloat radius, SkPaint* paint) {
408         canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
409                            SkFloatToScalar(radius), *paint);
410     }
411 
drawArc(JNIEnv * env,jobject,SkCanvas * canvas,jobject joval,jfloat startAngle,jfloat sweepAngle,jboolean useCenter,SkPaint * paint)412     static void drawArc(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
413                         jfloat startAngle, jfloat sweepAngle,
414                         jboolean useCenter, SkPaint* paint) {
415         SkRect oval;
416         GraphicsJNI::jrectf_to_rect(env, joval, &oval);
417         canvas->drawArc(oval, SkFloatToScalar(startAngle),
418                         SkFloatToScalar(sweepAngle), useCenter, *paint);
419     }
420 
drawRoundRect(JNIEnv * env,jobject,SkCanvas * canvas,jobject jrect,jfloat rx,jfloat ry,SkPaint * paint)421     static void drawRoundRect(JNIEnv* env, jobject, SkCanvas* canvas,
422                               jobject jrect, jfloat rx, jfloat ry,
423                               SkPaint* paint) {
424         SkRect rect;
425         GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
426         canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
427                               *paint);
428     }
429 
drawPath(JNIEnv * env,jobject,SkCanvas * canvas,SkPath * path,SkPaint * paint)430     static void drawPath(JNIEnv* env, jobject, SkCanvas* canvas, SkPath* path,
431                          SkPaint* paint) {
432         canvas->drawPath(*path, *paint);
433     }
434 
drawPicture(JNIEnv * env,jobject,SkCanvas * canvas,SkPicture * picture)435     static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
436                             SkPicture* picture) {
437         SkASSERT(canvas);
438         SkASSERT(picture);
439 
440 #ifdef TIME_DRAW
441         SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
442 #endif
443         canvas->drawPicture(*picture);
444 #ifdef TIME_DRAW
445         LOGD("---- picture playback %d ms\n", get_thread_msec() - now);
446 #endif
447     }
448 
drawBitmap__BitmapFFPaint(JNIEnv * env,jobject jcanvas,SkCanvas * canvas,SkBitmap * bitmap,jfloat left,jfloat top,SkPaint * paint,jint canvasDensity,jint screenDensity,jint bitmapDensity)449     static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
450                                           SkCanvas* canvas, SkBitmap* bitmap,
451                                           jfloat left, jfloat top,
452                                           SkPaint* paint, jint canvasDensity,
453                                           jint screenDensity, jint bitmapDensity) {
454         SkScalar left_ = SkFloatToScalar(left);
455         SkScalar top_ = SkFloatToScalar(top);
456 
457         if (canvasDensity == bitmapDensity || canvasDensity == 0
458                 || bitmapDensity == 0) {
459             if (screenDensity != 0 && screenDensity != bitmapDensity) {
460                 SkPaint filteredPaint;
461                 if (paint) {
462                     filteredPaint = *paint;
463                 }
464                 filteredPaint.setFilterBitmap(true);
465                 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
466             } else {
467                 canvas->drawBitmap(*bitmap, left_, top_, paint);
468             }
469         } else {
470             canvas->save();
471             SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
472             canvas->translate(left_, top_);
473             canvas->scale(scale, scale);
474 
475             SkPaint filteredPaint;
476             if (paint) {
477                 filteredPaint = *paint;
478             }
479             filteredPaint.setFilterBitmap(true);
480 
481             canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
482 
483             canvas->restore();
484         }
485     }
486 
doDrawBitmap(JNIEnv * env,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,const SkRect & dst,SkPaint * paint,jint screenDensity,jint bitmapDensity)487     static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
488                         jobject srcIRect, const SkRect& dst, SkPaint* paint,
489                         jint screenDensity, jint bitmapDensity) {
490         SkIRect    src, *srcPtr = NULL;
491 
492         if (NULL != srcIRect) {
493             GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
494             srcPtr = &src;
495         }
496 
497         if (screenDensity != 0 && screenDensity != bitmapDensity) {
498             SkPaint filteredPaint;
499             if (paint) {
500                 filteredPaint = *paint;
501             }
502             filteredPaint.setFilterBitmap(true);
503             canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
504         } else {
505             canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
506         }
507     }
508 
drawBitmapRF(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,jobject dstRectF,SkPaint * paint,jint screenDensity,jint bitmapDensity)509     static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
510                              SkBitmap* bitmap, jobject srcIRect,
511                              jobject dstRectF, SkPaint* paint,
512                              jint screenDensity, jint bitmapDensity) {
513         SkRect      dst;
514         GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
515         doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
516                 screenDensity, bitmapDensity);
517     }
518 
drawBitmapRR(JNIEnv * env,jobject,SkCanvas * canvas,SkBitmap * bitmap,jobject srcIRect,jobject dstRect,SkPaint * paint,jint screenDensity,jint bitmapDensity)519     static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
520                              SkBitmap* bitmap, jobject srcIRect,
521                              jobject dstRect, SkPaint* paint,
522                              jint screenDensity, jint bitmapDensity) {
523         SkRect      dst;
524         GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
525         doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
526                 screenDensity, bitmapDensity);
527     }
528 
drawBitmapArray(JNIEnv * env,jobject,SkCanvas * canvas,jintArray jcolors,int offset,int stride,jfloat x,jfloat y,int width,int height,jboolean hasAlpha,SkPaint * paint)529     static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
530                                 jintArray jcolors, int offset, int stride,
531                                 jfloat x, jfloat y, int width, int height,
532                                 jboolean hasAlpha, SkPaint* paint)
533     {
534         SkBitmap    bitmap;
535 
536         bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
537                          SkBitmap::kRGB_565_Config, width, height);
538         if (!bitmap.allocPixels()) {
539             return;
540         }
541 
542         if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
543                                     0, 0, width, height, bitmap)) {
544             return;
545         }
546 
547         canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
548                            paint);
549     }
550 
drawBitmapMatrix(JNIEnv * env,jobject,SkCanvas * canvas,const SkBitmap * bitmap,const SkMatrix * matrix,const SkPaint * paint)551     static void drawBitmapMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
552                                  const SkBitmap* bitmap, const SkMatrix* matrix,
553                                  const SkPaint* paint) {
554         canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
555     }
556 
drawBitmapMesh(JNIEnv * env,jobject,SkCanvas * canvas,const SkBitmap * bitmap,int meshWidth,int meshHeight,jfloatArray jverts,int vertIndex,jintArray jcolors,int colorIndex,const SkPaint * paint)557     static void drawBitmapMesh(JNIEnv* env, jobject, SkCanvas* canvas,
558                           const SkBitmap* bitmap, int meshWidth, int meshHeight,
559                           jfloatArray jverts, int vertIndex, jintArray jcolors,
560                           int colorIndex, const SkPaint* paint) {
561 
562         const int ptCount = (meshWidth + 1) * (meshHeight + 1);
563         const int indexCount = meshWidth * meshHeight * 6;
564 
565         AutoJavaFloatArray  vertA(env, jverts, vertIndex + (ptCount << 1));
566         AutoJavaIntArray    colorA(env, jcolors, colorIndex + ptCount);
567 
568         /*  Our temp storage holds 2 or 3 arrays.
569             texture points [ptCount * sizeof(SkPoint)]
570             optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
571                 copy to convert from float to fixed
572             indices [ptCount * sizeof(uint16_t)]
573         */
574         ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
575 #ifdef SK_SCALAR_IS_FIXED
576         storageSize += ptCount * sizeof(SkPoint);  // storage for verts
577 #endif
578         storageSize += indexCount * sizeof(uint16_t);  // indices[]
579 
580         SkAutoMalloc storage(storageSize);
581         SkPoint* texs = (SkPoint*)storage.get();
582         SkPoint* verts;
583         uint16_t* indices;
584 #ifdef SK_SCALAR_IS_FLOAT
585         verts = (SkPoint*)(vertA.ptr() + vertIndex);
586         indices = (uint16_t*)(texs + ptCount);
587 #else
588         verts = texs + ptCount;
589         indices = (uint16_t*)(verts + ptCount);
590         // convert floats to fixed
591         {
592             const float* src = vertA.ptr() + vertIndex;
593             for (int i = 0; i < ptCount; i++) {
594                 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
595                 src += 2;
596             }
597         }
598 #endif
599 
600         // cons up texture coordinates and indices
601         {
602             const SkScalar w = SkIntToScalar(bitmap->width());
603             const SkScalar h = SkIntToScalar(bitmap->height());
604             const SkScalar dx = w / meshWidth;
605             const SkScalar dy = h / meshHeight;
606 
607             SkPoint* texsPtr = texs;
608             SkScalar y = 0;
609             for (int i = 0; i <= meshHeight; i++) {
610                 if (i == meshHeight) {
611                     y = h;  // to ensure numerically we hit h exactly
612                 }
613                 SkScalar x = 0;
614                 for (int j = 0; j < meshWidth; j++) {
615                     texsPtr->set(x, y);
616                     texsPtr += 1;
617                     x += dx;
618                 }
619                 texsPtr->set(w, y);
620                 texsPtr += 1;
621                 y += dy;
622             }
623             SkASSERT(texsPtr - texs == ptCount);
624         }
625 
626         // cons up indices
627         {
628             uint16_t* indexPtr = indices;
629             int index = 0;
630             for (int i = 0; i < meshHeight; i++) {
631                 for (int j = 0; j < meshWidth; j++) {
632                     // lower-left triangle
633                     *indexPtr++ = index;
634                     *indexPtr++ = index + meshWidth + 1;
635                     *indexPtr++ = index + meshWidth + 2;
636                     // upper-right triangle
637                     *indexPtr++ = index;
638                     *indexPtr++ = index + meshWidth + 2;
639                     *indexPtr++ = index + 1;
640                     // bump to the next cell
641                     index += 1;
642                 }
643                 // bump to the next row
644                 index += 1;
645             }
646             SkASSERT(indexPtr - indices == indexCount);
647             SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
648         }
649 
650         // double-check that we have legal indices
651 #ifdef SK_DEBUG
652         {
653             for (int i = 0; i < indexCount; i++) {
654                 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
655             }
656         }
657 #endif
658 
659         // cons-up a shader for the bitmap
660         SkPaint tmpPaint;
661         if (paint) {
662             tmpPaint = *paint;
663         }
664         SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
665                         SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
666         SkSafeUnref(tmpPaint.setShader(shader));
667 
668         canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
669                              texs, (const SkColor*)colorA.ptr(), NULL, indices,
670                              indexCount, tmpPaint);
671     }
672 
drawVertices(JNIEnv * env,jobject,SkCanvas * canvas,SkCanvas::VertexMode mode,int vertexCount,jfloatArray jverts,int vertIndex,jfloatArray jtexs,int texIndex,jintArray jcolors,int colorIndex,jshortArray jindices,int indexIndex,int indexCount,const SkPaint * paint)673     static void drawVertices(JNIEnv* env, jobject, SkCanvas* canvas,
674                              SkCanvas::VertexMode mode, int vertexCount,
675                              jfloatArray jverts, int vertIndex,
676                              jfloatArray jtexs, int texIndex,
677                              jintArray jcolors, int colorIndex,
678                              jshortArray jindices, int indexIndex,
679                              int indexCount, const SkPaint* paint) {
680 
681         AutoJavaFloatArray  vertA(env, jverts, vertIndex + vertexCount);
682         AutoJavaFloatArray  texA(env, jtexs, texIndex + vertexCount);
683         AutoJavaIntArray    colorA(env, jcolors, colorIndex + vertexCount);
684         AutoJavaShortArray  indexA(env, jindices, indexIndex + indexCount);
685 
686         const int ptCount = vertexCount >> 1;
687 
688         SkPoint* verts;
689         SkPoint* texs = NULL;
690 #ifdef SK_SCALAR_IS_FLOAT
691         verts = (SkPoint*)(vertA.ptr() + vertIndex);
692         if (jtexs != NULL) {
693             texs = (SkPoint*)(texA.ptr() + texIndex);
694         }
695 #else
696         int count = ptCount;    // for verts
697         if (jtexs != NULL) {
698             count += ptCount;   // += for texs
699         }
700         SkAutoMalloc storage(count * sizeof(SkPoint));
701         verts = (SkPoint*)storage.get();
702         const float* src = vertA.ptr() + vertIndex;
703         for (int i = 0; i < ptCount; i++) {
704             verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
705             src += 2;
706         }
707         if (jtexs != NULL) {
708             texs = verts + ptCount;
709             src = texA.ptr() + texIndex;
710             for (int i = 0; i < ptCount; i++) {
711                 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
712                 src += 2;
713             }
714         }
715 #endif
716 
717         const SkColor* colors = NULL;
718         const uint16_t* indices = NULL;
719         if (jcolors != NULL) {
720             colors = (const SkColor*)(colorA.ptr() + colorIndex);
721         }
722         if (jindices != NULL) {
723             indices = (const uint16_t*)(indexA.ptr() + indexIndex);
724         }
725 
726         canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
727                              indices, indexCount, *paint);
728     }
729 
730 
drawText___CIIFFIPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,jfloat x,jfloat y,int flags,SkPaint * paint)731     static void drawText___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
732                                       jcharArray text, int index, int count,
733                                       jfloat x, jfloat y, int flags, SkPaint* paint) {
734         jchar* textArray = env->GetCharArrayElements(text, NULL);
735 #if RTL_USE_HARFBUZZ
736         drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
737 #else
738         TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas);
739 #endif
740         env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
741     }
742 
drawText__StringIIFFIPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,int start,int end,jfloat x,jfloat y,int flags,SkPaint * paint)743     static void drawText__StringIIFFIPaint(JNIEnv* env, jobject,
744                                           SkCanvas* canvas, jstring text,
745                                           int start, int end,
746                                           jfloat x, jfloat y, int flags, SkPaint* paint) {
747         const jchar* textArray = env->GetStringChars(text, NULL);
748 #if RTL_USE_HARFBUZZ
749         drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
750 #else
751         TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas);
752 #endif
753         env->ReleaseStringChars(text, textArray);
754     }
755 
drawTextWithGlyphs(SkCanvas * canvas,const jchar * textArray,int start,int end,jfloat x,jfloat y,int flags,SkPaint * paint)756     static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
757             int start, int end,
758             jfloat x, jfloat y, int flags, SkPaint* paint) {
759 
760         jint count = end - start;
761         drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint);
762     }
763 
drawTextWithGlyphs(SkCanvas * canvas,const jchar * textArray,int start,int count,int contextCount,jfloat x,jfloat y,int flags,SkPaint * paint)764     static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
765             int start, int count, int contextCount,
766             jfloat x, jfloat y, int flags, SkPaint* paint) {
767 
768         sp<TextLayoutCacheValue> value;
769 #if USE_TEXT_LAYOUT_CACHE
770         value = TextLayoutCache::getInstance().getValue(paint, textArray, start, count,
771                 contextCount, flags);
772         if (value == NULL) {
773             LOGE("Cannot get TextLayoutCache value");
774             return ;
775         }
776 #else
777         value = new TextLayoutCacheValue();
778         value->computeValues(paint, textArray, start, count, contextCount, flags);
779 #endif
780         doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), x, y, flags, paint);
781     }
782 
doDrawGlyphs(SkCanvas * canvas,const jchar * glyphArray,int index,int count,jfloat x,jfloat y,int flags,SkPaint * paint)783     static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
784             jfloat x, jfloat y, int flags, SkPaint* paint) {
785         // TODO: need to suppress this code after the GL renderer is modified for not
786         // copying the paint
787 
788         // Save old text encoding
789         SkPaint::TextEncoding oldEncoding = paint->getTextEncoding();
790         // Define Glyph encoding
791         paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
792 
793         canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
794 
795         // Get back old encoding
796         paint->setTextEncoding(oldEncoding);
797     }
798 
drawTextRun___CIIIIFFIPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,int contextIndex,int contextCount,jfloat x,jfloat y,int dirFlags,SkPaint * paint)799     static void drawTextRun___CIIIIFFIPaint(
800         JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
801         int count, int contextIndex, int contextCount,
802         jfloat x, jfloat y, int dirFlags, SkPaint* paint) {
803 
804         jchar* chars = env->GetCharArrayElements(text, NULL);
805 #if RTL_USE_HARFBUZZ
806         drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
807                 count, contextCount, x, y, dirFlags, paint);
808 #else
809         TextLayout::drawTextRun(paint, chars + contextIndex, index - contextIndex,
810                 count, contextCount, dirFlags, x, y, canvas);
811 #endif
812         env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
813     }
814 
drawTextRun__StringIIIIFFIPaint(JNIEnv * env,jobject obj,SkCanvas * canvas,jstring text,jint start,jint end,jint contextStart,jint contextEnd,jfloat x,jfloat y,jint dirFlags,SkPaint * paint)815     static void drawTextRun__StringIIIIFFIPaint(
816         JNIEnv* env, jobject obj, SkCanvas* canvas, jstring text, jint start,
817         jint end, jint contextStart, jint contextEnd,
818         jfloat x, jfloat y, jint dirFlags, SkPaint* paint) {
819 
820         jint count = end - start;
821         jint contextCount = contextEnd - contextStart;
822         const jchar* chars = env->GetStringChars(text, NULL);
823 #if RTL_USE_HARFBUZZ
824         drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
825                 count, contextCount, x, y, dirFlags, paint);
826 #else
827         TextLayout::drawTextRun(paint, chars + contextStart, start - contextStart,
828                 count, contextCount, dirFlags, x, y, canvas);
829 #endif
830         env->ReleaseStringChars(text, chars);
831     }
832 
drawPosText___CII_FPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,jfloatArray pos,SkPaint * paint)833     static void drawPosText___CII_FPaint(JNIEnv* env, jobject, SkCanvas* canvas,
834                                          jcharArray text, int index, int count,
835                                          jfloatArray pos, SkPaint* paint) {
836         jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
837         jsize textCount = text ? env->GetArrayLength(text) : NULL;
838         float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
839         int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
840         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
841         int indx;
842         for (indx = 0; indx < posCount; indx++) {
843             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
844             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
845         }
846         canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
847         if (text) {
848             env->ReleaseCharArrayElements(text, textArray, 0);
849         }
850         if (pos) {
851             env->ReleaseFloatArrayElements(pos, posArray, 0);
852         }
853         delete[] posPtr;
854     }
855 
drawPosText__String_FPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,jfloatArray pos,SkPaint * paint)856     static void drawPosText__String_FPaint(JNIEnv* env, jobject,
857                                            SkCanvas* canvas, jstring text,
858                                            jfloatArray pos,
859                                            SkPaint* paint) {
860         const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
861         int byteLength = text ? env->GetStringLength(text) : 0;
862         float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
863         int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
864         SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
865 
866         for (int indx = 0; indx < posCount; indx++) {
867             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
868             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
869         }
870         canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
871         if (text) {
872             env->ReleaseStringChars(text, (const jchar*) text_);
873         }
874         if (pos) {
875             env->ReleaseFloatArrayElements(pos, posArray, 0);
876         }
877         delete[] posPtr;
878     }
879 
drawTextOnPath___CIIPathFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jcharArray text,int index,int count,SkPath * path,jfloat hOffset,jfloat vOffset,jint bidiFlags,SkPaint * paint)880     static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
881             SkCanvas* canvas, jcharArray text, int index, int count,
882             SkPath* path, jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) {
883 
884         jchar* textArray = env->GetCharArrayElements(text, NULL);
885         TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
886                                    path, canvas);
887         env->ReleaseCharArrayElements(text, textArray, 0);
888     }
889 
drawTextOnPath__StringPathFFPaint(JNIEnv * env,jobject,SkCanvas * canvas,jstring text,SkPath * path,jfloat hOffset,jfloat vOffset,jint bidiFlags,SkPaint * paint)890     static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
891             SkCanvas* canvas, jstring text, SkPath* path,
892             jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) {
893         const jchar* text_ = env->GetStringChars(text, NULL);
894         int count = env->GetStringLength(text);
895         TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
896                                    path, canvas);
897         env->ReleaseStringChars(text, text_);
898     }
899 
getClipBounds(JNIEnv * env,jobject,SkCanvas * canvas,jobject bounds)900     static bool getClipBounds(JNIEnv* env, jobject, SkCanvas* canvas,
901                               jobject bounds) {
902         SkRect   r;
903         SkIRect ir;
904         bool     result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
905 
906         r.round(&ir);
907         (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
908         return result;
909     }
910 
getCTM(JNIEnv * env,jobject,SkCanvas * canvas,SkMatrix * matrix)911     static void getCTM(JNIEnv* env, jobject, SkCanvas* canvas,
912                        SkMatrix* matrix) {
913         *matrix = canvas->getTotalMatrix();
914     }
915 };
916 
917 static JNINativeMethod gCanvasMethods[] = {
918     {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
919     {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster},
920     {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
921     {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
922     {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
923     {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
924     {"save","()I", (void*) SkCanvasGlue::saveAll},
925     {"save","(I)I", (void*) SkCanvasGlue::save},
926     {"native_saveLayer","(ILandroid/graphics/RectF;II)I",
927         (void*) SkCanvasGlue::saveLayer},
928     {"native_saveLayer","(IFFFFII)I", (void*) SkCanvasGlue::saveLayer4F},
929     {"native_saveLayerAlpha","(ILandroid/graphics/RectF;II)I",
930         (void*) SkCanvasGlue::saveLayerAlpha},
931     {"native_saveLayerAlpha","(IFFFFII)I",
932         (void*) SkCanvasGlue::saveLayerAlpha4F},
933     {"restore","()V", (void*) SkCanvasGlue::restore},
934     {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
935     {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
936     {"translate","(FF)V", (void*) SkCanvasGlue::translate},
937     {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
938     {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
939     {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
940     {"native_concat","(II)V", (void*) SkCanvasGlue::concat},
941     {"native_setMatrix","(II)V", (void*) SkCanvasGlue::setMatrix},
942     {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
943     {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
944     {"clipRect","(Landroid/graphics/RectF;)Z",
945         (void*) SkCanvasGlue::clipRect_RectF},
946     {"clipRect","(Landroid/graphics/Rect;)Z",
947         (void*) SkCanvasGlue::clipRect_Rect},
948     {"native_clipRect","(IFFFFI)Z", (void*) SkCanvasGlue::clipRect},
949     {"native_clipPath","(III)Z", (void*) SkCanvasGlue::clipPath},
950     {"native_clipRegion","(III)Z", (void*) SkCanvasGlue::clipRegion},
951     {"nativeSetDrawFilter", "(II)V", (void*) SkCanvasGlue::setDrawFilter},
952     {"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
953         (void*) SkCanvasGlue::getClipBounds},
954     {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
955     {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
956         (void*) SkCanvasGlue::quickReject__RectFI},
957     {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
958     {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
959     {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
960     {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
961     {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
962     {"native_drawColor","(III)V", (void*) SkCanvasGlue::drawColor__II},
963     {"native_drawPaint","(II)V", (void*) SkCanvasGlue::drawPaint},
964     {"drawPoint", "(FFLandroid/graphics/Paint;)V",
965     (void*) SkCanvasGlue::drawPoint},
966     {"drawPoints", "([FIILandroid/graphics/Paint;)V",
967         (void*) SkCanvasGlue::drawPoints},
968     {"drawLines", "([FIILandroid/graphics/Paint;)V",
969         (void*) SkCanvasGlue::drawLines},
970     {"native_drawLine","(IFFFFI)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
971     {"native_drawRect","(ILandroid/graphics/RectF;I)V",
972         (void*) SkCanvasGlue::drawRect__RectFPaint},
973     {"native_drawRect","(IFFFFI)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
974     {"native_drawOval","(ILandroid/graphics/RectF;I)V",
975         (void*) SkCanvasGlue::drawOval},
976     {"native_drawCircle","(IFFFI)V", (void*) SkCanvasGlue::drawCircle},
977     {"native_drawArc","(ILandroid/graphics/RectF;FFZI)V",
978         (void*) SkCanvasGlue::drawArc},
979     {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
980         (void*) SkCanvasGlue::drawRoundRect},
981     {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
982     {"native_drawBitmap","(IIFFIIII)V",
983         (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
984     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V",
985         (void*) SkCanvasGlue::drawBitmapRF},
986     {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V",
987         (void*) SkCanvasGlue::drawBitmapRR},
988     {"native_drawBitmap", "(I[IIIFFIIZI)V",
989     (void*)SkCanvasGlue::drawBitmapArray},
990     {"nativeDrawBitmapMatrix", "(IIII)V",
991         (void*)SkCanvasGlue::drawBitmapMatrix},
992     {"nativeDrawBitmapMesh", "(IIII[FI[III)V",
993         (void*)SkCanvasGlue::drawBitmapMesh},
994     {"nativeDrawVertices", "(III[FI[FI[II[SIII)V",
995         (void*)SkCanvasGlue::drawVertices},
996     {"native_drawText","(I[CIIFFII)V",
997         (void*) SkCanvasGlue::drawText___CIIFFIPaint},
998     {"native_drawText","(ILjava/lang/String;IIFFII)V",
999         (void*) SkCanvasGlue::drawText__StringIIFFIPaint},
1000     {"native_drawTextRun","(I[CIIIIFFII)V",
1001         (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint},
1002     {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V",
1003         (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint},
1004     {"native_drawPosText","(I[CII[FI)V",
1005         (void*) SkCanvasGlue::drawPosText___CII_FPaint},
1006     {"native_drawPosText","(ILjava/lang/String;[FI)V",
1007         (void*) SkCanvasGlue::drawPosText__String_FPaint},
1008     {"native_drawTextOnPath","(I[CIIIFFII)V",
1009         (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
1010     {"native_drawTextOnPath","(ILjava/lang/String;IFFII)V",
1011         (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
1012     {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
1013 
1014     {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
1015 };
1016 
1017 ///////////////////////////////////////////////////////////////////////////////
1018 
1019 #include <android_runtime/AndroidRuntime.h>
1020 
1021 #define REG(env, name, array) \
1022     result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
1023                                                     SK_ARRAY_COUNT(array));  \
1024     if (result < 0) return result
1025 
register_android_graphics_Canvas(JNIEnv * env)1026 int register_android_graphics_Canvas(JNIEnv* env) {
1027     int result;
1028 
1029     REG(env, "android/graphics/Canvas", gCanvasMethods);
1030 
1031     return result;
1032 }
1033 
1034 }
1035