1 /* 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 "SkScalar.h"
27 #include "SkScalerContext.h"
28 #include "SkStroke.h"
29 #include "SkTextFormatParams.h"
30 #include "SkTypeface.h"
31 #include "SkXfermode.h"
32 #include "SkAutoKern.h"
33
34 #define SK_DefaultTextSize SkIntToScalar(12)
35
36 #define SK_DefaultFlags 0 //(kNativeHintsText_Flag)
37
38 #ifdef ANDROID
39 #define GEN_ID_INC fGenerationID++
40 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
41 #else
42 #define GEN_ID_INC
43 #define GEN_ID_INC_EVAL(expression)
44 #endif
45
SkPaint()46 SkPaint::SkPaint() {
47 // since we may have padding, we zero everything so that our memcmp() call
48 // in operator== will work correctly.
49 // with this, we can skip 0 and null individual initializations
50 sk_bzero(this, sizeof(*this));
51
52 #if 0 // not needed with the bzero call above
53 fTypeface = NULL;
54 fTextSkewX = 0;
55 fPathEffect = NULL;
56 fShader = NULL;
57 fXfermode = NULL;
58 fMaskFilter = NULL;
59 fColorFilter = NULL;
60 fRasterizer = NULL;
61 fLooper = NULL;
62 fWidth = 0;
63 #endif
64
65 fTextSize = SK_DefaultTextSize;
66 fTextScaleX = SK_Scalar1;
67 fColor = SK_ColorBLACK;
68 fMiterLimit = SK_DefaultMiterLimit;
69 fFlags = SK_DefaultFlags;
70 fCapType = kDefault_Cap;
71 fJoinType = kDefault_Join;
72 fTextAlign = kLeft_Align;
73 fStyle = kFill_Style;
74 fTextEncoding = kUTF8_TextEncoding;
75 fHinting = kNormal_Hinting;
76 #ifdef ANDROID
77 fGenerationID = 0;
78 #endif
79 }
80
SkPaint(const SkPaint & src)81 SkPaint::SkPaint(const SkPaint& src) {
82 memcpy(this, &src, sizeof(src));
83
84 SkSafeRef(fTypeface);
85 SkSafeRef(fPathEffect);
86 SkSafeRef(fShader);
87 SkSafeRef(fXfermode);
88 SkSafeRef(fMaskFilter);
89 SkSafeRef(fColorFilter);
90 SkSafeRef(fRasterizer);
91 SkSafeRef(fLooper);
92 }
93
~SkPaint()94 SkPaint::~SkPaint() {
95 SkSafeUnref(fTypeface);
96 SkSafeUnref(fPathEffect);
97 SkSafeUnref(fShader);
98 SkSafeUnref(fXfermode);
99 SkSafeUnref(fMaskFilter);
100 SkSafeUnref(fColorFilter);
101 SkSafeUnref(fRasterizer);
102 SkSafeUnref(fLooper);
103 }
104
operator =(const SkPaint & src)105 SkPaint& SkPaint::operator=(const SkPaint& src) {
106 SkASSERT(&src);
107
108 SkSafeRef(src.fTypeface);
109 SkSafeRef(src.fPathEffect);
110 SkSafeRef(src.fShader);
111 SkSafeRef(src.fXfermode);
112 SkSafeRef(src.fMaskFilter);
113 SkSafeRef(src.fColorFilter);
114 SkSafeRef(src.fRasterizer);
115 SkSafeRef(src.fLooper);
116
117 SkSafeUnref(fTypeface);
118 SkSafeUnref(fPathEffect);
119 SkSafeUnref(fShader);
120 SkSafeUnref(fXfermode);
121 SkSafeUnref(fMaskFilter);
122 SkSafeUnref(fColorFilter);
123 SkSafeUnref(fRasterizer);
124 SkSafeUnref(fLooper);
125
126 #ifdef ANDROID
127 uint32_t oldGenerationID = fGenerationID;
128 #endif
129 memcpy(this, &src, sizeof(src));
130 #ifdef ANDROID
131 fGenerationID = oldGenerationID + 1;
132 #endif
133
134 return *this;
135 }
136
operator ==(const SkPaint & a,const SkPaint & b)137 int operator==(const SkPaint& a, const SkPaint& b) {
138 return memcmp(&a, &b, sizeof(a)) == 0;
139 }
140
reset()141 void SkPaint::reset() {
142 SkPaint init;
143
144 #ifdef ANDROID
145 uint32_t oldGenerationID = fGenerationID;
146 #endif
147 *this = init;
148 #ifdef ANDROID
149 fGenerationID = oldGenerationID + 1;
150 #endif
151 }
152
153 #ifdef ANDROID
getGenerationID() const154 uint32_t SkPaint::getGenerationID() const {
155 return fGenerationID;
156 }
157 #endif
158
setHinting(Hinting hintingLevel)159 void SkPaint::setHinting(Hinting hintingLevel) {
160 GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
161 fHinting = hintingLevel;
162 }
163
setFlags(uint32_t flags)164 void SkPaint::setFlags(uint32_t flags) {
165 GEN_ID_INC_EVAL(fFlags != flags);
166 fFlags = flags;
167 }
168
setAntiAlias(bool doAA)169 void SkPaint::setAntiAlias(bool doAA) {
170 GEN_ID_INC_EVAL(doAA != isAntiAlias());
171 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
172 }
173
setDither(bool doDither)174 void SkPaint::setDither(bool doDither) {
175 GEN_ID_INC_EVAL(doDither != isDither());
176 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
177 }
178
setSubpixelText(bool doSubpixel)179 void SkPaint::setSubpixelText(bool doSubpixel) {
180 GEN_ID_INC_EVAL(doSubpixel != isSubpixelText());
181 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
182 }
183
setLCDRenderText(bool doLCDRender)184 void SkPaint::setLCDRenderText(bool doLCDRender) {
185 GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText());
186 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
187 }
188
setEmbeddedBitmapText(bool doEmbeddedBitmapText)189 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
190 GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText());
191 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
192 }
193
setAutohinted(bool useAutohinter)194 void SkPaint::setAutohinted(bool useAutohinter) {
195 GEN_ID_INC_EVAL(useAutohinter != isAutohinted());
196 this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
197 }
198
setLinearText(bool doLinearText)199 void SkPaint::setLinearText(bool doLinearText) {
200 GEN_ID_INC_EVAL(doLinearText != isLinearText());
201 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
202 }
203
setUnderlineText(bool doUnderline)204 void SkPaint::setUnderlineText(bool doUnderline) {
205 GEN_ID_INC_EVAL(doUnderline != isUnderlineText());
206 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
207 }
208
setStrikeThruText(bool doStrikeThru)209 void SkPaint::setStrikeThruText(bool doStrikeThru) {
210 GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText());
211 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
212 }
213
setFakeBoldText(bool doFakeBold)214 void SkPaint::setFakeBoldText(bool doFakeBold) {
215 GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText());
216 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
217 }
218
setDevKernText(bool doDevKern)219 void SkPaint::setDevKernText(bool doDevKern) {
220 GEN_ID_INC_EVAL(doDevKern != isDevKernText());
221 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
222 }
223
setFilterBitmap(bool doFilter)224 void SkPaint::setFilterBitmap(bool doFilter) {
225 GEN_ID_INC_EVAL(doFilter != isFilterBitmap());
226 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
227 }
228
setStyle(Style style)229 void SkPaint::setStyle(Style style) {
230 if ((unsigned)style < kStyleCount) {
231 GEN_ID_INC_EVAL((unsigned)style != fStyle);
232 fStyle = style;
233 } else {
234 SkDEBUGCODE(SkDebugf("SkPaint::setStyle(%d) out of range\n", style);)
235 }
236 }
237
setColor(SkColor color)238 void SkPaint::setColor(SkColor color) {
239 GEN_ID_INC_EVAL(color != fColor);
240 fColor = color;
241 }
242
setAlpha(U8CPU a)243 void SkPaint::setAlpha(U8CPU a) {
244 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
245 SkColorGetG(fColor), SkColorGetB(fColor)));
246 }
247
setARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)248 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
249 this->setColor(SkColorSetARGB(a, r, g, b));
250 }
251
setStrokeWidth(SkScalar width)252 void SkPaint::setStrokeWidth(SkScalar width) {
253 if (width >= 0) {
254 GEN_ID_INC_EVAL(width != fWidth);
255 fWidth = width;
256 } else {
257 SkDEBUGCODE(SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");)
258 }
259 }
260
setStrokeMiter(SkScalar limit)261 void SkPaint::setStrokeMiter(SkScalar limit) {
262 if (limit >= 0) {
263 GEN_ID_INC_EVAL(limit != fMiterLimit);
264 fMiterLimit = limit;
265 } else {
266 SkDEBUGCODE(SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");)
267 }
268 }
269
setStrokeCap(Cap ct)270 void SkPaint::setStrokeCap(Cap ct) {
271 if ((unsigned)ct < kCapCount) {
272 GEN_ID_INC_EVAL((unsigned)ct != fCapType);
273 fCapType = SkToU8(ct);
274 } else {
275 SkDEBUGCODE(SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);)
276 }
277 }
278
setStrokeJoin(Join jt)279 void SkPaint::setStrokeJoin(Join jt) {
280 if ((unsigned)jt < kJoinCount) {
281 GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
282 fJoinType = SkToU8(jt);
283 } else {
284 SkDEBUGCODE(SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);)
285 }
286 }
287
288 ///////////////////////////////////////////////////////////////////////////////
289
setTextAlign(Align align)290 void SkPaint::setTextAlign(Align align) {
291 if ((unsigned)align < kAlignCount) {
292 GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
293 fTextAlign = SkToU8(align);
294 } else {
295 SkDEBUGCODE(SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);)
296 }
297 }
298
setTextSize(SkScalar ts)299 void SkPaint::setTextSize(SkScalar ts) {
300 if (ts > 0) {
301 GEN_ID_INC_EVAL(ts != fTextSize);
302 fTextSize = ts;
303 } else {
304 SkDEBUGCODE(SkDebugf("SkPaint::setTextSize() called with negative value\n");)
305 }
306 }
307
setTextScaleX(SkScalar scaleX)308 void SkPaint::setTextScaleX(SkScalar scaleX) {
309 GEN_ID_INC_EVAL(scaleX != fTextScaleX);
310 fTextScaleX = scaleX;
311 }
312
setTextSkewX(SkScalar skewX)313 void SkPaint::setTextSkewX(SkScalar skewX) {
314 GEN_ID_INC_EVAL(skewX != fTextSkewX);
315 fTextSkewX = skewX;
316 }
317
setTextEncoding(TextEncoding encoding)318 void SkPaint::setTextEncoding(TextEncoding encoding) {
319 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
320 GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
321 fTextEncoding = encoding;
322 } else {
323 SkDEBUGCODE(SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);)
324 }
325 }
326
327 ///////////////////////////////////////////////////////////////////////////////
328
setTypeface(SkTypeface * font)329 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
330 SkRefCnt_SafeAssign(fTypeface, font);
331 GEN_ID_INC;
332 return font;
333 }
334
setRasterizer(SkRasterizer * r)335 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
336 SkRefCnt_SafeAssign(fRasterizer, r);
337 GEN_ID_INC;
338 return r;
339 }
340
setLooper(SkDrawLooper * looper)341 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
342 SkRefCnt_SafeAssign(fLooper, looper);
343 GEN_ID_INC;
344 return looper;
345 }
346
347 ///////////////////////////////////////////////////////////////////////////////
348
349 #include "SkGlyphCache.h"
350 #include "SkUtils.h"
351
DetachDescProc(const SkDescriptor * desc,void * context)352 static void DetachDescProc(const SkDescriptor* desc, void* context) {
353 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
354 }
355
356 #ifdef ANDROID
getUnicharMetrics(SkUnichar text)357 const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
358 SkGlyphCache* cache;
359 descriptorProc(NULL, DetachDescProc, &cache, true);
360
361 const SkGlyph& glyph = cache->getUnicharMetrics(text);
362
363 SkGlyphCache::AttachCache(cache);
364 return glyph;
365 }
366
getGlyphMetrics(uint16_t glyphId)367 const SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId) {
368 SkGlyphCache* cache;
369 descriptorProc(NULL, DetachDescProc, &cache, true);
370
371 const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
372
373 SkGlyphCache::AttachCache(cache);
374 return glyph;
375 }
376
findImage(const SkGlyph & glyph)377 const void* SkPaint::findImage(const SkGlyph& glyph) {
378 // See ::detachCache()
379 SkGlyphCache* cache;
380 descriptorProc(NULL, DetachDescProc, &cache, true);
381
382 const void* image = cache->findImage(glyph);
383
384 SkGlyphCache::AttachCache(cache);
385 return image;
386 }
387 #endif
388
textToGlyphs(const void * textData,size_t byteLength,uint16_t glyphs[]) const389 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
390 uint16_t glyphs[]) const {
391 if (byteLength == 0) {
392 return 0;
393 }
394
395 SkASSERT(textData != NULL);
396
397 if (NULL == glyphs) {
398 switch (this->getTextEncoding()) {
399 case kUTF8_TextEncoding:
400 return SkUTF8_CountUnichars((const char*)textData, byteLength);
401 case kUTF16_TextEncoding:
402 return SkUTF16_CountUnichars((const uint16_t*)textData,
403 byteLength >> 1);
404 case kGlyphID_TextEncoding:
405 return byteLength >> 1;
406 default:
407 SkASSERT(!"unknown text encoding");
408 }
409 return 0;
410 }
411
412 // if we get here, we have a valid glyphs[] array, so time to fill it in
413
414 // handle this encoding before the setup for the glyphcache
415 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
416 // we want to ignore the low bit of byteLength
417 memcpy(glyphs, textData, byteLength >> 1 << 1);
418 return byteLength >> 1;
419 }
420
421 SkAutoGlyphCache autoCache(*this, NULL);
422 SkGlyphCache* cache = autoCache.getCache();
423
424 const char* text = (const char*)textData;
425 const char* stop = text + byteLength;
426 uint16_t* gptr = glyphs;
427
428 switch (this->getTextEncoding()) {
429 case SkPaint::kUTF8_TextEncoding:
430 while (text < stop) {
431 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
432 }
433 break;
434 case SkPaint::kUTF16_TextEncoding: {
435 const uint16_t* text16 = (const uint16_t*)text;
436 const uint16_t* stop16 = (const uint16_t*)stop;
437 while (text16 < stop16) {
438 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
439 }
440 break;
441 }
442 default:
443 SkASSERT(!"unknown text encoding");
444 }
445 return gptr - glyphs;
446 }
447
containsText(const void * textData,size_t byteLength) const448 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
449 if (0 == byteLength) {
450 return true;
451 }
452
453 SkASSERT(textData != NULL);
454
455 // handle this encoding before the setup for the glyphcache
456 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
457 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
458 size_t count = byteLength >> 1;
459 for (size_t i = 0; i < count; i++) {
460 if (0 == glyphID[i]) {
461 return false;
462 }
463 }
464 return true;
465 }
466
467 SkAutoGlyphCache autoCache(*this, NULL);
468 SkGlyphCache* cache = autoCache.getCache();
469
470 switch (this->getTextEncoding()) {
471 case SkPaint::kUTF8_TextEncoding: {
472 const char* text = static_cast<const char*>(textData);
473 const char* stop = text + byteLength;
474 while (text < stop) {
475 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
476 return false;
477 }
478 }
479 break;
480 }
481 case SkPaint::kUTF16_TextEncoding: {
482 const uint16_t* text = static_cast<const uint16_t*>(textData);
483 const uint16_t* stop = text + (byteLength >> 1);
484 while (text < stop) {
485 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
486 return false;
487 }
488 }
489 break;
490 }
491 default:
492 SkASSERT(!"unknown text encoding");
493 return false;
494 }
495 return true;
496 }
497
glyphsToUnichars(const uint16_t glyphs[],int count,SkUnichar textData[]) const498 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
499 SkUnichar textData[]) const {
500 if (count <= 0) {
501 return;
502 }
503
504 SkASSERT(glyphs != NULL);
505 SkASSERT(textData != NULL);
506
507 SkAutoGlyphCache autoCache(*this, NULL);
508 SkGlyphCache* cache = autoCache.getCache();
509
510 for (int index = 0; index < count; index++) {
511 textData[index] = cache->glyphToUnichar(glyphs[index]);
512 }
513 }
514
515 ///////////////////////////////////////////////////////////////////////////////
516
sk_getMetrics_utf8_next(SkGlyphCache * cache,const char ** text)517 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
518 const char** text) {
519 SkASSERT(cache != NULL);
520 SkASSERT(text != NULL);
521
522 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
523 }
524
sk_getMetrics_utf8_prev(SkGlyphCache * cache,const char ** text)525 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
526 const char** text) {
527 SkASSERT(cache != NULL);
528 SkASSERT(text != NULL);
529
530 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
531 }
532
sk_getMetrics_utf16_next(SkGlyphCache * cache,const char ** text)533 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
534 const char** text) {
535 SkASSERT(cache != NULL);
536 SkASSERT(text != NULL);
537
538 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
539 }
540
sk_getMetrics_utf16_prev(SkGlyphCache * cache,const char ** text)541 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
542 const char** text) {
543 SkASSERT(cache != NULL);
544 SkASSERT(text != NULL);
545
546 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
547 }
548
sk_getMetrics_glyph_next(SkGlyphCache * cache,const char ** text)549 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
550 const char** text) {
551 SkASSERT(cache != NULL);
552 SkASSERT(text != NULL);
553
554 const uint16_t* ptr = *(const uint16_t**)text;
555 unsigned glyphID = *ptr;
556 ptr += 1;
557 *text = (const char*)ptr;
558 return cache->getGlyphIDMetrics(glyphID);
559 }
560
sk_getMetrics_glyph_prev(SkGlyphCache * cache,const char ** text)561 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
562 const char** text) {
563 SkASSERT(cache != NULL);
564 SkASSERT(text != NULL);
565
566 const uint16_t* ptr = *(const uint16_t**)text;
567 ptr -= 1;
568 unsigned glyphID = *ptr;
569 *text = (const char*)ptr;
570 return cache->getGlyphIDMetrics(glyphID);
571 }
572
sk_getAdvance_utf8_next(SkGlyphCache * cache,const char ** text)573 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
574 const char** text) {
575 SkASSERT(cache != NULL);
576 SkASSERT(text != NULL);
577
578 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
579 }
580
sk_getAdvance_utf8_prev(SkGlyphCache * cache,const char ** text)581 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
582 const char** text) {
583 SkASSERT(cache != NULL);
584 SkASSERT(text != NULL);
585
586 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
587 }
588
sk_getAdvance_utf16_next(SkGlyphCache * cache,const char ** text)589 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
590 const char** text) {
591 SkASSERT(cache != NULL);
592 SkASSERT(text != NULL);
593
594 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
595 }
596
sk_getAdvance_utf16_prev(SkGlyphCache * cache,const char ** text)597 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
598 const char** text) {
599 SkASSERT(cache != NULL);
600 SkASSERT(text != NULL);
601
602 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
603 }
604
sk_getAdvance_glyph_next(SkGlyphCache * cache,const char ** text)605 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
606 const char** text) {
607 SkASSERT(cache != NULL);
608 SkASSERT(text != NULL);
609
610 const uint16_t* ptr = *(const uint16_t**)text;
611 unsigned glyphID = *ptr;
612 ptr += 1;
613 *text = (const char*)ptr;
614 return cache->getGlyphIDAdvance(glyphID);
615 }
616
sk_getAdvance_glyph_prev(SkGlyphCache * cache,const char ** text)617 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
618 const char** text) {
619 SkASSERT(cache != NULL);
620 SkASSERT(text != NULL);
621
622 const uint16_t* ptr = *(const uint16_t**)text;
623 ptr -= 1;
624 unsigned glyphID = *ptr;
625 *text = (const char*)ptr;
626 return cache->getGlyphIDAdvance(glyphID);
627 }
628
getMeasureCacheProc(TextBufferDirection tbd,bool needFullMetrics) const629 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
630 bool needFullMetrics) const {
631 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
632 sk_getMetrics_utf8_next,
633 sk_getMetrics_utf16_next,
634 sk_getMetrics_glyph_next,
635
636 sk_getMetrics_utf8_prev,
637 sk_getMetrics_utf16_prev,
638 sk_getMetrics_glyph_prev,
639
640 sk_getAdvance_utf8_next,
641 sk_getAdvance_utf16_next,
642 sk_getAdvance_glyph_next,
643
644 sk_getAdvance_utf8_prev,
645 sk_getAdvance_utf16_prev,
646 sk_getAdvance_glyph_prev
647 };
648
649 unsigned index = this->getTextEncoding();
650
651 if (kBackward_TextBufferDirection == tbd) {
652 index += 3;
653 }
654 if (!needFullMetrics && !this->isDevKernText()) {
655 index += 6;
656 }
657
658 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
659 return gMeasureCacheProcs[index];
660 }
661
662 ///////////////////////////////////////////////////////////////////////////////
663
sk_getMetrics_utf8_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)664 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
665 const char** text, SkFixed, SkFixed) {
666 SkASSERT(cache != NULL);
667 SkASSERT(text != NULL);
668
669 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
670 }
671
sk_getMetrics_utf8_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)672 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
673 const char** text, SkFixed x, SkFixed y) {
674 SkASSERT(cache != NULL);
675 SkASSERT(text != NULL);
676
677 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
678 }
679
sk_getMetrics_utf16_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)680 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
681 const char** text, SkFixed, SkFixed) {
682 SkASSERT(cache != NULL);
683 SkASSERT(text != NULL);
684
685 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
686 }
687
sk_getMetrics_utf16_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)688 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
689 const char** text, SkFixed x, SkFixed y) {
690 SkASSERT(cache != NULL);
691 SkASSERT(text != NULL);
692
693 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
694 x, y);
695 }
696
sk_getMetrics_glyph_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)697 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
698 const char** text, SkFixed, SkFixed) {
699 SkASSERT(cache != NULL);
700 SkASSERT(text != NULL);
701
702 const uint16_t* ptr = *(const uint16_t**)text;
703 unsigned glyphID = *ptr;
704 ptr += 1;
705 *text = (const char*)ptr;
706 return cache->getGlyphIDMetrics(glyphID);
707 }
708
sk_getMetrics_glyph_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)709 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
710 const char** text, SkFixed x, SkFixed y) {
711 SkASSERT(cache != NULL);
712 SkASSERT(text != NULL);
713
714 const uint16_t* ptr = *(const uint16_t**)text;
715 unsigned glyphID = *ptr;
716 ptr += 1;
717 *text = (const char*)ptr;
718 return cache->getGlyphIDMetrics(glyphID, x, y);
719 }
720
getDrawCacheProc() const721 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
722 static const SkDrawCacheProc gDrawCacheProcs[] = {
723 sk_getMetrics_utf8_00,
724 sk_getMetrics_utf16_00,
725 sk_getMetrics_glyph_00,
726
727 sk_getMetrics_utf8_xy,
728 sk_getMetrics_utf16_xy,
729 sk_getMetrics_glyph_xy
730 };
731
732 unsigned index = this->getTextEncoding();
733 if (fFlags & kSubpixelText_Flag) {
734 index += 3;
735 }
736
737 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
738 return gDrawCacheProcs[index];
739 }
740
741 ///////////////////////////////////////////////////////////////////////////////
742
743 class SkAutoRestorePaintTextSizeAndFrame {
744 public:
SkAutoRestorePaintTextSizeAndFrame(const SkPaint * paint)745 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
746 : fPaint((SkPaint*)paint) {
747 fTextSize = paint->getTextSize();
748 fStyle = paint->getStyle();
749 fPaint->setStyle(SkPaint::kFill_Style);
750 }
751
~SkAutoRestorePaintTextSizeAndFrame()752 ~SkAutoRestorePaintTextSizeAndFrame() {
753 fPaint->setStyle(fStyle);
754 fPaint->setTextSize(fTextSize);
755 }
756
757 private:
758 SkPaint* fPaint;
759 SkScalar fTextSize;
760 SkPaint::Style fStyle;
761 };
762
set_bounds(const SkGlyph & g,SkRect * bounds)763 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
764 bounds->set(SkIntToScalar(g.fLeft),
765 SkIntToScalar(g.fTop),
766 SkIntToScalar(g.fLeft + g.fWidth),
767 SkIntToScalar(g.fTop + g.fHeight));
768 }
769
770 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
771 // we don't overflow along the way
772 typedef int64_t Sk48Dot16;
773
774 #ifdef SK_SCALAR_IS_FLOAT
Sk48Dot16ToScalar(Sk48Dot16 x)775 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
776 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
777 }
778 #else
Sk48Dot16ToScalar(Sk48Dot16 x)779 static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
780 // just return the low 32bits
781 return static_cast<SkFixed>(x);
782 }
783 #endif
784
join_bounds(const SkGlyph & g,SkRect * bounds,Sk48Dot16 dx)785 static void join_bounds(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
786 SkScalar sx = Sk48Dot16ToScalar(dx);
787 bounds->join(SkIntToScalar(g.fLeft) + sx,
788 SkIntToScalar(g.fTop),
789 SkIntToScalar(g.fLeft + g.fWidth) + sx,
790 SkIntToScalar(g.fTop + g.fHeight));
791 }
792
measure_text(SkGlyphCache * cache,const char * text,size_t byteLength,int * count,SkRect * bounds) const793 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
794 const char* text, size_t byteLength,
795 int* count, SkRect* bounds) const {
796 SkASSERT(count);
797 if (byteLength == 0) {
798 *count = 0;
799 if (bounds) {
800 bounds->setEmpty();
801 }
802 return 0;
803 }
804
805 SkMeasureCacheProc glyphCacheProc;
806 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
807 NULL != bounds);
808
809 int n = 1;
810 const char* stop = (const char*)text + byteLength;
811 const SkGlyph* g = &glyphCacheProc(cache, &text);
812 // our accumulated fixed-point advances might overflow 16.16, so we use
813 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
814 // very end.
815 Sk48Dot16 x = g->fAdvanceX;
816
817 SkAutoKern autokern;
818
819 if (NULL == bounds) {
820 if (this->isDevKernText()) {
821 int rsb;
822 for (; text < stop; n++) {
823 rsb = g->fRsbDelta;
824 g = &glyphCacheProc(cache, &text);
825 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + g->fAdvanceX;
826 }
827 } else {
828 for (; text < stop; n++) {
829 x += glyphCacheProc(cache, &text).fAdvanceX;
830 }
831 }
832 } else {
833 set_bounds(*g, bounds);
834 if (this->isDevKernText()) {
835 int rsb;
836 for (; text < stop; n++) {
837 rsb = g->fRsbDelta;
838 g = &glyphCacheProc(cache, &text);
839 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
840 join_bounds(*g, bounds, x);
841 x += g->fAdvanceX;
842 }
843 } else {
844 for (; text < stop; n++) {
845 g = &glyphCacheProc(cache, &text);
846 join_bounds(*g, bounds, x);
847 x += g->fAdvanceX;
848 }
849 }
850 }
851 SkASSERT(text == stop);
852
853 *count = n;
854 return Sk48Dot16ToScalar(x);
855 }
856
measureText(const void * textData,size_t length,SkRect * bounds,SkScalar zoom) const857 SkScalar SkPaint::measureText(const void* textData, size_t length,
858 SkRect* bounds, SkScalar zoom) const {
859 const char* text = (const char*)textData;
860 SkASSERT(text != NULL || length == 0);
861
862 SkScalar scale = 0;
863 SkAutoRestorePaintTextSizeAndFrame restore(this);
864
865 if (this->isLinearText()) {
866 scale = fTextSize / kCanonicalTextSizeForPaths;
867 // this gets restored by restore
868 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
869 }
870
871 SkMatrix zoomMatrix, *zoomPtr = NULL;
872 if (zoom) {
873 zoomMatrix.setScale(zoom, zoom);
874 zoomPtr = &zoomMatrix;
875 }
876
877 SkAutoGlyphCache autoCache(*this, zoomPtr);
878 SkGlyphCache* cache = autoCache.getCache();
879
880 SkScalar width = 0;
881
882 if (length > 0) {
883 int tempCount;
884
885 width = this->measure_text(cache, text, length, &tempCount, bounds);
886 if (scale) {
887 width = SkScalarMul(width, scale);
888 if (bounds) {
889 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
890 bounds->fTop = SkScalarMul(bounds->fTop, scale);
891 bounds->fRight = SkScalarMul(bounds->fRight, scale);
892 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
893 }
894 }
895 }
896 return width;
897 }
898
899 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
900
forward_textBufferPred(const char * text,const char * stop)901 static bool forward_textBufferPred(const char* text, const char* stop) {
902 return text < stop;
903 }
904
backward_textBufferPred(const char * text,const char * stop)905 static bool backward_textBufferPred(const char* text, const char* stop) {
906 return text > stop;
907 }
908
chooseTextBufferPred(SkPaint::TextBufferDirection tbd,const char ** text,size_t length,const char ** stop)909 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
910 const char** text, size_t length,
911 const char** stop) {
912 if (SkPaint::kForward_TextBufferDirection == tbd) {
913 *stop = *text + length;
914 return forward_textBufferPred;
915 } else {
916 // text should point to the end of the buffer, and stop to the beginning
917 *stop = *text;
918 *text += length;
919 return backward_textBufferPred;
920 }
921 }
922
breakText(const void * textD,size_t length,SkScalar maxWidth,SkScalar * measuredWidth,TextBufferDirection tbd) const923 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
924 SkScalar* measuredWidth,
925 TextBufferDirection tbd) const {
926 if (0 == length || 0 >= maxWidth) {
927 if (measuredWidth) {
928 *measuredWidth = 0;
929 }
930 return 0;
931 }
932
933 SkASSERT(textD != NULL);
934 const char* text = (const char*)textD;
935
936 SkScalar scale = 0;
937 SkAutoRestorePaintTextSizeAndFrame restore(this);
938
939 if (this->isLinearText()) {
940 scale = fTextSize / kCanonicalTextSizeForPaths;
941 maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
942 // this gets restored by restore
943 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
944 }
945
946 SkAutoGlyphCache autoCache(*this, NULL);
947 SkGlyphCache* cache = autoCache.getCache();
948
949 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
950 const char* stop;
951 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
952 // use 64bits for our accumulator, to avoid overflowing 16.16
953 Sk48Dot16 max = SkScalarToFixed(maxWidth);
954 Sk48Dot16 width = 0;
955
956 SkAutoKern autokern;
957
958 if (this->isDevKernText()) {
959 int rsb = 0;
960 while (pred(text, stop)) {
961 const char* curr = text;
962 const SkGlyph& g = glyphCacheProc(cache, &text);
963 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + g.fAdvanceX;
964 if ((width += x) > max) {
965 width -= x;
966 text = curr;
967 break;
968 }
969 rsb = g.fRsbDelta;
970 }
971 } else {
972 while (pred(text, stop)) {
973 const char* curr = text;
974 SkFixed x = glyphCacheProc(cache, &text).fAdvanceX;
975 if ((width += x) > max) {
976 width -= x;
977 text = curr;
978 break;
979 }
980 }
981 }
982
983 if (measuredWidth) {
984 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
985 if (scale) {
986 scalarWidth = SkScalarMul(scalarWidth, scale);
987 }
988 *measuredWidth = scalarWidth;
989 }
990
991 // return the number of bytes measured
992 return (kForward_TextBufferDirection == tbd) ?
993 text - stop + length : stop - text + length;
994 }
995
996 ///////////////////////////////////////////////////////////////////////////////
997
FontMetricsCacheProc(const SkGlyphCache * cache,void * context)998 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
999 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
1000 return false; // don't detach the cache
1001 }
1002
FontMetricsDescProc(const SkDescriptor * desc,void * context)1003 static void FontMetricsDescProc(const SkDescriptor* desc, void* context) {
1004 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
1005 }
1006
getFontMetrics(FontMetrics * metrics,SkScalar zoom) const1007 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1008 SkScalar scale = 0;
1009 SkAutoRestorePaintTextSizeAndFrame restore(this);
1010
1011 if (this->isLinearText()) {
1012 scale = fTextSize / kCanonicalTextSizeForPaths;
1013 // this gets restored by restore
1014 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
1015 }
1016
1017 SkMatrix zoomMatrix, *zoomPtr = NULL;
1018 if (zoom) {
1019 zoomMatrix.setScale(zoom, zoom);
1020 zoomPtr = &zoomMatrix;
1021 }
1022
1023 #if 0
1024 SkAutoGlyphCache autoCache(*this, zoomPtr);
1025 SkGlyphCache* cache = autoCache.getCache();
1026 const FontMetrics& my = cache->getFontMetricsY();
1027 #endif
1028 FontMetrics storage;
1029 if (NULL == metrics) {
1030 metrics = &storage;
1031 }
1032
1033 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics);
1034
1035 if (scale) {
1036 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1037 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1038 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1039 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1040 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1041 }
1042 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1043 }
1044
1045 ///////////////////////////////////////////////////////////////////////////////
1046
set_bounds(const SkGlyph & g,SkRect * bounds,SkScalar scale)1047 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1048 bounds->set(g.fLeft * scale,
1049 g.fTop * scale,
1050 (g.fLeft + g.fWidth) * scale,
1051 (g.fTop + g.fHeight) * scale);
1052 }
1053
getTextWidths(const void * textData,size_t byteLength,SkScalar widths[],SkRect bounds[]) const1054 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1055 SkScalar widths[], SkRect bounds[]) const {
1056 if (0 == byteLength) {
1057 return 0;
1058 }
1059
1060 SkASSERT(NULL != textData);
1061
1062 if (NULL == widths && NULL == bounds) {
1063 return this->countText(textData, byteLength);
1064 }
1065
1066 SkAutoRestorePaintTextSizeAndFrame restore(this);
1067 SkScalar scale = 0;
1068
1069 if (this->isLinearText()) {
1070 scale = fTextSize / kCanonicalTextSizeForPaths;
1071 // this gets restored by restore
1072 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
1073 }
1074
1075 SkAutoGlyphCache autoCache(*this, NULL);
1076 SkGlyphCache* cache = autoCache.getCache();
1077 SkMeasureCacheProc glyphCacheProc;
1078 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1079 NULL != bounds);
1080
1081 const char* text = (const char*)textData;
1082 const char* stop = text + byteLength;
1083 int count = 0;
1084
1085 if (this->isDevKernText()) {
1086 // we adjust the widths returned here through auto-kerning
1087 SkAutoKern autokern;
1088 SkFixed prevWidth = 0;
1089
1090 if (scale) {
1091 while (text < stop) {
1092 const SkGlyph& g = glyphCacheProc(cache, &text);
1093 if (widths) {
1094 SkFixed adjust = autokern.adjust(g);
1095
1096 if (count > 0) {
1097 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1098 *widths++ = SkScalarMul(w, scale);
1099 }
1100 prevWidth = g.fAdvanceX;
1101 }
1102 if (bounds) {
1103 set_bounds(g, bounds++, scale);
1104 }
1105 ++count;
1106 }
1107 if (count > 0 && widths) {
1108 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1109 }
1110 } else {
1111 while (text < stop) {
1112 const SkGlyph& g = glyphCacheProc(cache, &text);
1113 if (widths) {
1114 SkFixed adjust = autokern.adjust(g);
1115
1116 if (count > 0) {
1117 *widths++ = SkFixedToScalar(prevWidth + adjust);
1118 }
1119 prevWidth = g.fAdvanceX;
1120 }
1121 if (bounds) {
1122 set_bounds(g, bounds++);
1123 }
1124 ++count;
1125 }
1126 if (count > 0 && widths) {
1127 *widths = SkFixedToScalar(prevWidth);
1128 }
1129 }
1130 } else { // no devkern
1131 if (scale) {
1132 while (text < stop) {
1133 const SkGlyph& g = glyphCacheProc(cache, &text);
1134 if (widths) {
1135 *widths++ = SkScalarMul(SkFixedToScalar(g.fAdvanceX),
1136 scale);
1137 }
1138 if (bounds) {
1139 set_bounds(g, bounds++, scale);
1140 }
1141 ++count;
1142 }
1143 } else {
1144 while (text < stop) {
1145 const SkGlyph& g = glyphCacheProc(cache, &text);
1146 if (widths) {
1147 *widths++ = SkFixedToScalar(g.fAdvanceX);
1148 }
1149 if (bounds) {
1150 set_bounds(g, bounds++);
1151 }
1152 ++count;
1153 }
1154 }
1155 }
1156
1157 SkASSERT(text == stop);
1158 return count;
1159 }
1160
1161 ///////////////////////////////////////////////////////////////////////////////
1162
1163 #include "SkDraw.h"
1164
getTextPath(const void * textData,size_t length,SkScalar x,SkScalar y,SkPath * path) const1165 void SkPaint::getTextPath(const void* textData, size_t length,
1166 SkScalar x, SkScalar y, SkPath* path) const {
1167 SkASSERT(length == 0 || textData != NULL);
1168
1169 const char* text = (const char*)textData;
1170 if (text == NULL || length == 0 || path == NULL) {
1171 return;
1172 }
1173
1174 SkTextToPathIter iter(text, length, *this, false, true);
1175 SkMatrix matrix;
1176 SkScalar prevXPos = 0;
1177
1178 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1179 matrix.postTranslate(x, y);
1180 path->reset();
1181
1182 SkScalar xpos;
1183 const SkPath* iterPath;
1184 while ((iterPath = iter.next(&xpos)) != NULL) {
1185 matrix.postTranslate(xpos - prevXPos, 0);
1186 path->addPath(*iterPath, matrix);
1187 prevXPos = xpos;
1188 }
1189 }
1190
add_flattenable(SkDescriptor * desc,uint32_t tag,SkFlattenableWriteBuffer * buffer)1191 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1192 SkFlattenableWriteBuffer* buffer) {
1193 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
1194 }
1195
computeMaskFormat(const SkPaint & paint)1196 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1197 uint32_t flags = paint.getFlags();
1198
1199 // Antialiasing being disabled trumps all other settings.
1200 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1201 return SkMask::kBW_Format;
1202 }
1203
1204 #if defined(SK_SUPPORT_LCDTEXT)
1205 if (flags & SkPaint::kLCDRenderText_Flag) {
1206 return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
1207 SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
1208 }
1209 #else
1210 if (flags & SkPaint::kLCDRenderText_Flag) {
1211 return SkMask::kLCD16_Format;
1212 }
1213 #endif
1214
1215 return SkMask::kA8_Format;
1216 }
1217
1218 // if linear-text is on, then we force hinting to be off (since that's sort of
1219 // the point of linear-text.
computeHinting(const SkPaint & paint)1220 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1221 SkPaint::Hinting h = paint.getHinting();
1222 if (paint.isLinearText()) {
1223 h = SkPaint::kNo_Hinting;
1224 }
1225 return h;
1226 }
1227
1228 /*
1229 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1230 * that vary only slightly when we create our key into the font cache, since the font scaler
1231 * typically returns the same looking resuts for tiny changes in the matrix.
1232 */
sk_relax(SkScalar x)1233 static SkScalar sk_relax(SkScalar x) {
1234 #ifdef SK_SCALAR_IS_FLOAT
1235 int n = sk_float_round2int(x * 1024);
1236 return n / 1024.0f;
1237 #else
1238 // round to the nearest 10 fractional bits
1239 return (x + (1 << 5)) & ~(1024 - 1);
1240 #endif
1241 }
1242
MakeRec(const SkPaint & paint,const SkMatrix * deviceMatrix,Rec * rec)1243 void SkScalerContext::MakeRec(const SkPaint& paint,
1244 const SkMatrix* deviceMatrix, Rec* rec) {
1245 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1246
1247 rec->fOrigFontID = SkTypeface::UniqueID(paint.getTypeface());
1248 rec->fFontID = rec->fOrigFontID;
1249 rec->fTextSize = paint.getTextSize();
1250 rec->fPreScaleX = paint.getTextScaleX();
1251 rec->fPreSkewX = paint.getTextSkewX();
1252
1253 if (deviceMatrix) {
1254 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1255 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1256 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1257 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1258 } else {
1259 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1260 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1261 }
1262
1263 SkPaint::Style style = paint.getStyle();
1264 SkScalar strokeWidth = paint.getStrokeWidth();
1265
1266 unsigned flags = SkFontHost::ComputeGammaFlag(paint);
1267
1268 if (paint.isFakeBoldText()) {
1269 #ifdef SK_USE_FREETYPE_EMBOLDEN
1270 flags |= SkScalerContext::kEmbolden_Flag;
1271 #else
1272 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1273 kStdFakeBoldInterpKeys,
1274 kStdFakeBoldInterpValues,
1275 kStdFakeBoldInterpLength);
1276 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1277
1278 if (style == SkPaint::kFill_Style) {
1279 style = SkPaint::kStrokeAndFill_Style;
1280 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1281 } else {
1282 strokeWidth += extra;
1283 }
1284 #endif
1285 }
1286
1287 if (paint.isDevKernText()) {
1288 flags |= SkScalerContext::kDevKernText_Flag;
1289 }
1290
1291 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1292 rec->fFrameWidth = strokeWidth;
1293 rec->fMiterLimit = paint.getStrokeMiter();
1294 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1295
1296 if (style == SkPaint::kStrokeAndFill_Style) {
1297 flags |= SkScalerContext::kFrameAndFill_Flag;
1298 }
1299 } else {
1300 rec->fFrameWidth = 0;
1301 rec->fMiterLimit = 0;
1302 rec->fStrokeJoin = 0;
1303 }
1304
1305 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1306
1307 if (SkMask::kLCD16_Format == rec->fMaskFormat) {
1308 SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
1309 SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
1310 if (SkFontHost::kNONE_LCDOrder == order) {
1311 // eeek, can't support LCD
1312 rec->fMaskFormat = SkMask::kA8_Format;
1313 } else {
1314 if (SkFontHost::kVertical_LCDOrientation == orient) {
1315 flags |= SkScalerContext::kLCD_Vertical_Flag;
1316 }
1317 if (SkFontHost::kBGR_LCDOrder == order) {
1318 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1319 }
1320 }
1321 }
1322
1323 if (paint.isEmbeddedBitmapText()) {
1324 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1325 }
1326 if (paint.isSubpixelText()) {
1327 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1328 }
1329 if (paint.isAutohinted()) {
1330 flags |= SkScalerContext::kAutohinting_Flag;
1331 }
1332 rec->fFlags = SkToU16(flags);
1333
1334 // setHinting modifies fFlags, so do this last
1335 rec->setHinting(computeHinting(paint));
1336
1337 /* Allow the fonthost to modify our rec before we use it as a key into the
1338 cache. This way if we're asking for something that they will ignore,
1339 they can modify our rec up front, so we don't create duplicate cache
1340 entries.
1341 */
1342 SkFontHost::FilterRec(rec);
1343 }
1344
1345 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1346
1347 #ifdef SK_DEBUG
1348 #define TEST_DESC
1349 #endif
1350
descriptorProc(const SkMatrix * deviceMatrix,void (* proc)(const SkDescriptor *,void *),void * context,bool ignoreGamma) const1351 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
1352 void (*proc)(const SkDescriptor*, void*),
1353 void* context, bool ignoreGamma) const {
1354 SkScalerContext::Rec rec;
1355
1356 SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1357 if (ignoreGamma) {
1358 rec.fFlags &= ~(SkScalerContext::kGammaForBlack_Flag |
1359 SkScalerContext::kGammaForWhite_Flag);
1360 }
1361
1362 size_t descSize = sizeof(rec);
1363 int entryCount = 1;
1364 SkPathEffect* pe = this->getPathEffect();
1365 SkMaskFilter* mf = this->getMaskFilter();
1366 SkRasterizer* ra = this->getRasterizer();
1367
1368 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1369 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1370 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1371
1372 if (pe) {
1373 peBuffer.writeFlattenable(pe);
1374 descSize += peBuffer.size();
1375 entryCount += 1;
1376 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1377 // seems like we could support kLCD as well at this point...
1378 }
1379 if (mf) {
1380 mfBuffer.writeFlattenable(mf);
1381 descSize += mfBuffer.size();
1382 entryCount += 1;
1383 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1384 }
1385 if (ra) {
1386 raBuffer.writeFlattenable(ra);
1387 descSize += raBuffer.size();
1388 entryCount += 1;
1389 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1390 }
1391 descSize += SkDescriptor::ComputeOverhead(entryCount);
1392
1393 SkAutoDescriptor ad(descSize);
1394 SkDescriptor* desc = ad.getDesc();
1395
1396 desc->init();
1397 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1398
1399 if (pe) {
1400 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1401 }
1402 if (mf) {
1403 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1404 }
1405 if (ra) {
1406 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1407 }
1408
1409 SkASSERT(descSize == desc->getLength());
1410 desc->computeChecksum();
1411
1412 #ifdef TEST_DESC
1413 {
1414 // Check that we completely write the bytes in desc (our key), and that
1415 // there are no uninitialized bytes. If there were, then we would get
1416 // false-misses (or worse, false-hits) in our fontcache.
1417 //
1418 // We do this buy filling 2 others, one with 0s and the other with 1s
1419 // and create those, and then check that all 3 are identical.
1420 SkAutoDescriptor ad1(descSize);
1421 SkAutoDescriptor ad2(descSize);
1422 SkDescriptor* desc1 = ad1.getDesc();
1423 SkDescriptor* desc2 = ad2.getDesc();
1424
1425 memset(desc1, 0x00, descSize);
1426 memset(desc2, 0xFF, descSize);
1427
1428 desc1->init();
1429 desc2->init();
1430 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1431 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1432
1433 if (pe) {
1434 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
1435 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
1436 }
1437 if (mf) {
1438 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
1439 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
1440 }
1441 if (ra) {
1442 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
1443 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
1444 }
1445
1446 SkASSERT(descSize == desc1->getLength());
1447 SkASSERT(descSize == desc2->getLength());
1448 desc1->computeChecksum();
1449 desc2->computeChecksum();
1450 SkASSERT(!memcmp(desc, desc1, descSize));
1451 SkASSERT(!memcmp(desc, desc2, descSize));
1452 }
1453 #endif
1454
1455 proc(desc, context);
1456 }
1457
detachCache(const SkMatrix * deviceMatrix) const1458 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const {
1459 SkGlyphCache* cache;
1460 this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
1461 return cache;
1462 }
1463
1464 ///////////////////////////////////////////////////////////////////////////////
1465
1466 #include "SkStream.h"
1467
asint(const void * p)1468 static uintptr_t asint(const void* p) {
1469 return reinterpret_cast<uintptr_t>(p);
1470 }
1471
1472 union Scalar32 {
1473 SkScalar fScalar;
1474 uint32_t f32;
1475 };
1476
write_scalar(uint32_t * ptr,SkScalar value)1477 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1478 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1479 Scalar32 tmp;
1480 tmp.fScalar = value;
1481 *ptr = tmp.f32;
1482 return ptr + 1;
1483 }
1484
read_scalar(const uint32_t * & ptr)1485 static SkScalar read_scalar(const uint32_t*& ptr) {
1486 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1487 Scalar32 tmp;
1488 tmp.f32 = *ptr++;
1489 return tmp.fScalar;
1490 }
1491
pack_4(unsigned a,unsigned b,unsigned c,unsigned d)1492 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1493 SkASSERT(a == (uint8_t)a);
1494 SkASSERT(b == (uint8_t)b);
1495 SkASSERT(c == (uint8_t)c);
1496 SkASSERT(d == (uint8_t)d);
1497 return (a << 24) | (b << 16) | (c << 8) | d;
1498 }
1499
1500 enum FlatFlags {
1501 kHasTypeface_FlatFlag = 0x01,
1502 kHasEffects_FlatFlag = 0x02
1503 };
1504
1505 // The size of a flat paint's POD fields
1506 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1507 1 * sizeof(SkColor) +
1508 1 * sizeof(uint16_t) +
1509 6 * sizeof(uint8_t);
1510
1511 /* To save space/time, we analyze the paint, and write a truncated version of
1512 it if there are not tricky elements like shaders, etc.
1513 */
flatten(SkFlattenableWriteBuffer & buffer) const1514 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
1515 uint8_t flatFlags = 0;
1516 if (this->getTypeface()) {
1517 flatFlags |= kHasTypeface_FlatFlag;
1518 }
1519 if (asint(this->getPathEffect()) |
1520 asint(this->getShader()) |
1521 asint(this->getXfermode()) |
1522 asint(this->getMaskFilter()) |
1523 asint(this->getColorFilter()) |
1524 asint(this->getRasterizer()) |
1525 asint(this->getLooper())) {
1526 flatFlags |= kHasEffects_FlatFlag;
1527 }
1528
1529 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1530 uint32_t* ptr = buffer.reserve(kPODPaintSize);
1531
1532 ptr = write_scalar(ptr, this->getTextSize());
1533 ptr = write_scalar(ptr, this->getTextScaleX());
1534 ptr = write_scalar(ptr, this->getTextSkewX());
1535 ptr = write_scalar(ptr, this->getStrokeWidth());
1536 ptr = write_scalar(ptr, this->getStrokeMiter());
1537 *ptr++ = this->getColor();
1538 *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
1539 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1540 this->getStyle(), this->getTextEncoding());
1541
1542 // now we're done with ptr and the (pre)reserved space. If we need to write
1543 // additional fields, use the buffer directly
1544 if (flatFlags & kHasTypeface_FlatFlag) {
1545 buffer.writeTypeface(this->getTypeface());
1546 }
1547 if (flatFlags & kHasEffects_FlatFlag) {
1548 buffer.writeFlattenable(this->getPathEffect());
1549 buffer.writeFlattenable(this->getShader());
1550 buffer.writeFlattenable(this->getXfermode());
1551 buffer.writeFlattenable(this->getMaskFilter());
1552 buffer.writeFlattenable(this->getColorFilter());
1553 buffer.writeFlattenable(this->getRasterizer());
1554 buffer.writeFlattenable(this->getLooper());
1555 }
1556 }
1557
unflatten(SkFlattenableReadBuffer & buffer)1558 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
1559 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1560 const void* podData = buffer.skip(kPODPaintSize);
1561 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1562
1563 // the order we read must match the order we wrote in flatten()
1564 this->setTextSize(read_scalar(pod));
1565 this->setTextScaleX(read_scalar(pod));
1566 this->setTextSkewX(read_scalar(pod));
1567 this->setStrokeWidth(read_scalar(pod));
1568 this->setStrokeMiter(read_scalar(pod));
1569 this->setColor(*pod++);
1570
1571 uint32_t tmp = *pod++;
1572 this->setFlags(tmp >> 16);
1573 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
1574 uint8_t flatFlags = tmp & 0xFF;
1575
1576 tmp = *pod++;
1577 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1578 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1579 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1580 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1581
1582 if (flatFlags & kHasTypeface_FlatFlag) {
1583 this->setTypeface(buffer.readTypeface());
1584 } else {
1585 this->setTypeface(NULL);
1586 }
1587
1588 if (flatFlags & kHasEffects_FlatFlag) {
1589 SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
1590 SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
1591 SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
1592 SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
1593 SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
1594 SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
1595 SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
1596 } else {
1597 this->setPathEffect(NULL);
1598 this->setShader(NULL);
1599 this->setXfermode(NULL);
1600 this->setMaskFilter(NULL);
1601 this->setColorFilter(NULL);
1602 this->setRasterizer(NULL);
1603 this->setLooper(NULL);
1604 }
1605 }
1606
1607 ///////////////////////////////////////////////////////////////////////////////
1608
setShader(SkShader * shader)1609 SkShader* SkPaint::setShader(SkShader* shader) {
1610 GEN_ID_INC_EVAL(shader != fShader);
1611 SkRefCnt_SafeAssign(fShader, shader);
1612 return shader;
1613 }
1614
setColorFilter(SkColorFilter * filter)1615 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
1616 GEN_ID_INC_EVAL(filter != fColorFilter);
1617 SkRefCnt_SafeAssign(fColorFilter, filter);
1618 return filter;
1619 }
1620
setXfermode(SkXfermode * mode)1621 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
1622 GEN_ID_INC_EVAL(mode != fXfermode);
1623 SkRefCnt_SafeAssign(fXfermode, mode);
1624 return mode;
1625 }
1626
setXfermodeMode(SkXfermode::Mode mode)1627 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
1628 SkSafeUnref(fXfermode);
1629 fXfermode = SkXfermode::Create(mode);
1630 GEN_ID_INC;
1631 return fXfermode;
1632 }
1633
setPathEffect(SkPathEffect * effect)1634 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
1635 GEN_ID_INC_EVAL(effect != fPathEffect);
1636 SkRefCnt_SafeAssign(fPathEffect, effect);
1637 return effect;
1638 }
1639
setMaskFilter(SkMaskFilter * filter)1640 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
1641 GEN_ID_INC_EVAL(filter != fMaskFilter);
1642 SkRefCnt_SafeAssign(fMaskFilter, filter);
1643 return filter;
1644 }
1645
1646 ///////////////////////////////////////////////////////////////////////////////
1647
getFillPath(const SkPath & src,SkPath * dst) const1648 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
1649 SkPath effectPath, strokePath;
1650 const SkPath* path = &src;
1651
1652 SkScalar width = this->getStrokeWidth();
1653
1654 switch (this->getStyle()) {
1655 case SkPaint::kFill_Style:
1656 width = -1; // mark it as no-stroke
1657 break;
1658 case SkPaint::kStrokeAndFill_Style:
1659 if (width == 0) {
1660 width = -1; // mark it as no-stroke
1661 }
1662 break;
1663 case SkPaint::kStroke_Style:
1664 break;
1665 default:
1666 SkASSERT(!"unknown paint style");
1667 }
1668
1669 if (this->getPathEffect()) {
1670 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
1671 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
1672 width = -1; // mark it as no-stroke
1673 }
1674
1675 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
1676 path = &effectPath;
1677 }
1678
1679 // restore the width if we earlier had to lie, and if we're still set to no-stroke
1680 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
1681 // and we want to respect that (i.e. don't overwrite their setting for width)
1682 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
1683 width = this->getStrokeWidth();
1684 if (width == 0) {
1685 width = -1;
1686 }
1687 }
1688 }
1689
1690 if (width > 0 && !path->isEmpty()) {
1691 SkStroke stroker(*this, width);
1692 stroker.strokePath(*path, &strokePath);
1693 path = &strokePath;
1694 }
1695
1696 if (path == &src) {
1697 *dst = src;
1698 } else {
1699 SkASSERT(path == &effectPath || path == &strokePath);
1700 dst->swap(*(SkPath*)path);
1701 }
1702
1703 return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
1704 }
1705
computeStrokeFastBounds(const SkRect & src,SkRect * storage) const1706 const SkRect& SkPaint::computeStrokeFastBounds(const SkRect& src,
1707 SkRect* storage) const {
1708 SkASSERT(storage);
1709 SkASSERT(this->getStyle() != SkPaint::kFill_Style);
1710
1711 // since we're stroked, outset the rect by the radius (and join type)
1712 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
1713 if (0 == radius) { // hairline
1714 radius = SK_Scalar1;
1715 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
1716 SkScalar scale = this->getStrokeMiter();
1717 if (scale > SK_Scalar1) {
1718 radius = SkScalarMul(radius, scale);
1719 }
1720 }
1721 storage->set(src.fLeft - radius, src.fTop - radius,
1722 src.fRight + radius, src.fBottom + radius);
1723 return *storage;
1724 }
1725
1726 ///////////////////////////////////////////////////////////////////////////////
1727
has_thick_frame(const SkPaint & paint)1728 static bool has_thick_frame(const SkPaint& paint) {
1729 return paint.getStrokeWidth() > 0 &&
1730 paint.getStyle() != SkPaint::kFill_Style;
1731 }
1732
SkTextToPathIter(const char text[],size_t length,const SkPaint & paint,bool applyStrokeAndPathEffects,bool forceLinearTextOn)1733 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
1734 const SkPaint& paint,
1735 bool applyStrokeAndPathEffects,
1736 bool forceLinearTextOn) : fPaint(paint) {
1737 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
1738 true);
1739
1740 if (forceLinearTextOn) {
1741 fPaint.setLinearText(true);
1742 }
1743 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
1744
1745 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
1746 applyStrokeAndPathEffects = false;
1747 }
1748
1749 // can't use our canonical size if we need to apply patheffects/strokes
1750 if (fPaint.isLinearText() && !applyStrokeAndPathEffects) {
1751 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
1752 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
1753 } else {
1754 fScale = SK_Scalar1;
1755 }
1756
1757 if (!applyStrokeAndPathEffects) {
1758 fPaint.setStyle(SkPaint::kFill_Style);
1759 fPaint.setPathEffect(NULL);
1760 }
1761
1762 fCache = fPaint.detachCache(NULL);
1763
1764 SkPaint::Style style = SkPaint::kFill_Style;
1765 SkPathEffect* pe = NULL;
1766
1767 if (!applyStrokeAndPathEffects) {
1768 style = paint.getStyle(); // restore
1769 pe = paint.getPathEffect(); // restore
1770 }
1771 fPaint.setStyle(style);
1772 fPaint.setPathEffect(pe);
1773 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
1774
1775 // now compute fXOffset if needed
1776
1777 SkScalar xOffset = 0;
1778 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
1779 int count;
1780 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
1781 &count, NULL), fScale);
1782 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1783 width = SkScalarHalf(width);
1784 }
1785 xOffset = -width;
1786 }
1787 fXPos = xOffset;
1788 fPrevAdvance = 0;
1789
1790 fText = text;
1791 fStop = text + length;
1792 }
1793
~SkTextToPathIter()1794 SkTextToPathIter::~SkTextToPathIter() {
1795 SkGlyphCache::AttachCache(fCache);
1796 }
1797
next(SkScalar * xpos)1798 const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
1799 while (fText < fStop) {
1800 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
1801
1802 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
1803 fPrevAdvance = glyph.fAdvanceX; // + fPaint.getTextTracking();
1804
1805 if (glyph.fWidth) {
1806 if (xpos) {
1807 *xpos = fXPos;
1808 }
1809 return fCache->findPath(glyph);
1810 }
1811 }
1812 return NULL;
1813 }
1814