1 /*
2  * Copyright (C) 2014 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 "Canvas.h"
18 
19 #include <SkCanvas.h>
20 #include <SkClipStack.h>
21 #include <SkDevice.h>
22 #include <SkDeque.h>
23 #include <SkDrawFilter.h>
24 #include <SkGraphics.h>
25 #include <SkShader.h>
26 #include <SkTArray.h>
27 #include <SkTemplates.h>
28 
29 namespace android {
30 
31 // Holds an SkCanvas reference plus additional native data.
32 class SkiaCanvas : public Canvas {
33 public:
34     explicit SkiaCanvas(const SkBitmap& bitmap);
35 
36     /**
37      *  Create a new SkiaCanvas.
38      *
39      *  @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must
40      *      not be NULL. This constructor will ref() the SkCanvas, and unref()
41      *      it in its destructor.
42      */
SkiaCanvas(SkCanvas * canvas)43     explicit SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {
44         SkASSERT(canvas);
45         canvas->ref();
46     }
47 
asSkCanvas()48     virtual SkCanvas* asSkCanvas() override {
49         return mCanvas.get();
50     }
51 
52     virtual void setBitmap(const SkBitmap& bitmap) override;
53 
54     virtual bool isOpaque() override;
55     virtual int width() override;
56     virtual int height() override;
57 
58     virtual int getSaveCount() const override;
59     virtual int save(SkCanvas::SaveFlags flags) override;
60     virtual void restore() override;
61     virtual void restoreToCount(int saveCount) override;
62 
63     virtual int saveLayer(float left, float top, float right, float bottom,
64                 const SkPaint* paint, SkCanvas::SaveFlags flags) override;
65     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
66             int alpha, SkCanvas::SaveFlags flags) override;
67 
68     virtual void getMatrix(SkMatrix* outMatrix) const override;
69     virtual void setMatrix(const SkMatrix& matrix) override;
setLocalMatrix(const SkMatrix & matrix)70     virtual void setLocalMatrix(const SkMatrix& matrix) override { this->setMatrix(matrix); }
71     virtual void concat(const SkMatrix& matrix) override;
72     virtual void rotate(float degrees) override;
73     virtual void scale(float sx, float sy) override;
74     virtual void skew(float sx, float sy) override;
75     virtual void translate(float dx, float dy) override;
76 
77     virtual bool getClipBounds(SkRect* outRect) const override;
78     virtual bool quickRejectRect(float left, float top, float right, float bottom) const override;
79     virtual bool quickRejectPath(const SkPath& path) const override;
80     virtual bool clipRect(float left, float top, float right, float bottom,
81             SkRegion::Op op) override;
82     virtual bool clipPath(const SkPath* path, SkRegion::Op op) override;
83     virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override;
84 
85     virtual SkDrawFilter* getDrawFilter() override;
86     virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
87 
88     virtual void drawColor(int color, SkXfermode::Mode mode) override;
89     virtual void drawPaint(const SkPaint& paint) override;
90 
91     virtual void drawPoint(float x, float y, const SkPaint& paint) override;
92     virtual void drawPoints(const float* points, int count, const SkPaint& paint) override;
93     virtual void drawLine(float startX, float startY, float stopX, float stopY,
94             const SkPaint& paint) override;
95     virtual void drawLines(const float* points, int count, const SkPaint& paint) override;
96     virtual void drawRect(float left, float top, float right, float bottom,
97             const SkPaint& paint) override;
98     virtual void drawRoundRect(float left, float top, float right, float bottom,
99             float rx, float ry, const SkPaint& paint) override;
100     virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override;
101     virtual void drawOval(float left, float top, float right, float bottom,
102             const SkPaint& paint) override;
103     virtual void drawArc(float left, float top, float right, float bottom,
104             float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override;
105     virtual void drawPath(const SkPath& path, const SkPaint& paint) override;
106     virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
107             const float* verts, const float* tex, const int* colors,
108             const uint16_t* indices, int indexCount, const SkPaint& paint) override;
109 
110     virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
111             const SkPaint* paint) override;
112     virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
113             const SkPaint* paint) override;
114     virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
115             float srcRight, float srcBottom, float dstLeft, float dstTop,
116             float dstRight, float dstBottom, const SkPaint* paint) override;
117     virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
118             const float* vertices, const int* colors, const SkPaint* paint) override;
119 
120     virtual void drawText(const uint16_t* text, const float* positions, int count,
121             const SkPaint& paint, float x, float y,
122             float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
123             float totalAdvance) override;
124     virtual void drawPosText(const uint16_t* text, const float* positions, int count,
125             int posCount, const SkPaint& paint) override;
126     virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
127             float hOffset, float vOffset, const SkPaint& paint) override;
128 
drawTextAbsolutePos() const129     virtual bool drawTextAbsolutePos() const  override { return true; }
130 
131 private:
132     struct SaveRec {
133         int                 saveCount;
134         SkCanvas::SaveFlags saveFlags;
135     };
136 
137     void recordPartialSave(SkCanvas::SaveFlags flags);
138     void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount);
139     void applyClips(const SkTArray<SkClipStack::Element>& clips);
140 
141     void drawPoints(const float* points, int count, const SkPaint& paint,
142                     SkCanvas::PointMode mode);
143     void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
144 
145     SkAutoTUnref<SkCanvas> mCanvas;
146     SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
147 };
148 
create_canvas(const SkBitmap & bitmap)149 Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
150     return new SkiaCanvas(bitmap);
151 }
152 
create_canvas(SkCanvas * skiaCanvas)153 Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
154     return new SkiaCanvas(skiaCanvas);
155 }
156 
SkiaCanvas(const SkBitmap & bitmap)157 SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
158     mCanvas.reset(new SkCanvas(bitmap));
159 }
160 
161 // ----------------------------------------------------------------------------
162 // Canvas state operations: Replace Bitmap
163 // ----------------------------------------------------------------------------
164 
165 class ClipCopier : public SkCanvas::ClipVisitor {
166 public:
ClipCopier(SkCanvas * dstCanvas)167     ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
168 
clipRect(const SkRect & rect,SkRegion::Op op,bool antialias)169     virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
170         m_dstCanvas->clipRect(rect, op, antialias);
171     }
clipRRect(const SkRRect & rrect,SkRegion::Op op,bool antialias)172     virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
173         m_dstCanvas->clipRRect(rrect, op, antialias);
174     }
clipPath(const SkPath & path,SkRegion::Op op,bool antialias)175     virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
176         m_dstCanvas->clipPath(path, op, antialias);
177     }
178 
179 private:
180     SkCanvas* m_dstCanvas;
181 };
182 
setBitmap(const SkBitmap & bitmap)183 void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
184     SkCanvas* newCanvas = new SkCanvas(bitmap);
185     SkASSERT(newCanvas);
186 
187     if (!bitmap.isNull()) {
188         // Copy the canvas matrix & clip state.
189         newCanvas->setMatrix(mCanvas->getTotalMatrix());
190         if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
191             ClipCopier copier(newCanvas);
192             mCanvas->replayClips(&copier);
193         }
194     }
195 
196     // unrefs the existing canvas
197     mCanvas.reset(newCanvas);
198 
199     // clean up the old save stack
200     mSaveStack.reset(NULL);
201 }
202 
203 // ----------------------------------------------------------------------------
204 // Canvas state operations
205 // ----------------------------------------------------------------------------
206 
isOpaque()207 bool SkiaCanvas::isOpaque() {
208     return mCanvas->getDevice()->accessBitmap(false).isOpaque();
209 }
210 
width()211 int SkiaCanvas::width() {
212     return mCanvas->getBaseLayerSize().width();
213 }
214 
height()215 int SkiaCanvas::height() {
216     return mCanvas->getBaseLayerSize().height();
217 }
218 
219 // ----------------------------------------------------------------------------
220 // Canvas state operations: Save (layer)
221 // ----------------------------------------------------------------------------
222 
getSaveCount() const223 int SkiaCanvas::getSaveCount() const {
224     return mCanvas->getSaveCount();
225 }
226 
save(SkCanvas::SaveFlags flags)227 int SkiaCanvas::save(SkCanvas::SaveFlags flags) {
228     int count = mCanvas->save();
229     recordPartialSave(flags);
230     return count;
231 }
232 
restore()233 void SkiaCanvas::restore() {
234     const SaveRec* rec = (NULL == mSaveStack.get())
235             ? NULL
236             : static_cast<SaveRec*>(mSaveStack->back());
237     int currentSaveCount = mCanvas->getSaveCount() - 1;
238     SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
239 
240     if (NULL == rec || rec->saveCount != currentSaveCount) {
241         // Fast path - no record for this frame.
242         mCanvas->restore();
243         return;
244     }
245 
246     bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
247     bool preserveClip   = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
248 
249     SkMatrix savedMatrix;
250     if (preserveMatrix) {
251         savedMatrix = mCanvas->getTotalMatrix();
252     }
253 
254     SkTArray<SkClipStack::Element> savedClips;
255     if (preserveClip) {
256         saveClipsForFrame(savedClips, currentSaveCount);
257     }
258 
259     mCanvas->restore();
260 
261     if (preserveMatrix) {
262         mCanvas->setMatrix(savedMatrix);
263     }
264 
265     if (preserveClip && !savedClips.empty()) {
266         applyClips(savedClips);
267     }
268 
269     mSaveStack->pop_back();
270 }
271 
restoreToCount(int restoreCount)272 void SkiaCanvas::restoreToCount(int restoreCount) {
273     while (mCanvas->getSaveCount() > restoreCount) {
274         this->restore();
275     }
276 }
277 
saveLayer(float left,float top,float right,float bottom,const SkPaint * paint,SkCanvas::SaveFlags flags)278 int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
279             const SkPaint* paint, SkCanvas::SaveFlags flags) {
280     SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
281     int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
282     recordPartialSave(flags);
283     return count;
284 }
285 
saveLayerAlpha(float left,float top,float right,float bottom,int alpha,SkCanvas::SaveFlags flags)286 int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
287         int alpha, SkCanvas::SaveFlags flags) {
288     SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
289     int count = mCanvas->saveLayerAlpha(&bounds, alpha, flags | SkCanvas::kMatrixClip_SaveFlag);
290     recordPartialSave(flags);
291     return count;
292 }
293 
294 // ----------------------------------------------------------------------------
295 // functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags)
296 // ----------------------------------------------------------------------------
297 
recordPartialSave(SkCanvas::SaveFlags flags)298 void SkiaCanvas::recordPartialSave(SkCanvas::SaveFlags flags) {
299     // A partial save is a save operation which doesn't capture the full canvas state.
300     // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
301 
302     // Mask-out non canvas state bits.
303     flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
304 
305     if (SkCanvas::kMatrixClip_SaveFlag == flags) {
306         // not a partial save.
307         return;
308     }
309 
310     if (NULL == mSaveStack.get()) {
311         mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8)));
312     }
313 
314     SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
315     // Store the save counter in the SkClipStack domain.
316     // (0-based, equal to the number of save ops on the stack).
317     rec->saveCount = mCanvas->getSaveCount() - 1;
318     rec->saveFlags = flags;
319 }
320 
saveClipsForFrame(SkTArray<SkClipStack::Element> & clips,int frameSaveCount)321 void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) {
322     SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
323                                    SkClipStack::Iter::kTop_IterStart);
324     while (const SkClipStack::Element* elem = clipIterator.next()) {
325         if (elem->getSaveCount() < frameSaveCount) {
326             // done with the current frame.
327             break;
328         }
329         SkASSERT(elem->getSaveCount() == frameSaveCount);
330         clips.push_back(*elem);
331     }
332 }
333 
applyClips(const SkTArray<SkClipStack::Element> & clips)334 void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) {
335     ClipCopier clipCopier(mCanvas);
336 
337     // The clip stack stores clips in device space.
338     SkMatrix origMatrix = mCanvas->getTotalMatrix();
339     mCanvas->resetMatrix();
340 
341     // We pushed the clips in reverse order.
342     for (int i = clips.count() - 1; i >= 0; --i) {
343         clips[i].replay(&clipCopier);
344     }
345 
346     mCanvas->setMatrix(origMatrix);
347 }
348 
349 // ----------------------------------------------------------------------------
350 // Canvas state operations: Matrix
351 // ----------------------------------------------------------------------------
352 
getMatrix(SkMatrix * outMatrix) const353 void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const {
354     *outMatrix = mCanvas->getTotalMatrix();
355 }
356 
setMatrix(const SkMatrix & matrix)357 void SkiaCanvas::setMatrix(const SkMatrix& matrix) {
358     mCanvas->setMatrix(matrix);
359 }
360 
concat(const SkMatrix & matrix)361 void SkiaCanvas::concat(const SkMatrix& matrix) {
362     mCanvas->concat(matrix);
363 }
364 
rotate(float degrees)365 void SkiaCanvas::rotate(float degrees) {
366     mCanvas->rotate(degrees);
367 }
368 
scale(float sx,float sy)369 void SkiaCanvas::scale(float sx, float sy) {
370     mCanvas->scale(sx, sy);
371 }
372 
skew(float sx,float sy)373 void SkiaCanvas::skew(float sx, float sy) {
374     mCanvas->skew(sx, sy);
375 }
376 
translate(float dx,float dy)377 void SkiaCanvas::translate(float dx, float dy) {
378     mCanvas->translate(dx, dy);
379 }
380 
381 // ----------------------------------------------------------------------------
382 // Canvas state operations: Clips
383 // ----------------------------------------------------------------------------
384 
385 // This function is a mirror of SkCanvas::getClipBounds except that it does
386 // not outset the edge of the clip to account for anti-aliasing. There is
387 // a skia bug to investigate pushing this logic into back into skia.
388 // (see https://code.google.com/p/skia/issues/detail?id=1303)
getClipBounds(SkRect * outRect) const389 bool SkiaCanvas::getClipBounds(SkRect* outRect) const {
390     SkIRect ibounds;
391     if (!mCanvas->getClipDeviceBounds(&ibounds)) {
392         return false;
393     }
394 
395     SkMatrix inverse;
396     // if we can't invert the CTM, we can't return local clip bounds
397     if (!mCanvas->getTotalMatrix().invert(&inverse)) {
398         if (outRect) {
399             outRect->setEmpty();
400         }
401         return false;
402     }
403 
404     if (NULL != outRect) {
405         SkRect r = SkRect::Make(ibounds);
406         inverse.mapRect(outRect, r);
407     }
408     return true;
409 }
410 
quickRejectRect(float left,float top,float right,float bottom) const411 bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
412     SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
413     return mCanvas->quickReject(bounds);
414 }
415 
quickRejectPath(const SkPath & path) const416 bool SkiaCanvas::quickRejectPath(const SkPath& path) const {
417     return mCanvas->quickReject(path);
418 }
419 
clipRect(float left,float top,float right,float bottom,SkRegion::Op op)420 bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
421     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
422     mCanvas->clipRect(rect, op);
423     return !mCanvas->isClipEmpty();
424 }
425 
clipPath(const SkPath * path,SkRegion::Op op)426 bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
427     mCanvas->clipPath(*path, op);
428     return !mCanvas->isClipEmpty();
429 }
430 
clipRegion(const SkRegion * region,SkRegion::Op op)431 bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
432     SkPath rgnPath;
433     if (region->getBoundaryPath(&rgnPath)) {
434         // The region is specified in device space.
435         SkMatrix savedMatrix = mCanvas->getTotalMatrix();
436         mCanvas->resetMatrix();
437         mCanvas->clipPath(rgnPath, op);
438         mCanvas->setMatrix(savedMatrix);
439     } else {
440         mCanvas->clipRect(SkRect::MakeEmpty(), op);
441     }
442     return !mCanvas->isClipEmpty();
443 }
444 
445 // ----------------------------------------------------------------------------
446 // Canvas state operations: Filters
447 // ----------------------------------------------------------------------------
448 
getDrawFilter()449 SkDrawFilter* SkiaCanvas::getDrawFilter() {
450     return mCanvas->getDrawFilter();
451 }
452 
setDrawFilter(SkDrawFilter * drawFilter)453 void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
454     mCanvas->setDrawFilter(drawFilter);
455 }
456 
457 // ----------------------------------------------------------------------------
458 // Canvas draw operations
459 // ----------------------------------------------------------------------------
460 
drawColor(int color,SkXfermode::Mode mode)461 void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) {
462     mCanvas->drawColor(color, mode);
463 }
464 
drawPaint(const SkPaint & paint)465 void SkiaCanvas::drawPaint(const SkPaint& paint) {
466     mCanvas->drawPaint(paint);
467 }
468 
469 // ----------------------------------------------------------------------------
470 // Canvas draw operations: Geometry
471 // ----------------------------------------------------------------------------
472 
drawPoints(const float * points,int count,const SkPaint & paint,SkCanvas::PointMode mode)473 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
474                             SkCanvas::PointMode mode) {
475     // convert the floats into SkPoints
476     count >>= 1;    // now it is the number of points
477     SkAutoSTMalloc<32, SkPoint> storage(count);
478     SkPoint* pts = storage.get();
479     for (int i = 0; i < count; i++) {
480         pts[i].set(points[0], points[1]);
481         points += 2;
482     }
483     mCanvas->drawPoints(mode, count, pts, paint);
484 }
485 
486 
drawPoint(float x,float y,const SkPaint & paint)487 void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
488     mCanvas->drawPoint(x, y, paint);
489 }
490 
drawPoints(const float * points,int count,const SkPaint & paint)491 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
492     this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
493 }
494 
drawLine(float startX,float startY,float stopX,float stopY,const SkPaint & paint)495 void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
496                           const SkPaint& paint) {
497     mCanvas->drawLine(startX, startY, stopX, stopY, paint);
498 }
499 
drawLines(const float * points,int count,const SkPaint & paint)500 void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
501     this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
502 }
503 
drawRect(float left,float top,float right,float bottom,const SkPaint & paint)504 void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
505         const SkPaint& paint) {
506     mCanvas->drawRectCoords(left, top, right, bottom, paint);
507 
508 }
509 
drawRoundRect(float left,float top,float right,float bottom,float rx,float ry,const SkPaint & paint)510 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
511         float rx, float ry, const SkPaint& paint) {
512     SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
513     mCanvas->drawRoundRect(rect, rx, ry, paint);
514 }
515 
drawCircle(float x,float y,float radius,const SkPaint & paint)516 void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
517     mCanvas->drawCircle(x, y, radius, paint);
518 }
519 
drawOval(float left,float top,float right,float bottom,const SkPaint & paint)520 void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
521     SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
522     mCanvas->drawOval(oval, paint);
523 }
524 
drawArc(float left,float top,float right,float bottom,float startAngle,float sweepAngle,bool useCenter,const SkPaint & paint)525 void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
526         float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
527     SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
528     mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
529 }
530 
drawPath(const SkPath & path,const SkPaint & paint)531 void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
532     mCanvas->drawPath(path, paint);
533 }
534 
drawVertices(SkCanvas::VertexMode vertexMode,int vertexCount,const float * verts,const float * texs,const int * colors,const uint16_t * indices,int indexCount,const SkPaint & paint)535 void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
536                               const float* verts, const float* texs, const int* colors,
537                               const uint16_t* indices, int indexCount, const SkPaint& paint) {
538 #ifndef SK_SCALAR_IS_FLOAT
539     SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
540 #endif
541     const int ptCount = vertexCount >> 1;
542     mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
543                           (SkColor*)colors, NULL, indices, indexCount, paint);
544 }
545 
546 // ----------------------------------------------------------------------------
547 // Canvas draw operations: Bitmaps
548 // ----------------------------------------------------------------------------
549 
drawBitmap(const SkBitmap & bitmap,float left,float top,const SkPaint * paint)550 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
551     mCanvas->drawBitmap(bitmap, left, top, paint);
552 }
553 
drawBitmap(const SkBitmap & bitmap,const SkMatrix & matrix,const SkPaint * paint)554 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
555     SkAutoCanvasRestore acr(mCanvas, true);
556     mCanvas->concat(matrix);
557     mCanvas->drawBitmap(bitmap, 0, 0, paint);
558 }
559 
drawBitmap(const SkBitmap & bitmap,float srcLeft,float srcTop,float srcRight,float srcBottom,float dstLeft,float dstTop,float dstRight,float dstBottom,const SkPaint * paint)560 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
561                             float srcRight, float srcBottom, float dstLeft, float dstTop,
562                             float dstRight, float dstBottom, const SkPaint* paint) {
563     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
564     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
565     mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
566 }
567 
drawBitmapMesh(const SkBitmap & bitmap,int meshWidth,int meshHeight,const float * vertices,const int * colors,const SkPaint * paint)568 void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
569         const float* vertices, const int* colors, const SkPaint* paint) {
570 
571     const int ptCount = (meshWidth + 1) * (meshHeight + 1);
572     const int indexCount = meshWidth * meshHeight * 6;
573 
574     /*  Our temp storage holds 2 or 3 arrays.
575         texture points [ptCount * sizeof(SkPoint)]
576         optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
577             copy to convert from float to fixed
578         indices [ptCount * sizeof(uint16_t)]
579     */
580     ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
581     storageSize += indexCount * sizeof(uint16_t);  // indices[]
582 
583 
584 #ifndef SK_SCALAR_IS_FLOAT
585     SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
586 #endif
587     SkAutoMalloc storage(storageSize);
588     SkPoint* texs = (SkPoint*)storage.get();
589     uint16_t* indices = (uint16_t*)(texs + ptCount);
590 
591     // cons up texture coordinates and indices
592     {
593         const SkScalar w = SkIntToScalar(bitmap.width());
594         const SkScalar h = SkIntToScalar(bitmap.height());
595         const SkScalar dx = w / meshWidth;
596         const SkScalar dy = h / meshHeight;
597 
598         SkPoint* texsPtr = texs;
599         SkScalar y = 0;
600         for (int i = 0; i <= meshHeight; i++) {
601             if (i == meshHeight) {
602                 y = h;  // to ensure numerically we hit h exactly
603             }
604             SkScalar x = 0;
605             for (int j = 0; j < meshWidth; j++) {
606                 texsPtr->set(x, y);
607                 texsPtr += 1;
608                 x += dx;
609             }
610             texsPtr->set(w, y);
611             texsPtr += 1;
612             y += dy;
613         }
614         SkASSERT(texsPtr - texs == ptCount);
615     }
616 
617     // cons up indices
618     {
619         uint16_t* indexPtr = indices;
620         int index = 0;
621         for (int i = 0; i < meshHeight; i++) {
622             for (int j = 0; j < meshWidth; j++) {
623                 // lower-left triangle
624                 *indexPtr++ = index;
625                 *indexPtr++ = index + meshWidth + 1;
626                 *indexPtr++ = index + meshWidth + 2;
627                 // upper-right triangle
628                 *indexPtr++ = index;
629                 *indexPtr++ = index + meshWidth + 2;
630                 *indexPtr++ = index + 1;
631                 // bump to the next cell
632                 index += 1;
633             }
634             // bump to the next row
635             index += 1;
636         }
637         SkASSERT(indexPtr - indices == indexCount);
638         SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
639     }
640 
641     // double-check that we have legal indices
642 #ifdef SK_DEBUG
643     {
644         for (int i = 0; i < indexCount; i++) {
645             SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
646         }
647     }
648 #endif
649 
650     // cons-up a shader for the bitmap
651     SkPaint tmpPaint;
652     if (paint) {
653         tmpPaint = *paint;
654     }
655     SkShader* shader = SkShader::CreateBitmapShader(bitmap,
656                                                     SkShader::kClamp_TileMode,
657                                                     SkShader::kClamp_TileMode);
658     SkSafeUnref(tmpPaint.setShader(shader));
659 
660     mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
661                          texs, (const SkColor*)colors, NULL, indices,
662                          indexCount, tmpPaint);
663 }
664 
665 // ----------------------------------------------------------------------------
666 // Canvas draw operations: Text
667 // ----------------------------------------------------------------------------
668 
drawText(const uint16_t * text,const float * positions,int count,const SkPaint & paint,float x,float y,float boundsLeft,float boundsTop,float boundsRight,float boundsBottom,float totalAdvance)669 void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int count,
670         const SkPaint& paint, float x, float y,
671         float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
672         float totalAdvance) {
673     // Set align to left for drawing, as we don't want individual
674     // glyphs centered or right-aligned; the offset above takes
675     // care of all alignment.
676     SkPaint paintCopy(paint);
677     paintCopy.setTextAlign(SkPaint::kLeft_Align);
678 
679     SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats);
680     mCanvas->drawPosText(text, count << 1, reinterpret_cast<const SkPoint*>(positions), paintCopy);
681 }
682 
drawPosText(const uint16_t * text,const float * positions,int count,int posCount,const SkPaint & paint)683 void SkiaCanvas::drawPosText(const uint16_t* text, const float* positions, int count, int posCount,
684         const SkPaint& paint) {
685     SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
686     int indx;
687     for (indx = 0; indx < posCount; indx++) {
688         posPtr[indx].fX = positions[indx << 1];
689         posPtr[indx].fY = positions[(indx << 1) + 1];
690     }
691 
692     SkPaint paintCopy(paint);
693     paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding);
694     mCanvas->drawPosText(text, count, posPtr, paintCopy);
695 
696     delete[] posPtr;
697 }
698 
drawTextOnPath(const uint16_t * glyphs,int count,const SkPath & path,float hOffset,float vOffset,const SkPaint & paint)699 void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
700         float hOffset, float vOffset, const SkPaint& paint) {
701     mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
702 }
703 
704 } // namespace android
705