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