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