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