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 #define __STDC_LIMIT_MACROS
8
9 #include "SkDraw.h"
10 #include "SkBlitter.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 "SkSmallAllocator.h"
25 #include "SkString.h"
26 #include "SkStroke.h"
27 #include "SkTextMapStateProc.h"
28 #include "SkTLazy.h"
29 #include "SkUtils.h"
30 #include "SkVertState.h"
31
32 #include "SkAutoKern.h"
33 #include "SkBitmapProcShader.h"
34 #include "SkDrawProcs.h"
35 #include "SkMatrixUtils.h"
36
37 //#define TRACE_BITMAP_DRAWS
38
39
40 /** Helper for allocating small blitters on the stack.
41 */
42 class SkAutoBlitterChoose : SkNoncopyable {
43 public:
SkAutoBlitterChoose()44 SkAutoBlitterChoose() {
45 fBlitter = NULL;
46 }
SkAutoBlitterChoose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint,bool drawCoverage=false)47 SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
48 const SkPaint& paint, bool drawCoverage = false) {
49 fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
50 drawCoverage);
51 }
52
operator ->()53 SkBlitter* operator->() { return fBlitter; }
get() const54 SkBlitter* get() const { return fBlitter; }
55
choose(const SkBitmap & device,const SkMatrix & matrix,const SkPaint & paint,bool drawCoverage=false)56 void choose(const SkBitmap& device, const SkMatrix& matrix,
57 const SkPaint& paint, bool drawCoverage = false) {
58 SkASSERT(!fBlitter);
59 fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
60 drawCoverage);
61 }
62
63 private:
64 // Owned by fAllocator, which will handle the delete.
65 SkBlitter* fBlitter;
66 SkTBlitterAllocator fAllocator;
67 };
68 #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
69
70 /**
71 * Since we are providing the storage for the shader (to avoid the perf cost
72 * of calling new) we insist that in our destructor we can account for all
73 * owners of the shader.
74 */
75 class SkAutoBitmapShaderInstall : SkNoncopyable {
76 public:
SkAutoBitmapShaderInstall(const SkBitmap & src,const SkPaint & paint,const SkMatrix * localMatrix=NULL)77 SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
78 const SkMatrix* localMatrix = NULL)
79 : fPaint(paint) /* makes a copy of the paint */ {
80 fPaint.setShader(SkCreateBitmapShader(src, SkShader::kClamp_TileMode,
81 SkShader::kClamp_TileMode,
82 localMatrix, &fAllocator));
83 // we deliberately left the shader with an owner-count of 2
84 SkASSERT(2 == fPaint.getShader()->getRefCnt());
85 }
86
~SkAutoBitmapShaderInstall()87 ~SkAutoBitmapShaderInstall() {
88 // since fAllocator will destroy shader, we insist that owners == 2
89 SkASSERT(2 == fPaint.getShader()->getRefCnt());
90
91 fPaint.setShader(NULL); // unref the shader by 1
92
93 }
94
95 // return the new paint that has the shader applied
paintWithShader() const96 const SkPaint& paintWithShader() const { return fPaint; }
97
98 private:
99 // copy of caller's paint (which we then modify)
100 SkPaint fPaint;
101 // Stores the shader.
102 SkTBlitterAllocator fAllocator;
103 };
104 #define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
105
106 ///////////////////////////////////////////////////////////////////////////////
107
SkDraw()108 SkDraw::SkDraw() {
109 sk_bzero(this, sizeof(*this));
110 }
111
SkDraw(const SkDraw & src)112 SkDraw::SkDraw(const SkDraw& src) {
113 memcpy(this, &src, sizeof(*this));
114 }
115
computeConservativeLocalClipBounds(SkRect * localBounds) const116 bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
117 if (fRC->isEmpty()) {
118 return false;
119 }
120
121 SkMatrix inverse;
122 if (!fMatrix->invert(&inverse)) {
123 return false;
124 }
125
126 SkIRect devBounds = fRC->getBounds();
127 // outset to have slop for antialasing and hairlines
128 devBounds.outset(1, 1);
129 inverse.mapRect(localBounds, SkRect::Make(devBounds));
130 return true;
131 }
132
133 ///////////////////////////////////////////////////////////////////////////////
134
135 typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
136
D_Clear_BitmapXferProc(void * pixels,size_t bytes,uint32_t)137 static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
138 sk_bzero(pixels, bytes);
139 }
140
D_Dst_BitmapXferProc(void *,size_t,uint32_t data)141 static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
142
D32_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)143 static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
144 sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2));
145 }
146
D16_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)147 static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
148 sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1));
149 }
150
DA8_Src_BitmapXferProc(void * pixels,size_t bytes,uint32_t data)151 static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
152 memset(pixels, data, bytes);
153 }
154
ChooseBitmapXferProc(const SkBitmap & bitmap,const SkPaint & paint,uint32_t * data)155 static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
156 const SkPaint& paint,
157 uint32_t* data) {
158 // todo: we can apply colorfilter up front if no shader, so we wouldn't
159 // need to abort this fastpath
160 if (paint.getShader() || paint.getColorFilter()) {
161 return NULL;
162 }
163
164 SkXfermode::Mode mode;
165 if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
166 return NULL;
167 }
168
169 SkColor color = paint.getColor();
170
171 // collaps modes based on color...
172 if (SkXfermode::kSrcOver_Mode == mode) {
173 unsigned alpha = SkColorGetA(color);
174 if (0 == alpha) {
175 mode = SkXfermode::kDst_Mode;
176 } else if (0xFF == alpha) {
177 mode = SkXfermode::kSrc_Mode;
178 }
179 }
180
181 switch (mode) {
182 case SkXfermode::kClear_Mode:
183 // SkDebugf("--- D_Clear_BitmapXferProc\n");
184 return D_Clear_BitmapXferProc; // ignore data
185 case SkXfermode::kDst_Mode:
186 // SkDebugf("--- D_Dst_BitmapXferProc\n");
187 return D_Dst_BitmapXferProc; // ignore data
188 case SkXfermode::kSrc_Mode: {
189 /*
190 should I worry about dithering for the lower depths?
191 */
192 SkPMColor pmc = SkPreMultiplyColor(color);
193 switch (bitmap.colorType()) {
194 case kN32_SkColorType:
195 if (data) {
196 *data = pmc;
197 }
198 // SkDebugf("--- D32_Src_BitmapXferProc\n");
199 return D32_Src_BitmapXferProc;
200 case kRGB_565_SkColorType:
201 if (data) {
202 *data = SkPixel32ToPixel16(pmc);
203 }
204 // SkDebugf("--- D16_Src_BitmapXferProc\n");
205 return D16_Src_BitmapXferProc;
206 case kAlpha_8_SkColorType:
207 if (data) {
208 *data = SkGetPackedA32(pmc);
209 }
210 // SkDebugf("--- DA8_Src_BitmapXferProc\n");
211 return DA8_Src_BitmapXferProc;
212 default:
213 break;
214 }
215 break;
216 }
217 default:
218 break;
219 }
220 return NULL;
221 }
222
CallBitmapXferProc(const SkBitmap & bitmap,const SkIRect & rect,BitmapXferProc proc,uint32_t procData)223 static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
224 BitmapXferProc proc, uint32_t procData) {
225 int shiftPerPixel;
226 switch (bitmap.colorType()) {
227 case kN32_SkColorType:
228 shiftPerPixel = 2;
229 break;
230 case kRGB_565_SkColorType:
231 shiftPerPixel = 1;
232 break;
233 case kAlpha_8_SkColorType:
234 shiftPerPixel = 0;
235 break;
236 default:
237 SkDEBUGFAIL("Can't use xferproc on this config");
238 return;
239 }
240
241 uint8_t* pixels = (uint8_t*)bitmap.getPixels();
242 SkASSERT(pixels);
243 const size_t rowBytes = bitmap.rowBytes();
244 const int widthBytes = rect.width() << shiftPerPixel;
245
246 // skip down to the first scanline and X position
247 pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
248 for (int scans = rect.height() - 1; scans >= 0; --scans) {
249 proc(pixels, widthBytes, procData);
250 pixels += rowBytes;
251 }
252 }
253
drawPaint(const SkPaint & paint) const254 void SkDraw::drawPaint(const SkPaint& paint) const {
255 SkDEBUGCODE(this->validate();)
256
257 if (fRC->isEmpty()) {
258 return;
259 }
260
261 SkIRect devRect;
262 devRect.set(0, 0, fBitmap->width(), fBitmap->height());
263
264 if (fRC->isBW()) {
265 /* If we don't have a shader (i.e. we're just a solid color) we may
266 be faster to operate directly on the device bitmap, rather than invoking
267 a blitter. Esp. true for xfermodes, which require a colorshader to be
268 present, which is just redundant work. Since we're drawing everywhere
269 in the clip, we don't have to worry about antialiasing.
270 */
271 uint32_t procData = 0; // to avoid the warning
272 BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
273 if (proc) {
274 if (D_Dst_BitmapXferProc == proc) { // nothing to do
275 return;
276 }
277
278 SkRegion::Iterator iter(fRC->bwRgn());
279 while (!iter.done()) {
280 CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
281 iter.next();
282 }
283 return;
284 }
285 }
286
287 // normal case: use a blitter
288 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
289 SkScan::FillIRect(devRect, *fRC, blitter.get());
290 }
291
292 ///////////////////////////////////////////////////////////////////////////////
293
294 struct PtProcRec {
295 SkCanvas::PointMode fMode;
296 const SkPaint* fPaint;
297 const SkRegion* fClip;
298 const SkRasterClip* fRC;
299
300 // computed values
301 SkFixed fRadius;
302
303 typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
304 SkBlitter*);
305
306 bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
307 const SkRasterClip*);
308 Proc chooseProc(SkBlitter** blitter);
309
310 private:
311 SkAAClipBlitterWrapper fWrapper;
312 };
313
bw_pt_rect_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)314 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
315 int count, SkBlitter* blitter) {
316 SkASSERT(rec.fClip->isRect());
317 const SkIRect& r = rec.fClip->getBounds();
318
319 for (int i = 0; i < count; i++) {
320 int x = SkScalarFloorToInt(devPts[i].fX);
321 int y = SkScalarFloorToInt(devPts[i].fY);
322 if (r.contains(x, y)) {
323 blitter->blitH(x, y, 1);
324 }
325 }
326 }
327
bw_pt_rect_16_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)328 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
329 const SkPoint devPts[], int count,
330 SkBlitter* blitter) {
331 SkASSERT(rec.fRC->isRect());
332 const SkIRect& r = rec.fRC->getBounds();
333 uint32_t value;
334 const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
335 SkASSERT(bitmap);
336
337 uint16_t* addr = bitmap->getAddr16(0, 0);
338 size_t rb = bitmap->rowBytes();
339
340 for (int i = 0; i < count; i++) {
341 int x = SkScalarFloorToInt(devPts[i].fX);
342 int y = SkScalarFloorToInt(devPts[i].fY);
343 if (r.contains(x, y)) {
344 ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
345 }
346 }
347 }
348
bw_pt_rect_32_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)349 static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
350 const SkPoint devPts[], int count,
351 SkBlitter* blitter) {
352 SkASSERT(rec.fRC->isRect());
353 const SkIRect& r = rec.fRC->getBounds();
354 uint32_t value;
355 const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
356 SkASSERT(bitmap);
357
358 SkPMColor* addr = bitmap->getAddr32(0, 0);
359 size_t rb = bitmap->rowBytes();
360
361 for (int i = 0; i < count; i++) {
362 int x = SkScalarFloorToInt(devPts[i].fX);
363 int y = SkScalarFloorToInt(devPts[i].fY);
364 if (r.contains(x, y)) {
365 ((SkPMColor*)((char*)addr + y * rb))[x] = value;
366 }
367 }
368 }
369
bw_pt_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)370 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
371 int count, SkBlitter* blitter) {
372 for (int i = 0; i < count; i++) {
373 int x = SkScalarFloorToInt(devPts[i].fX);
374 int y = SkScalarFloorToInt(devPts[i].fY);
375 if (rec.fClip->contains(x, y)) {
376 blitter->blitH(x, y, 1);
377 }
378 }
379 }
380
bw_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)381 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
382 int count, SkBlitter* blitter) {
383 for (int i = 0; i < count; i += 2) {
384 SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter);
385 }
386 }
387
bw_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)388 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
389 int count, SkBlitter* blitter) {
390 SkScan::HairLine(devPts, count, *rec.fRC, blitter);
391 }
392
393 // aa versions
394
aa_line_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)395 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
396 int count, SkBlitter* blitter) {
397 for (int i = 0; i < count; i += 2) {
398 SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter);
399 }
400 }
401
aa_poly_hair_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)402 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
403 int count, SkBlitter* blitter) {
404 SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter);
405 }
406
407 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
408
bw_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)409 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
410 int count, SkBlitter* blitter) {
411 const SkFixed radius = rec.fRadius;
412 for (int i = 0; i < count; i++) {
413 SkFixed x = SkScalarToFixed(devPts[i].fX);
414 SkFixed y = SkScalarToFixed(devPts[i].fY);
415
416 SkXRect r;
417 r.fLeft = x - radius;
418 r.fTop = y - radius;
419 r.fRight = x + radius;
420 r.fBottom = y + radius;
421
422 SkScan::FillXRect(r, *rec.fRC, blitter);
423 }
424 }
425
aa_square_proc(const PtProcRec & rec,const SkPoint devPts[],int count,SkBlitter * blitter)426 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
427 int count, SkBlitter* blitter) {
428 const SkFixed radius = rec.fRadius;
429 for (int i = 0; i < count; i++) {
430 SkFixed x = SkScalarToFixed(devPts[i].fX);
431 SkFixed y = SkScalarToFixed(devPts[i].fY);
432
433 SkXRect r;
434 r.fLeft = x - radius;
435 r.fTop = y - radius;
436 r.fRight = x + radius;
437 r.fBottom = y + radius;
438
439 SkScan::AntiFillXRect(r, *rec.fRC, blitter);
440 }
441 }
442
443 // 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)444 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
445 const SkMatrix* matrix, const SkRasterClip* rc) {
446 if (paint.getPathEffect()) {
447 return false;
448 }
449 SkScalar width = paint.getStrokeWidth();
450 if (0 == width) {
451 fMode = mode;
452 fPaint = &paint;
453 fClip = NULL;
454 fRC = rc;
455 fRadius = SK_FixedHalf;
456 return true;
457 }
458 if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
459 matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) {
460 SkScalar sx = matrix->get(SkMatrix::kMScaleX);
461 SkScalar sy = matrix->get(SkMatrix::kMScaleY);
462 if (SkScalarNearlyZero(sx - sy)) {
463 if (sx < 0) {
464 sx = -sx;
465 }
466
467 fMode = mode;
468 fPaint = &paint;
469 fClip = NULL;
470 fRC = rc;
471 fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
472 return true;
473 }
474 }
475 return false;
476 }
477
chooseProc(SkBlitter ** blitterPtr)478 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
479 Proc proc = NULL;
480
481 SkBlitter* blitter = *blitterPtr;
482 if (fRC->isBW()) {
483 fClip = &fRC->bwRgn();
484 } else {
485 fWrapper.init(*fRC, blitter);
486 fClip = &fWrapper.getRgn();
487 blitter = fWrapper.getBlitter();
488 *blitterPtr = blitter;
489 }
490
491 // for our arrays
492 SkASSERT(0 == SkCanvas::kPoints_PointMode);
493 SkASSERT(1 == SkCanvas::kLines_PointMode);
494 SkASSERT(2 == SkCanvas::kPolygon_PointMode);
495 SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
496
497 if (fPaint->isAntiAlias()) {
498 if (0 == fPaint->getStrokeWidth()) {
499 static const Proc gAAProcs[] = {
500 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
501 };
502 proc = gAAProcs[fMode];
503 } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
504 SkASSERT(SkCanvas::kPoints_PointMode == fMode);
505 proc = aa_square_proc;
506 }
507 } else { // BW
508 if (fRadius <= SK_FixedHalf) { // small radii and hairline
509 if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
510 uint32_t value;
511 const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
512 if (bm && kRGB_565_SkColorType == bm->colorType()) {
513 proc = bw_pt_rect_16_hair_proc;
514 } else if (bm && kN32_SkColorType == bm->colorType()) {
515 proc = bw_pt_rect_32_hair_proc;
516 } else {
517 proc = bw_pt_rect_hair_proc;
518 }
519 } else {
520 static Proc gBWProcs[] = {
521 bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
522 };
523 proc = gBWProcs[fMode];
524 }
525 } else {
526 proc = bw_square_proc;
527 }
528 }
529 return proc;
530 }
531
532 // each of these costs 8-bytes of stack space, so don't make it too large
533 // must be even for lines/polygon to work
534 #define MAX_DEV_PTS 32
535
drawPoints(SkCanvas::PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint,bool forceUseDevice) const536 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
537 const SkPoint pts[], const SkPaint& paint,
538 bool forceUseDevice) const {
539 // if we're in lines mode, force count to be even
540 if (SkCanvas::kLines_PointMode == mode) {
541 count &= ~(size_t)1;
542 }
543
544 if ((long)count <= 0) {
545 return;
546 }
547
548 SkASSERT(pts != NULL);
549 SkDEBUGCODE(this->validate();)
550
551 // nothing to draw
552 if (fRC->isEmpty()) {
553 return;
554 }
555
556 PtProcRec rec;
557 if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
558 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
559
560 SkPoint devPts[MAX_DEV_PTS];
561 const SkMatrix* matrix = fMatrix;
562 SkBlitter* bltr = blitter.get();
563 PtProcRec::Proc proc = rec.chooseProc(&bltr);
564 // we have to back up subsequent passes if we're in polygon mode
565 const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
566
567 do {
568 int n = SkToInt(count);
569 if (n > MAX_DEV_PTS) {
570 n = MAX_DEV_PTS;
571 }
572 matrix->mapPoints(devPts, pts, n);
573 proc(rec, devPts, n, bltr);
574 pts += n - backup;
575 SkASSERT(SkToInt(count) >= n);
576 count -= n;
577 if (count > 0) {
578 count += backup;
579 }
580 } while (count != 0);
581 } else {
582 switch (mode) {
583 case SkCanvas::kPoints_PointMode: {
584 // temporarily mark the paint as filling.
585 SkPaint newPaint(paint);
586 newPaint.setStyle(SkPaint::kFill_Style);
587
588 SkScalar width = newPaint.getStrokeWidth();
589 SkScalar radius = SkScalarHalf(width);
590
591 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
592 SkPath path;
593 SkMatrix preMatrix;
594
595 path.addCircle(0, 0, radius);
596 for (size_t i = 0; i < count; i++) {
597 preMatrix.setTranslate(pts[i].fX, pts[i].fY);
598 // pass true for the last point, since we can modify
599 // then path then
600 path.setIsVolatile((count-1) == i);
601 if (fDevice) {
602 fDevice->drawPath(*this, path, newPaint, &preMatrix,
603 (count-1) == i);
604 } else {
605 this->drawPath(path, newPaint, &preMatrix,
606 (count-1) == i);
607 }
608 }
609 } else {
610 SkRect r;
611
612 for (size_t i = 0; i < count; i++) {
613 r.fLeft = pts[i].fX - radius;
614 r.fTop = pts[i].fY - radius;
615 r.fRight = r.fLeft + width;
616 r.fBottom = r.fTop + width;
617 if (fDevice) {
618 fDevice->drawRect(*this, r, newPaint);
619 } else {
620 this->drawRect(r, newPaint);
621 }
622 }
623 }
624 break;
625 }
626 case SkCanvas::kLines_PointMode:
627 if (2 == count && paint.getPathEffect()) {
628 // most likely a dashed line - see if it is one of the ones
629 // we can accelerate
630 SkStrokeRec rec(paint);
631 SkPathEffect::PointData pointData;
632
633 SkPath path;
634 path.moveTo(pts[0]);
635 path.lineTo(pts[1]);
636
637 SkRect cullRect = SkRect::Make(fRC->getBounds());
638
639 if (paint.getPathEffect()->asPoints(&pointData, path, rec,
640 *fMatrix, &cullRect)) {
641 // 'asPoints' managed to find some fast path
642
643 SkPaint newP(paint);
644 newP.setPathEffect(NULL);
645 newP.setStyle(SkPaint::kFill_Style);
646
647 if (!pointData.fFirst.isEmpty()) {
648 if (fDevice) {
649 fDevice->drawPath(*this, pointData.fFirst, newP);
650 } else {
651 this->drawPath(pointData.fFirst, newP);
652 }
653 }
654
655 if (!pointData.fLast.isEmpty()) {
656 if (fDevice) {
657 fDevice->drawPath(*this, pointData.fLast, newP);
658 } else {
659 this->drawPath(pointData.fLast, newP);
660 }
661 }
662
663 if (pointData.fSize.fX == pointData.fSize.fY) {
664 // The rest of the dashed line can just be drawn as points
665 SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
666
667 if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
668 newP.setStrokeCap(SkPaint::kRound_Cap);
669 } else {
670 newP.setStrokeCap(SkPaint::kButt_Cap);
671 }
672
673 if (fDevice) {
674 fDevice->drawPoints(*this,
675 SkCanvas::kPoints_PointMode,
676 pointData.fNumPoints,
677 pointData.fPoints,
678 newP);
679 } else {
680 this->drawPoints(SkCanvas::kPoints_PointMode,
681 pointData.fNumPoints,
682 pointData.fPoints,
683 newP,
684 forceUseDevice);
685 }
686 break;
687 } else {
688 // The rest of the dashed line must be drawn as rects
689 SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
690 pointData.fFlags));
691
692 SkRect r;
693
694 for (int i = 0; i < pointData.fNumPoints; ++i) {
695 r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
696 pointData.fPoints[i].fY - pointData.fSize.fY,
697 pointData.fPoints[i].fX + pointData.fSize.fX,
698 pointData.fPoints[i].fY + pointData.fSize.fY);
699 if (fDevice) {
700 fDevice->drawRect(*this, r, newP);
701 } else {
702 this->drawRect(r, newP);
703 }
704 }
705 }
706
707 break;
708 }
709 }
710 // couldn't take fast path so fall through!
711 case SkCanvas::kPolygon_PointMode: {
712 count -= 1;
713 SkPath path;
714 SkPaint p(paint);
715 p.setStyle(SkPaint::kStroke_Style);
716 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
717 path.setIsVolatile(true);
718 for (size_t i = 0; i < count; i += inc) {
719 path.moveTo(pts[i]);
720 path.lineTo(pts[i+1]);
721 if (fDevice) {
722 fDevice->drawPath(*this, path, p, NULL, true);
723 } else {
724 this->drawPath(path, p, NULL, true);
725 }
726 path.rewind();
727 }
728 break;
729 }
730 }
731 }
732 }
733
compute_stroke_size(const SkPaint & paint,const SkMatrix & matrix)734 static inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) {
735 SkASSERT(matrix.rectStaysRect());
736 SkASSERT(SkPaint::kFill_Style != paint.getStyle());
737
738 SkVector size;
739 SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
740 matrix.mapVectors(&size, &pt, 1);
741 return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY));
742 }
743
easy_rect_join(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)744 static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
745 SkPoint* strokeSize) {
746 if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
747 paint.getStrokeMiter() < SK_ScalarSqrt2) {
748 return false;
749 }
750
751 *strokeSize = compute_stroke_size(paint, matrix);
752 return true;
753 }
754
ComputeRectType(const SkPaint & paint,const SkMatrix & matrix,SkPoint * strokeSize)755 SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
756 const SkMatrix& matrix,
757 SkPoint* strokeSize) {
758 RectType rtype;
759 const SkScalar width = paint.getStrokeWidth();
760 const bool zeroWidth = (0 == width);
761 SkPaint::Style style = paint.getStyle();
762
763 if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
764 style = SkPaint::kFill_Style;
765 }
766
767 if (paint.getPathEffect() || paint.getMaskFilter() ||
768 paint.getRasterizer() || !matrix.rectStaysRect() ||
769 SkPaint::kStrokeAndFill_Style == style) {
770 rtype = kPath_RectType;
771 } else if (SkPaint::kFill_Style == style) {
772 rtype = kFill_RectType;
773 } else if (zeroWidth) {
774 rtype = kHair_RectType;
775 } else if (easy_rect_join(paint, matrix, strokeSize)) {
776 rtype = kStroke_RectType;
777 } else {
778 rtype = kPath_RectType;
779 }
780 return rtype;
781 }
782
rect_points(const SkRect & r)783 static const SkPoint* rect_points(const SkRect& r) {
784 return SkTCast<const SkPoint*>(&r);
785 }
786
rect_points(SkRect & r)787 static SkPoint* rect_points(SkRect& r) {
788 return SkTCast<SkPoint*>(&r);
789 }
790
drawRect(const SkRect & prePaintRect,const SkPaint & paint,const SkMatrix * paintMatrix,const SkRect * postPaintRect) const791 void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint,
792 const SkMatrix* paintMatrix, const SkRect* postPaintRect) const {
793 SkDEBUGCODE(this->validate();)
794
795 // nothing to draw
796 if (fRC->isEmpty()) {
797 return;
798 }
799
800 const SkMatrix* matrix;
801 SkMatrix combinedMatrixStorage;
802 if (paintMatrix) {
803 SkASSERT(postPaintRect);
804 combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix);
805 matrix = &combinedMatrixStorage;
806 } else {
807 SkASSERT(!postPaintRect);
808 matrix = fMatrix;
809 }
810
811 SkPoint strokeSize;
812 RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
813
814 if (kPath_RectType == rtype) {
815 SkDraw draw(*this);
816 if (paintMatrix) {
817 draw.fMatrix = matrix;
818 }
819 SkPath tmp;
820 tmp.addRect(prePaintRect);
821 tmp.setFillType(SkPath::kWinding_FillType);
822 draw.drawPath(tmp, paint, NULL, true);
823 return;
824 }
825
826 SkRect devRect;
827 const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect;
828 // skip the paintMatrix when transforming the rect by the CTM
829 fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2);
830 devRect.sort();
831
832 // look for the quick exit, before we build a blitter
833 SkRect bbox = devRect;
834 if (paint.getStyle() != SkPaint::kFill_Style) {
835 // extra space for hairlines
836 if (paint.getStrokeWidth() == 0) {
837 bbox.outset(1, 1);
838 } else {
839 // For kStroke_RectType, strokeSize is already computed.
840 const SkPoint& ssize = (kStroke_RectType == rtype)
841 ? strokeSize
842 : compute_stroke_size(paint, *fMatrix);
843 bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y()));
844 }
845 }
846
847 SkIRect ir = bbox.roundOut();
848 if (fRC->quickReject(ir)) {
849 return;
850 }
851
852 SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
853 while (looper.next()) {
854 SkRect localDevRect;
855 looper.mapRect(&localDevRect, devRect);
856 SkMatrix localMatrix;
857 looper.mapMatrix(&localMatrix, *matrix);
858
859 SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, paint);
860 const SkRasterClip& clip = looper.getRC();
861 SkBlitter* blitter = blitterStorage.get();
862
863 // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
864 // case we are also hairline (if we've gotten to here), which devolves to
865 // effectively just kFill
866 switch (rtype) {
867 case kFill_RectType:
868 if (paint.isAntiAlias()) {
869 SkScan::AntiFillRect(localDevRect, clip, blitter);
870 } else {
871 SkScan::FillRect(localDevRect, clip, blitter);
872 }
873 break;
874 case kStroke_RectType:
875 if (paint.isAntiAlias()) {
876 SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
877 } else {
878 SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
879 }
880 break;
881 case kHair_RectType:
882 if (paint.isAntiAlias()) {
883 SkScan::AntiHairRect(localDevRect, clip, blitter);
884 } else {
885 SkScan::HairRect(localDevRect, clip, blitter);
886 }
887 break;
888 default:
889 SkDEBUGFAIL("bad rtype");
890 }
891 }
892 }
893
drawDevMask(const SkMask & srcM,const SkPaint & paint) const894 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
895 if (srcM.fBounds.isEmpty()) {
896 return;
897 }
898
899 const SkMask* mask = &srcM;
900
901 SkMask dstM;
902 if (paint.getMaskFilter() &&
903 paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
904 mask = &dstM;
905 } else {
906 dstM.fImage = NULL;
907 }
908 SkAutoMaskFreeImage ami(dstM.fImage);
909
910 SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
911 SkBlitter* blitter = blitterChooser.get();
912
913 SkAAClipBlitterWrapper wrapper;
914 const SkRegion* clipRgn;
915
916 if (fRC->isBW()) {
917 clipRgn = &fRC->bwRgn();
918 } else {
919 wrapper.init(*fRC, blitter);
920 clipRgn = &wrapper.getRgn();
921 blitter = wrapper.getBlitter();
922 }
923 blitter->blitMaskRegion(*mask, *clipRgn);
924 }
925
fast_len(const SkVector & vec)926 static SkScalar fast_len(const SkVector& vec) {
927 SkScalar x = SkScalarAbs(vec.fX);
928 SkScalar y = SkScalarAbs(vec.fY);
929 if (x < y) {
930 SkTSwap(x, y);
931 }
932 return x + SkScalarHalf(y);
933 }
934
SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth,const SkMatrix & matrix,SkScalar * coverage)935 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
936 SkScalar* coverage) {
937 SkASSERT(strokeWidth > 0);
938 // We need to try to fake a thick-stroke with a modulated hairline.
939
940 if (matrix.hasPerspective()) {
941 return false;
942 }
943
944 SkVector src[2], dst[2];
945 src[0].set(strokeWidth, 0);
946 src[1].set(0, strokeWidth);
947 matrix.mapVectors(dst, src, 2);
948 SkScalar len0 = fast_len(dst[0]);
949 SkScalar len1 = fast_len(dst[1]);
950 if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
951 if (coverage) {
952 *coverage = SkScalarAve(len0, len1);
953 }
954 return true;
955 }
956 return false;
957 }
958
drawRRect(const SkRRect & rrect,const SkPaint & paint) const959 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
960 SkDEBUGCODE(this->validate());
961
962 if (fRC->isEmpty()) {
963 return;
964 }
965
966 {
967 // TODO: Investigate optimizing these options. They are in the same
968 // order as SkDraw::drawPath, which handles each case. It may be
969 // that there is no way to optimize for these using the SkRRect path.
970 SkScalar coverage;
971 if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
972 goto DRAW_PATH;
973 }
974
975 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
976 goto DRAW_PATH;
977 }
978
979 if (paint.getRasterizer()) {
980 goto DRAW_PATH;
981 }
982 }
983
984 if (paint.getMaskFilter()) {
985 // Transform the rrect into device space.
986 SkRRect devRRect;
987 if (rrect.transform(*fMatrix, &devRRect)) {
988 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
989 if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(),
990 SkPaint::kFill_Style)) {
991 return; // filterRRect() called the blitter, so we're done
992 }
993 }
994 }
995
996 DRAW_PATH:
997 // Now fall back to the default case of using a path.
998 SkPath path;
999 path.addRRect(rrect);
1000 this->drawPath(path, paint, NULL, true);
1001 }
1002
compute_res_scale_for_stroking(const SkMatrix & matrix)1003 static SkScalar compute_res_scale_for_stroking(const SkMatrix& matrix) {
1004 if (!matrix.hasPerspective()) {
1005 SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]);
1006 SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]);
1007 if (SkScalarsAreFinite(sx, sy)) {
1008 return SkTMax(sx, sy);
1009 }
1010 }
1011 return 1;
1012 }
1013
drawPath(const SkPath & origSrcPath,const SkPaint & origPaint,const SkMatrix * prePathMatrix,bool pathIsMutable,bool drawCoverage,SkBlitter * customBlitter) const1014 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
1015 const SkMatrix* prePathMatrix, bool pathIsMutable,
1016 bool drawCoverage, SkBlitter* customBlitter) const {
1017 SkDEBUGCODE(this->validate();)
1018
1019 // nothing to draw
1020 if (fRC->isEmpty()) {
1021 return;
1022 }
1023
1024 SkPath* pathPtr = (SkPath*)&origSrcPath;
1025 bool doFill = true;
1026 SkPath tmpPath;
1027 SkMatrix tmpMatrix;
1028 const SkMatrix* matrix = fMatrix;
1029 tmpPath.setIsVolatile(true);
1030
1031 if (prePathMatrix) {
1032 if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
1033 origPaint.getRasterizer()) {
1034 SkPath* result = pathPtr;
1035
1036 if (!pathIsMutable) {
1037 result = &tmpPath;
1038 pathIsMutable = true;
1039 }
1040 pathPtr->transform(*prePathMatrix, result);
1041 pathPtr = result;
1042 } else {
1043 tmpMatrix.setConcat(*matrix, *prePathMatrix);
1044 matrix = &tmpMatrix;
1045 }
1046 }
1047 // at this point we're done with prePathMatrix
1048 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1049
1050 SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1051
1052 {
1053 SkScalar coverage;
1054 if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1055 if (SK_Scalar1 == coverage) {
1056 paint.writable()->setStrokeWidth(0);
1057 } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) {
1058 U8CPU newAlpha;
1059 #if 0
1060 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1061 origPaint.getAlpha()));
1062 #else
1063 // this is the old technique, which we preserve for now so
1064 // we don't change previous results (testing)
1065 // the new way seems fine, its just (a tiny bit) different
1066 int scale = (int)SkScalarMul(coverage, 256);
1067 newAlpha = origPaint.getAlpha() * scale >> 8;
1068 #endif
1069 SkPaint* writablePaint = paint.writable();
1070 writablePaint->setStrokeWidth(0);
1071 writablePaint->setAlpha(newAlpha);
1072 }
1073 }
1074 }
1075
1076 if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1077 SkRect cullRect;
1078 const SkRect* cullRectPtr = NULL;
1079 if (this->computeConservativeLocalClipBounds(&cullRect)) {
1080 cullRectPtr = &cullRect;
1081 }
1082 doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr,
1083 compute_res_scale_for_stroking(*fMatrix));
1084 pathPtr = &tmpPath;
1085 }
1086
1087 if (paint->getRasterizer()) {
1088 SkMask mask;
1089 if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1090 &fRC->getBounds(), paint->getMaskFilter(), &mask,
1091 SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1092 this->drawDevMask(mask, *paint);
1093 SkMask::FreeImage(mask.fImage);
1094 }
1095 return;
1096 }
1097
1098 // avoid possibly allocating a new path in transform if we can
1099 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1100
1101 // transform the path into device space
1102 pathPtr->transform(*matrix, devPathPtr);
1103
1104 SkBlitter* blitter = NULL;
1105 SkAutoBlitterChoose blitterStorage;
1106 if (NULL == customBlitter) {
1107 blitterStorage.choose(*fBitmap, *fMatrix, *paint, drawCoverage);
1108 blitter = blitterStorage.get();
1109 } else {
1110 blitter = customBlitter;
1111 }
1112
1113 if (paint->getMaskFilter()) {
1114 SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1115 SkPaint::kStroke_Style;
1116 if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter, style)) {
1117 return; // filterPath() called the blitter, so we're done
1118 }
1119 }
1120
1121 void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1122 if (doFill) {
1123 if (paint->isAntiAlias()) {
1124 proc = SkScan::AntiFillPath;
1125 } else {
1126 proc = SkScan::FillPath;
1127 }
1128 } else { // hairline
1129 if (paint->isAntiAlias()) {
1130 proc = SkScan::AntiHairPath;
1131 } else {
1132 proc = SkScan::HairPath;
1133 }
1134 }
1135 proc(*devPathPtr, *fRC, blitter);
1136 }
1137
1138 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1139 go ahead and treat it as if it were, so that subsequent code can go fast.
1140 */
just_translate(const SkMatrix & matrix,const SkBitmap & bitmap)1141 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1142 unsigned bits = 0; // TODO: find a way to allow the caller to tell us to
1143 // respect filtering.
1144 return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1145 }
1146
drawBitmapAsMask(const SkBitmap & bitmap,const SkPaint & paint) const1147 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1148 const SkPaint& paint) const {
1149 SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType);
1150
1151 if (just_translate(*fMatrix, bitmap)) {
1152 int ix = SkScalarRoundToInt(fMatrix->getTranslateX());
1153 int iy = SkScalarRoundToInt(fMatrix->getTranslateY());
1154
1155 SkAutoLockPixels alp(bitmap);
1156 if (!bitmap.readyToDraw()) {
1157 return;
1158 }
1159
1160 SkMask mask;
1161 mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1162 mask.fFormat = SkMask::kA8_Format;
1163 mask.fRowBytes = SkToU32(bitmap.rowBytes());
1164 mask.fImage = bitmap.getAddr8(0, 0);
1165
1166 this->drawDevMask(mask, paint);
1167 } else { // need to xform the bitmap first
1168 SkRect r;
1169 SkMask mask;
1170
1171 r.set(0, 0,
1172 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1173 fMatrix->mapRect(&r);
1174 r.round(&mask.fBounds);
1175
1176 // set the mask's bounds to the transformed bitmap-bounds,
1177 // clipped to the actual device
1178 {
1179 SkIRect devBounds;
1180 devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1181 // need intersect(l, t, r, b) on irect
1182 if (!mask.fBounds.intersect(devBounds)) {
1183 return;
1184 }
1185 }
1186
1187 mask.fFormat = SkMask::kA8_Format;
1188 mask.fRowBytes = SkAlign4(mask.fBounds.width());
1189 size_t size = mask.computeImageSize();
1190 if (0 == size) {
1191 // the mask is too big to allocated, draw nothing
1192 return;
1193 }
1194
1195 // allocate (and clear) our temp buffer to hold the transformed bitmap
1196 SkAutoMalloc storage(size);
1197 mask.fImage = (uint8_t*)storage.get();
1198 memset(mask.fImage, 0, size);
1199
1200 // now draw our bitmap(src) into mask(dst), transformed by the matrix
1201 {
1202 SkBitmap device;
1203 device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
1204 mask.fImage, mask.fRowBytes);
1205
1206 SkCanvas c(device);
1207 // need the unclipped top/left for the translate
1208 c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1209 -SkIntToScalar(mask.fBounds.fTop));
1210 c.concat(*fMatrix);
1211
1212 // We can't call drawBitmap, or we'll infinitely recurse. Instead
1213 // we manually build a shader and draw that into our new mask
1214 SkPaint tmpPaint;
1215 tmpPaint.setFlags(paint.getFlags());
1216 SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1217 SkRect rr;
1218 rr.set(0, 0, SkIntToScalar(bitmap.width()),
1219 SkIntToScalar(bitmap.height()));
1220 c.drawRect(rr, install.paintWithShader());
1221 }
1222 this->drawDevMask(mask, paint);
1223 }
1224 }
1225
clipped_out(const SkMatrix & m,const SkRasterClip & c,const SkRect & srcR)1226 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1227 const SkRect& srcR) {
1228 SkRect dstR;
1229 m.mapRect(&dstR, srcR);
1230 return c.quickReject(dstR.roundOut());
1231 }
1232
clipped_out(const SkMatrix & matrix,const SkRasterClip & clip,int width,int height)1233 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1234 int width, int height) {
1235 SkRect r;
1236 r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1237 return clipped_out(matrix, clip, r);
1238 }
1239
clipHandlesSprite(const SkRasterClip & clip,int x,int y,const SkBitmap & bitmap)1240 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1241 const SkBitmap& bitmap) {
1242 return clip.isBW() ||
1243 clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1244 }
1245
drawBitmap(const SkBitmap & bitmap,const SkMatrix & prematrix,const SkRect * dstBounds,const SkPaint & origPaint) const1246 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1247 const SkRect* dstBounds, const SkPaint& origPaint) const {
1248 SkDEBUGCODE(this->validate();)
1249
1250 // nothing to draw
1251 if (fRC->isEmpty() ||
1252 bitmap.width() == 0 || bitmap.height() == 0 ||
1253 bitmap.colorType() == kUnknown_SkColorType) {
1254 return;
1255 }
1256
1257 SkPaint paint(origPaint);
1258 paint.setStyle(SkPaint::kFill_Style);
1259
1260 SkMatrix matrix;
1261 matrix.setConcat(*fMatrix, prematrix);
1262
1263 if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1264 return;
1265 }
1266
1267 if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) {
1268 //
1269 // It is safe to call lock pixels now, since we know the matrix is
1270 // (more or less) identity.
1271 //
1272 SkAutoLockPixels alp(bitmap);
1273 if (!bitmap.readyToDraw()) {
1274 return;
1275 }
1276 int ix = SkScalarRoundToInt(matrix.getTranslateX());
1277 int iy = SkScalarRoundToInt(matrix.getTranslateY());
1278 if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1279 SkTBlitterAllocator allocator;
1280 // blitter will be owned by the allocator.
1281 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1282 ix, iy, &allocator);
1283 if (blitter) {
1284 SkIRect ir;
1285 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1286
1287 SkScan::FillIRect(ir, *fRC, blitter);
1288 return;
1289 }
1290 }
1291 }
1292
1293 // now make a temp draw on the stack, and use it
1294 //
1295 SkDraw draw(*this);
1296 draw.fMatrix = &matrix;
1297
1298 if (bitmap.colorType() == kAlpha_8_SkColorType) {
1299 draw.drawBitmapAsMask(bitmap, paint);
1300 } else {
1301 SkAutoBitmapShaderInstall install(bitmap, paint);
1302 const SkPaint& paintWithShader = install.paintWithShader();
1303 const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
1304 if (dstBounds) {
1305 this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds);
1306 } else {
1307 draw.drawRect(srcBounds, paintWithShader);
1308 }
1309 }
1310 }
1311
drawSprite(const SkBitmap & bitmap,int x,int y,const SkPaint & origPaint) const1312 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1313 const SkPaint& origPaint) const {
1314 SkDEBUGCODE(this->validate();)
1315
1316 // nothing to draw
1317 if (fRC->isEmpty() ||
1318 bitmap.width() == 0 || bitmap.height() == 0 ||
1319 bitmap.colorType() == kUnknown_SkColorType) {
1320 return;
1321 }
1322
1323 SkIRect bounds;
1324 bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1325
1326 if (fRC->quickReject(bounds)) {
1327 return; // nothing to draw
1328 }
1329
1330 SkPaint paint(origPaint);
1331 paint.setStyle(SkPaint::kFill_Style);
1332
1333 if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1334 SkTBlitterAllocator allocator;
1335 // blitter will be owned by the allocator.
1336 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1337 x, y, &allocator);
1338
1339 if (blitter) {
1340 SkScan::FillIRect(bounds, *fRC, blitter);
1341 return;
1342 }
1343 }
1344
1345 SkMatrix matrix;
1346 SkRect r;
1347
1348 // get a scalar version of our rect
1349 r.set(bounds);
1350
1351 // create shader with offset
1352 matrix.setTranslate(r.fLeft, r.fTop);
1353 SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
1354 const SkPaint& shaderPaint = install.paintWithShader();
1355
1356 SkDraw draw(*this);
1357 matrix.reset();
1358 draw.fMatrix = &matrix;
1359 // call ourself with a rect
1360 // is this OK if paint has a rasterizer?
1361 draw.drawRect(r, shaderPaint);
1362 }
1363
1364 ///////////////////////////////////////////////////////////////////////////////
1365
1366 #include "SkScalerContext.h"
1367 #include "SkGlyphCache.h"
1368 #include "SkTextToPathIter.h"
1369 #include "SkUtils.h"
1370
measure_text(SkGlyphCache * cache,SkDrawCacheProc glyphCacheProc,const char text[],size_t byteLength,SkVector * stopVector)1371 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1372 const char text[], size_t byteLength, SkVector* stopVector) {
1373 SkFixed x = 0, y = 0;
1374 const char* stop = text + byteLength;
1375
1376 SkAutoKern autokern;
1377
1378 while (text < stop) {
1379 // don't need x, y here, since all subpixel variants will have the
1380 // same advance
1381 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1382
1383 x += autokern.adjust(glyph) + glyph.fAdvanceX;
1384 y += glyph.fAdvanceY;
1385 }
1386 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1387
1388 SkASSERT(text == stop);
1389 }
1390
ShouldDrawTextAsPaths(const SkPaint & paint,const SkMatrix & ctm)1391 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
1392 // hairline glyphs are fast enough so we don't need to cache them
1393 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
1394 return true;
1395 }
1396
1397 // we don't cache perspective
1398 if (ctm.hasPerspective()) {
1399 return true;
1400 }
1401
1402 SkMatrix textM;
1403 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
1404 }
1405
drawText_asPaths(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1406 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1407 SkScalar x, SkScalar y,
1408 const SkPaint& paint) const {
1409 SkDEBUGCODE(this->validate();)
1410
1411 SkTextToPathIter iter(text, byteLength, paint, true);
1412
1413 SkMatrix matrix;
1414 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1415 matrix.postTranslate(x, y);
1416
1417 const SkPath* iterPath;
1418 SkScalar xpos, prevXPos = 0;
1419
1420 while (iter.next(&iterPath, &xpos)) {
1421 matrix.postTranslate(xpos - prevXPos, 0);
1422 if (iterPath) {
1423 const SkPaint& pnt = iter.getPaint();
1424 if (fDevice) {
1425 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1426 } else {
1427 this->drawPath(*iterPath, pnt, &matrix, false);
1428 }
1429 }
1430 prevXPos = xpos;
1431 }
1432 }
1433
1434 // disable warning : local variable used without having been initialized
1435 #if defined _WIN32 && _MSC_VER >= 1300
1436 #pragma warning ( push )
1437 #pragma warning ( disable : 4701 )
1438 #endif
1439
1440 //////////////////////////////////////////////////////////////////////////////
1441
D1G_RectClip(const SkDraw1Glyph & state,Sk48Dot16 fx,Sk48Dot16 fy,const SkGlyph & glyph)1442 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) {
1443 // Prevent glyphs from being drawn outside of or straddling the edge of device space.
1444 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1445 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1446 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1447 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))
1448 {
1449 return;
1450 }
1451
1452 int left = Sk48Dot16FloorToInt(fx);
1453 int top = Sk48Dot16FloorToInt(fy);
1454 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1455 SkASSERT((NULL == state.fClip && state.fAAClip) ||
1456 (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1457
1458 left += glyph.fLeft;
1459 top += glyph.fTop;
1460
1461 int right = left + glyph.fWidth;
1462 int bottom = top + glyph.fHeight;
1463
1464 SkMask mask;
1465 SkIRect storage;
1466 SkIRect* bounds = &mask.fBounds;
1467
1468 mask.fBounds.set(left, top, right, bottom);
1469
1470 // this extra test is worth it, assuming that most of the time it succeeds
1471 // since we can avoid writing to storage
1472 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1473 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1474 return;
1475 bounds = &storage;
1476 }
1477
1478 uint8_t* aa = (uint8_t*)glyph.fImage;
1479 if (NULL == aa) {
1480 aa = (uint8_t*)state.fCache->findImage(glyph);
1481 if (NULL == aa) {
1482 return; // can't rasterize glyph
1483 }
1484 }
1485
1486 mask.fRowBytes = glyph.rowBytes();
1487 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1488 mask.fImage = aa;
1489 state.blitMask(mask, *bounds);
1490 }
1491
D1G_RgnClip(const SkDraw1Glyph & state,Sk48Dot16 fx,Sk48Dot16 fy,const SkGlyph & glyph)1492 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) {
1493 int left = Sk48Dot16FloorToInt(fx);
1494 int top = Sk48Dot16FloorToInt(fy);
1495 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1496 SkASSERT(!state.fClip->isRect());
1497
1498 SkMask mask;
1499
1500 left += glyph.fLeft;
1501 top += glyph.fTop;
1502
1503 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1504 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1505
1506 if (!clipper.done()) {
1507 const SkIRect& cr = clipper.rect();
1508 const uint8_t* aa = (const uint8_t*)glyph.fImage;
1509 if (NULL == aa) {
1510 aa = (uint8_t*)state.fCache->findImage(glyph);
1511 if (NULL == aa) {
1512 return;
1513 }
1514 }
1515
1516 mask.fRowBytes = glyph.rowBytes();
1517 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1518 mask.fImage = (uint8_t*)aa;
1519 do {
1520 state.blitMask(mask, cr);
1521 clipper.next();
1522 } while (!clipper.done());
1523 }
1524 }
1525
hasCustomD1GProc(const SkDraw & draw)1526 static bool hasCustomD1GProc(const SkDraw& draw) {
1527 return draw.fProcs && draw.fProcs->fD1GProc;
1528 }
1529
needsRasterTextBlit(const SkDraw & draw)1530 static bool needsRasterTextBlit(const SkDraw& draw) {
1531 return !hasCustomD1GProc(draw);
1532 }
1533
init(const SkDraw * draw,SkBlitter * blitter,SkGlyphCache * cache,const SkPaint & pnt)1534 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
1535 const SkPaint& pnt) {
1536 fDraw = draw;
1537 fBlitter = blitter;
1538 fCache = cache;
1539 fPaint = &pnt;
1540
1541 if (cache->isSubpixel()) {
1542 fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
1543 } else {
1544 fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
1545 }
1546
1547 if (hasCustomD1GProc(*draw)) {
1548 // todo: fix this assumption about clips w/ custom
1549 fClip = draw->fClip;
1550 fClipBounds = fClip->getBounds();
1551 return draw->fProcs->fD1GProc;
1552 }
1553
1554 if (draw->fRC->isBW()) {
1555 fAAClip = NULL;
1556 fClip = &draw->fRC->bwRgn();
1557 fClipBounds = fClip->getBounds();
1558 if (fClip->isRect()) {
1559 return D1G_RectClip;
1560 } else {
1561 return D1G_RgnClip;
1562 }
1563 } else { // aaclip
1564 fAAClip = &draw->fRC->aaRgn();
1565 fClip = NULL;
1566 fClipBounds = fAAClip->getBounds();
1567 return D1G_RectClip;
1568 }
1569 }
1570
blitMaskAsSprite(const SkMask & mask) const1571 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1572 SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1573
1574 SkBitmap bm;
1575 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
1576 (SkPMColor*)mask.fImage, mask.fRowBytes);
1577
1578 fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1579 }
1580
1581 ///////////////////////////////////////////////////////////////////////////////
1582
drawText(const char text[],size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint) const1583 void SkDraw::drawText(const char text[], size_t byteLength,
1584 SkScalar x, SkScalar y, const SkPaint& paint) const {
1585 SkASSERT(byteLength == 0 || text != NULL);
1586
1587 SkDEBUGCODE(this->validate();)
1588
1589 // nothing to draw
1590 if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1591 return;
1592 }
1593
1594 // SkScalarRec doesn't currently have a way of representing hairline stroke and
1595 // will fill if its frame-width is 0.
1596 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1597 this->drawText_asPaths(text, byteLength, x, y, paint);
1598 return;
1599 }
1600
1601 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1602
1603 SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
1604 SkGlyphCache* cache = autoCache.getCache();
1605
1606 // transform our starting point
1607 {
1608 SkPoint loc;
1609 fMatrix->mapXY(x, y, &loc);
1610 x = loc.fX;
1611 y = loc.fY;
1612 }
1613
1614 // need to measure first
1615 if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1616 SkVector stop;
1617
1618 measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1619
1620 SkScalar stopX = stop.fX;
1621 SkScalar stopY = stop.fY;
1622
1623 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1624 stopX = SkScalarHalf(stopX);
1625 stopY = SkScalarHalf(stopY);
1626 }
1627 x -= stopX;
1628 y -= stopY;
1629 }
1630
1631 const char* stop = text + byteLength;
1632
1633 SkAAClipBlitter aaBlitter;
1634 SkAutoBlitterChoose blitterChooser;
1635 SkBlitter* blitter = NULL;
1636 if (needsRasterTextBlit(*this)) {
1637 blitterChooser.choose(*fBitmap, *fMatrix, paint);
1638 blitter = blitterChooser.get();
1639 if (fRC->isAA()) {
1640 aaBlitter.init(blitter, &fRC->aaRgn());
1641 blitter = &aaBlitter;
1642 }
1643 }
1644
1645 SkAutoKern autokern;
1646 SkDraw1Glyph d1g;
1647 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1648
1649 SkFixed fxMask = ~0;
1650 SkFixed fyMask = ~0;
1651 if (cache->isSubpixel()) {
1652 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1653 if (kX_SkAxisAlignment == baseline) {
1654 fyMask = 0;
1655 d1g.fHalfSampleY = SK_ScalarHalf;
1656 } else if (kY_SkAxisAlignment == baseline) {
1657 fxMask = 0;
1658 d1g.fHalfSampleX = SK_ScalarHalf;
1659 }
1660 }
1661
1662 Sk48Dot16 fx = SkScalarTo48Dot16(x + d1g.fHalfSampleX);
1663 Sk48Dot16 fy = SkScalarTo48Dot16(y + d1g.fHalfSampleY);
1664
1665 while (text < stop) {
1666 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1667
1668 fx += autokern.adjust(glyph);
1669
1670 if (glyph.fWidth) {
1671 proc(d1g, fx, fy, glyph);
1672 }
1673
1674 fx += glyph.fAdvanceX;
1675 fy += glyph.fAdvanceY;
1676 }
1677 }
1678
1679 //////////////////////////////////////////////////////////////////////////////
1680
drawPosText_asPaths(const char text[],size_t byteLength,const SkScalar pos[],int scalarsPerPosition,const SkPoint & offset,const SkPaint & origPaint) const1681 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1682 const SkScalar pos[], int scalarsPerPosition,
1683 const SkPoint& offset, const SkPaint& origPaint) const {
1684 // setup our std paint, in hopes of getting hits in the cache
1685 SkPaint paint(origPaint);
1686 SkScalar matrixScale = paint.setupForAsPaths();
1687
1688 SkMatrix matrix;
1689 matrix.setScale(matrixScale, matrixScale);
1690
1691 // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
1692 paint.setStyle(SkPaint::kFill_Style);
1693 paint.setPathEffect(NULL);
1694
1695 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1696 SkAutoGlyphCache autoCache(paint, NULL, NULL);
1697 SkGlyphCache* cache = autoCache.getCache();
1698
1699 const char* stop = text + byteLength;
1700 SkTextAlignProc alignProc(paint.getTextAlign());
1701 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
1702
1703 // Now restore the original settings, so we "draw" with whatever style/stroking.
1704 paint.setStyle(origPaint.getStyle());
1705 paint.setPathEffect(origPaint.getPathEffect());
1706
1707 while (text < stop) {
1708 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1709 if (glyph.fWidth) {
1710 const SkPath* path = cache->findPath(glyph);
1711 if (path) {
1712 SkPoint tmsLoc;
1713 tmsProc(pos, &tmsLoc);
1714 SkPoint loc;
1715 alignProc(tmsLoc, glyph, &loc);
1716
1717 matrix[SkMatrix::kMTransX] = loc.fX;
1718 matrix[SkMatrix::kMTransY] = loc.fY;
1719 if (fDevice) {
1720 fDevice->drawPath(*this, *path, paint, &matrix, false);
1721 } else {
1722 this->drawPath(*path, paint, &matrix, false);
1723 }
1724 }
1725 }
1726 pos += scalarsPerPosition;
1727 }
1728 }
1729
drawPosText(const char text[],size_t byteLength,const SkScalar pos[],int scalarsPerPosition,const SkPoint & offset,const SkPaint & paint) const1730 void SkDraw::drawPosText(const char text[], size_t byteLength,
1731 const SkScalar pos[], int scalarsPerPosition,
1732 const SkPoint& offset, const SkPaint& paint) const {
1733 SkASSERT(byteLength == 0 || text != NULL);
1734 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1735
1736 SkDEBUGCODE(this->validate();)
1737
1738 // nothing to draw
1739 if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1740 return;
1741 }
1742
1743 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1744 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint);
1745 return;
1746 }
1747
1748 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1749 SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
1750 SkGlyphCache* cache = autoCache.getCache();
1751
1752 SkAAClipBlitterWrapper wrapper;
1753 SkAutoBlitterChoose blitterChooser;
1754 SkBlitter* blitter = NULL;
1755 if (needsRasterTextBlit(*this)) {
1756 blitterChooser.choose(*fBitmap, *fMatrix, paint);
1757 blitter = blitterChooser.get();
1758 if (fRC->isAA()) {
1759 wrapper.init(*fRC, blitter);
1760 blitter = wrapper.getBlitter();
1761 }
1762 }
1763
1764 const char* stop = text + byteLength;
1765 SkTextAlignProc alignProc(paint.getTextAlign());
1766 SkDraw1Glyph d1g;
1767 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1768 SkTextMapStateProc tmsProc(*fMatrix, offset, scalarsPerPosition);
1769
1770 if (cache->isSubpixel()) {
1771 // maybe we should skip the rounding if linearText is set
1772 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1773
1774 SkFixed fxMask = ~0;
1775 SkFixed fyMask = ~0;
1776 if (kX_SkAxisAlignment == baseline) {
1777 fyMask = 0;
1778 d1g.fHalfSampleY = SK_ScalarHalf;
1779 } else if (kY_SkAxisAlignment == baseline) {
1780 fxMask = 0;
1781 d1g.fHalfSampleX = SK_ScalarHalf;
1782 }
1783
1784 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1785 while (text < stop) {
1786 SkPoint tmsLoc;
1787 tmsProc(pos, &tmsLoc);
1788
1789 Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + d1g.fHalfSampleX);
1790 Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + d1g.fHalfSampleY);
1791
1792 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1793
1794 if (glyph.fWidth) {
1795 proc(d1g, fx, fy, glyph);
1796 }
1797 pos += scalarsPerPosition;
1798 }
1799 } else {
1800 while (text < stop) {
1801 const char* currentText = text;
1802 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
1803
1804 if (metricGlyph.fWidth) {
1805 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
1806 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
1807 SkPoint tmsLoc;
1808 tmsProc(pos, &tmsLoc);
1809
1810 SkPoint alignLoc;
1811 alignProc(tmsLoc, metricGlyph, &alignLoc);
1812
1813 Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + d1g.fHalfSampleX);
1814 Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + d1g.fHalfSampleY);
1815
1816 // have to call again, now that we've been "aligned"
1817 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText,
1818 fx & fxMask, fy & fyMask);
1819 // the assumption is that the metrics haven't changed
1820 SkASSERT(prevAdvX == glyph.fAdvanceX);
1821 SkASSERT(prevAdvY == glyph.fAdvanceY);
1822 SkASSERT(glyph.fWidth);
1823
1824 proc(d1g, fx, fy, glyph);
1825 }
1826 pos += scalarsPerPosition;
1827 }
1828 }
1829 } else { // not subpixel
1830 if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1831 while (text < stop) {
1832 // the last 2 parameters are ignored
1833 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1834
1835 if (glyph.fWidth) {
1836 SkPoint tmsLoc;
1837 tmsProc(pos, &tmsLoc);
1838
1839 proc(d1g,
1840 SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX,
1841 SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY,
1842 glyph);
1843 }
1844 pos += scalarsPerPosition;
1845 }
1846 } else {
1847 while (text < stop) {
1848 // the last 2 parameters are ignored
1849 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1850
1851 if (glyph.fWidth) {
1852 SkPoint tmsLoc;
1853 tmsProc(pos, &tmsLoc);
1854
1855 SkPoint alignLoc;
1856 alignProc(tmsLoc, glyph, &alignLoc);
1857
1858 proc(d1g,
1859 SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX,
1860 SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY,
1861 glyph);
1862 }
1863 pos += scalarsPerPosition;
1864 }
1865 }
1866 }
1867 }
1868
1869 #if defined _WIN32 && _MSC_VER >= 1300
1870 #pragma warning ( pop )
1871 #endif
1872
1873 ///////////////////////////////////////////////////////////////////////////////
1874
ChooseHairProc(bool doAntiAlias)1875 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
1876 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
1877 }
1878
texture_to_matrix(const VertState & state,const SkPoint verts[],const SkPoint texs[],SkMatrix * matrix)1879 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
1880 const SkPoint texs[], SkMatrix* matrix) {
1881 SkPoint src[3], dst[3];
1882
1883 src[0] = texs[state.f0];
1884 src[1] = texs[state.f1];
1885 src[2] = texs[state.f2];
1886 dst[0] = verts[state.f0];
1887 dst[1] = verts[state.f1];
1888 dst[2] = verts[state.f2];
1889 return matrix->setPolyToPoly(src, dst, 3);
1890 }
1891
1892 class SkTriColorShader : public SkShader {
1893 public:
SkTriColorShader()1894 SkTriColorShader() {}
1895
1896 size_t contextSize() const override;
1897
1898 class TriColorShaderContext : public SkShader::Context {
1899 public:
1900 TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&);
1901 virtual ~TriColorShaderContext();
1902
1903 bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
1904
1905 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override;
1906
1907 private:
1908 SkMatrix fDstToUnit;
1909 SkPMColor fColors[3];
1910
1911 typedef SkShader::Context INHERITED;
1912 };
1913
SK_TO_STRING_OVERRIDE()1914 SK_TO_STRING_OVERRIDE()
1915
1916 // For serialization. This will never be called.
1917 Factory getFactory() const override { sk_throw(); return NULL; }
1918
1919 protected:
onCreateContext(const ContextRec & rec,void * storage) const1920 Context* onCreateContext(const ContextRec& rec, void* storage) const override {
1921 return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec));
1922 }
1923
1924 private:
1925 typedef SkShader INHERITED;
1926 };
1927
setup(const SkPoint pts[],const SkColor colors[],int index0,int index1,int index2)1928 bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[],
1929 int index0, int index1, int index2) {
1930
1931 fColors[0] = SkPreMultiplyColor(colors[index0]);
1932 fColors[1] = SkPreMultiplyColor(colors[index1]);
1933 fColors[2] = SkPreMultiplyColor(colors[index2]);
1934
1935 SkMatrix m, im;
1936 m.reset();
1937 m.set(0, pts[index1].fX - pts[index0].fX);
1938 m.set(1, pts[index2].fX - pts[index0].fX);
1939 m.set(2, pts[index0].fX);
1940 m.set(3, pts[index1].fY - pts[index0].fY);
1941 m.set(4, pts[index2].fY - pts[index0].fY);
1942 m.set(5, pts[index0].fY);
1943 if (!m.invert(&im)) {
1944 return false;
1945 }
1946 // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix
1947 // as our interators are intrinsically tied to the vertices, and nothing else.
1948 SkMatrix ctmInv;
1949 if (!this->getCTM().invert(&ctmInv)) {
1950 return false;
1951 }
1952 fDstToUnit.setConcat(im, ctmInv);
1953 return true;
1954 }
1955
1956 #include "SkColorPriv.h"
1957 #include "SkComposeShader.h"
1958
ScalarTo256(SkScalar v)1959 static int ScalarTo256(SkScalar v) {
1960 int scale = SkScalarToFixed(v) >> 8;
1961 if (scale < 0) {
1962 scale = 0;
1963 }
1964 if (scale > 255) {
1965 scale = 255;
1966 }
1967 return SkAlpha255To256(scale);
1968 }
1969
1970
TriColorShaderContext(const SkTriColorShader & shader,const ContextRec & rec)1971 SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader,
1972 const ContextRec& rec)
1973 : INHERITED(shader, rec) {}
1974
~TriColorShaderContext()1975 SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {}
1976
contextSize() const1977 size_t SkTriColorShader::contextSize() const {
1978 return sizeof(TriColorShaderContext);
1979 }
shadeSpan(int x,int y,SkPMColor dstC[],int count)1980 void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
1981 const int alphaScale = Sk255To256(this->getPaintAlpha());
1982
1983 SkPoint src;
1984
1985 for (int i = 0; i < count; i++) {
1986 fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
1987 x += 1;
1988
1989 int scale1 = ScalarTo256(src.fX);
1990 int scale2 = ScalarTo256(src.fY);
1991 int scale0 = 256 - scale1 - scale2;
1992 if (scale0 < 0) {
1993 if (scale1 > scale2) {
1994 scale2 = 256 - scale1;
1995 } else {
1996 scale1 = 256 - scale2;
1997 }
1998 scale0 = 0;
1999 }
2000
2001 if (256 != alphaScale) {
2002 scale0 = SkAlphaMul(scale0, alphaScale);
2003 scale1 = SkAlphaMul(scale1, alphaScale);
2004 scale2 = SkAlphaMul(scale2, alphaScale);
2005 }
2006
2007 dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2008 SkAlphaMulQ(fColors[1], scale1) +
2009 SkAlphaMulQ(fColors[2], scale2);
2010 }
2011 }
2012
2013 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const2014 void SkTriColorShader::toString(SkString* str) const {
2015 str->append("SkTriColorShader: (");
2016
2017 this->INHERITED::toString(str);
2018
2019 str->append(")");
2020 }
2021 #endif
2022
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) const2023 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2024 const SkPoint vertices[], const SkPoint textures[],
2025 const SkColor colors[], SkXfermode* xmode,
2026 const uint16_t indices[], int indexCount,
2027 const SkPaint& paint) const {
2028 SkASSERT(0 == count || vertices);
2029
2030 // abort early if there is nothing to draw
2031 if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2032 return;
2033 }
2034
2035 // transform out vertices into device coordinates
2036 SkAutoSTMalloc<16, SkPoint> storage(count);
2037 SkPoint* devVerts = storage.get();
2038 fMatrix->mapPoints(devVerts, vertices, count);
2039
2040 /*
2041 We can draw the vertices in 1 of 4 ways:
2042
2043 - solid color (no shader/texture[], no colors[])
2044 - just colors (no shader/texture[], has colors[])
2045 - just texture (has shader/texture[], no colors[])
2046 - colors * texture (has shader/texture[], has colors[])
2047
2048 Thus for texture drawing, we need both texture[] and a shader.
2049 */
2050
2051 SkTriColorShader triShader; // must be above declaration of p
2052 SkPaint p(paint);
2053
2054 SkShader* shader = p.getShader();
2055 if (NULL == shader) {
2056 // if we have no shader, we ignore the texture coordinates
2057 textures = NULL;
2058 } else if (NULL == textures) {
2059 // if we don't have texture coordinates, ignore the shader
2060 p.setShader(NULL);
2061 shader = NULL;
2062 }
2063
2064 // setup the custom shader (if needed)
2065 SkAutoTUnref<SkComposeShader> composeShader;
2066 if (colors) {
2067 if (NULL == textures) {
2068 // just colors (no texture)
2069 shader = p.setShader(&triShader);
2070 } else {
2071 // colors * texture
2072 SkASSERT(shader);
2073 bool releaseMode = false;
2074 if (NULL == xmode) {
2075 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2076 releaseMode = true;
2077 }
2078 composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode)));
2079 p.setShader(composeShader);
2080 if (releaseMode) {
2081 xmode->unref();
2082 }
2083 }
2084 }
2085
2086 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2087 // Abort early if we failed to create a shader context.
2088 if (blitter->isNullBlitter()) {
2089 return;
2090 }
2091
2092 // setup our state and function pointer for iterating triangles
2093 VertState state(count, indices, indexCount);
2094 VertState::Proc vertProc = state.chooseProc(vmode);
2095
2096 if (textures || colors) {
2097 while (vertProc(&state)) {
2098 if (textures) {
2099 SkMatrix tempM;
2100 if (texture_to_matrix(state, vertices, textures, &tempM)) {
2101 SkShader::ContextRec rec(*fBitmap, p, *fMatrix);
2102 rec.fLocalMatrix = &tempM;
2103 if (!blitter->resetShaderContext(rec)) {
2104 continue;
2105 }
2106 }
2107 }
2108 if (colors) {
2109 // Find the context for triShader.
2110 SkTriColorShader::TriColorShaderContext* triColorShaderContext;
2111
2112 SkShader::Context* shaderContext = blitter->getShaderContext();
2113 SkASSERT(shaderContext);
2114 if (p.getShader() == &triShader) {
2115 triColorShaderContext =
2116 static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext);
2117 } else {
2118 // The shader is a compose shader and triShader is its first shader.
2119 SkASSERT(p.getShader() == composeShader);
2120 SkASSERT(composeShader->getShaderA() == &triShader);
2121 SkComposeShader::ComposeShaderContext* composeShaderContext =
2122 static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext);
2123 SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA();
2124 triColorShaderContext =
2125 static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA);
2126 }
2127
2128 if (!triColorShaderContext->setup(vertices, colors,
2129 state.f0, state.f1, state.f2)) {
2130 continue;
2131 }
2132 }
2133
2134 SkPoint tmp[] = {
2135 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2136 };
2137 SkScan::FillTriangle(tmp, *fRC, blitter.get());
2138 }
2139 } else {
2140 // no colors[] and no texture, stroke hairlines with paint's color.
2141 SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias());
2142 const SkRasterClip& clip = *fRC;
2143 while (vertProc(&state)) {
2144 SkPoint array[] = {
2145 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0]
2146 };
2147 hairProc(array, 4, clip, blitter.get());
2148 }
2149 }
2150 }
2151
2152 ///////////////////////////////////////////////////////////////////////////////
2153 ///////////////////////////////////////////////////////////////////////////////
2154
2155 #ifdef SK_DEBUG
2156
validate() const2157 void SkDraw::validate() const {
2158 SkASSERT(fBitmap != NULL);
2159 SkASSERT(fMatrix != NULL);
2160 SkASSERT(fClip != NULL);
2161 SkASSERT(fRC != NULL);
2162
2163 const SkIRect& cr = fRC->getBounds();
2164 SkIRect br;
2165
2166 br.set(0, 0, fBitmap->width(), fBitmap->height());
2167 SkASSERT(cr.isEmpty() || br.contains(cr));
2168 }
2169
2170 #endif
2171
2172 ////////////////////////////////////////////////////////////////////////////////////////////////
2173
2174 #include "SkPath.h"
2175 #include "SkDraw.h"
2176 #include "SkRegion.h"
2177 #include "SkBlitter.h"
2178
compute_bounds(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkIRect * bounds)2179 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2180 const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2181 SkIRect* bounds) {
2182 if (devPath.isEmpty()) {
2183 return false;
2184 }
2185
2186 // init our bounds from the path
2187 *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut();
2188
2189 SkIPoint margin = SkIPoint::Make(0, 0);
2190 if (filter) {
2191 SkASSERT(filterMatrix);
2192
2193 SkMask srcM, dstM;
2194
2195 srcM.fBounds = *bounds;
2196 srcM.fFormat = SkMask::kA8_Format;
2197 srcM.fImage = NULL;
2198 if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2199 return false;
2200 }
2201 }
2202
2203 // (possibly) trim the bounds to reflect the clip
2204 // (plus whatever slop the filter needs)
2205 if (clipBounds) {
2206 // Ugh. Guard against gigantic margins from wacky filters. Without this
2207 // check we can request arbitrary amounts of slop beyond our visible
2208 // clip, and bring down the renderer (at least on finite RAM machines
2209 // like handsets, etc.). Need to balance this invented value between
2210 // quality of large filters like blurs, and the corresponding memory
2211 // requests.
2212 static const int MAX_MARGIN = 128;
2213 if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN),
2214 SkMin32(margin.fY, MAX_MARGIN)))) {
2215 return false;
2216 }
2217 }
2218
2219 return true;
2220 }
2221
draw_into_mask(const SkMask & mask,const SkPath & devPath,SkPaint::Style style)2222 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2223 SkPaint::Style style) {
2224 SkBitmap bm;
2225 SkDraw draw;
2226 SkRasterClip clip;
2227 SkMatrix matrix;
2228 SkPaint paint;
2229
2230 bm.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
2231 mask.fImage, mask.fRowBytes);
2232
2233 clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2234 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2235 -SkIntToScalar(mask.fBounds.fTop));
2236
2237 draw.fBitmap = &bm;
2238 draw.fRC = &clip;
2239 draw.fClip = &clip.bwRgn();
2240 draw.fMatrix = &matrix;
2241 paint.setAntiAlias(true);
2242 paint.setStyle(style);
2243 draw.drawPath(devPath, paint);
2244 }
2245
DrawToMask(const SkPath & devPath,const SkIRect * clipBounds,const SkMaskFilter * filter,const SkMatrix * filterMatrix,SkMask * mask,SkMask::CreateMode mode,SkPaint::Style style)2246 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2247 const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2248 SkMask* mask, SkMask::CreateMode mode,
2249 SkPaint::Style style) {
2250 if (SkMask::kJustRenderImage_CreateMode != mode) {
2251 if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2252 return false;
2253 }
2254
2255 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2256 mask->fFormat = SkMask::kA8_Format;
2257 mask->fRowBytes = mask->fBounds.width();
2258 size_t size = mask->computeImageSize();
2259 if (0 == size) {
2260 // we're too big to allocate the mask, abort
2261 return false;
2262 }
2263 mask->fImage = SkMask::AllocImage(size);
2264 memset(mask->fImage, 0, mask->computeImageSize());
2265 }
2266
2267 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2268 draw_into_mask(*mask, devPath, style);
2269 }
2270
2271 return true;
2272 }
2273