• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libs/graphics/sgl/SkDraw.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #include "SkDraw.h"
19 #include "SkBlitter.h"
20 #include "SkBounder.h"
21 #include "SkCanvas.h"
22 #include "SkColorPriv.h"
23 #include "SkDevice.h"
24 #include "SkMaskFilter.h"
25 #include "SkPaint.h"
26 #include "SkPathEffect.h"
27 #include "SkRasterizer.h"
28 #include "SkScan.h"
29 #include "SkShader.h"
30 #include "SkStroke.h"
31 #include "SkTemplatesPriv.h"
32 #include "SkUtils.h"
33 
34 #include "SkAutoKern.h"
35 #include "SkBitmapProcShader.h"
36 #include "SkDrawProcs.h"
37 
38 //#define TRACE_BITMAP_DRAWS
39 
40 class SkAutoRestoreBounder : SkNoncopyable {
41 public:
42     // note: initializing fBounder is done only to fix a warning
SkAutoRestoreBounder()43     SkAutoRestoreBounder() : fDraw(NULL), fBounder(NULL) {}
~SkAutoRestoreBounder()44     ~SkAutoRestoreBounder() {
45         if (fDraw) {
46             fDraw->fBounder = fBounder;
47         }
48     }
49 
clearBounder(const SkDraw * draw)50     void clearBounder(const SkDraw* draw) {
51         fDraw = const_cast<SkDraw*>(draw);
52         fBounder = draw->fBounder;
53         fDraw->fBounder = NULL;
54     }
55 
56 private:
57     SkDraw*     fDraw;
58     SkBounder*  fBounder;
59 };
60 
rect_points(SkRect & r,int index)61 static SkPoint* rect_points(SkRect& r, int index) {
62     SkASSERT((unsigned)index < 2);
63     return &((SkPoint*)(void*)&r)[index];
64 }
65 
66 /** Helper for allocating small blitters on the stack.
67 */
68 
69 #define kBlitterStorageLongCount    (sizeof(SkBitmapProcShader) >> 2)
70 
71 class SkAutoBlitterChoose {
72 public:
SkAutoBlitterChoose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint)73     SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
74                         const SkPaint& paint) {
75         fBlitter = SkBlitter::Choose(device, matrix, paint,
76                                      fStorage, sizeof(fStorage));
77     }
78     ~SkAutoBlitterChoose();
79 
operator ->()80     SkBlitter*  operator->() { return fBlitter; }
get() const81     SkBlitter*  get() const { return fBlitter; }
82 
83 private:
84     SkBlitter*  fBlitter;
85     uint32_t    fStorage[kBlitterStorageLongCount];
86 };
87 
~SkAutoBlitterChoose()88 SkAutoBlitterChoose::~SkAutoBlitterChoose() {
89     if ((void*)fBlitter == (void*)fStorage) {
90         fBlitter->~SkBlitter();
91     } else {
92         SkDELETE(fBlitter);
93     }
94 }
95 
96 class SkAutoBitmapShaderInstall {
97 public:
SkAutoBitmapShaderInstall(const SkBitmap & src,const SkPaint * paint)98     SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint* paint)
99             : fPaint((SkPaint*)paint) {
100         fPrevShader = paint->getShader();
101         fPrevShader->safeRef();
102         fPaint->setShader(SkShader::CreateBitmapShader( src,
103                            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
104                            fStorage, sizeof(fStorage)));
105     }
~SkAutoBitmapShaderInstall()106     ~SkAutoBitmapShaderInstall() {
107         SkShader* shader = fPaint->getShader();
108 
109         fPaint->setShader(fPrevShader);
110         fPrevShader->safeUnref();
111 
112         if ((void*)shader == (void*)fStorage) {
113             shader->~SkShader();
114         } else {
115             SkDELETE(shader);
116         }
117     }
118 private:
119     SkPaint*    fPaint;
120     SkShader*   fPrevShader;
121     uint32_t    fStorage[kBlitterStorageLongCount];
122 };
123 
124 class SkAutoPaintStyleRestore {
125 public:
SkAutoPaintStyleRestore(const SkPaint & paint,SkPaint::Style style)126     SkAutoPaintStyleRestore(const SkPaint& paint, SkPaint::Style style)
127             : fPaint((SkPaint&)paint) {
128         fStyle = paint.getStyle();  // record the old
129         fPaint.setStyle(style);     // change it to the specified style
130     }
~SkAutoPaintStyleRestore()131     ~SkAutoPaintStyleRestore() {
132         fPaint.setStyle(fStyle);    // restore the old
133     }
134 private:
135     SkPaint&        fPaint;
136     SkPaint::Style  fStyle;
137 
138     // illegal
139     SkAutoPaintStyleRestore(const SkAutoPaintStyleRestore&);
140     SkAutoPaintStyleRestore& operator=(const SkAutoPaintStyleRestore&);
141 };
142 
143 ///////////////////////////////////////////////////////////////////////////////
144 
SkDraw(const SkDraw & src)145 SkDraw::SkDraw(const SkDraw& src) {
146     memcpy(this, &src, sizeof(*this));
147 }
148 
149 ///////////////////////////////////////////////////////////////////////////////
150 
151 typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
152 
D_Clear_BitmapXferProc(void * pixels,size_t bytes,uint32_t)153 static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
154     sk_bzero(pixels, bytes);
155 }
156 
D_Dst_BitmapXferProc(void *,size_t,uint32_t data)157 static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
158 
D32_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)159 static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
160     sk_memset32((uint32_t*)pixels, data, bytes >> 2);
161 }
162 
D16_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)163 static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
164     sk_memset16((uint16_t*)pixels, data, bytes >> 1);
165 }
166 
DA8_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)167 static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
168     memset(pixels, data, bytes);
169 }
170 
ChooseBitmapXferProc(const SkBitmap & bitmap,const SkPaint & paint,uint32_t * data)171 static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
172                                            const SkPaint& paint,
173                                            uint32_t* data) {
174     // todo: we can apply colorfilter up front if no shader, so we wouldn't
175     // need to abort this fastpath
176     if (paint.getShader() || paint.getColorFilter()) {
177         return NULL;
178     }
179 
180     SkXfermode::Mode mode;
181     if (!SkXfermode::IsMode(paint.getXfermode(), &mode)) {
182         return NULL;
183     }
184 
185     SkColor color = paint.getColor();
186 
187     // collaps modes based on color...
188     if (SkXfermode::kSrcOver_Mode == mode) {
189         unsigned alpha = SkColorGetA(color);
190         if (0 == alpha) {
191             mode = SkXfermode::kDst_Mode;
192         } else if (0xFF == alpha) {
193             mode = SkXfermode::kSrc_Mode;
194         }
195     }
196 
197     switch (mode) {
198         case SkXfermode::kClear_Mode:
199 //            SkDebugf("--- D_Clear_BitmapXferProc\n");
200             return D_Clear_BitmapXferProc;  // ignore data
201         case SkXfermode::kDst_Mode:
202 //            SkDebugf("--- D_Dst_BitmapXferProc\n");
203             return D_Dst_BitmapXferProc;    // ignore data
204         case SkXfermode::kSrc_Mode: {
205             /*
206                 should I worry about dithering for the lower depths?
207             */
208             SkPMColor pmc = SkPreMultiplyColor(color);
209             switch (bitmap.config()) {
210                 case SkBitmap::kARGB_8888_Config:
211                     if (data) {
212                         *data = pmc;
213                     }
214 //                    SkDebugf("--- D32_Src_BitmapXferProc\n");
215                     return D32_Src_BitmapXferProc;
216                 case SkBitmap::kARGB_4444_Config:
217                     if (data) {
218                         *data = SkPixel32ToPixel4444(pmc);
219                     }
220 //                    SkDebugf("--- D16_Src_BitmapXferProc\n");
221                     return D16_Src_BitmapXferProc;
222                 case SkBitmap::kRGB_565_Config:
223                     if (data) {
224                         *data = SkPixel32ToPixel16(pmc);
225                     }
226 //                    SkDebugf("--- D16_Src_BitmapXferProc\n");
227                     return D16_Src_BitmapXferProc;
228                 case SkBitmap::kA8_Config:
229                     if (data) {
230                         *data = SkGetPackedA32(pmc);
231                     }
232 //                    SkDebugf("--- DA8_Src_BitmapXferProc\n");
233                     return DA8_Src_BitmapXferProc;
234                 default:
235                     break;
236             }
237             break;
238         }
239         default:
240             break;
241     }
242     return NULL;
243 }
244 
CallBitmapXferProc(const SkBitmap & bitmap,const SkIRect & rect,BitmapXferProc proc,uint32_t procData)245 static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
246                                BitmapXferProc proc, uint32_t procData) {
247     int shiftPerPixel;
248     switch (bitmap.config()) {
249         case SkBitmap::kARGB_8888_Config:
250             shiftPerPixel = 2;
251             break;
252         case SkBitmap::kARGB_4444_Config:
253         case SkBitmap::kRGB_565_Config:
254             shiftPerPixel = 1;
255             break;
256         case SkBitmap::kA8_Config:
257             shiftPerPixel = 0;
258             break;
259         default:
260             SkASSERT(!"Can't use xferproc on this config");
261             return;
262     }
263 
264     uint8_t* pixels = (uint8_t*)bitmap.getPixels();
265     SkASSERT(pixels);
266     const size_t rowBytes = bitmap.rowBytes();
267     const int widthBytes = rect.width() << shiftPerPixel;
268 
269     // skip down to the first scanline and X position
270     pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
271     for (int scans = rect.height() - 1; scans >= 0; --scans) {
272         proc(pixels, widthBytes, procData);
273         pixels += rowBytes;
274     }
275 }
276 
drawPaint(const SkPaint & paint) const277 void SkDraw::drawPaint(const SkPaint& paint) const {
278     SkDEBUGCODE(this->validate();)
279 
280     if (fClip->isEmpty()) {
281         return;
282     }
283 
284     SkIRect    devRect;
285     devRect.set(0, 0, fBitmap->width(), fBitmap->height());
286     if (fBounder && !fBounder->doIRect(devRect)) {
287         return;
288     }
289 
290     /*  If we don't have a shader (i.e. we're just a solid color) we may
291         be faster to operate directly on the device bitmap, rather than invoking
292         a blitter. Esp. true for xfermodes, which require a colorshader to be
293         present, which is just redundant work. Since we're drawing everywhere
294         in the clip, we don't have to worry about antialiasing.
295     */
296     uint32_t procData = 0;  // to avoid the warning
297     BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
298     if (proc) {
299         if (D_Dst_BitmapXferProc == proc) { // nothing to do
300             return;
301         }
302 
303         SkRegion::Iterator iter(*fClip);
304         while (!iter.done()) {
305             CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
306             iter.next();
307         }
308     } else {
309         // normal case: use a blitter
310         SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
311         SkScan::FillIRect(devRect, fClip, blitter.get());
312     }
313 }
314 
315 ///////////////////////////////////////////////////////////////////////////////
316 
317 struct PtProcRec {
318     SkCanvas::PointMode fMode;
319     const SkPaint*  fPaint;
320     const SkRegion* fClip;
321 
322     // computed values
323     SkFixed fRadius;
324 
325     typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
326                          SkBlitter*);
327 
328     bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
329               const SkRegion* clip);
330     Proc chooseProc(SkBlitter* blitter);
331 };
332 
bw_pt_rect_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)333 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
334                                  int count, SkBlitter* blitter) {
335     SkASSERT(rec.fClip->isRect());
336     const SkIRect& r = rec.fClip->getBounds();
337 
338     for (int i = 0; i < count; i++) {
339         int x = SkScalarFloor(devPts[i].fX);
340         int y = SkScalarFloor(devPts[i].fY);
341         if (r.contains(x, y)) {
342             blitter->blitH(x, y, 1);
343         }
344     }
345 }
346 
bw_pt_rect_16_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)347 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
348                                     const SkPoint devPts[], int count,
349                                     SkBlitter* blitter) {
350     SkASSERT(rec.fClip->isRect());
351     const SkIRect& r = rec.fClip->getBounds();
352     uint32_t value;
353     const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
354     SkASSERT(bitmap);
355 
356     uint16_t* addr = bitmap->getAddr16(0, 0);
357     int rb = bitmap->rowBytes();
358 
359     for (int i = 0; i < count; i++) {
360         int x = SkScalarFloor(devPts[i].fX);
361         int y = SkScalarFloor(devPts[i].fY);
362         if (r.contains(x, y)) {
363 //            *bitmap->getAddr16(x, y) = SkToU16(value);
364             ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
365         }
366     }
367 }
368 
bw_pt_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)369 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
370                             int count, SkBlitter* blitter) {
371     for (int i = 0; i < count; i++) {
372         int x = SkScalarFloor(devPts[i].fX);
373         int y = SkScalarFloor(devPts[i].fY);
374         if (rec.fClip->contains(x, y)) {
375             blitter->blitH(x, y, 1);
376         }
377     }
378 }
379 
bw_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)380 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
381                               int count, SkBlitter* blitter) {
382     for (int i = 0; i < count; i += 2) {
383         SkScan::HairLine(devPts[i], devPts[i+1], rec.fClip, blitter);
384     }
385 }
386 
bw_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)387 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
388                               int count, SkBlitter* blitter) {
389     for (int i = 0; i < count - 1; i++) {
390         SkScan::HairLine(devPts[i], devPts[i+1], rec.fClip, blitter);
391     }
392 }
393 
394 // aa versions
395 
aa_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)396 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
397                               int count, SkBlitter* blitter) {
398     for (int i = 0; i < count; i += 2) {
399         SkScan::AntiHairLine(devPts[i], devPts[i+1], rec.fClip, blitter);
400     }
401 }
402 
aa_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)403 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
404                               int count, SkBlitter* blitter) {
405     for (int i = 0; i < count - 1; i++) {
406         SkScan::AntiHairLine(devPts[i], devPts[i+1], rec.fClip, blitter);
407     }
408 }
409 
410 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
411 
bw_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)412 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
413                            int count, SkBlitter* blitter) {
414     const SkFixed radius = rec.fRadius;
415     for (int i = 0; i < count; i++) {
416         SkFixed x = SkScalarToFixed(devPts[i].fX);
417         SkFixed y = SkScalarToFixed(devPts[i].fY);
418 
419         SkXRect r;
420         r.fLeft = x - radius;
421         r.fTop = y - radius;
422         r.fRight = x + radius;
423         r.fBottom = y + radius;
424 
425         SkScan::FillXRect(r, rec.fClip, blitter);
426     }
427 }
428 
aa_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)429 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
430                            int count, SkBlitter* blitter) {
431     const SkFixed radius = rec.fRadius;
432     for (int i = 0; i < count; i++) {
433         SkFixed x = SkScalarToFixed(devPts[i].fX);
434         SkFixed y = SkScalarToFixed(devPts[i].fY);
435 
436         SkXRect r;
437         r.fLeft = x - radius;
438         r.fTop = y - radius;
439         r.fRight = x + radius;
440         r.fBottom = y + radius;
441 
442         SkScan::AntiFillXRect(r, rec.fClip, blitter);
443     }
444 }
445 
446 // If this guy returns true, then chooseProc() must return a valid proc
init(SkCanvas::PointMode mode,const SkPaint & paint,const SkMatrix * matrix,const SkRegion * clip)447 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
448                      const SkMatrix* matrix, const SkRegion* clip) {
449     if (paint.getPathEffect()) {
450         return false;
451     }
452     SkScalar width = paint.getStrokeWidth();
453     if (0 == width) {
454         fMode = mode;
455         fPaint = &paint;
456         fClip = clip;
457         fRadius = SK_Fixed1 >> 1;
458         return true;
459     }
460     if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
461             matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) {
462         SkScalar sx = matrix->get(SkMatrix::kMScaleX);
463         SkScalar sy = matrix->get(SkMatrix::kMScaleY);
464         if (SkScalarNearlyZero(sx - sy)) {
465             if (sx < 0) {
466                 sx = -sx;
467             }
468 
469             fMode = mode;
470             fPaint = &paint;
471             fClip = clip;
472             fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
473             return true;
474         }
475     }
476     return false;
477 }
478 
chooseProc(SkBlitter * blitter)479 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter* blitter) {
480     Proc proc = NULL;
481 
482     // for our arrays
483     SkASSERT(0 == SkCanvas::kPoints_PointMode);
484     SkASSERT(1 == SkCanvas::kLines_PointMode);
485     SkASSERT(2 == SkCanvas::kPolygon_PointMode);
486     SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
487 
488     // first check for hairlines
489     if (0 == fPaint->getStrokeWidth()) {
490         if (fPaint->isAntiAlias()) {
491             static const Proc gAAProcs[] = {
492                 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
493             };
494             proc = gAAProcs[fMode];
495         } else {
496             if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
497                 uint32_t value;
498                 const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
499                 if (bm && bm->config() == SkBitmap::kRGB_565_Config) {
500                     proc = bw_pt_rect_16_hair_proc;
501                 } else {
502                     proc = bw_pt_rect_hair_proc;
503                 }
504             } else {
505                 static Proc gBWProcs[] = {
506                     bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
507                 };
508                 proc = gBWProcs[fMode];
509             }
510         }
511     } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
512         SkASSERT(SkCanvas::kPoints_PointMode == fMode);
513         if (fPaint->isAntiAlias()) {
514             proc = aa_square_proc;
515         } else {
516             proc = bw_square_proc;
517         }
518     }
519     return proc;
520 }
521 
bounder_points(SkBounder * bounder,SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,const SkMatrix & matrix)522 static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
523                            size_t count, const SkPoint pts[],
524                            const SkPaint& paint, const SkMatrix& matrix) {
525     SkIRect ibounds;
526     SkRect bounds;
527     SkScalar inset = paint.getStrokeWidth();
528 
529     bounds.set(pts, count);
530     bounds.inset(-inset, -inset);
531     matrix.mapRect(&bounds);
532 
533     bounds.roundOut(&ibounds);
534     return bounder->doIRect(ibounds);
535 }
536 
537 // each of these costs 8-bytes of stack space, so don't make it too large
538 // must be even for lines/polygon to work
539 #define MAX_DEV_PTS     32
540 
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint) const541 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
542                         const SkPoint pts[], const SkPaint& paint) const {
543     // if we're in lines mode, force count to be even
544     if (SkCanvas::kLines_PointMode == mode) {
545         count &= ~(size_t)1;
546     }
547 
548     if ((long)count <= 0) {
549         return;
550     }
551 
552     SkAutoRestoreBounder arb;
553 
554     if (fBounder) {
555         if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
556             return;
557         }
558         // clear the bounder for the rest of this function, so we don't call it
559         // again later if we happen to call ourselves for drawRect, drawPath,
560         // etc.
561         arb.clearBounder(this);
562     }
563 
564     SkASSERT(pts != NULL);
565     SkDEBUGCODE(this->validate();)
566 
567      // nothing to draw
568     if (fClip->isEmpty() ||
569         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
570         return;
571     }
572 
573     PtProcRec rec;
574     if (rec.init(mode, paint, fMatrix, fClip)) {
575         SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
576 
577         SkPoint             devPts[MAX_DEV_PTS];
578         const SkMatrix*     matrix = fMatrix;
579         SkBlitter*          bltr = blitter.get();
580         PtProcRec::Proc     proc = rec.chooseProc(bltr);
581         // we have to back up subsequent passes if we're in polygon mode
582         const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
583 
584         do {
585             size_t n = count;
586             if (n > MAX_DEV_PTS) {
587                 n = MAX_DEV_PTS;
588             }
589             matrix->mapPoints(devPts, pts, n);
590             proc(rec, devPts, n, bltr);
591             pts += n - backup;
592             SkASSERT(count >= n);
593             count -= n;
594             if (count > 0) {
595                 count += backup;
596             }
597         } while (count != 0);
598     } else {
599         switch (mode) {
600             case SkCanvas::kPoints_PointMode: {
601                 // temporarily mark the paint as filling.
602                 SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style);
603 
604                 SkScalar width = paint.getStrokeWidth();
605                 SkScalar radius = SkScalarHalf(width);
606 
607                 if (paint.getStrokeCap() == SkPaint::kRound_Cap) {
608                     SkPath      path;
609                     SkMatrix    preMatrix;
610 
611                     path.addCircle(0, 0, radius);
612                     for (size_t i = 0; i < count; i++) {
613                         preMatrix.setTranslate(pts[i].fX, pts[i].fY);
614                         // pass true for the last point, since we can modify
615                         // then path then
616                         this->drawPath(path, paint, &preMatrix, (count-1) == i);
617                     }
618                 } else {
619                     SkRect  r;
620 
621                     for (size_t i = 0; i < count; i++) {
622                         r.fLeft = pts[i].fX - radius;
623                         r.fTop = pts[i].fY - radius;
624                         r.fRight = r.fLeft + width;
625                         r.fBottom = r.fTop + width;
626                         this->drawRect(r, paint);
627                     }
628                 }
629                 break;
630             }
631             case SkCanvas::kLines_PointMode:
632             case SkCanvas::kPolygon_PointMode: {
633                 count -= 1;
634                 SkPath path;
635                 SkPaint p(paint);
636                 p.setStyle(SkPaint::kStroke_Style);
637                 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
638                 for (size_t i = 0; i < count; i += inc) {
639                     path.moveTo(pts[i]);
640                     path.lineTo(pts[i+1]);
641                     this->drawPath(path, p, NULL, true);
642                     path.rewind();
643                 }
644                 break;
645             }
646         }
647     }
648 }
649 
as_lefttop(SkRect * r)650 static inline SkPoint* as_lefttop(SkRect* r) {
651     return (SkPoint*)(void*)r;
652 }
653 
as_rightbottom(SkRect * r)654 static inline SkPoint* as_rightbottom(SkRect* r) {
655     return ((SkPoint*)(void*)r) + 1;
656 }
657 
drawRect(const SkRect & rect,const SkPaint & paint) const658 void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
659     SkDEBUGCODE(this->validate();)
660 
661     // nothing to draw
662     if (fClip->isEmpty() ||
663         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
664         return;
665     }
666 
667     // complex enough to draw as a path
668     if (paint.getPathEffect() || paint.getMaskFilter() ||
669             paint.getRasterizer() || !fMatrix->rectStaysRect() ||
670             (paint.getStyle() != SkPaint::kFill_Style &&
671              SkScalarHalf(paint.getStrokeWidth()) > 0)) {
672         SkPath  tmp;
673         tmp.addRect(rect);
674         tmp.setFillType(SkPath::kWinding_FillType);
675         this->drawPath(tmp, paint, NULL, true);
676         return;
677     }
678 
679     const SkMatrix& matrix = *fMatrix;
680     SkRect          devRect;
681 
682     // transform rect into devRect
683     {
684         matrix.mapXY(rect.fLeft, rect.fTop, rect_points(devRect, 0));
685         matrix.mapXY(rect.fRight, rect.fBottom, rect_points(devRect, 1));
686         devRect.sort();
687     }
688 
689     if (fBounder && !fBounder->doRect(devRect, paint)) {
690         return;
691     }
692 
693     // look for the quick exit, before we build a blitter
694     {
695         SkIRect ir;
696         devRect.roundOut(&ir);
697         if (fClip->quickReject(ir))
698             return;
699     }
700 
701     SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint);
702     SkBlitter*          blitter = blitterStorage.get();
703     const SkRegion*     clip = fClip;
704 
705     if (paint.getStyle() == SkPaint::kFill_Style) {
706         if (paint.isAntiAlias()) {
707             SkScan::AntiFillRect(devRect, clip, blitter);
708         } else {
709             SkScan::FillRect(devRect, clip, blitter);
710         }
711     } else {
712         if (paint.isAntiAlias()) {
713             SkScan::AntiHairRect(devRect, clip, blitter);
714         } else {
715             SkScan::HairRect(devRect, clip, blitter);
716         }
717     }
718 }
719 
drawDevMask(const SkMask & srcM,const SkPaint & paint) const720 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
721     if (srcM.fBounds.isEmpty()) {
722         return;
723     }
724 
725     SkMask          dstM;
726     const SkMask*   mask = &srcM;
727 
728     dstM.fImage = NULL;
729     SkAutoMaskImage ami(&dstM, false);
730 
731     if (paint.getMaskFilter() &&
732             paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
733         mask = &dstM;
734     }
735 
736     if (fBounder && !fBounder->doIRect(mask->fBounds)) {
737         return;
738     }
739 
740     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
741 
742     blitter->blitMaskRegion(*mask, *fClip);
743 }
744 
745 class SkAutoPaintRestoreColorStrokeWidth {
746 public:
SkAutoPaintRestoreColorStrokeWidth(const SkPaint & paint)747     SkAutoPaintRestoreColorStrokeWidth(const SkPaint& paint) {
748         fPaint = (SkPaint*)&paint;
749         fColor = paint.getColor();
750         fWidth = paint.getStrokeWidth();
751     }
~SkAutoPaintRestoreColorStrokeWidth()752     ~SkAutoPaintRestoreColorStrokeWidth() {
753         fPaint->setColor(fColor);
754         fPaint->setStrokeWidth(fWidth);
755     }
756 
757 private:
758     SkPaint*    fPaint;
759     SkColor     fColor;
760     SkScalar    fWidth;
761 };
762 
fast_len(const SkVector & vec)763 static SkScalar fast_len(const SkVector& vec) {
764     SkScalar x = SkScalarAbs(vec.fX);
765     SkScalar y = SkScalarAbs(vec.fY);
766     if (x < y) {
767         SkTSwap(x, y);
768     }
769     return x + SkScalarHalf(y);
770 }
771 
772 // our idea is to return true if there is no appreciable skew or non-square scale
773 // for that we'll transform (0,1) and (1,0), and check that the resulting dot-prod
774 // is nearly one
map_radius(const SkMatrix & matrix,SkScalar * value)775 static bool map_radius(const SkMatrix& matrix, SkScalar* value) {
776     if (matrix.getType() & SkMatrix::kPerspective_Mask) {
777         return false;
778     }
779     SkVector src[2], dst[2];
780     src[0].set(*value, 0);
781     src[1].set(0, *value);
782     matrix.mapVectors(dst, src, 2);
783     SkScalar len0 = fast_len(dst[0]);
784     SkScalar len1 = fast_len(dst[1]);
785     if (len0 < SK_Scalar1 && len1 < SK_Scalar1) {
786         *value = SkScalarAve(len0, len1);
787         return true;
788     }
789     return false;
790 }
791 
drawPath(const SkPath & origSrcPath,const SkPaint & paint,const SkMatrix * prePathMatrix,bool pathIsMutable) const792 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
793                       const SkMatrix* prePathMatrix, bool pathIsMutable) const {
794     SkDEBUGCODE(this->validate();)
795 
796     // nothing to draw
797     if (fClip->isEmpty() ||
798         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
799         return;
800     }
801 
802     SkPath*         pathPtr = (SkPath*)&origSrcPath;
803     bool            doFill = true;
804     SkPath          tmpPath;
805     SkMatrix        tmpMatrix;
806     const SkMatrix* matrix = fMatrix;
807 
808     if (prePathMatrix) {
809         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style ||
810                 paint.getRasterizer()) {
811             SkPath* result = pathPtr;
812 
813             if (!pathIsMutable) {
814                 result = &tmpPath;
815                 pathIsMutable = true;
816             }
817             pathPtr->transform(*prePathMatrix, result);
818             pathPtr = result;
819         } else {
820             if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
821                 // overflow
822                 return;
823             }
824             matrix = &tmpMatrix;
825         }
826     }
827     // at this point we're done with prePathMatrix
828     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
829 
830     /*
831         If the device thickness < 1.0, then make it a hairline, and
832         modulate alpha if the thickness is even smaller (e.g. thickness == 0.5
833         should modulate the alpha by 1/2)
834     */
835 
836     SkAutoPaintRestoreColorStrokeWidth aprc(paint);
837 
838     // can we approximate a thin (but not hairline) stroke with an alpha-modulated
839     // hairline? Only if the matrix scales evenly in X and Y, and the device-width is
840     // less than a pixel
841     if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
842         SkScalar width = paint.getStrokeWidth();
843         if (width > 0 && map_radius(*matrix, &width)) {
844             int scale = (int)SkScalarMul(width, 256);
845             int alpha = paint.getAlpha() * scale >> 8;
846 
847             // pretend to be a hairline, with a modulated alpha
848             ((SkPaint*)&paint)->setAlpha(alpha);
849             ((SkPaint*)&paint)->setStrokeWidth(0);
850         }
851     }
852 
853     if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
854         doFill = paint.getFillPath(*pathPtr, &tmpPath);
855         pathPtr = &tmpPath;
856     }
857 
858     if (paint.getRasterizer()) {
859         SkMask  mask;
860         if (paint.getRasterizer()->rasterize(*pathPtr, *matrix,
861                             &fClip->getBounds(), paint.getMaskFilter(), &mask,
862                             SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
863             this->drawDevMask(mask, paint);
864             SkMask::FreeImage(mask.fImage);
865         }
866         return;
867     }
868 
869     // avoid possibly allocating a new path in transform if we can
870     SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
871 
872     // transform the path into device space
873     pathPtr->transform(*matrix, devPathPtr);
874 
875     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
876 
877     // how does filterPath() know to fill or hairline the path??? <mrr>
878     if (paint.getMaskFilter() &&
879             paint.getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fClip,
880                                               fBounder, blitter.get())) {
881         return; // filterPath() called the blitter, so we're done
882     }
883 
884     if (fBounder && !fBounder->doPath(*devPathPtr, paint, doFill)) {
885         return;
886     }
887 
888     if (doFill) {
889         if (paint.isAntiAlias()) {
890             SkScan::AntiFillPath(*devPathPtr, *fClip, blitter.get());
891         } else {
892             SkScan::FillPath(*devPathPtr, *fClip, blitter.get());
893         }
894     } else {    // hairline
895         if (paint.isAntiAlias()) {
896             SkScan::AntiHairPath(*devPathPtr, fClip, blitter.get());
897         } else {
898             SkScan::HairPath(*devPathPtr, fClip, blitter.get());
899         }
900     }
901 }
902 
903 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
904     go ahead and treat it as if it were, so that subsequent code can go fast.
905  */
just_translate(const SkMatrix & matrix,const SkBitmap & bitmap)906 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
907     SkMatrix::TypeMask mask = matrix.getType();
908 
909     if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
910         return false;
911     }
912     if (mask & SkMatrix::kScale_Mask) {
913         SkScalar sx = matrix[SkMatrix::kMScaleX];
914         SkScalar sy = matrix[SkMatrix::kMScaleY];
915         int w = bitmap.width();
916         int h = bitmap.height();
917         int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
918         int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
919         return sw == w && sh == h;
920     }
921     // if we got here, we're either kTranslate_Mask or identity
922     return true;
923 }
924 
drawBitmapAsMask(const SkBitmap & bitmap,const SkPaint & paint) const925 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
926                               const SkPaint& paint) const {
927     SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config);
928 
929     if (just_translate(*fMatrix, bitmap)) {
930         int ix = SkScalarRound(fMatrix->getTranslateX());
931         int iy = SkScalarRound(fMatrix->getTranslateY());
932 
933         SkMask  mask;
934         mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
935         mask.fFormat = SkMask::kA8_Format;
936         mask.fRowBytes = bitmap.rowBytes();
937         mask.fImage = bitmap.getAddr8(0, 0);
938 
939         this->drawDevMask(mask, paint);
940     } else {    // need to xform the bitmap first
941         SkRect  r;
942         SkMask  mask;
943 
944         r.set(0, 0,
945               SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
946         fMatrix->mapRect(&r);
947         r.round(&mask.fBounds);
948 
949         // set the mask's bounds to the transformed bitmap-bounds,
950         // clipped to the actual device
951         {
952             SkIRect    devBounds;
953             devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
954             // need intersect(l, t, r, b) on irect
955             if (!mask.fBounds.intersect(devBounds)) {
956                 return;
957             }
958         }
959 
960         mask.fFormat = SkMask::kA8_Format;
961         mask.fRowBytes = SkAlign4(mask.fBounds.width());
962         size_t size = mask.computeImageSize();
963         if (0 == size) {
964             // the mask is too big to allocated, draw nothing
965             return;
966         }
967 
968         // allocate (and clear) our temp buffer to hold the transformed bitmap
969         SkAutoMalloc    storage(size);
970         mask.fImage = (uint8_t*)storage.get();
971         memset(mask.fImage, 0, size);
972 
973         // now draw our bitmap(src) into mask(dst), transformed by the matrix
974         {
975             SkBitmap    device;
976             device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
977                              mask.fBounds.height(), mask.fRowBytes);
978             device.setPixels(mask.fImage);
979 
980             SkCanvas c(device);
981             // need the unclipped top/left for the translate
982             c.translate(-SkIntToScalar(mask.fBounds.fLeft),
983                         -SkIntToScalar(mask.fBounds.fTop));
984             c.concat(*fMatrix);
985 
986             // We can't call drawBitmap, or we'll infinitely recurse. Instead
987             // we manually build a shader and draw that into our new mask
988             SkPaint tmpPaint;
989             tmpPaint.setFlags(paint.getFlags());
990             SkAutoBitmapShaderInstall   install(bitmap, &tmpPaint);
991             SkRect rr;
992             rr.set(0, 0, SkIntToScalar(bitmap.width()),
993                    SkIntToScalar(bitmap.height()));
994             c.drawRect(rr, tmpPaint);
995         }
996         this->drawDevMask(mask, paint);
997     }
998 }
999 
clipped_out(const SkMatrix & m,const SkRegion & c,const SkRect & srcR)1000 static bool clipped_out(const SkMatrix& m, const SkRegion& c,
1001                         const SkRect& srcR) {
1002     SkRect  dstR;
1003     SkIRect devIR;
1004 
1005     m.mapRect(&dstR, srcR);
1006     dstR.roundOut(&devIR);
1007     return c.quickReject(devIR);
1008 }
1009 
clipped_out(const SkMatrix & matrix,const SkRegion & clip,int width,int height)1010 static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip,
1011                         int width, int height) {
1012     SkRect  r;
1013     r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1014     return clipped_out(matrix, clip, r);
1015 }
1016 
drawBitmap(const SkBitmap & bitmap,const SkMatrix & prematrix,const SkPaint & paint) const1017 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1018                         const SkPaint& paint) const {
1019     SkDEBUGCODE(this->validate();)
1020 
1021     // nothing to draw
1022     if (fClip->isEmpty() ||
1023             bitmap.width() == 0 || bitmap.height() == 0 ||
1024             bitmap.getConfig() == SkBitmap::kNo_Config ||
1025             (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1026         return;
1027     }
1028 
1029     // run away on too-big bitmaps for now (exceed 16.16)
1030     if (bitmap.width() > 32767 || bitmap.height() > 32767) {
1031         return;
1032     }
1033 
1034     SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style);
1035 
1036     SkMatrix matrix;
1037     if (!matrix.setConcat(*fMatrix, prematrix)) {
1038         return;
1039     }
1040 
1041     // do I need to call the bounder first???
1042     if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) {
1043         return;
1044     }
1045 
1046     // only lock the pixels if we passed the clip test
1047     SkAutoLockPixels alp(bitmap);
1048     // after the lock, check if we are valid
1049     if (!bitmap.readyToDraw()) {
1050         return;
1051     }
1052 
1053     if (bitmap.getConfig() != SkBitmap::kA8_Config &&
1054             just_translate(matrix, bitmap)) {
1055         int         ix = SkScalarRound(matrix.getTranslateX());
1056         int         iy = SkScalarRound(matrix.getTranslateY());
1057         uint32_t    storage[kBlitterStorageLongCount];
1058         SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1059                                             ix, iy, storage, sizeof(storage));
1060         if (blitter) {
1061             SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
1062 
1063             SkIRect    ir;
1064             ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1065 
1066             if (fBounder && !fBounder->doIRect(ir)) {
1067                 return;
1068             }
1069 
1070             SkRegion::Cliperator iter(*fClip, ir);
1071             const SkIRect&       cr = iter.rect();
1072 
1073             for (; !iter.done(); iter.next()) {
1074                 SkASSERT(!cr.isEmpty());
1075                 blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
1076             }
1077             return;
1078         }
1079 #if 0
1080         SkDebugf("---- MISSING sprite case: config=%d [%d %d], device=%d, xfer=%p, alpha=0x%X colorFilter=%p\n",
1081                 bitmap.config(), bitmap.width(), bitmap.height(), fBitmap->config(),
1082                 paint.getXfermode(), paint.getAlpha(), paint.getColorFilter());
1083 #endif
1084     }
1085 
1086     // now make a temp draw on the stack, and use it
1087     //
1088     SkDraw draw(*this);
1089     draw.fMatrix = &matrix;
1090 
1091     if (bitmap.getConfig() == SkBitmap::kA8_Config) {
1092         draw.drawBitmapAsMask(bitmap, paint);
1093     } else {
1094         SkAutoBitmapShaderInstall   install(bitmap, &paint);
1095 
1096         SkRect  r;
1097         r.set(0, 0, SkIntToScalar(bitmap.width()),
1098               SkIntToScalar(bitmap.height()));
1099         // is this ok if paint has a rasterizer?
1100         draw.drawRect(r, paint);
1101     }
1102 }
1103 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint & paint) const1104 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1105                         const SkPaint& paint) const {
1106     SkDEBUGCODE(this->validate();)
1107 
1108     // nothing to draw
1109     if (fClip->isEmpty() ||
1110             bitmap.width() == 0 || bitmap.height() == 0 ||
1111             bitmap.getConfig() == SkBitmap::kNo_Config ||
1112             (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1113         return;
1114     }
1115 
1116     SkIRect    bounds;
1117     bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1118 
1119     if (fClip->quickReject(bounds)) {
1120         return; // nothing to draw
1121     }
1122 
1123     SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style);
1124 
1125     if (NULL == paint.getColorFilter()) {
1126         uint32_t    storage[kBlitterStorageLongCount];
1127         SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1128                                                 x, y, storage, sizeof(storage));
1129 
1130         if (blitter) {
1131             SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1132 
1133             if (fBounder && !fBounder->doIRect(bounds)) {
1134                 return;
1135             }
1136 
1137             SkRegion::Cliperator iter(*fClip, bounds);
1138             const SkIRect&       cr = iter.rect();
1139 
1140             for (; !iter.done(); iter.next()) {
1141                 SkASSERT(!cr.isEmpty());
1142                 blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
1143             }
1144             return;
1145         }
1146     }
1147 
1148     SkAutoBitmapShaderInstall   install(bitmap, &paint);
1149 
1150     SkMatrix        matrix;
1151     SkRect          r;
1152 
1153     // get a scalar version of our rect
1154     r.set(bounds);
1155 
1156     // tell the shader our offset
1157     matrix.setTranslate(r.fLeft, r.fTop);
1158     paint.getShader()->setLocalMatrix(matrix);
1159 
1160     SkDraw draw(*this);
1161     matrix.reset();
1162     draw.fMatrix = &matrix;
1163     // call ourself with a rect
1164     // is this OK if paint has a rasterizer?
1165     draw.drawRect(r, paint);
1166 }
1167 
1168 ///////////////////////////////////////////////////////////////////////////////
1169 
1170 #include "SkScalerContext.h"
1171 #include "SkGlyphCache.h"
1172 #include "SkUtils.h"
1173 
measure_text(SkGlyphCache * cache,SkDrawCacheProc glyphCacheProc,const char text[],size_t byteLength,SkVector * stopVector)1174 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1175                 const char text[], size_t byteLength, SkVector* stopVector) {
1176     SkFixed     x = 0, y = 0;
1177     const char* stop = text + byteLength;
1178 
1179     SkAutoKern  autokern;
1180 
1181     while (text < stop) {
1182         // don't need x, y here, since all subpixel variants will have the
1183         // same advance
1184         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1185 
1186         x += autokern.adjust(glyph) + glyph.fAdvanceX;
1187         y += glyph.fAdvanceY;
1188     }
1189     stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1190 
1191     SkASSERT(text == stop);
1192 }
1193 
drawText_asPaths(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1194 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1195                               SkScalar x, SkScalar y,
1196                               const SkPaint& paint) const {
1197     SkDEBUGCODE(this->validate();)
1198 
1199     SkTextToPathIter iter(text, byteLength, paint, true, true);
1200 
1201     SkMatrix    matrix;
1202     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1203     matrix.postTranslate(x, y);
1204 
1205     const SkPath* iterPath;
1206     SkScalar xpos, prevXPos = 0;
1207 
1208     while ((iterPath = iter.next(&xpos)) != NULL) {
1209         matrix.postTranslate(xpos - prevXPos, 0);
1210         this->drawPath(*iterPath, iter.getPaint(), &matrix, false);
1211         prevXPos = xpos;
1212     }
1213 }
1214 
1215 #define kStdStrikeThru_Offset       (-SK_Scalar1 * 6 / 21)
1216 #define kStdUnderline_Offset        (SK_Scalar1 / 9)
1217 #define kStdUnderline_Thickness     (SK_Scalar1 / 18)
1218 
draw_paint_rect(const SkDraw * draw,const SkPaint & paint,const SkRect & r,SkScalar textSize)1219 static void draw_paint_rect(const SkDraw* draw, const SkPaint& paint,
1220                             const SkRect& r, SkScalar textSize) {
1221     if (paint.getStyle() == SkPaint::kFill_Style) {
1222         draw->drawRect(r, paint);
1223     } else {
1224         SkPaint p(paint);
1225         p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1226         draw->drawRect(r, p);
1227     }
1228 }
1229 
handle_aftertext(const SkDraw * draw,const SkPaint & paint,SkScalar width,const SkPoint & start)1230 static void handle_aftertext(const SkDraw* draw, const SkPaint& paint,
1231                              SkScalar width, const SkPoint& start) {
1232     uint32_t flags = paint.getFlags();
1233 
1234     if (flags & (SkPaint::kUnderlineText_Flag |
1235                  SkPaint::kStrikeThruText_Flag)) {
1236         SkScalar textSize = paint.getTextSize();
1237         SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1238         SkRect   r;
1239 
1240         r.fLeft = start.fX;
1241         r.fRight = start.fX + width;
1242 
1243         if (flags & SkPaint::kUnderlineText_Flag) {
1244             SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1245                                              start.fY);
1246             r.fTop = offset;
1247             r.fBottom = offset + height;
1248             draw_paint_rect(draw, paint, r, textSize);
1249         }
1250         if (flags & SkPaint::kStrikeThruText_Flag) {
1251             SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1252                                              start.fY);
1253             r.fTop = offset;
1254             r.fBottom = offset + height;
1255             draw_paint_rect(draw, paint, r, textSize);
1256         }
1257     }
1258 }
1259 
1260 // disable warning : local variable used without having been initialized
1261 #if defined _WIN32 && _MSC_VER >= 1300
1262 #pragma warning ( push )
1263 #pragma warning ( disable : 4701 )
1264 #endif
1265 
1266 //////////////////////////////////////////////////////////////////////////////
1267 
D1G_NoBounder_RectClip(const SkDraw1Glyph & state,const SkGlyph & glyph,int left,int top)1268 static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1269 								   const SkGlyph& glyph, int left, int top) {
1270     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1271 	SkASSERT(state.fClip->isRect());
1272 	SkASSERT(NULL == state.fBounder);
1273 	SkASSERT(state.fClipBounds == state.fClip->getBounds());
1274 
1275     left += glyph.fLeft;
1276     top  += glyph.fTop;
1277 
1278     int right   = left + glyph.fWidth;
1279     int bottom  = top + glyph.fHeight;
1280 
1281 	SkMask		mask;
1282 	SkIRect		storage;
1283 	SkIRect*	bounds = &mask.fBounds;
1284 
1285 	mask.fBounds.set(left, top, right, bottom);
1286 
1287 	// this extra test is worth it, assuming that most of the time it succeeds
1288 	// since we can avoid writing to storage
1289 	if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1290 		if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1291 			return;
1292 		bounds = &storage;
1293 	}
1294 
1295 	uint8_t* aa = (uint8_t*)glyph.fImage;
1296 	if (NULL == aa) {
1297 		aa = (uint8_t*)state.fCache->findImage(glyph);
1298 		if (NULL == aa) {
1299 			return; // can't rasterize glyph
1300         }
1301 	}
1302 
1303 	mask.fRowBytes = glyph.rowBytes();
1304 	mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1305 	mask.fImage = aa;
1306 	state.fBlitter->blitMask(mask, *bounds);
1307 }
1308 
D1G_NoBounder_RgnClip(const SkDraw1Glyph & state,const SkGlyph & glyph,int left,int top)1309 static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1310 								  const SkGlyph& glyph, int left, int top) {
1311     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1312 	SkASSERT(!state.fClip->isRect());
1313 	SkASSERT(NULL == state.fBounder);
1314 
1315     SkMask  mask;
1316 
1317     left += glyph.fLeft;
1318     top  += glyph.fTop;
1319 
1320     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1321 	SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1322 
1323 	if (!clipper.done()) {
1324 		const SkIRect&  cr = clipper.rect();
1325 		const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1326 		if (NULL == aa) {
1327 			aa = (uint8_t*)state.fCache->findImage(glyph);
1328 			if (NULL == aa) {
1329 				return;
1330             }
1331 		}
1332 
1333 		mask.fRowBytes = glyph.rowBytes();
1334 		mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1335 		mask.fImage = (uint8_t*)aa;
1336 		do {
1337 			state.fBlitter->blitMask(mask, cr);
1338 			clipper.next();
1339 		} while (!clipper.done());
1340 	}
1341 }
1342 
D1G_Bounder(const SkDraw1Glyph & state,const SkGlyph & glyph,int left,int top)1343 static void D1G_Bounder(const SkDraw1Glyph& state,
1344 						const SkGlyph& glyph, int left, int top) {
1345     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1346 
1347     SkMask  mask;
1348 
1349     left += glyph.fLeft;
1350     top  += glyph.fTop;
1351 
1352     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1353     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1354 
1355 	if (!clipper.done()) {
1356 		const SkIRect&  cr = clipper.rect();
1357 		const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1358 		if (NULL == aa) {
1359 			aa = (uint8_t*)state.fCache->findImage(glyph);
1360 			if (NULL == aa) {
1361 				return;
1362             }
1363 		}
1364 
1365 		if (state.fBounder->doIRect(cr)) {
1366 			mask.fRowBytes = glyph.rowBytes();
1367 			mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1368 			mask.fImage = (uint8_t*)aa;
1369 			do {
1370 				state.fBlitter->blitMask(mask, cr);
1371 				clipper.next();
1372 			} while (!clipper.done());
1373 		}
1374 	}
1375 }
1376 
init(const SkDraw * draw,SkBlitter * blitter,SkGlyphCache * cache)1377 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1378                                       SkGlyphCache* cache) {
1379     fDraw = draw;
1380 	fBounder = draw->fBounder;
1381 	fClip = draw->fClip;
1382     fClipBounds = fClip->getBounds();
1383 	fBlitter = blitter;
1384 	fCache = cache;
1385 
1386     if (draw->fProcs && draw->fProcs->fD1GProc) {
1387         return draw->fProcs->fD1GProc;
1388     }
1389 
1390     if (NULL == fBounder) {
1391         if (fClip->isRect()) {
1392             return D1G_NoBounder_RectClip;
1393         } else {
1394             return D1G_NoBounder_RgnClip;
1395         }
1396     } else {
1397         return D1G_Bounder;
1398     }
1399 }
1400 
1401 enum RoundBaseline {
1402     kDont_Round_Baseline,
1403     kRound_X_Baseline,
1404     kRound_Y_Baseline
1405 };
1406 
computeRoundBaseline(const SkMatrix & mat)1407 static RoundBaseline computeRoundBaseline(const SkMatrix& mat) {
1408     if (mat[1] == 0 && mat[3] == 0) {
1409         // we're 0 or 180 degrees, round the y coordinate of the baseline
1410         return kRound_Y_Baseline;
1411     } else if (mat[0] == 0 && mat[4] == 0) {
1412         // we're 90 or 270 degrees, round the x coordinate of the baseline
1413         return kRound_X_Baseline;
1414     } else {
1415         return kDont_Round_Baseline;
1416     }
1417 }
1418 
1419 ///////////////////////////////////////////////////////////////////////////////
1420 
drawText(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1421 void SkDraw::drawText(const char text[], size_t byteLength,
1422                       SkScalar x, SkScalar y, const SkPaint& paint) const {
1423     SkASSERT(byteLength == 0 || text != NULL);
1424 
1425     SkDEBUGCODE(this->validate();)
1426 
1427     // nothing to draw
1428     if (text == NULL || byteLength == 0 ||
1429         fClip->isEmpty() ||
1430         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1431         return;
1432     }
1433 
1434     SkScalar    underlineWidth = 0;
1435     SkPoint     underlineStart;
1436 
1437     underlineStart.set(0, 0);    // to avoid warning
1438     if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1439                             SkPaint::kStrikeThruText_Flag)) {
1440         underlineWidth = paint.measureText(text, byteLength);
1441 
1442         SkScalar offsetX = 0;
1443         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1444             offsetX = SkScalarHalf(underlineWidth);
1445         } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1446             offsetX = underlineWidth;
1447         }
1448         underlineStart.set(x - offsetX, y);
1449     }
1450 
1451     if (/*paint.isLinearText() ||*/
1452         (fMatrix->getType() & SkMatrix::kPerspective_Mask)) {
1453         this->drawText_asPaths(text, byteLength, x, y, paint);
1454         handle_aftertext(this, paint, underlineWidth, underlineStart);
1455         return;
1456     }
1457 
1458     SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1459 
1460     SkAutoGlyphCache    autoCache(paint, fMatrix);
1461     SkGlyphCache*       cache = autoCache.getCache();
1462     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1463 
1464     // transform our starting point
1465     {
1466         SkPoint loc;
1467         fMatrix->mapXY(x, y, &loc);
1468         x = loc.fX;
1469         y = loc.fY;
1470     }
1471 
1472     // need to measure first
1473     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1474         SkVector    stop;
1475 
1476         measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1477 
1478         SkScalar    stopX = stop.fX;
1479         SkScalar    stopY = stop.fY;
1480 
1481         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1482             stopX = SkScalarHalf(stopX);
1483             stopY = SkScalarHalf(stopY);
1484         }
1485         x -= stopX;
1486         y -= stopY;
1487     }
1488 
1489     SkFixed fx = SkScalarToFixed(x);
1490     SkFixed fy = SkScalarToFixed(y);
1491     const char* stop = text + byteLength;
1492 
1493     if (paint.isSubpixelText()) {
1494         RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
1495         if (kRound_Y_Baseline == roundBaseline) {
1496             fy = (fy + 0x8000) & ~0xFFFF;
1497         } else if (kRound_X_Baseline == roundBaseline) {
1498             fx = (fx + 0x8000) & ~0xFFFF;
1499         }
1500     } else {
1501         // apply the bias here, so we don't have to add 1/2 in the loop
1502         fx += SK_Fixed1/2;
1503         fy += SK_Fixed1/2;
1504     }
1505 
1506     SkAutoKern          autokern;
1507 	SkDraw1Glyph        d1g;
1508 	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
1509 
1510     while (text < stop) {
1511         const SkGlyph& glyph  = glyphCacheProc(cache, &text, fx, fy);
1512 
1513         fx += autokern.adjust(glyph);
1514 
1515         if (glyph.fWidth) {
1516 			proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1517         }
1518         fx += glyph.fAdvanceX;
1519         fy += glyph.fAdvanceY;
1520     }
1521 
1522     if (underlineWidth) {
1523         autoCache.release();    // release this now to free up the RAM
1524         handle_aftertext(this, paint, underlineWidth, underlineStart);
1525     }
1526 }
1527 
1528 // last parameter is interpreted as SkFixed [x, y]
1529 // return the fixed position, which may be rounded or not by the caller
1530 //   e.g. subpixel doesn't round
1531 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1532 
leftAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1533 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1534                           SkIPoint* dst) {
1535     dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1536 }
1537 
centerAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1538 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1539                             SkIPoint* dst) {
1540     dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1541              SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1542 }
1543 
rightAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1544 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1545                            SkIPoint* dst) {
1546     dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1547              SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1548 }
1549 
pick_align_proc(SkPaint::Align align)1550 static AlignProc pick_align_proc(SkPaint::Align align) {
1551     static const AlignProc gProcs[] = {
1552         leftAlignProc, centerAlignProc, rightAlignProc
1553     };
1554 
1555     SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1556 
1557     return gProcs[align];
1558 }
1559 
1560 class TextMapState {
1561 public:
1562     mutable SkPoint fLoc;
1563 
TextMapState(const SkMatrix & matrix,SkScalar y)1564     TextMapState(const SkMatrix& matrix, SkScalar y)
1565         : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1566 
1567     typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1568 
1569     Proc pickProc(int scalarsPerPosition);
1570 
1571 private:
1572     const SkMatrix&     fMatrix;
1573     SkMatrix::MapXYProc fProc;
1574     SkScalar            fY; // ignored by MapXYProc
1575     // these are only used by Only... procs
1576     SkScalar            fScaleX, fTransX, fTransformedY;
1577 
MapXProc(const TextMapState & state,const SkScalar pos[])1578     static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1579         state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1580     }
1581 
MapXYProc(const TextMapState & state,const SkScalar pos[])1582     static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1583         state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1584     }
1585 
MapOnlyScaleXProc(const TextMapState & state,const SkScalar pos[])1586     static void MapOnlyScaleXProc(const TextMapState& state,
1587                                   const SkScalar pos[]) {
1588         state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1589                        state.fTransformedY);
1590     }
1591 
MapOnlyTransXProc(const TextMapState & state,const SkScalar pos[])1592     static void MapOnlyTransXProc(const TextMapState& state,
1593                                   const SkScalar pos[]) {
1594         state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1595     }
1596 };
1597 
pickProc(int scalarsPerPosition)1598 TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1599     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1600 
1601     if (1 == scalarsPerPosition) {
1602         unsigned mtype = fMatrix.getType();
1603         if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1604             return MapXProc;
1605         } else {
1606             fScaleX = fMatrix.getScaleX();
1607             fTransX = fMatrix.getTranslateX();
1608             fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1609                             fMatrix.getTranslateY();
1610             return (mtype & SkMatrix::kScale_Mask) ?
1611                         MapOnlyScaleXProc : MapOnlyTransXProc;
1612         }
1613     } else {
1614         return MapXYProc;
1615     }
1616 }
1617 
1618 //////////////////////////////////////////////////////////////////////////////
1619 
drawPosText(const char text[],size_t byteLength,const SkScalar pos[],SkScalar constY,int scalarsPerPosition,const SkPaint & paint) const1620 void SkDraw::drawPosText(const char text[], size_t byteLength,
1621                          const SkScalar pos[], SkScalar constY,
1622                          int scalarsPerPosition, const SkPaint& paint) const {
1623     SkASSERT(byteLength == 0 || text != NULL);
1624     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1625 
1626     SkDEBUGCODE(this->validate();)
1627 
1628     // nothing to draw
1629     if (text == NULL || byteLength == 0 ||
1630         fClip->isEmpty() ||
1631         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1632         return;
1633     }
1634 
1635     if (/*paint.isLinearText() ||*/
1636         (fMatrix->getType() & SkMatrix::kPerspective_Mask)) {
1637         // TODO !!!!
1638 //      this->drawText_asPaths(text, byteLength, x, y, paint);
1639         return;
1640     }
1641 
1642     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1643     SkAutoGlyphCache    autoCache(paint, fMatrix);
1644     SkGlyphCache*       cache = autoCache.getCache();
1645     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1646 
1647     const char*        stop = text + byteLength;
1648     AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1649 	SkDraw1Glyph	   d1g;
1650 	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
1651     TextMapState       tms(*fMatrix, constY);
1652     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1653 
1654     if (paint.isSubpixelText()) {
1655         // maybe we should skip the rounding if linearText is set
1656         RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
1657 
1658         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1659             while (text < stop) {
1660                 tmsProc(tms, pos);
1661 
1662                 SkFixed fx = SkScalarToFixed(tms.fLoc.fX);
1663                 SkFixed fy = SkScalarToFixed(tms.fLoc.fY);
1664 
1665                 if (kRound_Y_Baseline == roundBaseline) {
1666                     fy = (fy + 0x8000) & ~0xFFFF;
1667                 } else if (kRound_X_Baseline == roundBaseline) {
1668                     fx = (fx + 0x8000) & ~0xFFFF;
1669                 }
1670 
1671                 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
1672 
1673                 if (glyph.fWidth) {
1674                     proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1675                 }
1676                 pos += scalarsPerPosition;
1677             }
1678         } else {
1679             while (text < stop) {
1680                 const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0);
1681 
1682                 if (glyph->fWidth) {
1683                     SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;)
1684                     SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;)
1685 
1686                     SkFixed fx, fy;
1687                     tmsProc(tms, pos);
1688 
1689                     {
1690                         SkIPoint fixedLoc;
1691                         alignProc(tms.fLoc, *glyph, &fixedLoc);
1692                         fx = fixedLoc.fX;
1693                         fy = fixedLoc.fY;
1694 
1695                         if (kRound_Y_Baseline == roundBaseline) {
1696                             fy = (fy + 0x8000) & ~0xFFFF;
1697                         } else if (kRound_X_Baseline == roundBaseline) {
1698                             fx = (fx + 0x8000) & ~0xFFFF;
1699                         }
1700                     }
1701 
1702                     // have to call again, now that we've been "aligned"
1703                     glyph = &glyphCacheProc(cache, &text, fx, fy);
1704                     // the assumption is that the advance hasn't changed
1705                     SkASSERT(prevAdvX == glyph->fAdvanceX);
1706                     SkASSERT(prevAdvY == glyph->fAdvanceY);
1707 
1708                     proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1709                 }
1710                 pos += scalarsPerPosition;
1711             }
1712         }
1713     } else {    // not subpixel
1714         while (text < stop) {
1715             // the last 2 parameters are ignored
1716             const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1717 
1718             if (glyph.fWidth) {
1719                 tmsProc(tms, pos);
1720 
1721                 SkIPoint fixedLoc;
1722                 alignProc(tms.fLoc, glyph, &fixedLoc);
1723 
1724                 proc(d1g, glyph,
1725                      SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY));
1726             }
1727             pos += scalarsPerPosition;
1728         }
1729     }
1730 }
1731 
1732 #if defined _WIN32 && _MSC_VER >= 1300
1733 #pragma warning ( pop )
1734 #endif
1735 
1736 ///////////////////////////////////////////////////////////////////////////////
1737 
1738 #include "SkPathMeasure.h"
1739 
morphpoints(SkPoint dst[],const SkPoint src[],int count,SkPathMeasure & meas,const SkMatrix & matrix)1740 static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
1741                         SkPathMeasure& meas, const SkMatrix& matrix) {
1742     SkMatrix::MapXYProc proc = matrix.getMapXYProc();
1743 
1744     for (int i = 0; i < count; i++) {
1745         SkPoint pos;
1746         SkVector tangent;
1747 
1748         proc(matrix, src[i].fX, src[i].fY, &pos);
1749         SkScalar sx = pos.fX;
1750         SkScalar sy = pos.fY;
1751 
1752         meas.getPosTan(sx, &pos, &tangent);
1753 
1754         /*  This is the old way (that explains our approach but is way too slow
1755             SkMatrix    matrix;
1756             SkPoint     pt;
1757 
1758             pt.set(sx, sy);
1759             matrix.setSinCos(tangent.fY, tangent.fX);
1760             matrix.preTranslate(-sx, 0);
1761             matrix.postTranslate(pos.fX, pos.fY);
1762             matrix.mapPoints(&dst[i], &pt, 1);
1763         */
1764         dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
1765                    pos.fY + SkScalarMul(tangent.fX, sy));
1766     }
1767 }
1768 
1769 /*  TODO
1770 
1771     Need differentially more subdivisions when the follow-path is curvy. Not sure how to
1772     determine that, but we need it. I guess a cheap answer is let the caller tell us,
1773     but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
1774 */
morphpath(SkPath * dst,const SkPath & src,SkPathMeasure & meas,const SkMatrix & matrix)1775 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
1776                       const SkMatrix& matrix) {
1777     SkPath::Iter    iter(src, false);
1778     SkPoint         srcP[4], dstP[3];
1779     SkPath::Verb    verb;
1780 
1781     while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
1782         switch (verb) {
1783             case SkPath::kMove_Verb:
1784                 morphpoints(dstP, srcP, 1, meas, matrix);
1785                 dst->moveTo(dstP[0]);
1786                 break;
1787             case SkPath::kLine_Verb:
1788                 // turn lines into quads to look bendy
1789                 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
1790                 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
1791                 morphpoints(dstP, srcP, 2, meas, matrix);
1792                 dst->quadTo(dstP[0], dstP[1]);
1793                 break;
1794             case SkPath::kQuad_Verb:
1795                 morphpoints(dstP, &srcP[1], 2, meas, matrix);
1796                 dst->quadTo(dstP[0], dstP[1]);
1797                 break;
1798             case SkPath::kCubic_Verb:
1799                 morphpoints(dstP, &srcP[1], 3, meas, matrix);
1800                 dst->cubicTo(dstP[0], dstP[1], dstP[2]);
1801                 break;
1802             case SkPath::kClose_Verb:
1803                 dst->close();
1804                 break;
1805             default:
1806                 SkASSERT(!"unknown verb");
1807                 break;
1808         }
1809     }
1810 }
1811 
drawTextOnPath(const char text[],size_t byteLength,const SkPath & follow,const SkMatrix * matrix,const SkPaint & paint) const1812 void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
1813                             const SkPath& follow, const SkMatrix* matrix,
1814                             const SkPaint& paint) const {
1815     SkASSERT(byteLength == 0 || text != NULL);
1816 
1817     // nothing to draw
1818     if (text == NULL || byteLength == 0 ||
1819         fClip->isEmpty() ||
1820         (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1821         return;
1822     }
1823 
1824     SkTextToPathIter    iter(text, byteLength, paint, true, true);
1825     SkPathMeasure       meas(follow, false);
1826     SkScalar            hOffset = 0;
1827 
1828     // need to measure first
1829     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1830         SkScalar pathLen = meas.getLength();
1831         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1832             pathLen = SkScalarHalf(pathLen);
1833         }
1834         hOffset += pathLen;
1835     }
1836 
1837     const SkPath*   iterPath;
1838     SkScalar        xpos;
1839     SkMatrix        scaledMatrix;
1840     SkScalar        scale = iter.getPathScale();
1841 
1842     scaledMatrix.setScale(scale, scale);
1843 
1844     while ((iterPath = iter.next(&xpos)) != NULL) {
1845         SkPath      tmp;
1846         SkMatrix    m(scaledMatrix);
1847 
1848         m.postTranslate(xpos + hOffset, 0);
1849         if (matrix) {
1850             m.postConcat(*matrix);
1851         }
1852         morphpath(&tmp, *iterPath, meas, m);
1853         this->drawPath(tmp, iter.getPaint());
1854     }
1855 }
1856 
1857 ///////////////////////////////////////////////////////////////////////////////
1858 
1859 struct VertState {
1860     int f0, f1, f2;
1861 
VertStateVertState1862     VertState(int vCount, const uint16_t indices[], int indexCount)
1863             : fIndices(indices) {
1864         fCurrIndex = 0;
1865         if (indices) {
1866             fCount = indexCount;
1867         } else {
1868             fCount = vCount;
1869         }
1870     }
1871 
1872     typedef bool (*Proc)(VertState*);
1873     Proc chooseProc(SkCanvas::VertexMode mode);
1874 
1875 private:
1876     int             fCount;
1877     int             fCurrIndex;
1878     const uint16_t* fIndices;
1879 
1880     static bool Triangles(VertState*);
1881     static bool TrianglesX(VertState*);
1882     static bool TriangleStrip(VertState*);
1883     static bool TriangleStripX(VertState*);
1884     static bool TriangleFan(VertState*);
1885     static bool TriangleFanX(VertState*);
1886 };
1887 
Triangles(VertState * state)1888 bool VertState::Triangles(VertState* state) {
1889     int index = state->fCurrIndex;
1890     if (index + 3 > state->fCount) {
1891         return false;
1892     }
1893     state->f0 = index + 0;
1894     state->f1 = index + 1;
1895     state->f2 = index + 2;
1896     state->fCurrIndex = index + 3;
1897     return true;
1898 }
1899 
TrianglesX(VertState * state)1900 bool VertState::TrianglesX(VertState* state) {
1901     const uint16_t* indices = state->fIndices;
1902     int index = state->fCurrIndex;
1903     if (index + 3 > state->fCount) {
1904         return false;
1905     }
1906     state->f0 = indices[index + 0];
1907     state->f1 = indices[index + 1];
1908     state->f2 = indices[index + 2];
1909     state->fCurrIndex = index + 3;
1910     return true;
1911 }
1912 
TriangleStrip(VertState * state)1913 bool VertState::TriangleStrip(VertState* state) {
1914     int index = state->fCurrIndex;
1915     if (index + 3 > state->fCount) {
1916         return false;
1917     }
1918     state->f2 = index + 2;
1919     if (index & 1) {
1920         state->f0 = index + 1;
1921         state->f1 = index + 0;
1922     } else {
1923         state->f0 = index + 0;
1924         state->f1 = index + 1;
1925     }
1926     state->fCurrIndex = index + 1;
1927     return true;
1928 }
1929 
TriangleStripX(VertState * state)1930 bool VertState::TriangleStripX(VertState* state) {
1931     const uint16_t* indices = state->fIndices;
1932     int index = state->fCurrIndex;
1933     if (index + 3 > state->fCount) {
1934         return false;
1935     }
1936     state->f2 = indices[index + 2];
1937     if (index & 1) {
1938         state->f0 = indices[index + 1];
1939         state->f1 = indices[index + 0];
1940     } else {
1941         state->f0 = indices[index + 0];
1942         state->f1 = indices[index + 1];
1943     }
1944     state->fCurrIndex = index + 1;
1945     return true;
1946 }
1947 
TriangleFan(VertState * state)1948 bool VertState::TriangleFan(VertState* state) {
1949     int index = state->fCurrIndex;
1950     if (index + 3 > state->fCount) {
1951         return false;
1952     }
1953     state->f0 = 0;
1954     state->f1 = index + 1;
1955     state->f2 = index + 2;
1956     state->fCurrIndex = index + 1;
1957     return true;
1958 }
1959 
TriangleFanX(VertState * state)1960 bool VertState::TriangleFanX(VertState* state) {
1961     const uint16_t* indices = state->fIndices;
1962     int index = state->fCurrIndex;
1963     if (index + 3 > state->fCount) {
1964         return false;
1965     }
1966     state->f0 = indices[0];
1967     state->f1 = indices[index + 1];
1968     state->f2 = indices[index + 2];
1969     state->fCurrIndex = index + 1;
1970     return true;
1971 }
1972 
chooseProc(SkCanvas::VertexMode mode)1973 VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
1974     switch (mode) {
1975         case SkCanvas::kTriangles_VertexMode:
1976             return fIndices ? TrianglesX : Triangles;
1977         case SkCanvas::kTriangleStrip_VertexMode:
1978             return fIndices ? TriangleStripX : TriangleStrip;
1979         case SkCanvas::kTriangleFan_VertexMode:
1980             return fIndices ? TriangleFanX : TriangleFan;
1981         default:
1982             return NULL;
1983     }
1984 }
1985 
1986 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRegion*,
1987                          SkBlitter*);
1988 
ChooseHairProc(bool doAntiAlias)1989 static HairProc ChooseHairProc(bool doAntiAlias) {
1990     return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
1991 }
1992 
texture_to_matrix(const VertState & state,const SkPoint verts[],const SkPoint texs[],SkMatrix * matrix)1993 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
1994                               const SkPoint texs[], SkMatrix* matrix) {
1995     SkPoint src[3], dst[3];
1996 
1997     src[0] = texs[state.f0];
1998     src[1] = texs[state.f1];
1999     src[2] = texs[state.f2];
2000     dst[0] = verts[state.f0];
2001     dst[1] = verts[state.f1];
2002     dst[2] = verts[state.f2];
2003     return matrix->setPolyToPoly(src, dst, 3);
2004 }
2005 
2006 class SkTriColorShader : public SkShader {
2007 public:
SkTriColorShader()2008     SkTriColorShader() {}
2009 
2010     bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2011 
2012     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
2013 
2014 protected:
SkTriColorShader(SkFlattenableReadBuffer & buffer)2015     SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2016 
getFactory()2017     virtual Factory getFactory() { return CreateProc; }
2018 
2019 private:
2020     SkMatrix    fDstToUnit;
2021     SkPMColor   fColors[3];
2022 
CreateProc(SkFlattenableReadBuffer & buffer)2023     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
2024         return SkNEW_ARGS(SkTriColorShader, (buffer));
2025     }
2026     typedef SkShader INHERITED;
2027 };
2028 
setup(const SkPoint pts[],const SkColor colors[],int index0,int index1,int index2)2029 bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2030                              int index0, int index1, int index2) {
2031 
2032     fColors[0] = SkPreMultiplyColor(colors[index0]);
2033     fColors[1] = SkPreMultiplyColor(colors[index1]);
2034     fColors[2] = SkPreMultiplyColor(colors[index2]);
2035 
2036     SkMatrix m, im;
2037     m.reset();
2038     m.set(0, pts[index1].fX - pts[index0].fX);
2039     m.set(1, pts[index2].fX - pts[index0].fX);
2040     m.set(2, pts[index0].fX);
2041     m.set(3, pts[index1].fY - pts[index0].fY);
2042     m.set(4, pts[index2].fY - pts[index0].fY);
2043     m.set(5, pts[index0].fY);
2044     if (!m.invert(&im)) {
2045         return false;
2046     }
2047     return fDstToUnit.setConcat(im, this->getTotalInverse());
2048 }
2049 
2050 #include "SkColorPriv.h"
2051 #include "SkComposeShader.h"
2052 
ScalarTo256(SkScalar v)2053 static int ScalarTo256(SkScalar v) {
2054     int scale = SkScalarToFixed(v) >> 8;
2055     if (scale < 0) {
2056         scale = 0;
2057     }
2058     if (scale > 255) {
2059         scale = 255;
2060     }
2061     return SkAlpha255To256(scale);
2062 }
2063 
shadeSpan(int x,int y,SkPMColor dstC[],int count)2064 void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2065     SkPoint src;
2066 
2067     for (int i = 0; i < count; i++) {
2068         fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2069         x += 1;
2070 
2071         int scale1 = ScalarTo256(src.fX);
2072         int scale2 = ScalarTo256(src.fY);
2073         int scale0 = 256 - scale1 - scale2;
2074         if (scale0 < 0) {
2075             if (scale1 > scale2) {
2076                 scale2 = 256 - scale1;
2077             } else {
2078                 scale1 = 256 - scale2;
2079             }
2080             scale0 = 0;
2081         }
2082 
2083         dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2084         SkAlphaMulQ(fColors[1], scale1) +
2085         SkAlphaMulQ(fColors[2], scale2);
2086     }
2087 }
2088 
drawVertices(SkCanvas::VertexMode vmode,int count,const SkPoint vertices[],const SkPoint textures[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint) const2089 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2090                           const SkPoint vertices[], const SkPoint textures[],
2091                           const SkColor colors[], SkXfermode* xmode,
2092                           const uint16_t indices[], int indexCount,
2093                           const SkPaint& paint) const {
2094     SkASSERT(0 == count || NULL != vertices);
2095 
2096     // abort early if there is nothing to draw
2097     if (count < 3 || (indices && indexCount < 3) || fClip->isEmpty() ||
2098             (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2099         return;
2100     }
2101 
2102     // transform out vertices into device coordinates
2103     SkAutoSTMalloc<16, SkPoint> storage(count);
2104     SkPoint* devVerts = storage.get();
2105     fMatrix->mapPoints(devVerts, vertices, count);
2106 
2107     if (fBounder) {
2108         SkRect bounds;
2109         bounds.set(devVerts, count);
2110         if (!fBounder->doRect(bounds, paint)) {
2111             return;
2112         }
2113     }
2114 
2115     /*
2116         We can draw the vertices in 1 of 4 ways:
2117 
2118         - solid color (no shader/texture[], no colors[])
2119         - just colors (no shader/texture[], has colors[])
2120         - just texture (has shader/texture[], no colors[])
2121         - colors * texture (has shader/texture[], has colors[])
2122 
2123         Thus for texture drawing, we need both texture[] and a shader.
2124     */
2125 
2126     SkTriColorShader triShader; // must be above declaration of p
2127     SkPaint p(paint);
2128 
2129     SkShader* shader = p.getShader();
2130     if (NULL == shader) {
2131         // if we have no shader, we ignore the texture coordinates
2132         textures = NULL;
2133     } else if (NULL == textures) {
2134         // if we don't have texture coordinates, ignore the shader
2135         p.setShader(NULL);
2136         shader = NULL;
2137     }
2138 
2139     // setup the custom shader (if needed)
2140     if (NULL != colors) {
2141         if (NULL == textures) {
2142             // just colors (no texture)
2143             p.setShader(&triShader);
2144         } else {
2145             // colors * texture
2146             SkASSERT(shader);
2147             bool releaseMode = false;
2148             if (NULL == xmode) {
2149                 xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode);
2150                 releaseMode = true;
2151             }
2152             SkShader* compose = SkNEW_ARGS(SkComposeShader,
2153                                            (&triShader, shader, xmode));
2154             p.setShader(compose)->unref();
2155             if (releaseMode) {
2156                 xmode->unref();
2157             }
2158         }
2159     }
2160 
2161     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2162     // setup our state and function pointer for iterating triangles
2163     VertState       state(count, indices, indexCount);
2164     VertState::Proc vertProc = state.chooseProc(vmode);
2165 
2166     if (NULL != textures || NULL != colors) {
2167         SkMatrix  localM, tempM;
2168         bool      hasLocalM = shader && shader->getLocalMatrix(&localM);
2169 
2170         if (NULL != colors) {
2171             if (!triShader.setContext(*fBitmap, p, *fMatrix)) {
2172                 colors = NULL;
2173             }
2174         }
2175 
2176         while (vertProc(&state)) {
2177             if (NULL != textures) {
2178                 if (texture_to_matrix(state, vertices, textures, &tempM)) {
2179                     if (hasLocalM) {
2180                         tempM.postConcat(localM);
2181                     }
2182                     shader->setLocalMatrix(tempM);
2183                     // need to recal setContext since we changed the local matrix
2184                     if (!shader->setContext(*fBitmap, p, *fMatrix)) {
2185                         continue;
2186                     }
2187                 }
2188             }
2189             if (NULL != colors) {
2190                 if (!triShader.setup(vertices, colors,
2191                                      state.f0, state.f1, state.f2)) {
2192                     continue;
2193                 }
2194             }
2195             SkScan::FillTriangle(devVerts[state.f0], devVerts[state.f1],
2196                                  devVerts[state.f2], fClip, blitter.get());
2197         }
2198         // now restore the shader's original local matrix
2199         if (NULL != shader) {
2200             if (hasLocalM) {
2201                 shader->setLocalMatrix(localM);
2202             } else {
2203                 shader->resetLocalMatrix();
2204             }
2205         }
2206     } else {
2207         // no colors[] and no texture
2208         HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2209         while (vertProc(&state)) {
2210             hairProc(devVerts[state.f0], devVerts[state.f1], fClip, blitter.get());
2211             hairProc(devVerts[state.f1], devVerts[state.f2], fClip, blitter.get());
2212             hairProc(devVerts[state.f2], devVerts[state.f0], fClip, blitter.get());
2213         }
2214     }
2215 }
2216 
2217 ////////////////////////////////////////////////////////////////////////////////////////
2218 ////////////////////////////////////////////////////////////////////////////////////////
2219 
2220 #ifdef SK_DEBUG
2221 
validate() const2222 void SkDraw::validate() const {
2223     SkASSERT(fBitmap != NULL);
2224     SkASSERT(fMatrix != NULL);
2225     SkASSERT(fClip != NULL);
2226 
2227     const SkIRect&  cr = fClip->getBounds();
2228     SkIRect         br;
2229 
2230     br.set(0, 0, fBitmap->width(), fBitmap->height());
2231     SkASSERT(cr.isEmpty() || br.contains(cr));
2232 }
2233 
2234 #endif
2235 
2236 //////////////////////////////////////////////////////////////////////////////////////////
2237 
doIRect(const SkIRect & r)2238 bool SkBounder::doIRect(const SkIRect& r) {
2239     SkIRect    rr;
2240     return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2241 }
2242 
doHairline(const SkPoint & pt0,const SkPoint & pt1,const SkPaint & paint)2243 bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2244                            const SkPaint& paint) {
2245     SkIRect     r;
2246     SkScalar    v0, v1;
2247 
2248     v0 = pt0.fX;
2249     v1 = pt1.fX;
2250     if (v0 > v1) {
2251         SkTSwap<SkScalar>(v0, v1);
2252     }
2253     r.fLeft     = SkScalarFloor(v0);
2254     r.fRight    = SkScalarCeil(v1);
2255 
2256     v0 = pt0.fY;
2257     v1 = pt1.fY;
2258     if (v0 > v1) {
2259         SkTSwap<SkScalar>(v0, v1);
2260     }
2261     r.fTop      = SkScalarFloor(v0);
2262     r.fBottom   = SkScalarCeil(v1);
2263 
2264     if (paint.isAntiAlias()) {
2265         r.inset(-1, -1);
2266     }
2267     return this->doIRect(r);
2268 }
2269 
doRect(const SkRect & rect,const SkPaint & paint)2270 bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2271     SkIRect    r;
2272 
2273     if (paint.getStyle() == SkPaint::kFill_Style) {
2274         rect.round(&r);
2275     } else {
2276         int rad = -1;
2277         rect.roundOut(&r);
2278         if (paint.isAntiAlias()) {
2279             rad = -2;
2280         }
2281         r.inset(rad, rad);
2282     }
2283     return this->doIRect(r);
2284 }
2285 
doPath(const SkPath & path,const SkPaint & paint,bool doFill)2286 bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2287     SkIRect       r;
2288     const SkRect& bounds = path.getBounds();
2289 
2290     if (doFill) {
2291         bounds.round(&r);
2292     } else {    // hairline
2293         bounds.roundOut(&r);
2294     }
2295 
2296     if (paint.isAntiAlias()) {
2297         r.inset(-1, -1);
2298     }
2299     return this->doIRect(r);
2300 }
2301 
commit()2302 void SkBounder::commit() {
2303     // override in subclass
2304 }
2305 
2306 ////////////////////////////////////////////////////////////////////////////////////////////////
2307 
2308 #include "SkPath.h"
2309 #include "SkDraw.h"
2310 #include "SkRegion.h"
2311 #include "SkBlitter.h"
2312 
compute_bounds(const SkPath & devPath,const SkIRect * clipBounds,SkMaskFilter * filter,const SkMatrix * filterMatrix,SkIRect * bounds)2313 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2314                            SkMaskFilter* filter, const SkMatrix* filterMatrix,
2315                            SkIRect* bounds) {
2316     if (devPath.isEmpty()) {
2317         return false;
2318     }
2319 
2320     SkIPoint   margin;
2321     margin.set(0, 0);
2322 
2323     //  init our bounds from the path
2324     {
2325         SkRect pathBounds = devPath.getBounds();
2326         pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2327         pathBounds.roundOut(bounds);
2328     }
2329 
2330     if (filter) {
2331         SkASSERT(filterMatrix);
2332 
2333         SkMask  srcM, dstM;
2334 
2335         srcM.fBounds = *bounds;
2336         srcM.fFormat = SkMask::kA8_Format;
2337         srcM.fImage = NULL;
2338         if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2339             return false;
2340         }
2341         *bounds = dstM.fBounds;
2342     }
2343 
2344     if (clipBounds && !SkIRect::Intersects(*clipBounds, *bounds)) {
2345         return false;
2346     }
2347 
2348     // (possibly) trim the srcM bounds to reflect the clip
2349     // (plus whatever slop the filter needs)
2350     if (clipBounds && !clipBounds->contains(*bounds)) {
2351         SkIRect tmp = *bounds;
2352         (void)tmp.intersect(*clipBounds);
2353         // Ugh. Guard against gigantic margins from wacky filters. Without this
2354         // check we can request arbitrary amounts of slop beyond our visible
2355         // clip, and bring down the renderer (at least on finite RAM machines
2356         // like handsets, etc.). Need to balance this invented value between
2357         // quality of large filters like blurs, and the corresponding memory
2358         // requests.
2359         static const int MAX_MARGIN = 128;
2360         tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2361                   -SkMin32(margin.fY, MAX_MARGIN));
2362         (void)bounds->intersect(tmp);
2363     }
2364 
2365     return true;
2366 }
2367 
draw_into_mask(const SkMask & mask,const SkPath & devPath)2368 static void draw_into_mask(const SkMask& mask, const SkPath& devPath) {
2369     SkBitmap    bm;
2370     SkDraw      draw;
2371     SkRegion    clipRgn;
2372     SkMatrix    matrix;
2373     SkPaint     paint;
2374 
2375     bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2376     bm.setPixels(mask.fImage);
2377 
2378     clipRgn.setRect(0, 0, mask.fBounds.width(), mask.fBounds.height());
2379     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2380                         -SkIntToScalar(mask.fBounds.fTop));
2381 
2382     draw.fBitmap    = &bm;
2383     draw.fClip      = &clipRgn;
2384     draw.fMatrix    = &matrix;
2385     draw.fBounder   = NULL;
2386     paint.setAntiAlias(true);
2387     draw.drawPath(devPath, paint);
2388 }
2389 
DrawToMask(const SkPath & devPath,const SkIRect * clipBounds,SkMaskFilter * filter,const SkMatrix * filterMatrix,SkMask * mask,SkMask::CreateMode mode)2390 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2391                         SkMaskFilter* filter, const SkMatrix* filterMatrix,
2392                         SkMask* mask, SkMask::CreateMode mode) {
2393     if (SkMask::kJustRenderImage_CreateMode != mode) {
2394         if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2395             return false;
2396     }
2397 
2398     if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2399         mask->fFormat = SkMask::kA8_Format;
2400         mask->fRowBytes = mask->fBounds.width();
2401         size_t size = mask->computeImageSize();
2402         if (0 == size) {
2403             // we're too big to allocate the mask, abort
2404             return false;
2405         }
2406         mask->fImage = SkMask::AllocImage(size);
2407         memset(mask->fImage, 0, mask->computeImageSize());
2408     }
2409 
2410     if (SkMask::kJustComputeBounds_CreateMode != mode) {
2411         draw_into_mask(*mask, devPath);
2412     }
2413 
2414     return true;
2415 }
2416