blob: bb6b31eefc5e59e0499c25d0ea1014643ccd3840 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/sgl/SkPaint.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 "SkPaint.h"
19#include "SkColorFilter.h"
20#include "SkDrawLooper.h"
21#include "SkFontHost.h"
22#include "SkMaskFilter.h"
23#include "SkPathEffect.h"
24#include "SkRasterizer.h"
25#include "SkShader.h"
26#include "SkScalerContext.h"
27#include "SkStroke.h"
28#include "SkTypeface.h"
29#include "SkXfermode.h"
30#include "SkAutoKern.h"
31
32#define SK_DefaultTextSize SkIntToScalar(12)
33
34#define SK_DefaultFlags 0 //(kNativeHintsText_Flag)
35
36SkPaint::SkPaint()
37{
38 fTypeface = NULL;
39 fTextSize = SK_DefaultTextSize;
40 fTextScaleX = SK_Scalar1;
41 fTextSkewX = 0;
42
43 fPathEffect = NULL;
44 fShader = NULL;
45 fXfermode = NULL;
46 fMaskFilter = NULL;
47 fColorFilter = NULL;
48 fRasterizer = NULL;
49 fLooper = NULL;
50
51 fColor = SK_ColorBLACK;
52 fWidth = 0;
53 fMiterLimit = SK_DefaultMiterLimit;
54 fFlags = SK_DefaultFlags;
55 fCapType = kDefault_Cap;
56 fJoinType = kDefault_Join;
57 fTextAlign = kLeft_Align;
58 fStyle = kFill_Style;
59 fTextEncoding = kUTF8_TextEncoding;
60}
61
62SkPaint::SkPaint(const SkPaint& src)
63{
64 memcpy(this, &src, sizeof(src));
65
66 fTypeface->safeRef();
67 fPathEffect->safeRef();
68 fShader->safeRef();
69 fXfermode->safeRef();
70 fMaskFilter->safeRef();
71 fColorFilter->safeRef();
72 fRasterizer->safeRef();
73 fLooper->safeRef();
74}
75
76SkPaint::~SkPaint()
77{
78 fTypeface->safeUnref();
79 fPathEffect->safeUnref();
80 fShader->safeUnref();
81 fXfermode->safeUnref();
82 fMaskFilter->safeUnref();
83 fColorFilter->safeUnref();
84 fRasterizer->safeUnref();
85 fLooper->safeUnref();
86}
87
88SkPaint& SkPaint::operator=(const SkPaint& src)
89{
90 SkASSERT(&src);
91
92 src.fTypeface->safeRef();
93 src.fPathEffect->safeRef();
94 src.fShader->safeRef();
95 src.fXfermode->safeRef();
96 src.fMaskFilter->safeRef();
97 src.fColorFilter->safeRef();
98 src.fRasterizer->safeRef();
99 src.fLooper->safeRef();
100
101 fTypeface->safeUnref();
102 fPathEffect->safeUnref();
103 fShader->safeUnref();
104 fXfermode->safeUnref();
105 fMaskFilter->safeUnref();
106 fColorFilter->safeUnref();
107 fRasterizer->safeUnref();
108 fLooper->safeUnref();
109
110 memcpy(this, &src, sizeof(src));
111
112 return *this;
113}
114
115int operator==(const SkPaint& a, const SkPaint& b)
116{
117 return memcmp(&a, &b, sizeof(a)) == 0;
118}
119
120void SkPaint::reset()
121{
122 SkPaint init;
123
124 *this = init;
125}
126
127void SkPaint::setFlags(uint32_t flags)
128{
129 fFlags = flags;
130}
131
132void SkPaint::setAntiAlias(bool doAA)
133{
134 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
135}
136
137void SkPaint::setDither(bool doDither)
138{
139 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
140}
141
142void SkPaint::setSubpixelText(bool doSubpixel)
143{
144 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
145}
146
147void SkPaint::setLinearText(bool doLinearText)
148{
149 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
150}
151
152void SkPaint::setUnderlineText(bool doUnderline)
153{
154 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
155}
156
157void SkPaint::setStrikeThruText(bool doStrikeThru)
158{
159 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
160}
161
162void SkPaint::setFakeBoldText(bool doFakeBold)
163{
164 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
165}
166
167void SkPaint::setDevKernText(bool doDevKern)
168{
169 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
170}
171
172void SkPaint::setFilterBitmap(bool doFilter)
173{
174 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
175}
176
177void SkPaint::setStyle(Style style)
178{
179 if ((unsigned)style < kStyleCount)
180 fStyle = style;
181#ifdef SK_DEBUG
182 else
183 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
184#endif
185}
186
187void SkPaint::setColor(SkColor color)
188{
189 fColor = color;
190}
191
192void SkPaint::setAlpha(U8CPU a)
193{
194 fColor = SkColorSetARGB(a, SkColorGetR(fColor), SkColorGetG(fColor), SkColorGetB(fColor));
195}
196
197void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
198{
199 fColor = SkColorSetARGB(a, r, g, b);
200}
201
202void SkPaint::setStrokeWidth(SkScalar width)
203{
204 if (width >= 0)
205 fWidth = width;
206#ifdef SK_DEBUG
207 else
208 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
209#endif
210}
211
212void SkPaint::setStrokeMiter(SkScalar limit)
213{
214 if (limit >= 0)
215 fMiterLimit = limit;
216#ifdef SK_DEBUG
217 else
218 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
219#endif
220}
221
222void SkPaint::setStrokeCap(Cap ct)
223{
224 if ((unsigned)ct < kCapCount)
225 fCapType = SkToU8(ct);
226#ifdef SK_DEBUG
227 else
228 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
229#endif
230}
231
232void SkPaint::setStrokeJoin(Join jt)
233{
234 if ((unsigned)jt < kJoinCount)
235 fJoinType = SkToU8(jt);
236#ifdef SK_DEBUG
237 else
238 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
239#endif
240}
241
242//////////////////////////////////////////////////////////////////
243
244void SkPaint::setTextAlign(Align align)
245{
246 if ((unsigned)align < kAlignCount)
247 fTextAlign = SkToU8(align);
248#ifdef SK_DEBUG
249 else
250 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
251#endif
252}
253
254void SkPaint::setTextSize(SkScalar ts)
255{
256 if (ts > 0)
257 fTextSize = ts;
258#ifdef SK_DEBUG
259 else
260 SkDebugf("SkPaint::setTextSize() called with non-positive value\n");
261#endif
262}
263
264void SkPaint::setTextScaleX(SkScalar scaleX)
265{
266 fTextScaleX = scaleX;
267}
268
269void SkPaint::setTextSkewX(SkScalar skewX)
270{
271 fTextSkewX = skewX;
272}
273
274void SkPaint::setTextEncoding(TextEncoding encoding)
275{
276 if ((unsigned)encoding <= kGlyphID_TextEncoding)
277 fTextEncoding = encoding;
278#ifdef SK_DEBUG
279 else
280 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
281#endif
282}
283
284///////////////////////////////////////////////////////////////////////////////////////
285
286SkTypeface* SkPaint::setTypeface(SkTypeface* font)
287{
288 SkRefCnt_SafeAssign(fTypeface, font);
289 return font;
290}
291
292SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r)
293{
294 SkRefCnt_SafeAssign(fRasterizer, r);
295 return r;
296}
297
298SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper)
299{
300 SkRefCnt_SafeAssign(fLooper, looper);
301 return looper;
302}
303
304///////////////////////////////////////////////////////////////////////////////
305
306#include "SkGlyphCache.h"
307#include "SkUtils.h"
308
309int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
310 uint16_t glyphs[]) const {
311 if (byteLength == 0) {
312 return 0;
313 }
314
315 SkASSERT(textData != NULL);
316
317 if (NULL == glyphs) {
318 switch (this->getTextEncoding()) {
319 case kUTF8_TextEncoding:
320 return SkUTF8_CountUnichars((const char*)textData, byteLength);
321 case kUTF16_TextEncoding:
322 return SkUTF16_CountUnichars((const uint16_t*)textData,
323 byteLength >> 1);
324 case kGlyphID_TextEncoding:
325 return byteLength >> 1;
326 default:
327 SkASSERT(!"unknown text encoding");
328 }
329 return 0;
330 }
331
332 // if we get here, we have a valid glyphs[] array, so time to fill it in
333
334 // handle this encoding before the setup for the glyphcache
335 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
336 // we want to ignore the low bit of byteLength
337 memcpy(glyphs, textData, byteLength >> 1 << 1);
338 return byteLength >> 1;
339 }
340
341 SkAutoGlyphCache autoCache(*this, NULL);
342 SkGlyphCache* cache = autoCache.getCache();
343
344 const char* text = (const char*)textData;
345 const char* stop = text + byteLength;
346 uint16_t* gptr = glyphs;
347
348 switch (this->getTextEncoding()) {
349 case SkPaint::kUTF8_TextEncoding:
350 while (text < stop) {
351 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
352 }
353 break;
354 case SkPaint::kUTF16_TextEncoding: {
355 const uint16_t* text16 = (const uint16_t*)text;
356 const uint16_t* stop16 = (const uint16_t*)stop;
357 while (text16 < stop16) {
358 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
359 }
360 break;
361 }
362 default:
363 SkASSERT(!"unknown text encoding");
364 }
365 return gptr - glyphs;
366}
367
368///////////////////////////////////////////////////////////////////////////////
369
370static uint32_t sk_glyphID_next(const char** text)
371{
372 const uint16_t* glyph = (const uint16_t*)text;
373 int32_t value = *glyph;
374 glyph += 1;
375 *text = (const char*)glyph;
376 return value;
377}
378
379static uint32_t sk_glyphID_prev(const char** text)
380{
381 const uint16_t* glyph = (const uint16_t*)text;
382 glyph -= 1;
383 int32_t value = *glyph;
384 *text = (const char*)glyph;
385 return value;
386}
387
388//////////////////////////////////////////////////////////////////////////////
389
390static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache, const char** text)
391{
392 SkASSERT(cache != NULL);
393 SkASSERT(text != NULL);
394
395 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
396}
397
398static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache, const char** text)
399{
400 SkASSERT(cache != NULL);
401 SkASSERT(text != NULL);
402
403 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
404}
405
406static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache, const char** text)
407{
408 SkASSERT(cache != NULL);
409 SkASSERT(text != NULL);
410
411 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
412}
413
414static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache, const char** text)
415{
416 SkASSERT(cache != NULL);
417 SkASSERT(text != NULL);
418
419 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
420}
421
422static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache, const char** text)
423{
424 SkASSERT(cache != NULL);
425 SkASSERT(text != NULL);
426
427 const uint16_t* ptr = *(const uint16_t**)text;
428 unsigned glyphID = *ptr;
429 ptr += 1;
430 *text = (const char*)ptr;
431 return cache->getGlyphIDMetrics(glyphID);
432}
433
434static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache, const char** text)
435{
436 SkASSERT(cache != NULL);
437 SkASSERT(text != NULL);
438
439 const uint16_t* ptr = *(const uint16_t**)text;
440 ptr -= 1;
441 unsigned glyphID = *ptr;
442 *text = (const char*)ptr;
443 return cache->getGlyphIDMetrics(glyphID);
444}
445
446///
447
448static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache, const char** text)
449{
450 SkASSERT(cache != NULL);
451 SkASSERT(text != NULL);
452
453 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
454}
455
456static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache, const char** text)
457{
458 SkASSERT(cache != NULL);
459 SkASSERT(text != NULL);
460
461 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
462}
463
464static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache, const char** text)
465{
466 SkASSERT(cache != NULL);
467 SkASSERT(text != NULL);
468
469 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
470}
471
472static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache, const char** text)
473{
474 SkASSERT(cache != NULL);
475 SkASSERT(text != NULL);
476
477 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
478}
479
480static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache, const char** text)
481{
482 SkASSERT(cache != NULL);
483 SkASSERT(text != NULL);
484
485 const uint16_t* ptr = *(const uint16_t**)text;
486 unsigned glyphID = *ptr;
487 ptr += 1;
488 *text = (const char*)ptr;
489 return cache->getGlyphIDAdvance(glyphID);
490}
491
492static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache, const char** text)
493{
494 SkASSERT(cache != NULL);
495 SkASSERT(text != NULL);
496
497 const uint16_t* ptr = *(const uint16_t**)text;
498 ptr -= 1;
499 unsigned glyphID = *ptr;
500 *text = (const char*)ptr;
501 return cache->getGlyphIDAdvance(glyphID);
502}
503
504SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
505 bool needFullMetrics) const
506{
507 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
508 sk_getMetrics_utf8_next,
509 sk_getMetrics_utf16_next,
510 sk_getMetrics_glyph_next,
511
512 sk_getMetrics_utf8_prev,
513 sk_getMetrics_utf16_prev,
514 sk_getMetrics_glyph_prev,
515
516 sk_getAdvance_utf8_next,
517 sk_getAdvance_utf16_next,
518 sk_getAdvance_glyph_next,
519
520 sk_getAdvance_utf8_prev,
521 sk_getAdvance_utf16_prev,
522 sk_getAdvance_glyph_prev
523 };
524
525 unsigned index = this->getTextEncoding();
526
527 if (kBackward_TextBufferDirection == tbd)
528 index += 3;
529 if (!needFullMetrics && !this->isDevKernText())
530 index += 6;
531
532 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
533 return gMeasureCacheProcs[index];
534}
535
536///////////////////////////////////////////////////////////////////////////////
537
538static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
539 const char** text, SkFixed, SkFixed)
540{
541 SkASSERT(cache != NULL);
542 SkASSERT(text != NULL);
543
544 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
545}
546
547static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
548 const char** text, SkFixed x, SkFixed y)
549{
550 SkASSERT(cache != NULL);
551 SkASSERT(text != NULL);
552
553 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
554}
555
556static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache, const char** text,
557 SkFixed, SkFixed)
558{
559 SkASSERT(cache != NULL);
560 SkASSERT(text != NULL);
561
562 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
563}
564
565static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
566 const char** text, SkFixed x, SkFixed y)
567{
568 SkASSERT(cache != NULL);
569 SkASSERT(text != NULL);
570
571 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
572 x, y);
573}
574
575static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache, const char** text,
576 SkFixed, SkFixed)
577{
578 SkASSERT(cache != NULL);
579 SkASSERT(text != NULL);
580
581 const uint16_t* ptr = *(const uint16_t**)text;
582 unsigned glyphID = *ptr;
583 ptr += 1;
584 *text = (const char*)ptr;
585 return cache->getGlyphIDMetrics(glyphID);
586}
587
588static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
589 const char** text, SkFixed x, SkFixed y)
590{
591 SkASSERT(cache != NULL);
592 SkASSERT(text != NULL);
593
594 const uint16_t* ptr = *(const uint16_t**)text;
595 unsigned glyphID = *ptr;
596 ptr += 1;
597 *text = (const char*)ptr;
598 return cache->getGlyphIDMetrics(glyphID, x, y);
599}
600
601SkDrawCacheProc SkPaint::getDrawCacheProc() const
602{
603 static const SkDrawCacheProc gDrawCacheProcs[] = {
604 sk_getMetrics_utf8_00,
605 sk_getMetrics_utf16_00,
606 sk_getMetrics_glyph_00,
607
608 sk_getMetrics_utf8_xy,
609 sk_getMetrics_utf16_xy,
610 sk_getMetrics_glyph_xy
611 };
612
613 unsigned index = this->getTextEncoding();
614 if (fFlags & kSubpixelText_Flag)
615 index += 3;
616
617 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
618 return gDrawCacheProcs[index];
619}
620
621///////////////////////////////////////////////////////////////////////////////
622
623class SkAutoRestorePaintTextSizeAndFrame {
624public:
625 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint) : fPaint((SkPaint*)paint)
626 {
627 fTextSize = paint->getTextSize();
628 fStyle = paint->getStyle();
629 fPaint->setStyle(SkPaint::kFill_Style);
630 }
631 ~SkAutoRestorePaintTextSizeAndFrame()
632 {
633 fPaint->setStyle(fStyle);
634 fPaint->setTextSize(fTextSize);
635 }
636
637private:
638 SkPaint* fPaint;
639 SkScalar fTextSize;
640 SkPaint::Style fStyle;
641};
642
643static void set_bounds(const SkGlyph& g, SkRect* bounds)
644{
645 bounds->set(SkIntToScalar(g.fLeft),
646 SkIntToScalar(g.fTop),
647 SkIntToScalar(g.fLeft + g.fWidth),
648 SkIntToScalar(g.fTop + g.fHeight));
649}
650
651static void join_bounds(const SkGlyph& g, SkRect* bounds, SkFixed dx)
652{
653 SkScalar sx = SkFixedToScalar(dx);
654 bounds->join(SkIntToScalar(g.fLeft) + sx,
655 SkIntToScalar(g.fTop),
656 SkIntToScalar(g.fLeft + g.fWidth) + sx,
657 SkIntToScalar(g.fTop + g.fHeight));
658}
659
660SkScalar SkPaint::measure_text(SkGlyphCache* cache,
661 const char* text, size_t byteLength,
662 int* count, SkRect* bounds) const
663{
664 SkASSERT(count);
665 if (byteLength == 0)
666 {
667 *count = 0;
668 if (bounds)
669 bounds->setEmpty();
670 return 0;
671 }
672
673 SkMeasureCacheProc glyphCacheProc;
674 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
675 NULL != bounds);
676
677 int n = 1;
678 const char* stop = (const char*)text + byteLength;
679 const SkGlyph* g = &glyphCacheProc(cache, &text);
680 SkFixed x = g->fAdvanceX;
681
682 SkAutoKern autokern;
683
684 if (NULL == bounds)
685 {
686 if (this->isDevKernText())
687 {
688 int rsb;
689 for (; text < stop; n++) {
690 rsb = g->fRsbDelta;
691 g = &glyphCacheProc(cache, &text);
692 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
693 }
694 }
695 else
696 {
697 for (; text < stop; n++) {
698 x += glyphCacheProc(cache, &text).fAdvanceX;
699 }
700 }
701 }
702 else
703 {
704 set_bounds(*g, bounds);
705 if (this->isDevKernText())
706 {
707 int rsb;
708 for (; text < stop; n++) {
709 rsb = g->fRsbDelta;
710 g = &glyphCacheProc(cache, &text);
711 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
712 join_bounds(*g, bounds, x);
713 x += g->fAdvanceX;
714 }
715 }
716 else
717 {
718 for (; text < stop; n++) {
719 g = &glyphCacheProc(cache, &text);
720 join_bounds(*g, bounds, x);
721 x += g->fAdvanceX;
722 }
723 }
724 }
725 SkASSERT(text == stop);
726
727 *count = n;
728 return SkFixedToScalar(x);
729}
730
731SkScalar SkPaint::measureText(const void* textData, size_t length,
732 SkRect* bounds, SkScalar zoom) const
733{
734 const char* text = (const char*)textData;
735 SkASSERT(text != NULL || length == 0);
736
737 SkScalar scale = 0;
738 SkAutoRestorePaintTextSizeAndFrame restore(this);
739
740 if (this->isLinearText())
741 {
742 scale = fTextSize / kCanonicalTextSizeForPaths;
743 // this gets restored by restore
744 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
745 }
746
747 SkMatrix zoomMatrix, *zoomPtr = NULL;
748 if (zoom)
749 {
750 zoomMatrix.setScale(zoom, zoom);
751 zoomPtr = &zoomMatrix;
752 }
753
754 SkAutoGlyphCache autoCache(*this, zoomPtr);
755 SkGlyphCache* cache = autoCache.getCache();
756
757 SkScalar width = 0;
758
759 if (length > 0)
760 {
761 int tempCount;
762
763 width = this->measure_text(cache, text, length, &tempCount, bounds);
764 if (scale)
765 {
766 width = SkScalarMul(width, scale);
767 if (bounds)
768 {
769 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
770 bounds->fTop = SkScalarMul(bounds->fTop, scale);
771 bounds->fRight = SkScalarMul(bounds->fRight, scale);
772 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
773 }
774 }
775 }
776 return width;
777}
778
779typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
780
781static bool forward_textBufferPred(const char* text, const char* stop)
782{
783 return text < stop;
784}
785
786static bool backward_textBufferPred(const char* text, const char* stop)
787{
788 return text > stop;
789}
790
791static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
792 const char** text, size_t length, const char** stop)
793{
794 if (SkPaint::kForward_TextBufferDirection == tbd)
795 {
796 *stop = *text + length;
797 return forward_textBufferPred;
798 }
799 else
800 {
801 // text should point to the end of the buffer, and stop to the beginning
802 *stop = *text;
803 *text += length;
804 return backward_textBufferPred;
805 }
806}
807
808size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
809 SkScalar* measuredWidth,
810 TextBufferDirection tbd) const
811{
812 if (0 == length || 0 >= maxWidth)
813 {
814 if (measuredWidth)
815 *measuredWidth = 0;
816 return 0;
817 }
818
819 SkASSERT(textD != NULL);
820 const char* text = (const char*)textD;
821
822 SkScalar scale = 0;
823 SkAutoRestorePaintTextSizeAndFrame restore(this);
824
825 if (this->isLinearText())
826 {
827 scale = fTextSize / kCanonicalTextSizeForPaths;
828 // this gets restored by restore
829 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
830 }
831
832 SkAutoGlyphCache autoCache(*this, NULL);
833 SkGlyphCache* cache = autoCache.getCache();
834
835 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
836 const char* stop;
837 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
838 SkFixed max = SkScalarToFixed(maxWidth);
839 SkFixed width = 0;
840
841 SkAutoKern autokern;
842
843 if (this->isDevKernText())
844 {
845 int rsb = 0;
846 while (pred(text, stop))
847 {
848 const char* curr = text;
849 const SkGlyph& g = glyphCacheProc(cache, &text);
850 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
851 if ((width += x) > max)
852 {
853 width -= x;
854 text = curr;
855 break;
856 }
857 rsb = g.fRsbDelta;
858 }
859 }
860 else
861 {
862 while (pred(text, stop))
863 {
864 const char* curr = text;
865 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
866 if ((width += x) > max)
867 {
868 width -= x;
869 text = curr;
870 break;
871 }
872 }
873 }
874
875 if (measuredWidth)
876 {
877
878 SkScalar scalarWidth = SkFixedToScalar(width);
879 if (scale)
880 scalarWidth = SkScalarMul(scalarWidth, scale);
881 *measuredWidth = scalarWidth;
882 }
883
884 // return the number of bytes measured
885 return (kForward_TextBufferDirection == tbd) ?
886 text - stop + length : stop - text + length;
887}
888
889///////////////////////////////////////////////////////////////////////////////
890
891static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context)
892{
893 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
894 return false; // don't detach the cache
895}
896
897static void FontMetricsDescProc(const SkDescriptor* desc, void* context)
898{
899 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
900}
901
902SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const
903{
904 SkScalar scale = 0;
905 SkAutoRestorePaintTextSizeAndFrame restore(this);
906
907 if (this->isLinearText())
908 {
909 scale = fTextSize / kCanonicalTextSizeForPaths;
910 // this gets restored by restore
911 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
912 }
913
914 SkMatrix zoomMatrix, *zoomPtr = NULL;
915 if (zoom)
916 {
917 zoomMatrix.setScale(zoom, zoom);
918 zoomPtr = &zoomMatrix;
919 }
920
921#if 0
922 SkAutoGlyphCache autoCache(*this, zoomPtr);
923 SkGlyphCache* cache = autoCache.getCache();
924 const FontMetrics& my = cache->getFontMetricsY();
925#endif
926 FontMetrics storage;
927 if (NULL == metrics)
928 metrics = &storage;
929
930 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
931
932 if (scale)
933 {
934 metrics->fTop = SkScalarMul(metrics->fTop, scale);
935 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
936 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
937 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
938 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
939 }
940 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
941}
942
943////////////////////////////////////////////////////////////////////////////////////////////
944
945static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale)
946{
947 bounds->set(g.fLeft * scale,
948 g.fTop * scale,
949 (g.fLeft + g.fWidth) * scale,
950 (g.fTop + g.fHeight) * scale);
951}
952
953int SkPaint::getTextWidths(const void* textData, size_t byteLength, SkScalar widths[],
954 SkRect bounds[]) const
955{
956 if (0 == byteLength)
957 return 0;
958
959 SkASSERT(NULL != textData);
960
961 if (NULL == widths && NULL == bounds)
962 return this->countText(textData, byteLength);
963
964 SkAutoRestorePaintTextSizeAndFrame restore(this);
965 SkScalar scale = 0;
966
967 if (this->isLinearText())
968 {
969 scale = fTextSize / kCanonicalTextSizeForPaths;
970 // this gets restored by restore
971 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
972 }
973
974 SkAutoGlyphCache autoCache(*this, NULL);
975 SkGlyphCache* cache = autoCache.getCache();
976 SkMeasureCacheProc glyphCacheProc;
977 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
978 NULL != bounds);
979
980 const char* text = (const char*)textData;
981 const char* stop = text + byteLength;
982 int count = 0;
983
984 if (this->isDevKernText())
985 {
986 // we adjust the widths returned here through auto-kerning
987 SkAutoKern autokern;
988 SkFixed prevWidth = 0;
989
990 if (scale) {
991 while (text < stop) {
992 const SkGlyph& g = glyphCacheProc(cache, &text);
993 if (widths) {
994 SkFixed adjust = autokern.adjust(g);
995
996 if (count > 0) {
997 SkScalar w = SkFixedToScalar(prevWidth + adjust);
998 *widths++ = SkScalarMul(w, scale);
999 }
1000 prevWidth = g.fAdvanceX;
1001 }
1002 if (bounds) {
1003 set_bounds(g, bounds++, scale);
1004 }
1005 ++count;
1006 }
1007 if (count > 0 && widths) {
1008 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1009 }
1010 } else {
1011 while (text < stop) {
1012 const SkGlyph& g = glyphCacheProc(cache, &text);
1013 if (widths) {
1014 SkFixed adjust = autokern.adjust(g);
1015
1016 if (count > 0) {
1017 *widths++ = SkFixedToScalar(prevWidth + adjust);
1018 }
1019 prevWidth = g.fAdvanceX;
1020 }
1021 if (bounds) {
1022 set_bounds(g, bounds++);
1023 }
1024 ++count;
1025 }
1026 if (count > 0 && widths) {
1027 *widths = SkFixedToScalar(prevWidth);
1028 }
1029 }
1030 } else { // no devkern
1031 if (scale) {
1032 while (text < stop) {
1033 const SkGlyph& g = glyphCacheProc(cache, &text);
1034 if (widths) {
1035 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
1036 scale);
1037 }
1038 if (bounds) {
1039 set_bounds(g, bounds++, scale);
1040 }
1041 ++count;
1042 }
1043 } else {
1044 while (text < stop) {
1045 const SkGlyph& g = glyphCacheProc(cache, &text);
1046 if (widths) {
1047 *widths++ = SkFixedToScalar(g.fAdvanceX);
1048 }
1049 if (bounds) {
1050 set_bounds(g, bounds++);
1051 }
1052 ++count;
1053 }
1054 }
1055 }
1056
1057 SkASSERT(text == stop);
1058 return count;
1059}
1060
1061////////////////////////////////////////////////////////////////////////////////////////////
1062
1063#include "SkDraw.h"
1064
1065void SkPaint::getTextPath(const void* textData, size_t length, SkScalar x, SkScalar y, SkPath* path) const
1066{
1067 const char* text = (const char*)textData;
1068 SkASSERT(length == 0 || text != NULL);
1069 if (text == NULL || length == 0 || path == NULL)
1070 return;
1071
1072 SkTextToPathIter iter(text, length, *this, false, true);
1073 SkMatrix matrix;
1074 SkScalar prevXPos = 0;
1075
1076 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1077 matrix.postTranslate(x, y);
1078 path->reset();
1079
1080 SkScalar xpos;
1081 const SkPath* iterPath;
1082 while ((iterPath = iter.next(&xpos)) != NULL)
1083 {
1084 matrix.postTranslate(xpos - prevXPos, 0);
1085 path->addPath(*iterPath, matrix);
1086 prevXPos = xpos;
1087 }
1088}
1089
1090static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1091 SkFlattenableWriteBuffer* buffer) {
1092 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
1093}
1094
1095/*
1096 * interpolates to find the right value for key, in the function represented by the 'length' number of pairs: (keys[i], values[i])
1097 inspired by a desire to change the multiplier for thickness in fakebold
1098 therefore, i assumed number of pairs (length) will be small, so a linear search is sufficient
1099 repeated keys are allowed for discontinuous functions (so long as keys is monotonically increasing), and if
1100 key is the value of a repeated scalar in keys, the first one will be used
1101 - this may change if a binary search is used
1102 - also, this ensures that there is no divide by zero (an assert also checks for that)
1103*/
1104static SkScalar interpolate(SkScalar key, const SkScalar keys[], const SkScalar values[], int length)
1105{
1106
1107 SkASSERT(length > 0);
1108 SkASSERT(keys != NULL);
1109 SkASSERT(values != NULL);
1110#ifdef SK_DEBUG
1111 for (int i = 1; i < length; i++)
1112 SkASSERT(keys[i] >= keys[i-1]);
1113#endif
1114 int right = 0;
1115 while (right < length && key > keys[right])
1116 right++;
1117 //could use sentinal values to eliminate conditionals
1118 //i assume i am not in control of input values, so i want to make it simple
1119 if (length == right)
1120 return values[length-1];
1121 if (0 == right)
1122 return values[0];
1123 //otherwise, we interpolate between right-1 and right
1124 SkScalar rVal = values[right];
1125 SkScalar lVal = values[right-1];
1126 SkScalar rightKey = keys[right];
1127 SkScalar leftKey = keys[right-1];
1128 SkASSERT(rightKey != leftKey);
1129 //fractional amount which we will multiply by the difference in the left value and right value
1130 SkScalar fract = SkScalarDiv(key-leftKey,rightKey-leftKey);
1131 return lVal + SkScalarMul(fract, rVal-lVal);
1132}
1133
1134//used for interpolating in fakeBold
1135static const SkScalar pointSizes[] = { SkIntToScalar(9), SkIntToScalar(36) };
1136static const SkScalar multipliers[] = { SK_Scalar1/24, SK_Scalar1/32 };
1137
1138static SkMask::Format computeMaskFormat(const SkPaint& paint)
1139{
1140 uint32_t flags = paint.getFlags();
1141
1142 return (flags & SkPaint::kAntiAlias_Flag) ? SkMask::kA8_Format : SkMask::kBW_Format;
1143}
1144
1145static SkScalerContext::Hints computeScalerHints(const SkPaint& paint)
1146{
1147 uint32_t flags = paint.getFlags();
1148
1149 if (flags & SkPaint::kLinearText_Flag)
1150 return SkScalerContext::kNo_Hints;
1151 else if (flags & SkPaint::kSubpixelText_Flag)
1152 return SkScalerContext::kSubpixel_Hints;
1153 else
1154 return SkScalerContext::kNormal_Hints;
1155}
1156
1157void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec)
1158{
1159 SkASSERT(deviceMatrix == NULL || (deviceMatrix->getType() & SkMatrix::kPerspective_Mask) == 0);
1160
1161 rec->fFontID = SkTypeface::UniqueID(paint.getTypeface());
1162 rec->fTextSize = paint.getTextSize();
1163 rec->fPreScaleX = paint.getTextScaleX();
1164 rec->fPreSkewX = paint.getTextSkewX();
1165
1166 if (deviceMatrix)
1167 {
1168 rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
1169 rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
1170 rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
1171 rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
1172 }
1173 else
1174 {
1175 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1176 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1177 }
1178
1179 SkPaint::Style style = paint.getStyle();
1180 SkScalar strokeWidth = paint.getStrokeWidth();
1181
1182 if (paint.isFakeBoldText())
1183 {
1184 SkScalar fakeBoldScale = interpolate(paint.getTextSize(), pointSizes, multipliers, 2);
1185 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1186
1187 if (style == SkPaint::kFill_Style)
1188 {
1189 style = SkPaint::kStrokeAndFill_Style;
1190 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1191 }
1192 else
1193 strokeWidth += extra;
1194 }
1195
1196 unsigned flags = SkFontHost::ComputeGammaFlag(paint);
1197
1198 if (paint.isDevKernText())
1199 flags |= SkScalerContext::kDevKernText_Flag;
1200
1201 if (style != SkPaint::kFill_Style && strokeWidth > 0)
1202 {
1203 rec->fFrameWidth = strokeWidth;
1204 rec->fMiterLimit = paint.getStrokeMiter();
1205 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1206
1207 if (style == SkPaint::kStrokeAndFill_Style)
1208 flags |= SkScalerContext::kFrameAndFill_Flag;
1209 }
1210 else
1211 {
1212 rec->fFrameWidth = 0;
1213 rec->fMiterLimit = 0;
1214 rec->fStrokeJoin = 0;
1215 }
1216
1217 rec->fHints = SkToU8(computeScalerHints(paint));
1218 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1219 rec->fFlags = SkToU8(flags);
1220}
1221
1222#define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1223
1224void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
1225 void (*proc)(const SkDescriptor*, void*),
1226 void* context) const
1227{
1228 SkScalerContext::Rec rec;
1229
1230 SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1231
1232 size_t descSize = sizeof(rec);
1233 int entryCount = 1;
1234 SkPathEffect* pe = this->getPathEffect();
1235 SkMaskFilter* mf = this->getMaskFilter();
1236 SkRasterizer* ra = this->getRasterizer();
1237
1238 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1239 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1240 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1241
1242 if (pe) {
1243 peBuffer.writeFlattenable(pe);
1244 descSize += peBuffer.size();
1245 entryCount += 1;
1246 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1247 // seems like we could support kLCD as well at this point...
1248 }
1249 if (mf) {
1250 mfBuffer.writeFlattenable(mf);
1251 descSize += mfBuffer.size();
1252 entryCount += 1;
1253 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1254 }
1255 if (ra) {
1256 raBuffer.writeFlattenable(ra);
1257 descSize += raBuffer.size();
1258 entryCount += 1;
1259 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1260 }
1261 descSize += SkDescriptor::ComputeOverhead(entryCount);
1262
1263 SkAutoDescriptor ad(descSize);
1264 SkDescriptor* desc = ad.getDesc();
1265
1266 desc->init();
1267 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1268
1269 if (pe) {
1270 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1271 }
1272 if (mf) {
1273 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1274 }
1275 if (ra) {
1276 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1277 }
1278
1279 SkASSERT(descSize == desc->getLength());
1280 desc->computeChecksum();
1281
1282 proc(desc, context);
1283}
1284
1285static void DetachDescProc(const SkDescriptor* desc, void* context)
1286{
1287 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
1288}
1289
1290SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
1291{
1292 SkGlyphCache* cache;
1293 this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
1294 return cache;
1295}
1296
1297///////////////////////////////////////////////////////////////////////////////
1298
1299#include "SkStream.h"
1300
1301void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
1302 buffer.writeTypeface(this->getTypeface());
1303 buffer.writeScalar(this->getTextSize());
1304 buffer.writeScalar(this->getTextScaleX());
1305 buffer.writeScalar(this->getTextSkewX());
1306 buffer.writeFlattenable(this->getPathEffect());
1307 buffer.writeFlattenable(this->getShader());
1308 buffer.writeFlattenable(this->getXfermode());
1309 buffer.writeFlattenable(this->getMaskFilter());
1310 buffer.writeFlattenable(this->getColorFilter());
1311 buffer.writeFlattenable(this->getRasterizer());
1312 buffer.writeFlattenable(this->getLooper());
1313 buffer.write32(this->getColor());
1314 buffer.writeScalar(this->getStrokeWidth());
1315 buffer.writeScalar(this->getStrokeMiter());
1316 buffer.write16(this->getFlags());
1317 buffer.write8(this->getTextAlign());
1318 buffer.write8(this->getStrokeCap());
1319 buffer.write8(this->getStrokeJoin());
1320 buffer.write8(this->getStyle());
1321 buffer.write8(this->getTextEncoding());
1322}
1323
1324void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
1325 this->setTypeface(buffer.readTypeface());
1326 this->setTextSize(buffer.readScalar());
1327 this->setTextScaleX(buffer.readScalar());
1328 this->setTextSkewX(buffer.readScalar());
1329 this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
1330 this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
1331 this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
1332 this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
1333 this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
1334 this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
1335 this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
1336 this->setColor(buffer.readU32());
1337 this->setStrokeWidth(buffer.readScalar());
1338 this->setStrokeMiter(buffer.readScalar());
1339 this->setFlags(buffer.readU16());
1340 this->setTextAlign((SkPaint::Align) buffer.readU8());
1341 this->setStrokeCap((SkPaint::Cap) buffer.readU8());
1342 this->setStrokeJoin((SkPaint::Join) buffer.readU8());
1343 this->setStyle((SkPaint::Style) buffer.readU8());
1344 this->setTextEncoding((SkPaint::TextEncoding) buffer.readU8());
1345}
1346
1347///////////////////////////////////////////////////////////////////////////////
1348
1349SkShader* SkPaint::setShader(SkShader* shader)
1350{
1351 SkRefCnt_SafeAssign(fShader, shader);
1352 return shader;
1353}
1354
1355SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter)
1356{
1357 SkRefCnt_SafeAssign(fColorFilter, filter);
1358 return filter;
1359}
1360
1361SkXfermode* SkPaint::setXfermode(SkXfermode* mode)
1362{
1363 SkRefCnt_SafeAssign(fXfermode, mode);
1364 return mode;
1365}
1366
1367SkXfermode* SkPaint::setPorterDuffXfermode(SkPorterDuff::Mode mode)
1368{
1369 fXfermode->safeUnref();
1370 fXfermode = SkPorterDuff::CreateXfermode(mode);
1371 return fXfermode;
1372}
1373
1374SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect)
1375{
1376 SkRefCnt_SafeAssign(fPathEffect, effect);
1377 return effect;
1378}
1379
1380SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter)
1381{
1382 SkRefCnt_SafeAssign(fMaskFilter, filter);
1383 return filter;
1384}
1385
1386////////////////////////////////////////////////////////////////////////////////////////
1387
1388bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const
1389{
1390 SkPath effectPath, strokePath;
1391 const SkPath* path = &src;
1392
1393 SkScalar width = this->getStrokeWidth();
1394
1395 switch (this->getStyle()) {
1396 case SkPaint::kFill_Style:
1397 width = -1; // mark it as no-stroke
1398 break;
1399 case SkPaint::kStrokeAndFill_Style:
1400 if (width == 0)
1401 width = -1; // mark it as no-stroke
1402 break;
1403 case SkPaint::kStroke_Style:
1404 break;
1405 default:
1406 SkASSERT(!"unknown paint style");
1407 }
1408
1409 if (this->getPathEffect())
1410 {
1411 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
1412 if (this->getStyle() == SkPaint::kStrokeAndFill_Style)
1413 width = -1; // mark it as no-stroke
1414
1415 if (this->getPathEffect()->filterPath(&effectPath, src, &width))
1416 path = &effectPath;
1417
1418 // restore the width if we earlier had to lie, and if we're still set to no-stroke
1419 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
1420 // and we want to respect that (i.e. don't overwrite their setting for width)
1421 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0)
1422 {
1423 width = this->getStrokeWidth();
1424 if (width == 0)
1425 width = -1;
1426 }
1427 }
1428
1429 if (width > 0 && !path->isEmpty())
1430 {
1431 SkStroke stroker(*this, width);
1432 stroker.strokePath(*path, &strokePath);
1433 path = &strokePath;
1434 }
1435
1436 if (path == &src)
1437 *dst = src;
1438 else
1439 {
1440 SkASSERT(path == &effectPath || path == &strokePath);
1441 dst->swap(*(SkPath*)path);
1442 }
1443
1444 return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
1445}
1446
1447bool SkPaint::canComputeFastBounds() const {
1448 // use bit-or since no need for early exit
1449 return (reinterpret_cast<uintptr_t>(this->getMaskFilter()) |
1450 reinterpret_cast<uintptr_t>(this->getLooper()) |
1451 reinterpret_cast<uintptr_t>(this->getRasterizer()) |
1452 reinterpret_cast<uintptr_t>(this->getPathEffect())) == 0;
1453}
1454
1455const SkRect& SkPaint::computeFastBounds(const SkRect& src,
1456 SkRect* storage) const {
1457 SkASSERT(storage);
1458
1459 if (this->getStyle() != SkPaint::kFill_Style) {
1460 // if we're stroked, outset the rect by the radius (and join type)
1461 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
1462
1463 if (0 == radius) { // hairline
1464 radius = SK_Scalar1;
1465 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
1466 SkScalar scale = this->getStrokeMiter();
1467 if (scale > SK_Scalar1) {
1468 radius = SkScalarMul(radius, scale);
1469 }
1470 }
1471 storage->set(src.fLeft - radius, src.fTop - radius,
1472 src.fRight + radius, src.fBottom + radius);
1473 return *storage;
1474 }
1475 // no adjustments needed, just return the original rect
1476 return src;
1477}
1478
1479////////////////////////////////////////////////////////////////////////////////////////
1480
1481static bool has_thick_frame(const SkPaint& paint)
1482{
1483 return paint.getStrokeWidth() > 0 && paint.getStyle() != SkPaint::kFill_Style;
1484}
1485
1486SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
1487 const SkPaint& paint,
1488 bool applyStrokeAndPathEffects,
1489 bool forceLinearTextOn)
1490 : fPaint(paint) /* make a copy of the paint */
1491{
1492 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
1493 true);
1494
1495 if (forceLinearTextOn)
1496 fPaint.setLinearText(true);
1497 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
1498
1499 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint))
1500 applyStrokeAndPathEffects = false;
1501
1502 // can't use our canonical size if we need to apply patheffects/strokes
1503 if (fPaint.isLinearText() && !applyStrokeAndPathEffects)
1504 {
1505 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
1506 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
1507 }
1508 else
1509 fScale = SK_Scalar1;
1510
1511 if (!applyStrokeAndPathEffects)
1512 {
1513 fPaint.setStyle(SkPaint::kFill_Style);
1514 fPaint.setPathEffect(NULL);
1515 }
1516
1517 fCache = fPaint.detachCache(NULL);
1518
1519 SkPaint::Style style = SkPaint::kFill_Style;
1520 SkPathEffect* pe = NULL;
1521
1522 if (!applyStrokeAndPathEffects)
1523 {
1524 style = paint.getStyle(); // restore
1525 pe = paint.getPathEffect(); // restore
1526 }
1527 fPaint.setStyle(style);
1528 fPaint.setPathEffect(pe);
1529 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
1530
1531 // now compute fXOffset if needed
1532
1533 SkScalar xOffset = 0;
1534 if (paint.getTextAlign() != SkPaint::kLeft_Align) // need to measure first
1535 {
1536 int count;
1537 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length, &count, NULL), fScale);
1538 if (paint.getTextAlign() == SkPaint::kCenter_Align)
1539 width = SkScalarHalf(width);
1540 xOffset = -width;
1541 }
1542 fXPos = xOffset;
1543 fPrevAdvance = 0;
1544
1545 fText = text;
1546 fStop = text + length;
1547}
1548
1549SkTextToPathIter::~SkTextToPathIter()
1550{
1551 SkGlyphCache::AttachCache(fCache);
1552}
1553
1554const SkPath* SkTextToPathIter::next(SkScalar* xpos)
1555{
1556 while (fText < fStop)
1557 {
1558 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1559
1560 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
1561 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking();
1562
1563 if (glyph.fWidth)
1564 {
1565 if (xpos)
1566 *xpos = fXPos;
1567 return fCache->findPath(glyph);
1568 }
1569 }
1570 return NULL;
1571}