• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkDraw.h"
9 #include "SkBlitter.h"
10 #include "SkBounder.h"
11 #include "SkCanvas.h"
12 #include "SkColorPriv.h"
13 #include "SkDevice.h"
14 #include "SkDeviceLooper.h"
15 #include "SkFixed.h"
16 #include "SkMaskFilter.h"
17 #include "SkPaint.h"
18 #include "SkPathEffect.h"
19 #include "SkRasterClip.h"
20 #include "SkRasterizer.h"
21 #include "SkRRect.h"
22 #include "SkScan.h"
23 #include "SkShader.h"
24 #include "SkString.h"
25 #include "SkStroke.h"
26 #include "SkTemplatesPriv.h"
27 #include "SkTLazy.h"
28 #include "SkUtils.h"
29 
30 #include "SkAutoKern.h"
31 #include "SkBitmapProcShader.h"
32 #include "SkDrawProcs.h"
33 #include "SkMatrixUtils.h"
34 
ShouldDrawTextAsPaths(const SkPaint & paint,const SkMatrix & ctm)35 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
36     // we don't cache hairlines in the cache
37     if (SkPaint::kStroke_Style == paint.getStyle() &&
38             0 == paint.getStrokeWidth()) {
39         return true;
40     }
41 
42     // we don't cache perspective
43     if (ctm.hasPerspective()) {
44         return true;
45     }
46 
47     SkMatrix textM;
48     return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
49 }
50 
51 //#define TRACE_BITMAP_DRAWS
52 
53 #define kBlitterStorageLongCount    (sizeof(SkBitmapProcShader) >> 2)
54 
55 /** Helper for allocating small blitters on the stack.
56  */
57 class SkAutoBlitterChoose : SkNoncopyable {
58 public:
SkAutoBlitterChoose()59     SkAutoBlitterChoose() {
60         fBlitter = NULL;
61     }
SkAutoBlitterChoose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint,bool drawCoverage=false)62     SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
63                         const SkPaint& paint, bool drawCoverage = false) {
64         fBlitter = SkBlitter::Choose(device, matrix, paint,
65                                      fStorage, sizeof(fStorage), drawCoverage);
66     }
67 
~SkAutoBlitterChoose()68     ~SkAutoBlitterChoose() {
69         if ((void*)fBlitter == (void*)fStorage) {
70             fBlitter->~SkBlitter();
71         } else {
72             SkDELETE(fBlitter);
73         }
74     }
75 
operator ->()76     SkBlitter*  operator->() { return fBlitter; }
get() const77     SkBlitter*  get() const { return fBlitter; }
78 
choose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint)79     void choose(const SkBitmap& device, const SkMatrix& matrix,
80                 const SkPaint& paint) {
81         SkASSERT(!fBlitter);
82         fBlitter = SkBlitter::Choose(device, matrix, paint,
83                                      fStorage, sizeof(fStorage));
84     }
85 
86 private:
87     SkBlitter*  fBlitter;
88     uint32_t    fStorage[kBlitterStorageLongCount];
89 };
90 #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
91 
92 /**
93  *  Since we are providing the storage for the shader (to avoid the perf cost
94  *  of calling new) we insist that in our destructor we can account for all
95  *  owners of the shader.
96  */
97 class SkAutoBitmapShaderInstall : SkNoncopyable {
98 public:
SkAutoBitmapShaderInstall(const SkBitmap & src,const SkPaint & paint)99     SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
100             : fPaint(paint) /* makes a copy of the paint */ {
101         fPaint.setShader(SkShader::CreateBitmapShader(src,
102                            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
103                            fStorage, sizeof(fStorage)));
104         // we deliberately left the shader with an owner-count of 2
105         SkASSERT(2 == fPaint.getShader()->getRefCnt());
106     }
107 
~SkAutoBitmapShaderInstall()108     ~SkAutoBitmapShaderInstall() {
109         SkShader* shader = fPaint.getShader();
110         // since we manually destroy shader, we insist that owners == 2
111         SkASSERT(2 == shader->getRefCnt());
112 
113         fPaint.setShader(NULL); // unref the shader by 1
114 
115         // now destroy to take care of the 2nd owner-count
116         if ((void*)shader == (void*)fStorage) {
117             shader->~SkShader();
118         } else {
119             SkDELETE(shader);
120         }
121     }
122 
123     // return the new paint that has the shader applied
paintWithShader() const124     const SkPaint& paintWithShader() const { return fPaint; }
125 
126 private:
127     SkPaint     fPaint; // copy of caller's paint (which we then modify)
128     uint32_t    fStorage[kBlitterStorageLongCount];
129 };
130 #define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
131 
132 ///////////////////////////////////////////////////////////////////////////////
133 
SkDraw()134 SkDraw::SkDraw() {
135     sk_bzero(this, sizeof(*this));
136 }
137 
SkDraw(const SkDraw & src)138 SkDraw::SkDraw(const SkDraw& src) {
139     memcpy(this, &src, sizeof(*this));
140 }
141 
computeConservativeLocalClipBounds(SkRect * localBounds) const142 bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
143     if (fRC->isEmpty()) {
144         return false;
145     }
146 
147     SkMatrix inverse;
148     if (!fMatrix->invert(&inverse)) {
149         return false;
150     }
151 
152     SkIRect devBounds = fRC->getBounds();
153     // outset to have slop for antialasing and hairlines
154     devBounds.outset(1, 1);
155     inverse.mapRect(localBounds, SkRect::Make(devBounds));
156     return true;
157 }
158 
159 ///////////////////////////////////////////////////////////////////////////////
160 
161 typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
162 
D_Clear_BitmapXferProc(void * pixels,size_t bytes,uint32_t)163 static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
164     sk_bzero(pixels, bytes);
165 }
166 
D_Dst_BitmapXferProc(void *,size_t,uint32_t data)167 static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
168 
D32_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)169 static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
170     sk_memset32((uint32_t*)pixels, data, bytes >> 2);
171 }
172 
D16_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)173 static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
174     sk_memset16((uint16_t*)pixels, data, bytes >> 1);
175 }
176 
DA8_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)177 static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
178     memset(pixels, data, bytes);
179 }
180 
ChooseBitmapXferProc(const SkBitmap & bitmap,const SkPaint & paint,uint32_t * data)181 static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
182                                            const SkPaint& paint,
183                                            uint32_t* data) {
184     // todo: we can apply colorfilter up front if no shader, so we wouldn't
185     // need to abort this fastpath
186     if (paint.getShader() || paint.getColorFilter()) {
187         return NULL;
188     }
189 
190     SkXfermode::Mode mode;
191     if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
192         return NULL;
193     }
194 
195     SkColor color = paint.getColor();
196 
197     // collaps modes based on color...
198     if (SkXfermode::kSrcOver_Mode == mode) {
199         unsigned alpha = SkColorGetA(color);
200         if (0 == alpha) {
201             mode = SkXfermode::kDst_Mode;
202         } else if (0xFF == alpha) {
203             mode = SkXfermode::kSrc_Mode;
204         }
205     }
206 
207     switch (mode) {
208         case SkXfermode::kClear_Mode:
209 //            SkDebugf("--- D_Clear_BitmapXferProc\n");
210             return D_Clear_BitmapXferProc;  // ignore data
211         case SkXfermode::kDst_Mode:
212 //            SkDebugf("--- D_Dst_BitmapXferProc\n");
213             return D_Dst_BitmapXferProc;    // ignore data
214         case SkXfermode::kSrc_Mode: {
215             /*
216                 should I worry about dithering for the lower depths?
217             */
218             SkPMColor pmc = SkPreMultiplyColor(color);
219             switch (bitmap.config()) {
220                 case SkBitmap::kARGB_8888_Config:
221                     if (data) {
222                         *data = pmc;
223                     }
224 //                    SkDebugf("--- D32_Src_BitmapXferProc\n");
225                     return D32_Src_BitmapXferProc;
226                 case SkBitmap::kRGB_565_Config:
227                     if (data) {
228                         *data = SkPixel32ToPixel16(pmc);
229                     }
230 //                    SkDebugf("--- D16_Src_BitmapXferProc\n");
231                     return D16_Src_BitmapXferProc;
232                 case SkBitmap::kA8_Config:
233                     if (data) {
234                         *data = SkGetPackedA32(pmc);
235                     }
236 //                    SkDebugf("--- DA8_Src_BitmapXferProc\n");
237                     return DA8_Src_BitmapXferProc;
238                 default:
239                     break;
240             }
241             break;
242         }
243         default:
244             break;
245     }
246     return NULL;
247 }
248 
CallBitmapXferProc(const SkBitmap & bitmap,const SkIRect & rect,BitmapXferProc proc,uint32_t procData)249 static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
250                                BitmapXferProc proc, uint32_t procData) {
251     int shiftPerPixel;
252     switch (bitmap.config()) {
253         case SkBitmap::kARGB_8888_Config:
254             shiftPerPixel = 2;
255             break;
256         case SkBitmap::kRGB_565_Config:
257             shiftPerPixel = 1;
258             break;
259         case SkBitmap::kA8_Config:
260             shiftPerPixel = 0;
261             break;
262         default:
263             SkDEBUGFAIL("Can't use xferproc on this config");
264             return;
265     }
266 
267     uint8_t* pixels = (uint8_t*)bitmap.getPixels();
268     SkASSERT(pixels);
269     const size_t rowBytes = bitmap.rowBytes();
270     const int widthBytes = rect.width() << shiftPerPixel;
271 
272     // skip down to the first scanline and X position
273     pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
274     for (int scans = rect.height() - 1; scans >= 0; --scans) {
275         proc(pixels, widthBytes, procData);
276         pixels += rowBytes;
277     }
278 }
279 
drawPaint(const SkPaint & paint) const280 void SkDraw::drawPaint(const SkPaint& paint) const {
281     SkDEBUGCODE(this->validate();)
282 
283     if (fRC->isEmpty()) {
284         return;
285     }
286 
287     SkIRect    devRect;
288     devRect.set(0, 0, fBitmap->width(), fBitmap->height());
289     if (fBounder && !fBounder->doIRect(devRect)) {
290         return;
291     }
292 
293     if (fRC->isBW()) {
294         /*  If we don't have a shader (i.e. we're just a solid color) we may
295             be faster to operate directly on the device bitmap, rather than invoking
296             a blitter. Esp. true for xfermodes, which require a colorshader to be
297             present, which is just redundant work. Since we're drawing everywhere
298             in the clip, we don't have to worry about antialiasing.
299         */
300         uint32_t procData = 0;  // to avoid the warning
301         BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
302         if (proc) {
303             if (D_Dst_BitmapXferProc == proc) { // nothing to do
304                 return;
305             }
306 
307             SkRegion::Iterator iter(fRC->bwRgn());
308             while (!iter.done()) {
309                 CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
310                 iter.next();
311             }
312             return;
313         }
314     }
315 
316     // normal case: use a blitter
317     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
318     SkScan::FillIRect(devRect, *fRC, blitter.get());
319 }
320 
321 ///////////////////////////////////////////////////////////////////////////////
322 
323 struct PtProcRec {
324     SkCanvas::PointMode fMode;
325     const SkPaint*  fPaint;
326     const SkRegion* fClip;
327     const SkRasterClip* fRC;
328 
329     // computed values
330     SkFixed fRadius;
331 
332     typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
333                          SkBlitter*);
334 
335     bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
336               const SkRasterClip*);
337     Proc chooseProc(SkBlitter** blitter);
338 
339 private:
340     SkAAClipBlitterWrapper fWrapper;
341 };
342 
bw_pt_rect_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)343 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
344                                  int count, SkBlitter* blitter) {
345     SkASSERT(rec.fClip->isRect());
346     const SkIRect& r = rec.fClip->getBounds();
347 
348     for (int i = 0; i < count; i++) {
349         int x = SkScalarFloorToInt(devPts[i].fX);
350         int y = SkScalarFloorToInt(devPts[i].fY);
351         if (r.contains(x, y)) {
352             blitter->blitH(x, y, 1);
353         }
354     }
355 }
356 
bw_pt_rect_16_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)357 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
358                                     const SkPoint devPts[], int count,
359                                     SkBlitter* blitter) {
360     SkASSERT(rec.fRC->isRect());
361     const SkIRect& r = rec.fRC->getBounds();
362     uint32_t value;
363     const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
364     SkASSERT(bitmap);
365 
366     uint16_t* addr = bitmap->getAddr16(0, 0);
367     size_t    rb = bitmap->rowBytes();
368 
369     for (int i = 0; i < count; i++) {
370         int x = SkScalarFloorToInt(devPts[i].fX);
371         int y = SkScalarFloorToInt(devPts[i].fY);
372         if (r.contains(x, y)) {
373             ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
374         }
375     }
376 }
377 
bw_pt_rect_32_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)378 static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
379                                     const SkPoint devPts[], int count,
380                                     SkBlitter* blitter) {
381     SkASSERT(rec.fRC->isRect());
382     const SkIRect& r = rec.fRC->getBounds();
383     uint32_t value;
384     const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
385     SkASSERT(bitmap);
386 
387     SkPMColor* addr = bitmap->getAddr32(0, 0);
388     size_t     rb = bitmap->rowBytes();
389 
390     for (int i = 0; i < count; i++) {
391         int x = SkScalarFloorToInt(devPts[i].fX);
392         int y = SkScalarFloorToInt(devPts[i].fY);
393         if (r.contains(x, y)) {
394             ((SkPMColor*)((char*)addr + y * rb))[x] = value;
395         }
396     }
397 }
398 
bw_pt_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)399 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
400                             int count, SkBlitter* blitter) {
401     for (int i = 0; i < count; i++) {
402         int x = SkScalarFloor(devPts[i].fX);
403         int y = SkScalarFloor(devPts[i].fY);
404         if (rec.fClip->contains(x, y)) {
405             blitter->blitH(x, y, 1);
406         }
407     }
408 }
409 
bw_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)410 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
411                               int count, SkBlitter* blitter) {
412     for (int i = 0; i < count; i += 2) {
413         SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
414     }
415 }
416 
bw_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)417 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
418                               int count, SkBlitter* blitter) {
419     for (int i = 0; i < count - 1; i++) {
420         SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
421     }
422 }
423 
424 // aa versions
425 
aa_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)426 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
427                               int count, SkBlitter* blitter) {
428     for (int i = 0; i < count; i += 2) {
429         SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
430     }
431 }
432 
aa_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)433 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
434                               int count, SkBlitter* blitter) {
435     for (int i = 0; i < count - 1; i++) {
436         SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
437     }
438 }
439 
440 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
441 
bw_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)442 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
443                            int count, SkBlitter* blitter) {
444     const SkFixed radius = rec.fRadius;
445     for (int i = 0; i < count; i++) {
446         SkFixed x = SkScalarToFixed(devPts[i].fX);
447         SkFixed y = SkScalarToFixed(devPts[i].fY);
448 
449         SkXRect r;
450         r.fLeft = x - radius;
451         r.fTop = y - radius;
452         r.fRight = x + radius;
453         r.fBottom = y + radius;
454 
455         SkScan::FillXRect(r, *rec.fRC, blitter);
456     }
457 }
458 
aa_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)459 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
460                            int count, SkBlitter* blitter) {
461     const SkFixed radius = rec.fRadius;
462     for (int i = 0; i < count; i++) {
463         SkFixed x = SkScalarToFixed(devPts[i].fX);
464         SkFixed y = SkScalarToFixed(devPts[i].fY);
465 
466         SkXRect r;
467         r.fLeft = x - radius;
468         r.fTop = y - radius;
469         r.fRight = x + radius;
470         r.fBottom = y + radius;
471 
472         SkScan::AntiFillXRect(r, *rec.fRC, blitter);
473     }
474 }
475 
476 // If this guy returns true, then chooseProc() must return a valid proc
init(SkCanvas::PointMode mode,const SkPaint & paint,const SkMatrix * matrix,const SkRasterClip * rc)477 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
478                      const SkMatrix* matrix, const SkRasterClip* rc) {
479     if (paint.getPathEffect()) {
480         return false;
481     }
482     SkScalar width = paint.getStrokeWidth();
483     if (0 == width) {
484         fMode = mode;
485         fPaint = &paint;
486         fClip = NULL;
487         fRC = rc;
488         fRadius = SK_FixedHalf;
489         return true;
490     }
491     if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
492             matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) {
493         SkScalar sx = matrix->get(SkMatrix::kMScaleX);
494         SkScalar sy = matrix->get(SkMatrix::kMScaleY);
495         if (SkScalarNearlyZero(sx - sy)) {
496             if (sx < 0) {
497                 sx = -sx;
498             }
499 
500             fMode = mode;
501             fPaint = &paint;
502             fClip = NULL;
503             fRC = rc;
504             fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
505             return true;
506         }
507     }
508     return false;
509 }
510 
chooseProc(SkBlitter ** blitterPtr)511 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
512     Proc proc = NULL;
513 
514     SkBlitter* blitter = *blitterPtr;
515     if (fRC->isBW()) {
516         fClip = &fRC->bwRgn();
517     } else {
518         fWrapper.init(*fRC, blitter);
519         fClip = &fWrapper.getRgn();
520         blitter = fWrapper.getBlitter();
521         *blitterPtr = blitter;
522     }
523 
524     // for our arrays
525     SkASSERT(0 == SkCanvas::kPoints_PointMode);
526     SkASSERT(1 == SkCanvas::kLines_PointMode);
527     SkASSERT(2 == SkCanvas::kPolygon_PointMode);
528     SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
529 
530     if (fPaint->isAntiAlias()) {
531         if (0 == fPaint->getStrokeWidth()) {
532             static const Proc gAAProcs[] = {
533                 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
534             };
535             proc = gAAProcs[fMode];
536         } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
537             SkASSERT(SkCanvas::kPoints_PointMode == fMode);
538             proc = aa_square_proc;
539         }
540     } else {    // BW
541         if (fRadius <= SK_FixedHalf) {    // small radii and hairline
542             if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
543                 uint32_t value;
544                 const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
545                 if (bm && SkBitmap::kRGB_565_Config == bm->config()) {
546                     proc = bw_pt_rect_16_hair_proc;
547                 } else if (bm && SkBitmap::kARGB_8888_Config == bm->config()) {
548                     proc = bw_pt_rect_32_hair_proc;
549                 } else {
550                     proc = bw_pt_rect_hair_proc;
551                 }
552             } else {
553                 static Proc gBWProcs[] = {
554                     bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
555                 };
556                 proc = gBWProcs[fMode];
557             }
558         } else {
559             proc = bw_square_proc;
560         }
561     }
562     return proc;
563 }
564 
bounder_points(SkBounder * bounder,SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,const SkMatrix & matrix)565 static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
566                            size_t count, const SkPoint pts[],
567                            const SkPaint& paint, const SkMatrix& matrix) {
568     SkIRect ibounds;
569     SkRect bounds;
570     SkScalar inset = paint.getStrokeWidth();
571 
572     bounds.set(pts, count);
573     bounds.inset(-inset, -inset);
574     matrix.mapRect(&bounds);
575 
576     bounds.roundOut(&ibounds);
577     return bounder->doIRect(ibounds);
578 }
579 
580 // each of these costs 8-bytes of stack space, so don't make it too large
581 // must be even for lines/polygon to work
582 #define MAX_DEV_PTS     32
583 
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,bool forceUseDevice) const584 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
585                         const SkPoint pts[], const SkPaint& paint,
586                         bool forceUseDevice) const {
587     // if we're in lines mode, force count to be even
588     if (SkCanvas::kLines_PointMode == mode) {
589         count &= ~(size_t)1;
590     }
591 
592     if ((long)count <= 0) {
593         return;
594     }
595 
596     SkASSERT(pts != NULL);
597     SkDEBUGCODE(this->validate();)
598 
599      // nothing to draw
600     if (fRC->isEmpty()) {
601         return;
602     }
603 
604     if (fBounder) {
605         if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
606             return;
607         }
608 
609         // clear the bounder and call this again, so we don't invoke the bounder
610         // later if we happen to call ourselves for drawRect, drawPath, etc.
611         SkDraw noBounder(*this);
612         noBounder.fBounder = NULL;
613         noBounder.drawPoints(mode, count, pts, paint, forceUseDevice);
614         return;
615     }
616 
617     PtProcRec rec;
618     if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
619         SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
620 
621         SkPoint             devPts[MAX_DEV_PTS];
622         const SkMatrix*     matrix = fMatrix;
623         SkBlitter*          bltr = blitter.get();
624         PtProcRec::Proc     proc = rec.chooseProc(&bltr);
625         // we have to back up subsequent passes if we're in polygon mode
626         const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
627 
628         do {
629             size_t n = count;
630             if (n > MAX_DEV_PTS) {
631                 n = MAX_DEV_PTS;
632             }
633             matrix->mapPoints(devPts, pts, n);
634             proc(rec, devPts, n, bltr);
635             pts += n - backup;
636             SkASSERT(count >= n);
637             count -= n;
638             if (count > 0) {
639                 count += backup;
640             }
641         } while (count != 0);
642     } else {
643         switch (mode) {
644             case SkCanvas::kPoints_PointMode: {
645                 // temporarily mark the paint as filling.
646                 SkPaint newPaint(paint);
647                 newPaint.setStyle(SkPaint::kFill_Style);
648 
649                 SkScalar width = newPaint.getStrokeWidth();
650                 SkScalar radius = SkScalarHalf(width);
651 
652                 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
653                     SkPath      path;
654                     SkMatrix    preMatrix;
655 
656                     path.addCircle(0, 0, radius);
657                     for (size_t i = 0; i < count; i++) {
658                         preMatrix.setTranslate(pts[i].fX, pts[i].fY);
659                         // pass true for the last point, since we can modify
660                         // then path then
661                         if (fDevice) {
662                             fDevice->drawPath(*this, path, newPaint, &preMatrix,
663                                               (count-1) == i);
664                         } else {
665                             this->drawPath(path, newPaint, &preMatrix,
666                                            (count-1) == i);
667                         }
668                     }
669                 } else {
670                     SkRect  r;
671 
672                     for (size_t i = 0; i < count; i++) {
673                         r.fLeft = pts[i].fX - radius;
674                         r.fTop = pts[i].fY - radius;
675                         r.fRight = r.fLeft + width;
676                         r.fBottom = r.fTop + width;
677                         if (fDevice) {
678                             fDevice->drawRect(*this, r, newPaint);
679                         } else {
680                             this->drawRect(r, newPaint);
681                         }
682                     }
683                 }
684                 break;
685             }
686             case SkCanvas::kLines_PointMode:
687 #ifndef SK_DISABLE_DASHING_OPTIMIZATION
688                 if (2 == count && NULL != paint.getPathEffect()) {
689                     // most likely a dashed line - see if it is one of the ones
690                     // we can accelerate
691                     SkStrokeRec rec(paint);
692                     SkPathEffect::PointData pointData;
693 
694                     SkPath path;
695                     path.moveTo(pts[0]);
696                     path.lineTo(pts[1]);
697 
698                     SkRect cullRect = SkRect::Make(fRC->getBounds());
699 
700                     if (paint.getPathEffect()->asPoints(&pointData, path, rec,
701                                                         *fMatrix, &cullRect)) {
702                         // 'asPoints' managed to find some fast path
703 
704                         SkPaint newP(paint);
705                         newP.setPathEffect(NULL);
706                         newP.setStyle(SkPaint::kFill_Style);
707 
708                         if (!pointData.fFirst.isEmpty()) {
709                             if (fDevice) {
710                                 fDevice->drawPath(*this, pointData.fFirst, newP);
711                             } else {
712                                 this->drawPath(pointData.fFirst, newP);
713                             }
714                         }
715 
716                         if (!pointData.fLast.isEmpty()) {
717                             if (fDevice) {
718                                 fDevice->drawPath(*this, pointData.fLast, newP);
719                             } else {
720                                 this->drawPath(pointData.fLast, newP);
721                             }
722                         }
723 
724                         if (pointData.fSize.fX == pointData.fSize.fY) {
725                             // The rest of the dashed line can just be drawn as points
726                             SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
727 
728                             if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
729                                 newP.setStrokeCap(SkPaint::kRound_Cap);
730                             } else {
731                                 newP.setStrokeCap(SkPaint::kButt_Cap);
732                             }
733 
734                             if (fDevice) {
735                                 fDevice->drawPoints(*this,
736                                                     SkCanvas::kPoints_PointMode,
737                                                     pointData.fNumPoints,
738                                                     pointData.fPoints,
739                                                     newP);
740                             } else {
741                                 this->drawPoints(SkCanvas::kPoints_PointMode,
742                                                  pointData.fNumPoints,
743                                                  pointData.fPoints,
744                                                  newP,
745                                                  forceUseDevice);
746                             }
747                             break;
748                         } else {
749                             // The rest of the dashed line must be drawn as rects
750                             SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
751                                       pointData.fFlags));
752 
753                             SkRect r;
754 
755                             for (int i = 0; i < pointData.fNumPoints; ++i) {
756                                 r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
757                                       pointData.fPoints[i].fY - pointData.fSize.fY,
758                                       pointData.fPoints[i].fX + pointData.fSize.fX,
759                                       pointData.fPoints[i].fY + pointData.fSize.fY);
760                                 if (fDevice) {
761                                     fDevice->drawRect(*this, r, newP);
762                                 } else {
763                                     this->drawRect(r, newP);
764                                 }
765                             }
766                         }
767 
768                         break;
769                     }
770                 }
771 #endif // DISABLE_DASHING_OPTIMIZATION
772                 // couldn't take fast path so fall through!
773             case SkCanvas::kPolygon_PointMode: {
774                 count -= 1;
775                 SkPath path;
776                 SkPaint p(paint);
777                 p.setStyle(SkPaint::kStroke_Style);
778                 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
779                 for (size_t i = 0; i < count; i += inc) {
780                     path.moveTo(pts[i]);
781                     path.lineTo(pts[i+1]);
782                     if (fDevice) {
783                         fDevice->drawPath(*this, path, p, NULL, true);
784                     } else {
785                         this->drawPath(path, p, NULL, true);
786                     }
787                     path.rewind();
788                 }
789                 break;
790             }
791         }
792     }
793 }
794 
easy_rect_join(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)795 static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
796                            SkPoint* strokeSize) {
797     if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
798         paint.getStrokeMiter() < SK_ScalarSqrt2) {
799         return false;
800     }
801 
802     SkASSERT(matrix.rectStaysRect());
803     SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
804     matrix.mapVectors(strokeSize, &pt, 1);
805     strokeSize->fX = SkScalarAbs(strokeSize->fX);
806     strokeSize->fY = SkScalarAbs(strokeSize->fY);
807     return true;
808 }
809 
ComputeRectType(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)810 SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
811                                          const SkMatrix& matrix,
812                                          SkPoint* strokeSize) {
813     RectType rtype;
814     const SkScalar width = paint.getStrokeWidth();
815     const bool zeroWidth = (0 == width);
816     SkPaint::Style style = paint.getStyle();
817 
818     if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
819         style = SkPaint::kFill_Style;
820     }
821 
822     if (paint.getPathEffect() || paint.getMaskFilter() ||
823         paint.getRasterizer() || !matrix.rectStaysRect() ||
824         SkPaint::kStrokeAndFill_Style == style) {
825         rtype = kPath_RectType;
826     } else if (SkPaint::kFill_Style == style) {
827         rtype = kFill_RectType;
828     } else if (zeroWidth) {
829         rtype = kHair_RectType;
830     } else if (easy_rect_join(paint, matrix, strokeSize)) {
831         rtype = kStroke_RectType;
832     } else {
833         rtype = kPath_RectType;
834     }
835     return rtype;
836 }
837 
rect_points(const SkRect & r)838 static const SkPoint* rect_points(const SkRect& r) {
839     return SkTCast<const SkPoint*>(&r);
840 }
841 
rect_points(SkRect & r)842 static SkPoint* rect_points(SkRect& r) {
843     return SkTCast<SkPoint*>(&r);
844 }
845 
drawRect(const SkRect & rect,const SkPaint & paint) const846 void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
847     SkDEBUGCODE(this->validate();)
848 
849     // nothing to draw
850     if (fRC->isEmpty()) {
851         return;
852     }
853 
854     SkPoint strokeSize;
855     RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
856 
857     if (kPath_RectType == rtype) {
858         SkPath  tmp;
859         tmp.addRect(rect);
860         tmp.setFillType(SkPath::kWinding_FillType);
861         this->drawPath(tmp, paint, NULL, true);
862         return;
863     }
864 
865     const SkMatrix& matrix = *fMatrix;
866     SkRect          devRect;
867 
868     // transform rect into devRect
869     matrix.mapPoints(rect_points(devRect), rect_points(rect), 2);
870     devRect.sort();
871 
872     if (fBounder && !fBounder->doRect(devRect, paint)) {
873         return;
874     }
875 
876     // look for the quick exit, before we build a blitter
877     SkIRect ir;
878     devRect.roundOut(&ir);
879     if (paint.getStyle() != SkPaint::kFill_Style) {
880         // extra space for hairlines
881         ir.inset(-1, -1);
882     }
883     if (fRC->quickReject(ir)) {
884         return;
885     }
886 
887     SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
888     while (looper.next()) {
889         SkRect localDevRect;
890         looper.mapRect(&localDevRect, devRect);
891         SkMatrix localMatrix;
892         looper.mapMatrix(&localMatrix, matrix);
893 
894         SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix,
895                                            paint);
896         const SkRasterClip& clip = looper.getRC();
897         SkBlitter*          blitter = blitterStorage.get();
898 
899         // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
900         // case we are also hairline (if we've gotten to here), which devolves to
901         // effectively just kFill
902         switch (rtype) {
903             case kFill_RectType:
904                 if (paint.isAntiAlias()) {
905                     SkScan::AntiFillRect(localDevRect, clip, blitter);
906                 } else {
907                     SkScan::FillRect(localDevRect, clip, blitter);
908                 }
909                 break;
910             case kStroke_RectType:
911                 if (paint.isAntiAlias()) {
912                     SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
913                 } else {
914                     SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
915                 }
916                 break;
917             case kHair_RectType:
918                 if (paint.isAntiAlias()) {
919                     SkScan::AntiHairRect(localDevRect, clip, blitter);
920                 } else {
921                     SkScan::HairRect(localDevRect, clip, blitter);
922                 }
923                 break;
924             default:
925                 SkDEBUGFAIL("bad rtype");
926         }
927     }
928 }
929 
drawDevMask(const SkMask & srcM,const SkPaint & paint) const930 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
931     if (srcM.fBounds.isEmpty()) {
932         return;
933     }
934 
935     const SkMask* mask = &srcM;
936 
937     SkMask dstM;
938     if (paint.getMaskFilter() &&
939             paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
940         mask = &dstM;
941     } else {
942         dstM.fImage = NULL;
943     }
944     SkAutoMaskFreeImage ami(dstM.fImage);
945 
946     if (fBounder && !fBounder->doIRect(mask->fBounds)) {
947         return;
948     }
949 
950     SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
951     SkBlitter* blitter = blitterChooser.get();
952 
953     SkAAClipBlitterWrapper wrapper;
954     const SkRegion* clipRgn;
955 
956     if (fRC->isBW()) {
957         clipRgn = &fRC->bwRgn();
958     } else {
959         wrapper.init(*fRC, blitter);
960         clipRgn = &wrapper.getRgn();
961         blitter = wrapper.getBlitter();
962     }
963     blitter->blitMaskRegion(*mask, *clipRgn);
964 }
965 
fast_len(const SkVector & vec)966 static SkScalar fast_len(const SkVector& vec) {
967     SkScalar x = SkScalarAbs(vec.fX);
968     SkScalar y = SkScalarAbs(vec.fY);
969     if (x < y) {
970         SkTSwap(x, y);
971     }
972     return x + SkScalarHalf(y);
973 }
974 
xfermodeSupportsCoverageAsAlpha(SkXfermode * xfer)975 static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
976     SkXfermode::Coeff dc;
977     if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) {
978         return false;
979     }
980 
981     switch (dc) {
982         case SkXfermode::kOne_Coeff:
983         case SkXfermode::kISA_Coeff:
984         case SkXfermode::kISC_Coeff:
985             return true;
986         default:
987             return false;
988     }
989 }
990 
SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth,const SkMatrix & matrix,SkScalar * coverage)991 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
992                                    SkScalar* coverage) {
993     SkASSERT(strokeWidth > 0);
994     // We need to try to fake a thick-stroke with a modulated hairline.
995 
996     if (matrix.hasPerspective()) {
997         return false;
998     }
999 
1000     SkVector src[2], dst[2];
1001     src[0].set(strokeWidth, 0);
1002     src[1].set(0, strokeWidth);
1003     matrix.mapVectors(dst, src, 2);
1004     SkScalar len0 = fast_len(dst[0]);
1005     SkScalar len1 = fast_len(dst[1]);
1006     if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
1007         if (NULL != coverage) {
1008             *coverage = SkScalarAve(len0, len1);
1009         }
1010         return true;
1011     }
1012     return false;
1013 }
1014 
drawRRect(const SkRRect & rrect,const SkPaint & paint) const1015 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
1016     SkDEBUGCODE(this->validate());
1017 
1018     if (fRC->isEmpty()) {
1019         return;
1020     }
1021 
1022     {
1023         // TODO: Investigate optimizing these options. They are in the same
1024         // order as SkDraw::drawPath, which handles each case. It may be
1025         // that there is no way to optimize for these using the SkRRect path.
1026         SkScalar coverage;
1027         if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
1028             goto DRAW_PATH;
1029         }
1030 
1031         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
1032             goto DRAW_PATH;
1033         }
1034 
1035         if (paint.getRasterizer()) {
1036             goto DRAW_PATH;
1037         }
1038     }
1039 
1040     if (paint.getMaskFilter()) {
1041         // Transform the rrect into device space.
1042         SkRRect devRRect;
1043         if (rrect.transform(*fMatrix, &devRRect)) {
1044             SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1045             if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC,
1046                                                    fBounder, blitter.get(),
1047                                                    SkPaint::kFill_Style)) {
1048                 return; // filterRRect() called the blitter, so we're done
1049             }
1050         }
1051     }
1052 
1053 DRAW_PATH:
1054     // Now fall back to the default case of using a path.
1055     SkPath path;
1056     path.addRRect(rrect);
1057     this->drawPath(path, paint, NULL, true);
1058 }
1059 
drawPath(const SkPath & origSrcPath,const SkPaint & origPaint,const SkMatrix * prePathMatrix,bool pathIsMutable,bool drawCoverage) const1060 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
1061                       const SkMatrix* prePathMatrix, bool pathIsMutable,
1062                       bool drawCoverage) const {
1063     SkDEBUGCODE(this->validate();)
1064 
1065     // nothing to draw
1066     if (fRC->isEmpty()) {
1067         return;
1068     }
1069 
1070     SkPath*         pathPtr = (SkPath*)&origSrcPath;
1071     bool            doFill = true;
1072     SkPath          tmpPath;
1073     SkMatrix        tmpMatrix;
1074     const SkMatrix* matrix = fMatrix;
1075 
1076     if (prePathMatrix) {
1077         if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
1078                 origPaint.getRasterizer()) {
1079             SkPath* result = pathPtr;
1080 
1081             if (!pathIsMutable) {
1082                 result = &tmpPath;
1083                 pathIsMutable = true;
1084             }
1085             pathPtr->transform(*prePathMatrix, result);
1086             pathPtr = result;
1087         } else {
1088             if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
1089                 // overflow
1090                 return;
1091             }
1092             matrix = &tmpMatrix;
1093         }
1094     }
1095     // at this point we're done with prePathMatrix
1096     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1097 
1098     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1099 
1100     {
1101         SkScalar coverage;
1102         if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1103             if (SK_Scalar1 == coverage) {
1104                 paint.writable()->setStrokeWidth(0);
1105             } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
1106                 U8CPU newAlpha;
1107 #if 0
1108                 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1109                                                      origPaint.getAlpha()));
1110 #else
1111                 // this is the old technique, which we preserve for now so
1112                 // we don't change previous results (testing)
1113                 // the new way seems fine, its just (a tiny bit) different
1114                 int scale = (int)SkScalarMul(coverage, 256);
1115                 newAlpha = origPaint.getAlpha() * scale >> 8;
1116 #endif
1117                 SkPaint* writablePaint = paint.writable();
1118                 writablePaint->setStrokeWidth(0);
1119                 writablePaint->setAlpha(newAlpha);
1120             }
1121         }
1122     }
1123 
1124     if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1125         SkRect cullRect;
1126         const SkRect* cullRectPtr = NULL;
1127         if (this->computeConservativeLocalClipBounds(&cullRect)) {
1128             cullRectPtr = &cullRect;
1129         }
1130         doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
1131         pathPtr = &tmpPath;
1132     }
1133 
1134     if (paint->getRasterizer()) {
1135         SkMask  mask;
1136         if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1137                             &fRC->getBounds(), paint->getMaskFilter(), &mask,
1138                             SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1139             this->drawDevMask(mask, *paint);
1140             SkMask::FreeImage(mask.fImage);
1141         }
1142         return;
1143     }
1144 
1145     // avoid possibly allocating a new path in transform if we can
1146     SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1147 
1148     // transform the path into device space
1149     pathPtr->transform(*matrix, devPathPtr);
1150 
1151     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage);
1152 
1153     if (paint->getMaskFilter()) {
1154         SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1155             SkPaint::kStroke_Style;
1156         if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
1157                                                fBounder, blitter.get(),
1158                                                style)) {
1159             return; // filterPath() called the blitter, so we're done
1160         }
1161     }
1162 
1163     if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
1164         return;
1165     }
1166 
1167     void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1168     if (doFill) {
1169         if (paint->isAntiAlias()) {
1170             proc = SkScan::AntiFillPath;
1171         } else {
1172             proc = SkScan::FillPath;
1173         }
1174     } else {    // hairline
1175         if (paint->isAntiAlias()) {
1176             proc = SkScan::AntiHairPath;
1177         } else {
1178             proc = SkScan::HairPath;
1179         }
1180     }
1181     proc(*devPathPtr, *fRC, blitter.get());
1182 }
1183 
1184 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1185     go ahead and treat it as if it were, so that subsequent code can go fast.
1186  */
just_translate(const SkMatrix & matrix,const SkBitmap & bitmap)1187 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1188     unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
1189                         // respect filtering.
1190     return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1191 }
1192 
drawBitmapAsMask(const SkBitmap & bitmap,const SkPaint & paint) const1193 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1194                               const SkPaint& paint) const {
1195     SkASSERT(bitmap.config() == SkBitmap::kA8_Config);
1196 
1197     if (just_translate(*fMatrix, bitmap)) {
1198         int ix = SkScalarRound(fMatrix->getTranslateX());
1199         int iy = SkScalarRound(fMatrix->getTranslateY());
1200 
1201         SkAutoLockPixels alp(bitmap);
1202         if (!bitmap.readyToDraw()) {
1203             return;
1204         }
1205 
1206         SkMask  mask;
1207         mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1208         mask.fFormat = SkMask::kA8_Format;
1209         mask.fRowBytes = SkToU32(bitmap.rowBytes());
1210         mask.fImage = bitmap.getAddr8(0, 0);
1211 
1212         this->drawDevMask(mask, paint);
1213     } else {    // need to xform the bitmap first
1214         SkRect  r;
1215         SkMask  mask;
1216 
1217         r.set(0, 0,
1218               SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1219         fMatrix->mapRect(&r);
1220         r.round(&mask.fBounds);
1221 
1222         // set the mask's bounds to the transformed bitmap-bounds,
1223         // clipped to the actual device
1224         {
1225             SkIRect    devBounds;
1226             devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1227             // need intersect(l, t, r, b) on irect
1228             if (!mask.fBounds.intersect(devBounds)) {
1229                 return;
1230             }
1231         }
1232 
1233         mask.fFormat = SkMask::kA8_Format;
1234         mask.fRowBytes = SkAlign4(mask.fBounds.width());
1235         size_t size = mask.computeImageSize();
1236         if (0 == size) {
1237             // the mask is too big to allocated, draw nothing
1238             return;
1239         }
1240 
1241         // allocate (and clear) our temp buffer to hold the transformed bitmap
1242         SkAutoMalloc    storage(size);
1243         mask.fImage = (uint8_t*)storage.get();
1244         memset(mask.fImage, 0, size);
1245 
1246         // now draw our bitmap(src) into mask(dst), transformed by the matrix
1247         {
1248             SkBitmap    device;
1249             device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
1250                              mask.fBounds.height(), mask.fRowBytes);
1251             device.setPixels(mask.fImage);
1252 
1253             SkCanvas c(device);
1254             // need the unclipped top/left for the translate
1255             c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1256                         -SkIntToScalar(mask.fBounds.fTop));
1257             c.concat(*fMatrix);
1258 
1259             // We can't call drawBitmap, or we'll infinitely recurse. Instead
1260             // we manually build a shader and draw that into our new mask
1261             SkPaint tmpPaint;
1262             tmpPaint.setFlags(paint.getFlags());
1263             SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1264             SkRect rr;
1265             rr.set(0, 0, SkIntToScalar(bitmap.width()),
1266                    SkIntToScalar(bitmap.height()));
1267             c.drawRect(rr, install.paintWithShader());
1268         }
1269         this->drawDevMask(mask, paint);
1270     }
1271 }
1272 
clipped_out(const SkMatrix & m,const SkRasterClip & c,const SkRect & srcR)1273 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1274                         const SkRect& srcR) {
1275     SkRect  dstR;
1276     SkIRect devIR;
1277 
1278     m.mapRect(&dstR, srcR);
1279     dstR.roundOut(&devIR);
1280     return c.quickReject(devIR);
1281 }
1282 
clipped_out(const SkMatrix & matrix,const SkRasterClip & clip,int width,int height)1283 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1284                         int width, int height) {
1285     SkRect  r;
1286     r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1287     return clipped_out(matrix, clip, r);
1288 }
1289 
clipHandlesSprite(const SkRasterClip & clip,int x,int y,const SkBitmap & bitmap)1290 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1291                               const SkBitmap& bitmap) {
1292     return clip.isBW() ||
1293            clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1294 }
1295 
drawBitmap(const SkBitmap & bitmap,const SkMatrix & prematrix,const SkPaint & origPaint) const1296 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1297                         const SkPaint& origPaint) const {
1298     SkDEBUGCODE(this->validate();)
1299 
1300     // nothing to draw
1301     if (fRC->isEmpty() ||
1302             bitmap.width() == 0 || bitmap.height() == 0 ||
1303             bitmap.config() == SkBitmap::kNo_Config) {
1304         return;
1305     }
1306 
1307     SkPaint paint(origPaint);
1308     paint.setStyle(SkPaint::kFill_Style);
1309 
1310     SkMatrix matrix;
1311     if (!matrix.setConcat(*fMatrix, prematrix)) {
1312         return;
1313     }
1314 
1315     if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1316         return;
1317     }
1318 
1319     if (fBounder && just_translate(matrix, bitmap)) {
1320         SkIRect ir;
1321         int32_t ix = SkScalarRound(matrix.getTranslateX());
1322         int32_t iy = SkScalarRound(matrix.getTranslateY());
1323         ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1324         if (!fBounder->doIRect(ir)) {
1325             return;
1326         }
1327     }
1328 
1329     if (bitmap.config() != SkBitmap::kA8_Config &&
1330             just_translate(matrix, bitmap)) {
1331         //
1332         // It is safe to call lock pixels now, since we know the matrix is
1333         // (more or less) identity.
1334         //
1335         SkAutoLockPixels alp(bitmap);
1336         if (!bitmap.readyToDraw()) {
1337             return;
1338         }
1339         int ix = SkScalarRound(matrix.getTranslateX());
1340         int iy = SkScalarRound(matrix.getTranslateY());
1341         if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1342             uint32_t    storage[kBlitterStorageLongCount];
1343             SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1344                                                 ix, iy, storage, sizeof(storage));
1345             if (blitter) {
1346                 SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
1347 
1348                 SkIRect    ir;
1349                 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1350 
1351                 SkScan::FillIRect(ir, *fRC, blitter);
1352                 return;
1353             }
1354         }
1355     }
1356 
1357     // now make a temp draw on the stack, and use it
1358     //
1359     SkDraw draw(*this);
1360     draw.fMatrix = &matrix;
1361 
1362     if (bitmap.config() == SkBitmap::kA8_Config) {
1363         draw.drawBitmapAsMask(bitmap, paint);
1364     } else {
1365         SkAutoBitmapShaderInstall install(bitmap, paint);
1366 
1367         SkRect  r;
1368         r.set(0, 0, SkIntToScalar(bitmap.width()),
1369               SkIntToScalar(bitmap.height()));
1370         // is this ok if paint has a rasterizer?
1371         draw.drawRect(r, install.paintWithShader());
1372     }
1373 }
1374 
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint & origPaint) const1375 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1376                         const SkPaint& origPaint) const {
1377     SkDEBUGCODE(this->validate();)
1378 
1379     // nothing to draw
1380     if (fRC->isEmpty() ||
1381             bitmap.width() == 0 || bitmap.height() == 0 ||
1382             bitmap.config() == SkBitmap::kNo_Config) {
1383         return;
1384     }
1385 
1386     SkIRect    bounds;
1387     bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1388 
1389     if (fRC->quickReject(bounds)) {
1390         return; // nothing to draw
1391     }
1392 
1393     SkPaint paint(origPaint);
1394     paint.setStyle(SkPaint::kFill_Style);
1395 
1396     if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1397         uint32_t    storage[kBlitterStorageLongCount];
1398         SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1399                                                 x, y, storage, sizeof(storage));
1400 
1401         if (blitter) {
1402             SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1403 
1404             if (fBounder && !fBounder->doIRect(bounds)) {
1405                 return;
1406             }
1407 
1408             SkScan::FillIRect(bounds, *fRC, blitter);
1409             return;
1410         }
1411     }
1412 
1413     SkAutoBitmapShaderInstall install(bitmap, paint);
1414     const SkPaint& shaderPaint = install.paintWithShader();
1415 
1416     SkMatrix        matrix;
1417     SkRect          r;
1418 
1419     // get a scalar version of our rect
1420     r.set(bounds);
1421 
1422     // tell the shader our offset
1423     matrix.setTranslate(r.fLeft, r.fTop);
1424     shaderPaint.getShader()->setLocalMatrix(matrix);
1425 
1426     SkDraw draw(*this);
1427     matrix.reset();
1428     draw.fMatrix = &matrix;
1429     // call ourself with a rect
1430     // is this OK if paint has a rasterizer?
1431     draw.drawRect(r, shaderPaint);
1432 }
1433 
1434 ///////////////////////////////////////////////////////////////////////////////
1435 
1436 #include "SkScalerContext.h"
1437 #include "SkGlyphCache.h"
1438 #include "SkTextToPathIter.h"
1439 #include "SkUtils.h"
1440 
measure_text(SkGlyphCache * cache,SkDrawCacheProc glyphCacheProc,const char text[],size_t byteLength,SkVector * stopVector)1441 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1442                 const char text[], size_t byteLength, SkVector* stopVector) {
1443     SkFixed     x = 0, y = 0;
1444     const char* stop = text + byteLength;
1445 
1446     SkAutoKern  autokern;
1447 
1448     while (text < stop) {
1449         // don't need x, y here, since all subpixel variants will have the
1450         // same advance
1451         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1452 
1453         x += autokern.adjust(glyph) + glyph.fAdvanceX;
1454         y += glyph.fAdvanceY;
1455     }
1456     stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1457 
1458     SkASSERT(text == stop);
1459 }
1460 
drawText_asPaths(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1462                               SkScalar x, SkScalar y,
1463                               const SkPaint& paint) const {
1464     SkDEBUGCODE(this->validate();)
1465 
1466     SkTextToPathIter iter(text, byteLength, paint, true);
1467 
1468     SkMatrix    matrix;
1469     matrix.setScale(iter.getPathScale(), iter.getPathScale());
1470     matrix.postTranslate(x, y);
1471 
1472     const SkPath* iterPath;
1473     SkScalar xpos, prevXPos = 0;
1474 
1475     while (iter.next(&iterPath, &xpos)) {
1476         matrix.postTranslate(xpos - prevXPos, 0);
1477         if (iterPath) {
1478             const SkPaint& pnt = iter.getPaint();
1479             if (fDevice) {
1480                 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1481             } else {
1482                 this->drawPath(*iterPath, pnt, &matrix, false);
1483             }
1484         }
1485         prevXPos = xpos;
1486     }
1487 }
1488 
1489 // disable warning : local variable used without having been initialized
1490 #if defined _WIN32 && _MSC_VER >= 1300
1491 #pragma warning ( push )
1492 #pragma warning ( disable : 4701 )
1493 #endif
1494 
1495 //////////////////////////////////////////////////////////////////////////////
1496 
D1G_NoBounder_RectClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1497 static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1498                                    SkFixed fx, SkFixed fy,
1499                                    const SkGlyph& glyph) {
1500     int left = SkFixedFloor(fx);
1501     int top = SkFixedFloor(fy);
1502     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1503     SkASSERT(NULL == state.fBounder);
1504     SkASSERT((NULL == state.fClip && state.fAAClip) ||
1505              (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1506 
1507     left += glyph.fLeft;
1508     top  += glyph.fTop;
1509 
1510     int right   = left + glyph.fWidth;
1511     int bottom  = top + glyph.fHeight;
1512 
1513     SkMask        mask;
1514     SkIRect        storage;
1515     SkIRect*    bounds = &mask.fBounds;
1516 
1517     mask.fBounds.set(left, top, right, bottom);
1518 
1519     // this extra test is worth it, assuming that most of the time it succeeds
1520     // since we can avoid writing to storage
1521     if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1522         if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1523             return;
1524         bounds = &storage;
1525     }
1526 
1527     uint8_t* aa = (uint8_t*)glyph.fImage;
1528     if (NULL == aa) {
1529         aa = (uint8_t*)state.fCache->findImage(glyph);
1530         if (NULL == aa) {
1531             return; // can't rasterize glyph
1532         }
1533     }
1534 
1535     mask.fRowBytes = glyph.rowBytes();
1536     mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1537     mask.fImage = aa;
1538     state.blitMask(mask, *bounds);
1539 }
1540 
D1G_NoBounder_RgnClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1541 static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1542                                   SkFixed fx, SkFixed fy,
1543                                   const SkGlyph& glyph) {
1544     int left = SkFixedFloor(fx);
1545     int top = SkFixedFloor(fy);
1546     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1547     SkASSERT(!state.fClip->isRect());
1548     SkASSERT(NULL == state.fBounder);
1549 
1550     SkMask  mask;
1551 
1552     left += glyph.fLeft;
1553     top  += glyph.fTop;
1554 
1555     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1556     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1557 
1558     if (!clipper.done()) {
1559         const SkIRect&  cr = clipper.rect();
1560         const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1561         if (NULL == aa) {
1562             aa = (uint8_t*)state.fCache->findImage(glyph);
1563             if (NULL == aa) {
1564                 return;
1565             }
1566         }
1567 
1568         mask.fRowBytes = glyph.rowBytes();
1569         mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1570         mask.fImage = (uint8_t*)aa;
1571         do {
1572             state.blitMask(mask, cr);
1573             clipper.next();
1574         } while (!clipper.done());
1575     }
1576 }
1577 
D1G_Bounder(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1578 static void D1G_Bounder(const SkDraw1Glyph& state,
1579                         SkFixed fx, SkFixed fy,
1580                         const SkGlyph& glyph) {
1581     int left = SkFixedFloor(fx);
1582     int top = SkFixedFloor(fy);
1583     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1584 
1585     SkMask  mask;
1586 
1587     left += glyph.fLeft;
1588     top  += glyph.fTop;
1589 
1590     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1591     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1592 
1593     if (!clipper.done()) {
1594         const SkIRect&  cr = clipper.rect();
1595         const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1596         if (NULL == aa) {
1597             aa = (uint8_t*)state.fCache->findImage(glyph);
1598             if (NULL == aa) {
1599                 return;
1600             }
1601         }
1602 
1603         // we need to pass the origin, which we approximate with our
1604         // (unadjusted) left,top coordinates (the caller called fixedfloor)
1605         if (state.fBounder->doIRectGlyph(cr,
1606                                          left - glyph.fLeft,
1607                                          top - glyph.fTop, glyph)) {
1608             mask.fRowBytes = glyph.rowBytes();
1609             mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1610             mask.fImage = (uint8_t*)aa;
1611             do {
1612                 state.blitMask(mask, cr);
1613                 clipper.next();
1614             } while (!clipper.done());
1615         }
1616     }
1617 }
1618 
D1G_Bounder_AAClip(const SkDraw1Glyph & state,SkFixed fx,SkFixed fy,const SkGlyph & glyph)1619 static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
1620                                SkFixed fx, SkFixed fy,
1621                                const SkGlyph& glyph) {
1622     int left = SkFixedFloor(fx);
1623     int top = SkFixedFloor(fy);
1624     SkIRect bounds;
1625     bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1626 
1627     if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
1628         D1G_NoBounder_RectClip(state, fx, fy, glyph);
1629     }
1630 }
1631 
hasCustomD1GProc(const SkDraw & draw)1632 static bool hasCustomD1GProc(const SkDraw& draw) {
1633     return draw.fProcs && draw.fProcs->fD1GProc;
1634 }
1635 
needsRasterTextBlit(const SkDraw & draw)1636 static bool needsRasterTextBlit(const SkDraw& draw) {
1637     return !hasCustomD1GProc(draw);
1638 }
1639 
init(const SkDraw * draw,SkBlitter * blitter,SkGlyphCache * cache,const SkPaint & pnt)1640 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1641                                       SkGlyphCache* cache, const SkPaint& pnt) {
1642     fDraw = draw;
1643     fBounder = draw->fBounder;
1644     fBlitter = blitter;
1645     fCache = cache;
1646     fPaint = &pnt;
1647 
1648     if (cache->isSubpixel()) {
1649         fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
1650     } else {
1651         fHalfSampleX = fHalfSampleY = SK_FixedHalf;
1652     }
1653 
1654     if (hasCustomD1GProc(*draw)) {
1655         // todo: fix this assumption about clips w/ custom
1656         fClip = draw->fClip;
1657         fClipBounds = fClip->getBounds();
1658         return draw->fProcs->fD1GProc;
1659     }
1660 
1661     if (draw->fRC->isBW()) {
1662         fAAClip = NULL;
1663         fClip = &draw->fRC->bwRgn();
1664         fClipBounds = fClip->getBounds();
1665         if (NULL == fBounder) {
1666             if (fClip->isRect()) {
1667                 return D1G_NoBounder_RectClip;
1668             } else {
1669                 return D1G_NoBounder_RgnClip;
1670             }
1671         } else {
1672             return D1G_Bounder;
1673         }
1674     } else {    // aaclip
1675         fAAClip = &draw->fRC->aaRgn();
1676         fClip = NULL;
1677         fClipBounds = fAAClip->getBounds();
1678         if (NULL == fBounder) {
1679             return D1G_NoBounder_RectClip;
1680         } else {
1681             return D1G_Bounder_AAClip;
1682         }
1683     }
1684 }
1685 
blitMaskAsSprite(const SkMask & mask) const1686 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1687     SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1688 
1689     SkBitmap bm;
1690     bm.setConfig(SkBitmap::kARGB_8888_Config,
1691                  mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
1692     bm.setPixels((SkPMColor*)mask.fImage);
1693 
1694     fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1695 }
1696 
1697 ///////////////////////////////////////////////////////////////////////////////
1698 
drawText(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1699 void SkDraw::drawText(const char text[], size_t byteLength,
1700                       SkScalar x, SkScalar y, const SkPaint& paint) const {
1701     SkASSERT(byteLength == 0 || text != NULL);
1702 
1703     SkDEBUGCODE(this->validate();)
1704 
1705     // nothing to draw
1706     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1707         return;
1708     }
1709 
1710     // SkScalarRec doesn't currently have a way of representing hairline stroke and
1711     // will fill if its frame-width is 0.
1712     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1713         this->drawText_asPaths(text, byteLength, x, y, paint);
1714         return;
1715     }
1716 
1717     SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1718 
1719 #if SK_DISTANCEFIELD_FONTS
1720     const SkMatrix* ctm = fMatrix;
1721     const SkPaint* paintRef = &paint;
1722     SkPaint paintCopy;
1723     uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
1724     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1725         paintCopy = paint;
1726         paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
1727         paintCopy.setLCDRenderText(false);
1728         paintRef = &paintCopy;
1729     }
1730     if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
1731         ctm = NULL;
1732     }
1733     SkAutoGlyphCache    autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
1734 #else
1735     SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1736 #endif
1737     SkGlyphCache*       cache = autoCache.getCache();
1738 
1739     // transform our starting point
1740 #if SK_DISTANCEFIELD_FONTS
1741     if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag))
1742 #endif
1743     {
1744         SkPoint loc;
1745         fMatrix->mapXY(x, y, &loc);
1746         x = loc.fX;
1747         y = loc.fY;
1748     }
1749 
1750     // need to measure first
1751     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1752         SkVector    stop;
1753 
1754         measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1755 
1756         SkScalar    stopX = stop.fX;
1757         SkScalar    stopY = stop.fY;
1758 
1759         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1760             stopX = SkScalarHalf(stopX);
1761             stopY = SkScalarHalf(stopY);
1762         }
1763         x -= stopX;
1764         y -= stopY;
1765     }
1766 
1767     const char* stop = text + byteLength;
1768 
1769     SkAAClipBlitter     aaBlitter;
1770     SkAutoBlitterChoose blitterChooser;
1771     SkBlitter*          blitter = NULL;
1772     if (needsRasterTextBlit(*this)) {
1773         blitterChooser.choose(*fBitmap, *fMatrix, paint);
1774         blitter = blitterChooser.get();
1775         if (fRC->isAA()) {
1776             aaBlitter.init(blitter, &fRC->aaRgn());
1777             blitter = &aaBlitter;
1778         }
1779     }
1780 
1781     SkAutoKern          autokern;
1782     SkDraw1Glyph        d1g;
1783     SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
1784 
1785     SkFixed fxMask = ~0;
1786     SkFixed fyMask = ~0;
1787     if (cache->isSubpixel()) {
1788         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1789         if (kX_SkAxisAlignment == baseline) {
1790             fyMask = 0;
1791             d1g.fHalfSampleY = SK_FixedHalf;
1792         } else if (kY_SkAxisAlignment == baseline) {
1793             fxMask = 0;
1794             d1g.fHalfSampleX = SK_FixedHalf;
1795         }
1796     }
1797 
1798     SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
1799     SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
1800 
1801 #if SK_DISTANCEFIELD_FONTS
1802     SkFixed fixedScale;
1803     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1804         fixedScale = SkScalarToFixed(paint.getTextSize()/(float)SkDrawProcs::kBaseDFFontSize);
1805     }
1806 #endif
1807     while (text < stop) {
1808         const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1809 
1810 #if SK_DISTANCEFIELD_FONTS
1811         if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1812             fx += SkFixedMul_portable(autokern.adjust(glyph), fixedScale);
1813         } else {
1814             fx += autokern.adjust(glyph);
1815         }
1816 #else
1817         fx += autokern.adjust(glyph);
1818 #endif
1819 
1820         if (glyph.fWidth) {
1821             proc(d1g, fx, fy, glyph);
1822         }
1823 
1824 #if SK_DISTANCEFIELD_FONTS
1825         if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
1826             fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
1827             fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
1828         } else {
1829             fx += glyph.fAdvanceX;
1830             fy += glyph.fAdvanceY;
1831         }
1832 #else
1833         fx += glyph.fAdvanceX;
1834         fy += glyph.fAdvanceY;
1835 #endif
1836     }
1837 }
1838 
1839 // last parameter is interpreted as SkFixed [x, y]
1840 // return the fixed position, which may be rounded or not by the caller
1841 //   e.g. subpixel doesn't round
1842 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1843 
leftAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1844 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1845     dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1846 }
1847 
centerAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1848 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1849     dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1850              SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1851 }
1852 
rightAlignProc(const SkPoint & loc,const SkGlyph & glyph,SkIPoint * dst)1853 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1854     dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1855              SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1856 }
1857 
pick_align_proc(SkPaint::Align align)1858 static AlignProc pick_align_proc(SkPaint::Align align) {
1859     static const AlignProc gProcs[] = {
1860         leftAlignProc, centerAlignProc, rightAlignProc
1861     };
1862 
1863     SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1864 
1865     return gProcs[align];
1866 }
1867 
1868 typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
1869 
leftAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1870 static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1871     dst->set(loc.fX, loc.fY);
1872 }
1873 
centerAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1874 static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1875     dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
1876              loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
1877 }
1878 
rightAlignProc_scalar(const SkPoint & loc,const SkGlyph & glyph,SkPoint * dst)1879 static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1880     dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
1881              loc.fY - SkFixedToScalar(glyph.fAdvanceY));
1882 }
1883 
pick_align_proc_scalar(SkPaint::Align align)1884 static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
1885     static const AlignProc_scalar gProcs[] = {
1886         leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
1887     };
1888 
1889     SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1890 
1891     return gProcs[align];
1892 }
1893 
1894 class TextMapState {
1895 public:
1896     mutable SkPoint fLoc;
1897 
TextMapState(const SkMatrix & matrix,SkScalar y)1898     TextMapState(const SkMatrix& matrix, SkScalar y)
1899         : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1900 
1901     typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1902 
1903     Proc pickProc(int scalarsPerPosition);
1904 
1905 private:
1906     const SkMatrix&     fMatrix;
1907     SkMatrix::MapXYProc fProc;
1908     SkScalar            fY; // ignored by MapXYProc
1909     // these are only used by Only... procs
1910     SkScalar            fScaleX, fTransX, fTransformedY;
1911 
MapXProc(const TextMapState & state,const SkScalar pos[])1912     static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1913         state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1914     }
1915 
MapXYProc(const TextMapState & state,const SkScalar pos[])1916     static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1917         state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1918     }
1919 
MapOnlyScaleXProc(const TextMapState & state,const SkScalar pos[])1920     static void MapOnlyScaleXProc(const TextMapState& state,
1921                                   const SkScalar pos[]) {
1922         state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1923                        state.fTransformedY);
1924     }
1925 
MapOnlyTransXProc(const TextMapState & state,const SkScalar pos[])1926     static void MapOnlyTransXProc(const TextMapState& state,
1927                                   const SkScalar pos[]) {
1928         state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1929     }
1930 };
1931 
pickProc(int scalarsPerPosition)1932 TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1933     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1934 
1935     if (1 == scalarsPerPosition) {
1936         unsigned mtype = fMatrix.getType();
1937         if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1938             return MapXProc;
1939         } else {
1940             fScaleX = fMatrix.getScaleX();
1941             fTransX = fMatrix.getTranslateX();
1942             fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1943                             fMatrix.getTranslateY();
1944             return (mtype & SkMatrix::kScale_Mask) ?
1945                         MapOnlyScaleXProc : MapOnlyTransXProc;
1946         }
1947     } else {
1948         return MapXYProc;
1949     }
1950 }
1951 
1952 //////////////////////////////////////////////////////////////////////////////
1953 
drawPosText_asPaths(const char text[],size_t byteLength,const SkScalar pos[],SkScalar constY,int scalarsPerPosition,const SkPaint & origPaint) const1954 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1955                                  const SkScalar pos[], SkScalar constY,
1956                                  int scalarsPerPosition,
1957                                  const SkPaint& origPaint) const {
1958     // setup our std paint, in hopes of getting hits in the cache
1959     SkPaint paint(origPaint);
1960     SkScalar matrixScale = paint.setupForAsPaths();
1961 
1962     SkMatrix matrix;
1963     matrix.setScale(matrixScale, matrixScale);
1964 
1965     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1966     SkAutoGlyphCache    autoCache(paint, NULL, NULL);
1967     SkGlyphCache*       cache = autoCache.getCache();
1968 
1969     const char*        stop = text + byteLength;
1970     AlignProc_scalar   alignProc = pick_align_proc_scalar(paint.getTextAlign());
1971     TextMapState       tms(SkMatrix::I(), constY);
1972     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1973 
1974     while (text < stop) {
1975         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1976         if (glyph.fWidth) {
1977             const SkPath* path = cache->findPath(glyph);
1978             if (path) {
1979                 tmsProc(tms, pos);
1980                 SkPoint loc;
1981                 alignProc(tms.fLoc, glyph, &loc);
1982 
1983                 matrix[SkMatrix::kMTransX] = loc.fX;
1984                 matrix[SkMatrix::kMTransY] = loc.fY;
1985                 if (fDevice) {
1986                     fDevice->drawPath(*this, *path, paint, &matrix, false);
1987                 } else {
1988                     this->drawPath(*path, paint, &matrix, false);
1989                 }
1990             }
1991         }
1992         pos += scalarsPerPosition;
1993     }
1994 }
1995 
drawPosText(const char text[],size_t byteLength,const SkScalar pos[],SkScalar constY,int scalarsPerPosition,const SkPaint & paint) const1996 void SkDraw::drawPosText(const char text[], size_t byteLength,
1997                          const SkScalar pos[], SkScalar constY,
1998                          int scalarsPerPosition, const SkPaint& paint) const {
1999     SkASSERT(byteLength == 0 || text != NULL);
2000     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
2001 
2002     SkDEBUGCODE(this->validate();)
2003 
2004     // nothing to draw
2005     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2006         return;
2007     }
2008 
2009     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
2010         this->drawPosText_asPaths(text, byteLength, pos, constY,
2011                                   scalarsPerPosition, paint);
2012         return;
2013     }
2014 
2015     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
2016 #if SK_DISTANCEFIELD_FONTS
2017     const SkMatrix* ctm = fMatrix;
2018     const SkPaint* paintRef = &paint;
2019     SkPaint paintCopy;
2020     uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
2021     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
2022         paintCopy = paint;
2023         paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
2024         paintRef = &paintCopy;
2025     }
2026     if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
2027         ctm = &SkMatrix::I();
2028     }
2029     SkAutoGlyphCache    autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
2030 #else
2031     SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
2032 #endif
2033     SkGlyphCache*       cache = autoCache.getCache();
2034 
2035     SkAAClipBlitterWrapper wrapper;
2036     SkAutoBlitterChoose blitterChooser;
2037     SkBlitter* blitter = NULL;
2038     if (needsRasterTextBlit(*this)) {
2039         blitterChooser.choose(*fBitmap, *fMatrix, paint);
2040         blitter = blitterChooser.get();
2041         if (fRC->isAA()) {
2042             wrapper.init(*fRC, blitter);
2043             blitter = wrapper.getBlitter();
2044         }
2045     }
2046 
2047     const char*        stop = text + byteLength;
2048     AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
2049     SkDraw1Glyph       d1g;
2050     SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
2051 #if SK_DISTANCEFIELD_FONTS
2052     TextMapState       tms(*ctm, constY);
2053 #else
2054     TextMapState       tms(*fMatrix, constY);
2055 #endif
2056     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
2057 
2058     if (cache->isSubpixel()) {
2059         // maybe we should skip the rounding if linearText is set
2060         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
2061 
2062         SkFixed fxMask = ~0;
2063         SkFixed fyMask = ~0;
2064         if (kX_SkAxisAlignment == baseline) {
2065             fyMask = 0;
2066 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
2067             d1g.fHalfSampleY = SK_FixedHalf;
2068 #endif
2069         } else if (kY_SkAxisAlignment == baseline) {
2070             fxMask = 0;
2071 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
2072             d1g.fHalfSampleX = SK_FixedHalf;
2073 #endif
2074         }
2075 
2076         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2077             while (text < stop) {
2078 #if SK_DISTANCEFIELD_FONTS
2079                 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
2080                     tms.fLoc.fX = *pos;
2081                     tms.fLoc.fY = *(pos+1);
2082                 } else {
2083                     tmsProc(tms, pos);
2084                 }
2085 #else
2086                 tmsProc(tms, pos);
2087 #endif
2088                 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
2089                 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
2090 
2091                 const SkGlyph& glyph = glyphCacheProc(cache, &text,
2092                                                       fx & fxMask, fy & fyMask);
2093 
2094                 if (glyph.fWidth) {
2095                     proc(d1g, fx, fy, glyph);
2096                 }
2097                 pos += scalarsPerPosition;
2098             }
2099         } else {
2100             while (text < stop) {
2101                 const char* currentText = text;
2102                 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
2103 
2104                 if (metricGlyph.fWidth) {
2105                     SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
2106                     SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
2107 
2108                     tmsProc(tms, pos);
2109                     SkIPoint fixedLoc;
2110                     alignProc(tms.fLoc, metricGlyph, &fixedLoc);
2111 
2112                     SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
2113                     SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
2114 
2115                     // have to call again, now that we've been "aligned"
2116                     const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
2117                                                           fx & fxMask, fy & fyMask);
2118                     // the assumption is that the metrics haven't changed
2119                     SkASSERT(prevAdvX == glyph.fAdvanceX);
2120                     SkASSERT(prevAdvY == glyph.fAdvanceY);
2121                     SkASSERT(glyph.fWidth);
2122 
2123                     proc(d1g, fx, fy, glyph);
2124                 }
2125                 pos += scalarsPerPosition;
2126             }
2127         }
2128     } else {    // not subpixel
2129         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2130             while (text < stop) {
2131                 // the last 2 parameters are ignored
2132                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2133 
2134                 if (glyph.fWidth) {
2135                     tmsProc(tms, pos);
2136 
2137                     proc(d1g,
2138                          SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
2139                          SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
2140                          glyph);
2141                 }
2142                 pos += scalarsPerPosition;
2143             }
2144         } else {
2145             while (text < stop) {
2146                 // the last 2 parameters are ignored
2147                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2148 
2149                 if (glyph.fWidth) {
2150                     tmsProc(tms, pos);
2151 
2152                     SkIPoint fixedLoc;
2153                     alignProc(tms.fLoc, glyph, &fixedLoc);
2154 
2155                     proc(d1g,
2156                          fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
2157                          fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
2158                          glyph);
2159                 }
2160                 pos += scalarsPerPosition;
2161             }
2162         }
2163     }
2164 }
2165 
2166 #if defined _WIN32 && _MSC_VER >= 1300
2167 #pragma warning ( pop )
2168 #endif
2169 
2170 ///////////////////////////////////////////////////////////////////////////////
2171 
2172 #include "SkPathMeasure.h"
2173 
morphpoints(SkPoint dst[],const SkPoint src[],int count,SkPathMeasure & meas,const SkMatrix & matrix)2174 static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
2175                         SkPathMeasure& meas, const SkMatrix& matrix) {
2176     SkMatrix::MapXYProc proc = matrix.getMapXYProc();
2177 
2178     for (int i = 0; i < count; i++) {
2179         SkPoint pos;
2180         SkVector tangent;
2181 
2182         proc(matrix, src[i].fX, src[i].fY, &pos);
2183         SkScalar sx = pos.fX;
2184         SkScalar sy = pos.fY;
2185 
2186         if (!meas.getPosTan(sx, &pos, &tangent)) {
2187             // set to 0 if the measure failed, so that we just set dst == pos
2188             tangent.set(0, 0);
2189         }
2190 
2191         /*  This is the old way (that explains our approach but is way too slow
2192             SkMatrix    matrix;
2193             SkPoint     pt;
2194 
2195             pt.set(sx, sy);
2196             matrix.setSinCos(tangent.fY, tangent.fX);
2197             matrix.preTranslate(-sx, 0);
2198             matrix.postTranslate(pos.fX, pos.fY);
2199             matrix.mapPoints(&dst[i], &pt, 1);
2200         */
2201         dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
2202                    pos.fY + SkScalarMul(tangent.fX, sy));
2203     }
2204 }
2205 
2206 /*  TODO
2207 
2208     Need differentially more subdivisions when the follow-path is curvy. Not sure how to
2209     determine that, but we need it. I guess a cheap answer is let the caller tell us,
2210     but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
2211 */
morphpath(SkPath * dst,const SkPath & src,SkPathMeasure & meas,const SkMatrix & matrix)2212 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
2213                       const SkMatrix& matrix) {
2214     SkPath::Iter    iter(src, false);
2215     SkPoint         srcP[4], dstP[3];
2216     SkPath::Verb    verb;
2217 
2218     while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
2219         switch (verb) {
2220             case SkPath::kMove_Verb:
2221                 morphpoints(dstP, srcP, 1, meas, matrix);
2222                 dst->moveTo(dstP[0]);
2223                 break;
2224             case SkPath::kLine_Verb:
2225                 // turn lines into quads to look bendy
2226                 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
2227                 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
2228                 morphpoints(dstP, srcP, 2, meas, matrix);
2229                 dst->quadTo(dstP[0], dstP[1]);
2230                 break;
2231             case SkPath::kQuad_Verb:
2232                 morphpoints(dstP, &srcP[1], 2, meas, matrix);
2233                 dst->quadTo(dstP[0], dstP[1]);
2234                 break;
2235             case SkPath::kCubic_Verb:
2236                 morphpoints(dstP, &srcP[1], 3, meas, matrix);
2237                 dst->cubicTo(dstP[0], dstP[1], dstP[2]);
2238                 break;
2239             case SkPath::kClose_Verb:
2240                 dst->close();
2241                 break;
2242             default:
2243                 SkDEBUGFAIL("unknown verb");
2244                 break;
2245         }
2246     }
2247 }
2248 
drawTextOnPath(const char text[],size_t byteLength,const SkPath & follow,const SkMatrix * matrix,const SkPaint & paint) const2249 void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
2250                             const SkPath& follow, const SkMatrix* matrix,
2251                             const SkPaint& paint) const {
2252     SkASSERT(byteLength == 0 || text != NULL);
2253 
2254     // nothing to draw
2255     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2256         return;
2257     }
2258 
2259     SkTextToPathIter    iter(text, byteLength, paint, true);
2260     SkPathMeasure       meas(follow, false);
2261     SkScalar            hOffset = 0;
2262 
2263     // need to measure first
2264     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
2265         SkScalar pathLen = meas.getLength();
2266         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2267             pathLen = SkScalarHalf(pathLen);
2268         }
2269         hOffset += pathLen;
2270     }
2271 
2272     const SkPath*   iterPath;
2273     SkScalar        xpos;
2274     SkMatrix        scaledMatrix;
2275     SkScalar        scale = iter.getPathScale();
2276 
2277     scaledMatrix.setScale(scale, scale);
2278 
2279     while (iter.next(&iterPath, &xpos)) {
2280         if (iterPath) {
2281             SkPath      tmp;
2282             SkMatrix    m(scaledMatrix);
2283 
2284             m.postTranslate(xpos + hOffset, 0);
2285             if (matrix) {
2286                 m.postConcat(*matrix);
2287             }
2288             morphpath(&tmp, *iterPath, meas, m);
2289             if (fDevice) {
2290                 fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
2291             } else {
2292                 this->drawPath(tmp, iter.getPaint(), NULL, true);
2293             }
2294         }
2295     }
2296 }
2297 
2298 ///////////////////////////////////////////////////////////////////////////////
2299 
2300 struct VertState {
2301     int f0, f1, f2;
2302 
VertStateVertState2303     VertState(int vCount, const uint16_t indices[], int indexCount)
2304             : fIndices(indices) {
2305         fCurrIndex = 0;
2306         if (indices) {
2307             fCount = indexCount;
2308         } else {
2309             fCount = vCount;
2310         }
2311     }
2312 
2313     typedef bool (*Proc)(VertState*);
2314     Proc chooseProc(SkCanvas::VertexMode mode);
2315 
2316 private:
2317     int             fCount;
2318     int             fCurrIndex;
2319     const uint16_t* fIndices;
2320 
2321     static bool Triangles(VertState*);
2322     static bool TrianglesX(VertState*);
2323     static bool TriangleStrip(VertState*);
2324     static bool TriangleStripX(VertState*);
2325     static bool TriangleFan(VertState*);
2326     static bool TriangleFanX(VertState*);
2327 };
2328 
Triangles(VertState * state)2329 bool VertState::Triangles(VertState* state) {
2330     int index = state->fCurrIndex;
2331     if (index + 3 > state->fCount) {
2332         return false;
2333     }
2334     state->f0 = index + 0;
2335     state->f1 = index + 1;
2336     state->f2 = index + 2;
2337     state->fCurrIndex = index + 3;
2338     return true;
2339 }
2340 
TrianglesX(VertState * state)2341 bool VertState::TrianglesX(VertState* state) {
2342     const uint16_t* indices = state->fIndices;
2343     int index = state->fCurrIndex;
2344     if (index + 3 > state->fCount) {
2345         return false;
2346     }
2347     state->f0 = indices[index + 0];
2348     state->f1 = indices[index + 1];
2349     state->f2 = indices[index + 2];
2350     state->fCurrIndex = index + 3;
2351     return true;
2352 }
2353 
TriangleStrip(VertState * state)2354 bool VertState::TriangleStrip(VertState* state) {
2355     int index = state->fCurrIndex;
2356     if (index + 3 > state->fCount) {
2357         return false;
2358     }
2359     state->f2 = index + 2;
2360     if (index & 1) {
2361         state->f0 = index + 1;
2362         state->f1 = index + 0;
2363     } else {
2364         state->f0 = index + 0;
2365         state->f1 = index + 1;
2366     }
2367     state->fCurrIndex = index + 1;
2368     return true;
2369 }
2370 
TriangleStripX(VertState * state)2371 bool VertState::TriangleStripX(VertState* state) {
2372     const uint16_t* indices = state->fIndices;
2373     int index = state->fCurrIndex;
2374     if (index + 3 > state->fCount) {
2375         return false;
2376     }
2377     state->f2 = indices[index + 2];
2378     if (index & 1) {
2379         state->f0 = indices[index + 1];
2380         state->f1 = indices[index + 0];
2381     } else {
2382         state->f0 = indices[index + 0];
2383         state->f1 = indices[index + 1];
2384     }
2385     state->fCurrIndex = index + 1;
2386     return true;
2387 }
2388 
TriangleFan(VertState * state)2389 bool VertState::TriangleFan(VertState* state) {
2390     int index = state->fCurrIndex;
2391     if (index + 3 > state->fCount) {
2392         return false;
2393     }
2394     state->f0 = 0;
2395     state->f1 = index + 1;
2396     state->f2 = index + 2;
2397     state->fCurrIndex = index + 1;
2398     return true;
2399 }
2400 
TriangleFanX(VertState * state)2401 bool VertState::TriangleFanX(VertState* state) {
2402     const uint16_t* indices = state->fIndices;
2403     int index = state->fCurrIndex;
2404     if (index + 3 > state->fCount) {
2405         return false;
2406     }
2407     state->f0 = indices[0];
2408     state->f1 = indices[index + 1];
2409     state->f2 = indices[index + 2];
2410     state->fCurrIndex = index + 1;
2411     return true;
2412 }
2413 
chooseProc(SkCanvas::VertexMode mode)2414 VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
2415     switch (mode) {
2416         case SkCanvas::kTriangles_VertexMode:
2417             return fIndices ? TrianglesX : Triangles;
2418         case SkCanvas::kTriangleStrip_VertexMode:
2419             return fIndices ? TriangleStripX : TriangleStrip;
2420         case SkCanvas::kTriangleFan_VertexMode:
2421             return fIndices ? TriangleFanX : TriangleFan;
2422         default:
2423             return NULL;
2424     }
2425 }
2426 
2427 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
2428                          SkBlitter*);
2429 
ChooseHairProc(bool doAntiAlias)2430 static HairProc ChooseHairProc(bool doAntiAlias) {
2431     return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2432 }
2433 
texture_to_matrix(const VertState & state,const SkPoint verts[],const SkPoint texs[],SkMatrix * matrix)2434 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2435                               const SkPoint texs[], SkMatrix* matrix) {
2436     SkPoint src[3], dst[3];
2437 
2438     src[0] = texs[state.f0];
2439     src[1] = texs[state.f1];
2440     src[2] = texs[state.f2];
2441     dst[0] = verts[state.f0];
2442     dst[1] = verts[state.f1];
2443     dst[2] = verts[state.f2];
2444     return matrix->setPolyToPoly(src, dst, 3);
2445 }
2446 
2447 class SkTriColorShader : public SkShader {
2448 public:
SkTriColorShader()2449     SkTriColorShader() {}
2450 
2451     bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2452 
2453     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2454 
2455     SK_DEVELOPER_TO_STRING()
2456     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
2457 
2458 protected:
SkTriColorShader(SkFlattenableReadBuffer & buffer)2459     SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2460 
2461 private:
2462     SkMatrix    fDstToUnit;
2463     SkPMColor   fColors[3];
2464 
2465     typedef SkShader INHERITED;
2466 };
2467 
setup(const SkPoint pts[],const SkColor colors[],int index0,int index1,int index2)2468 bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2469                              int index0, int index1, int index2) {
2470 
2471     fColors[0] = SkPreMultiplyColor(colors[index0]);
2472     fColors[1] = SkPreMultiplyColor(colors[index1]);
2473     fColors[2] = SkPreMultiplyColor(colors[index2]);
2474 
2475     SkMatrix m, im;
2476     m.reset();
2477     m.set(0, pts[index1].fX - pts[index0].fX);
2478     m.set(1, pts[index2].fX - pts[index0].fX);
2479     m.set(2, pts[index0].fX);
2480     m.set(3, pts[index1].fY - pts[index0].fY);
2481     m.set(4, pts[index2].fY - pts[index0].fY);
2482     m.set(5, pts[index0].fY);
2483     if (!m.invert(&im)) {
2484         return false;
2485     }
2486     return fDstToUnit.setConcat(im, this->getTotalInverse());
2487 }
2488 
2489 #include "SkColorPriv.h"
2490 #include "SkComposeShader.h"
2491 
ScalarTo256(SkScalar v)2492 static int ScalarTo256(SkScalar v) {
2493     int scale = SkScalarToFixed(v) >> 8;
2494     if (scale < 0) {
2495         scale = 0;
2496     }
2497     if (scale > 255) {
2498         scale = 255;
2499     }
2500     return SkAlpha255To256(scale);
2501 }
2502 
shadeSpan(int x,int y,SkPMColor dstC[],int count)2503 void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2504     SkPoint src;
2505 
2506     for (int i = 0; i < count; i++) {
2507         fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2508         x += 1;
2509 
2510         int scale1 = ScalarTo256(src.fX);
2511         int scale2 = ScalarTo256(src.fY);
2512         int scale0 = 256 - scale1 - scale2;
2513         if (scale0 < 0) {
2514             if (scale1 > scale2) {
2515                 scale2 = 256 - scale1;
2516             } else {
2517                 scale1 = 256 - scale2;
2518             }
2519             scale0 = 0;
2520         }
2521 
2522         dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2523         SkAlphaMulQ(fColors[1], scale1) +
2524         SkAlphaMulQ(fColors[2], scale2);
2525     }
2526 }
2527 
2528 #ifdef SK_DEVELOPER
toString(SkString * str) const2529 void SkTriColorShader::toString(SkString* str) const {
2530     str->append("SkTriColorShader: (");
2531 
2532     this->INHERITED::toString(str);
2533 
2534     str->append(")");
2535 }
2536 #endif
2537 
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) const2538 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2539                           const SkPoint vertices[], const SkPoint textures[],
2540                           const SkColor colors[], SkXfermode* xmode,
2541                           const uint16_t indices[], int indexCount,
2542                           const SkPaint& paint) const {
2543     SkASSERT(0 == count || NULL != vertices);
2544 
2545     // abort early if there is nothing to draw
2546     if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2547         return;
2548     }
2549 
2550     // transform out vertices into device coordinates
2551     SkAutoSTMalloc<16, SkPoint> storage(count);
2552     SkPoint* devVerts = storage.get();
2553     fMatrix->mapPoints(devVerts, vertices, count);
2554 
2555     if (fBounder) {
2556         SkRect bounds;
2557         bounds.set(devVerts, count);
2558         if (!fBounder->doRect(bounds, paint)) {
2559             return;
2560         }
2561     }
2562 
2563     /*
2564         We can draw the vertices in 1 of 4 ways:
2565 
2566         - solid color (no shader/texture[], no colors[])
2567         - just colors (no shader/texture[], has colors[])
2568         - just texture (has shader/texture[], no colors[])
2569         - colors * texture (has shader/texture[], has colors[])
2570 
2571         Thus for texture drawing, we need both texture[] and a shader.
2572     */
2573 
2574     SkTriColorShader triShader; // must be above declaration of p
2575     SkPaint p(paint);
2576 
2577     SkShader* shader = p.getShader();
2578     if (NULL == shader) {
2579         // if we have no shader, we ignore the texture coordinates
2580         textures = NULL;
2581     } else if (NULL == textures) {
2582         // if we don't have texture coordinates, ignore the shader
2583         p.setShader(NULL);
2584         shader = NULL;
2585     }
2586 
2587     // setup the custom shader (if needed)
2588     if (NULL != colors) {
2589         if (NULL == textures) {
2590             // just colors (no texture)
2591             shader = p.setShader(&triShader);
2592         } else {
2593             // colors * texture
2594             SkASSERT(shader);
2595             bool releaseMode = false;
2596             if (NULL == xmode) {
2597                 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2598                 releaseMode = true;
2599             }
2600             SkShader* compose = SkNEW_ARGS(SkComposeShader,
2601                                            (&triShader, shader, xmode));
2602             p.setShader(compose)->unref();
2603             if (releaseMode) {
2604                 xmode->unref();
2605             }
2606             shader = compose;
2607         }
2608     }
2609 
2610     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2611     // important that we abort early, as below we may manipulate the shader
2612     // and that is only valid if the shader returned true from setContext.
2613     // If it returned false, then our blitter will be the NullBlitter.
2614     if (blitter->isNullBlitter()) {
2615         return;
2616     }
2617 
2618     // setup our state and function pointer for iterating triangles
2619     VertState       state(count, indices, indexCount);
2620     VertState::Proc vertProc = state.chooseProc(vmode);
2621 
2622     if (NULL != textures || NULL != colors) {
2623         SkMatrix  tempM;
2624         SkMatrix  savedLocalM;
2625         if (shader) {
2626             savedLocalM = shader->getLocalMatrix();
2627         }
2628 
2629         // setContext has already been called and verified to return true
2630         // by the constructor of SkAutoBlitterChoose
2631         bool prevContextSuccess = true;
2632         while (vertProc(&state)) {
2633             if (NULL != textures) {
2634                 if (texture_to_matrix(state, vertices, textures, &tempM)) {
2635                     tempM.postConcat(savedLocalM);
2636                     shader->setLocalMatrix(tempM);
2637                     // Need to recall setContext since we changed the local matrix.
2638                     // However, we also need to balance the calls this with a
2639                     // call to endContext which requires tracking the result of
2640                     // the previous call to setContext.
2641                     if (prevContextSuccess) {
2642                         shader->endContext();
2643                     }
2644                     prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
2645                     if (!prevContextSuccess) {
2646                         continue;
2647                     }
2648                 }
2649             }
2650             if (NULL != colors) {
2651                 if (!triShader.setup(vertices, colors,
2652                                      state.f0, state.f1, state.f2)) {
2653                     continue;
2654                 }
2655             }
2656 
2657             SkPoint tmp[] = {
2658                 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2659             };
2660             SkScan::FillTriangle(tmp, *fRC, blitter.get());
2661         }
2662 
2663         // now restore the shader's original local matrix
2664         if (NULL != shader) {
2665             shader->setLocalMatrix(savedLocalM);
2666         }
2667 
2668         // If the final call to setContext fails we must make it suceed so that the
2669         // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
2670         if (!prevContextSuccess) {
2671             prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
2672             SkASSERT(prevContextSuccess);
2673         }
2674     } else {
2675         // no colors[] and no texture
2676         HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2677         const SkRasterClip& clip = *fRC;
2678         while (vertProc(&state)) {
2679             hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2680             hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2681             hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2682         }
2683     }
2684 }
2685 
2686 ///////////////////////////////////////////////////////////////////////////////
2687 ///////////////////////////////////////////////////////////////////////////////
2688 
2689 #ifdef SK_DEBUG
2690 
validate() const2691 void SkDraw::validate() const {
2692     SkASSERT(fBitmap != NULL);
2693     SkASSERT(fMatrix != NULL);
2694     SkASSERT(fClip != NULL);
2695     SkASSERT(fRC != NULL);
2696 
2697     const SkIRect&  cr = fRC->getBounds();
2698     SkIRect         br;
2699 
2700     br.set(0, 0, fBitmap->width(), fBitmap->height());
2701     SkASSERT(cr.isEmpty() || br.contains(cr));
2702 }
2703 
2704 #endif
2705 
2706 ///////////////////////////////////////////////////////////////////////////////
2707 
SkBounder()2708 SkBounder::SkBounder() {
2709     // initialize up front. This gets reset by SkCanvas before each draw call.
2710     fClip = &SkRegion::GetEmptyRegion();
2711 }
2712 
doIRect(const SkIRect & r)2713 bool SkBounder::doIRect(const SkIRect& r) {
2714     SkIRect    rr;
2715     return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2716 }
2717 
2718 // TODO: change the prototype to take fixed, and update the callers
doIRectGlyph(const SkIRect & r,int x,int y,const SkGlyph & glyph)2719 bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2720                              const SkGlyph& glyph) {
2721     SkIRect    rr;
2722     if (!rr.intersect(fClip->getBounds(), r)) {
2723         return false;
2724     }
2725     GlyphRec rec;
2726     rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2727     rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2728                  rec.fLSB.fY + glyph.fAdvanceY);
2729     rec.fGlyphID = glyph.getGlyphID();
2730     rec.fFlags = 0;
2731     return this->onIRectGlyph(rr, rec);
2732 }
2733 
doHairline(const SkPoint & pt0,const SkPoint & pt1,const SkPaint & paint)2734 bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2735                            const SkPaint& paint) {
2736     SkIRect     r;
2737     SkScalar    v0, v1;
2738 
2739     v0 = pt0.fX;
2740     v1 = pt1.fX;
2741     if (v0 > v1) {
2742         SkTSwap<SkScalar>(v0, v1);
2743     }
2744     r.fLeft     = SkScalarFloor(v0);
2745     r.fRight    = SkScalarCeil(v1);
2746 
2747     v0 = pt0.fY;
2748     v1 = pt1.fY;
2749     if (v0 > v1) {
2750         SkTSwap<SkScalar>(v0, v1);
2751     }
2752     r.fTop      = SkScalarFloor(v0);
2753     r.fBottom   = SkScalarCeil(v1);
2754 
2755     if (paint.isAntiAlias()) {
2756         r.inset(-1, -1);
2757     }
2758     return this->doIRect(r);
2759 }
2760 
doRect(const SkRect & rect,const SkPaint & paint)2761 bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2762     SkIRect    r;
2763 
2764     if (paint.getStyle() == SkPaint::kFill_Style) {
2765         rect.round(&r);
2766     } else {
2767         int rad = -1;
2768         rect.roundOut(&r);
2769         if (paint.isAntiAlias()) {
2770             rad = -2;
2771         }
2772         r.inset(rad, rad);
2773     }
2774     return this->doIRect(r);
2775 }
2776 
doPath(const SkPath & path,const SkPaint & paint,bool doFill)2777 bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2778     SkIRect       r;
2779     const SkRect& bounds = path.getBounds();
2780 
2781     if (doFill) {
2782         bounds.round(&r);
2783     } else {    // hairline
2784         bounds.roundOut(&r);
2785     }
2786 
2787     if (paint.isAntiAlias()) {
2788         r.inset(-1, -1);
2789     }
2790     return this->doIRect(r);
2791 }
2792 
commit()2793 void SkBounder::commit() {
2794     // override in subclass
2795 }
2796 
2797 ////////////////////////////////////////////////////////////////////////////////////////////////
2798 
2799 #include "SkPath.h"
2800 #include "SkDraw.h"
2801 #include "SkRegion.h"
2802 #include "SkBlitter.h"
2803 
compute_bounds(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkIRect * bounds)2804 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2805                        const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2806                            SkIRect* bounds) {
2807     if (devPath.isEmpty()) {
2808         return false;
2809     }
2810 
2811     //  init our bounds from the path
2812     {
2813         SkRect pathBounds = devPath.getBounds();
2814         pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2815         pathBounds.roundOut(bounds);
2816     }
2817 
2818     SkIPoint margin = SkIPoint::Make(0, 0);
2819     if (filter) {
2820         SkASSERT(filterMatrix);
2821 
2822         SkMask srcM, dstM;
2823 
2824         srcM.fBounds = *bounds;
2825         srcM.fFormat = SkMask::kA8_Format;
2826         srcM.fImage = NULL;
2827         if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2828             return false;
2829         }
2830     }
2831 
2832     // (possibly) trim the bounds to reflect the clip
2833     // (plus whatever slop the filter needs)
2834     if (clipBounds) {
2835         SkIRect tmp = *clipBounds;
2836         // Ugh. Guard against gigantic margins from wacky filters. Without this
2837         // check we can request arbitrary amounts of slop beyond our visible
2838         // clip, and bring down the renderer (at least on finite RAM machines
2839         // like handsets, etc.). Need to balance this invented value between
2840         // quality of large filters like blurs, and the corresponding memory
2841         // requests.
2842         static const int MAX_MARGIN = 128;
2843         tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2844                   -SkMin32(margin.fY, MAX_MARGIN));
2845         if (!bounds->intersect(tmp)) {
2846             return false;
2847         }
2848     }
2849 
2850     return true;
2851 }
2852 
draw_into_mask(const SkMask & mask,const SkPath & devPath,SkPaint::Style style)2853 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2854                            SkPaint::Style style) {
2855     SkBitmap        bm;
2856     SkDraw          draw;
2857     SkRasterClip    clip;
2858     SkMatrix        matrix;
2859     SkPaint         paint;
2860 
2861     bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2862     bm.setPixels(mask.fImage);
2863 
2864     clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2865     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2866                         -SkIntToScalar(mask.fBounds.fTop));
2867 
2868     draw.fBitmap    = &bm;
2869     draw.fRC        = &clip;
2870     draw.fClip      = &clip.bwRgn();
2871     draw.fMatrix    = &matrix;
2872     draw.fBounder   = NULL;
2873     paint.setAntiAlias(true);
2874     paint.setStyle(style);
2875     draw.drawPath(devPath, paint);
2876 }
2877 
DrawToMask(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkMask * mask,SkMask::CreateMode mode,SkPaint::Style style)2878 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2879                         const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2880                         SkMask* mask, SkMask::CreateMode mode,
2881                         SkPaint::Style style) {
2882     if (SkMask::kJustRenderImage_CreateMode != mode) {
2883         if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2884             return false;
2885     }
2886 
2887     if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2888         mask->fFormat = SkMask::kA8_Format;
2889         mask->fRowBytes = mask->fBounds.width();
2890         size_t size = mask->computeImageSize();
2891         if (0 == size) {
2892             // we're too big to allocate the mask, abort
2893             return false;
2894         }
2895         mask->fImage = SkMask::AllocImage(size);
2896         memset(mask->fImage, 0, mask->computeImageSize());
2897     }
2898 
2899     if (SkMask::kJustComputeBounds_CreateMode != mode) {
2900         draw_into_mask(*mask, devPath, style);
2901     }
2902 
2903     return true;
2904 }
2905 
2906