1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #include <new>
11
12 #include "SkPaint.h"
13 #include "SkColorFilter.h"
14 #include "SkFontHost.h"
15 #include "SkImageFilter.h"
16 #include "SkMaskFilter.h"
17 #include "SkPathEffect.h"
18 #include "SkRasterizer.h"
19 #include "SkShader.h"
20 #include "SkScalar.h"
21 #include "SkScalerContext.h"
22 #include "SkStroke.h"
23 #include "SkTextFormatParams.h"
24 #include "SkTypeface.h"
25 #include "SkXfermode.h"
26 #include "SkAutoKern.h"
27 #include "SkGlyphCache.h"
28 #include "SkPaintDefaults.h"
29
30 // define this to get a printf for out-of-range parameter in setters
31 // e.g. setTextSize(-1)
32 //#define SK_REPORT_API_RANGE_CHECK
33
34 #ifdef SK_BUILD_FOR_ANDROID
35 #include "SkLanguage.h"
36 #define GEN_ID_INC fGenerationID++
37 #define GEN_ID_INC_EVAL(expression) if (expression) { fGenerationID++; }
38 #else
39 #define GEN_ID_INC
40 #define GEN_ID_INC_EVAL(expression)
41 #endif
42
SkPaint()43 SkPaint::SkPaint() {
44 // since we may have padding, we zero everything so that our memcmp() call
45 // in operator== will work correctly.
46 // with this, we can skip 0 and null individual initializations
47 sk_bzero(this, sizeof(*this));
48
49 #if 0 // not needed with the bzero call above
50 fTypeface = NULL;
51 fTextSkewX = 0;
52 fPathEffect = NULL;
53 fShader = NULL;
54 fXfermode = NULL;
55 fMaskFilter = NULL;
56 fColorFilter = NULL;
57 fRasterizer = NULL;
58 fLooper = NULL;
59 fImageFilter = NULL;
60 fWidth = 0;
61 #endif
62
63 fTextSize = SkPaintDefaults_TextSize;
64 fTextScaleX = SK_Scalar1;
65 fColor = SK_ColorBLACK;
66 fMiterLimit = SkPaintDefaults_MiterLimit;
67 fFlags = SkPaintDefaults_Flags;
68 fCapType = kDefault_Cap;
69 fJoinType = kDefault_Join;
70 fTextAlign = kLeft_Align;
71 fStyle = kFill_Style;
72 fTextEncoding = kUTF8_TextEncoding;
73 fHinting = SkPaintDefaults_Hinting;
74 #ifdef SK_BUILD_FOR_ANDROID
75 fLanguage = SkLanguage();
76 fFontVariant = kDefault_Variant;
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 SkSafeRef(fImageFilter);
93 }
94
~SkPaint()95 SkPaint::~SkPaint() {
96 SkSafeUnref(fTypeface);
97 SkSafeUnref(fPathEffect);
98 SkSafeUnref(fShader);
99 SkSafeUnref(fXfermode);
100 SkSafeUnref(fMaskFilter);
101 SkSafeUnref(fColorFilter);
102 SkSafeUnref(fRasterizer);
103 SkSafeUnref(fLooper);
104 SkSafeUnref(fImageFilter);
105 }
106
operator =(const SkPaint & src)107 SkPaint& SkPaint::operator=(const SkPaint& src) {
108 SkASSERT(&src);
109
110 SkSafeRef(src.fTypeface);
111 SkSafeRef(src.fPathEffect);
112 SkSafeRef(src.fShader);
113 SkSafeRef(src.fXfermode);
114 SkSafeRef(src.fMaskFilter);
115 SkSafeRef(src.fColorFilter);
116 SkSafeRef(src.fRasterizer);
117 SkSafeRef(src.fLooper);
118 SkSafeRef(src.fImageFilter);
119
120 SkSafeUnref(fTypeface);
121 SkSafeUnref(fPathEffect);
122 SkSafeUnref(fShader);
123 SkSafeUnref(fXfermode);
124 SkSafeUnref(fMaskFilter);
125 SkSafeUnref(fColorFilter);
126 SkSafeUnref(fRasterizer);
127 SkSafeUnref(fLooper);
128 SkSafeUnref(fImageFilter);
129
130 #ifdef SK_BUILD_FOR_ANDROID
131 uint32_t oldGenerationID = fGenerationID;
132 #endif
133 memcpy(this, &src, sizeof(src));
134 #ifdef SK_BUILD_FOR_ANDROID
135 fGenerationID = oldGenerationID + 1;
136 #endif
137
138 return *this;
139 }
140
operator ==(const SkPaint & a,const SkPaint & b)141 bool operator==(const SkPaint& a, const SkPaint& b) {
142 #ifdef SK_BUILD_FOR_ANDROID
143 //assumes that fGenerationID is the last field in the struct
144 return !memcmp(&a, &b, SK_OFFSETOF(SkPaint, fGenerationID));
145 #else
146 return !memcmp(&a, &b, sizeof(a));
147 #endif
148 }
149
reset()150 void SkPaint::reset() {
151 SkPaint init;
152
153 #ifdef SK_BUILD_FOR_ANDROID
154 uint32_t oldGenerationID = fGenerationID;
155 #endif
156 *this = init;
157 #ifdef SK_BUILD_FOR_ANDROID
158 fGenerationID = oldGenerationID + 1;
159 #endif
160 }
161
162 #ifdef SK_BUILD_FOR_ANDROID
getGenerationID() const163 uint32_t SkPaint::getGenerationID() const {
164 return fGenerationID;
165 }
166 #endif
167
168 #ifdef SK_BUILD_FOR_ANDROID
getBaseGlyphCount(SkUnichar text) const169 unsigned SkPaint::getBaseGlyphCount(SkUnichar text) const {
170 SkAutoGlyphCache autoCache(*this, NULL);
171 SkGlyphCache* cache = autoCache.getCache();
172 return cache->getBaseGlyphCount(text);
173 }
174 #endif
175
setHinting(Hinting hintingLevel)176 void SkPaint::setHinting(Hinting hintingLevel) {
177 GEN_ID_INC_EVAL((unsigned) hintingLevel != fHinting);
178 fHinting = hintingLevel;
179 }
180
setFlags(uint32_t flags)181 void SkPaint::setFlags(uint32_t flags) {
182 GEN_ID_INC_EVAL(fFlags != flags);
183 fFlags = flags;
184 }
185
setAntiAlias(bool doAA)186 void SkPaint::setAntiAlias(bool doAA) {
187 GEN_ID_INC_EVAL(doAA != isAntiAlias());
188 this->setFlags(SkSetClearMask(fFlags, doAA, kAntiAlias_Flag));
189 }
190
setDither(bool doDither)191 void SkPaint::setDither(bool doDither) {
192 GEN_ID_INC_EVAL(doDither != isDither());
193 this->setFlags(SkSetClearMask(fFlags, doDither, kDither_Flag));
194 }
195
setSubpixelText(bool doSubpixel)196 void SkPaint::setSubpixelText(bool doSubpixel) {
197 GEN_ID_INC_EVAL(doSubpixel != isSubpixelText());
198 this->setFlags(SkSetClearMask(fFlags, doSubpixel, kSubpixelText_Flag));
199 }
200
setLCDRenderText(bool doLCDRender)201 void SkPaint::setLCDRenderText(bool doLCDRender) {
202 GEN_ID_INC_EVAL(doLCDRender != isLCDRenderText());
203 this->setFlags(SkSetClearMask(fFlags, doLCDRender, kLCDRenderText_Flag));
204 }
205
setEmbeddedBitmapText(bool doEmbeddedBitmapText)206 void SkPaint::setEmbeddedBitmapText(bool doEmbeddedBitmapText) {
207 GEN_ID_INC_EVAL(doEmbeddedBitmapText != isEmbeddedBitmapText());
208 this->setFlags(SkSetClearMask(fFlags, doEmbeddedBitmapText, kEmbeddedBitmapText_Flag));
209 }
210
setAutohinted(bool useAutohinter)211 void SkPaint::setAutohinted(bool useAutohinter) {
212 GEN_ID_INC_EVAL(useAutohinter != isAutohinted());
213 this->setFlags(SkSetClearMask(fFlags, useAutohinter, kAutoHinting_Flag));
214 }
215
setLinearText(bool doLinearText)216 void SkPaint::setLinearText(bool doLinearText) {
217 GEN_ID_INC_EVAL(doLinearText != isLinearText());
218 this->setFlags(SkSetClearMask(fFlags, doLinearText, kLinearText_Flag));
219 }
220
setVerticalText(bool doVertical)221 void SkPaint::setVerticalText(bool doVertical) {
222 GEN_ID_INC_EVAL(doVertical != isVerticalText());
223 this->setFlags(SkSetClearMask(fFlags, doVertical, kVerticalText_Flag));
224 }
225
setUnderlineText(bool doUnderline)226 void SkPaint::setUnderlineText(bool doUnderline) {
227 GEN_ID_INC_EVAL(doUnderline != isUnderlineText());
228 this->setFlags(SkSetClearMask(fFlags, doUnderline, kUnderlineText_Flag));
229 }
230
setStrikeThruText(bool doStrikeThru)231 void SkPaint::setStrikeThruText(bool doStrikeThru) {
232 GEN_ID_INC_EVAL(doStrikeThru != isStrikeThruText());
233 this->setFlags(SkSetClearMask(fFlags, doStrikeThru, kStrikeThruText_Flag));
234 }
235
setFakeBoldText(bool doFakeBold)236 void SkPaint::setFakeBoldText(bool doFakeBold) {
237 GEN_ID_INC_EVAL(doFakeBold != isFakeBoldText());
238 this->setFlags(SkSetClearMask(fFlags, doFakeBold, kFakeBoldText_Flag));
239 }
240
setDevKernText(bool doDevKern)241 void SkPaint::setDevKernText(bool doDevKern) {
242 GEN_ID_INC_EVAL(doDevKern != isDevKernText());
243 this->setFlags(SkSetClearMask(fFlags, doDevKern, kDevKernText_Flag));
244 }
245
setFilterBitmap(bool doFilter)246 void SkPaint::setFilterBitmap(bool doFilter) {
247 GEN_ID_INC_EVAL(doFilter != isFilterBitmap());
248 this->setFlags(SkSetClearMask(fFlags, doFilter, kFilterBitmap_Flag));
249 }
250
setStyle(Style style)251 void SkPaint::setStyle(Style style) {
252 if ((unsigned)style < kStyleCount) {
253 GEN_ID_INC_EVAL((unsigned)style != fStyle);
254 fStyle = style;
255 } else {
256 #ifdef SK_REPORT_API_RANGE_CHECK
257 SkDebugf("SkPaint::setStyle(%d) out of range\n", style);
258 #endif
259 }
260 }
261
setColor(SkColor color)262 void SkPaint::setColor(SkColor color) {
263 GEN_ID_INC_EVAL(color != fColor);
264 fColor = color;
265 }
266
setAlpha(U8CPU a)267 void SkPaint::setAlpha(U8CPU a) {
268 this->setColor(SkColorSetARGB(a, SkColorGetR(fColor),
269 SkColorGetG(fColor), SkColorGetB(fColor)));
270 }
271
setARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)272 void SkPaint::setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
273 this->setColor(SkColorSetARGB(a, r, g, b));
274 }
275
setStrokeWidth(SkScalar width)276 void SkPaint::setStrokeWidth(SkScalar width) {
277 if (width >= 0) {
278 GEN_ID_INC_EVAL(width != fWidth);
279 fWidth = width;
280 } else {
281 #ifdef SK_REPORT_API_RANGE_CHECK
282 SkDebugf("SkPaint::setStrokeWidth() called with negative value\n");
283 #endif
284 }
285 }
286
setStrokeMiter(SkScalar limit)287 void SkPaint::setStrokeMiter(SkScalar limit) {
288 if (limit >= 0) {
289 GEN_ID_INC_EVAL(limit != fMiterLimit);
290 fMiterLimit = limit;
291 } else {
292 #ifdef SK_REPORT_API_RANGE_CHECK
293 SkDebugf("SkPaint::setStrokeMiter() called with negative value\n");
294 #endif
295 }
296 }
297
setStrokeCap(Cap ct)298 void SkPaint::setStrokeCap(Cap ct) {
299 if ((unsigned)ct < kCapCount) {
300 GEN_ID_INC_EVAL((unsigned)ct != fCapType);
301 fCapType = SkToU8(ct);
302 } else {
303 #ifdef SK_REPORT_API_RANGE_CHECK
304 SkDebugf("SkPaint::setStrokeCap(%d) out of range\n", ct);
305 #endif
306 }
307 }
308
setStrokeJoin(Join jt)309 void SkPaint::setStrokeJoin(Join jt) {
310 if ((unsigned)jt < kJoinCount) {
311 GEN_ID_INC_EVAL((unsigned)jt != fJoinType);
312 fJoinType = SkToU8(jt);
313 } else {
314 #ifdef SK_REPORT_API_RANGE_CHECK
315 SkDebugf("SkPaint::setStrokeJoin(%d) out of range\n", jt);
316 #endif
317 }
318 }
319
320 ///////////////////////////////////////////////////////////////////////////////
321
setTextAlign(Align align)322 void SkPaint::setTextAlign(Align align) {
323 if ((unsigned)align < kAlignCount) {
324 GEN_ID_INC_EVAL((unsigned)align != fTextAlign);
325 fTextAlign = SkToU8(align);
326 } else {
327 #ifdef SK_REPORT_API_RANGE_CHECK
328 SkDebugf("SkPaint::setTextAlign(%d) out of range\n", align);
329 #endif
330 }
331 }
332
setTextSize(SkScalar ts)333 void SkPaint::setTextSize(SkScalar ts) {
334 if (ts >= 0) {
335 GEN_ID_INC_EVAL(ts != fTextSize);
336 fTextSize = ts;
337 } else {
338 #ifdef SK_REPORT_API_RANGE_CHECK
339 SkDebugf("SkPaint::setTextSize() called with negative value\n");
340 #endif
341 }
342 }
343
setTextScaleX(SkScalar scaleX)344 void SkPaint::setTextScaleX(SkScalar scaleX) {
345 GEN_ID_INC_EVAL(scaleX != fTextScaleX);
346 fTextScaleX = scaleX;
347 }
348
setTextSkewX(SkScalar skewX)349 void SkPaint::setTextSkewX(SkScalar skewX) {
350 GEN_ID_INC_EVAL(skewX != fTextSkewX);
351 fTextSkewX = skewX;
352 }
353
setTextEncoding(TextEncoding encoding)354 void SkPaint::setTextEncoding(TextEncoding encoding) {
355 if ((unsigned)encoding <= kGlyphID_TextEncoding) {
356 GEN_ID_INC_EVAL((unsigned)encoding != fTextEncoding);
357 fTextEncoding = encoding;
358 } else {
359 #ifdef SK_REPORT_API_RANGE_CHECK
360 SkDebugf("SkPaint::setTextEncoding(%d) out of range\n", encoding);
361 #endif
362 }
363 }
364
365 #ifdef SK_BUILD_FOR_ANDROID
setLanguage(const SkLanguage & language)366 void SkPaint::setLanguage(const SkLanguage& language) {
367 if(fLanguage != language) {
368 fLanguage = language;
369 GEN_ID_INC;
370 }
371 }
372
setFontVariant(FontVariant fontVariant)373 void SkPaint::setFontVariant(FontVariant fontVariant) {
374 if ((unsigned)fontVariant <= kLast_Variant) {
375 GEN_ID_INC_EVAL((unsigned)fontVariant != fFontVariant);
376 fFontVariant = fontVariant;
377 } else {
378 #ifdef SK_REPORT_API_RANGE_CHECK
379 SkDebugf("SkPaint::setFontVariant(%d) out of range\n", fontVariant);
380 #endif
381 }
382 }
383
384 #endif
385
386 ///////////////////////////////////////////////////////////////////////////////
387
setTypeface(SkTypeface * font)388 SkTypeface* SkPaint::setTypeface(SkTypeface* font) {
389 SkRefCnt_SafeAssign(fTypeface, font);
390 GEN_ID_INC;
391 return font;
392 }
393
setRasterizer(SkRasterizer * r)394 SkRasterizer* SkPaint::setRasterizer(SkRasterizer* r) {
395 SkRefCnt_SafeAssign(fRasterizer, r);
396 GEN_ID_INC;
397 return r;
398 }
399
setLooper(SkDrawLooper * looper)400 SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) {
401 SkRefCnt_SafeAssign(fLooper, looper);
402 GEN_ID_INC;
403 return looper;
404 }
405
setImageFilter(SkImageFilter * imageFilter)406 SkImageFilter* SkPaint::setImageFilter(SkImageFilter* imageFilter) {
407 SkRefCnt_SafeAssign(fImageFilter, imageFilter);
408 GEN_ID_INC;
409 return imageFilter;
410 }
411
412 ///////////////////////////////////////////////////////////////////////////////
413
414 #include "SkGlyphCache.h"
415 #include "SkUtils.h"
416
DetachDescProc(const SkDescriptor * desc,void * context)417 static void DetachDescProc(const SkDescriptor* desc, void* context) {
418 *((SkGlyphCache**)context) = SkGlyphCache::DetachCache(desc);
419 }
420
421 #ifdef SK_BUILD_FOR_ANDROID
getUnicharMetrics(SkUnichar text)422 const SkGlyph& SkPaint::getUnicharMetrics(SkUnichar text) {
423 SkGlyphCache* cache;
424 descriptorProc(NULL, DetachDescProc, &cache, true);
425
426 const SkGlyph& glyph = cache->getUnicharMetrics(text);
427
428 SkGlyphCache::AttachCache(cache);
429 return glyph;
430 }
431
getGlyphMetrics(uint16_t glyphId)432 const SkGlyph& SkPaint::getGlyphMetrics(uint16_t glyphId) {
433 SkGlyphCache* cache;
434 descriptorProc(NULL, DetachDescProc, &cache, true);
435
436 const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphId);
437
438 SkGlyphCache::AttachCache(cache);
439 return glyph;
440 }
441
findImage(const SkGlyph & glyph)442 const void* SkPaint::findImage(const SkGlyph& glyph) {
443 // See ::detachCache()
444 SkGlyphCache* cache;
445 descriptorProc(NULL, DetachDescProc, &cache, true);
446
447 const void* image = cache->findImage(glyph);
448
449 SkGlyphCache::AttachCache(cache);
450 return image;
451 }
452
utfToGlyphs(const void * textData,TextEncoding encoding,size_t byteLength,uint16_t glyphs[]) const453 int SkPaint::utfToGlyphs(const void* textData, TextEncoding encoding,
454 size_t byteLength, uint16_t glyphs[]) const {
455
456 SkAutoGlyphCache autoCache(*this, NULL);
457 SkGlyphCache* cache = autoCache.getCache();
458
459 const char* text = (const char*) textData;
460 const char* stop = text + byteLength;
461 uint16_t* gptr = glyphs;
462
463 switch (encoding) {
464 case SkPaint::kUTF8_TextEncoding:
465 while (text < stop) {
466 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
467 }
468 break;
469 case SkPaint::kUTF16_TextEncoding: {
470 const uint16_t* text16 = (const uint16_t*)text;
471 const uint16_t* stop16 = (const uint16_t*)stop;
472 while (text16 < stop16) {
473 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
474 }
475 break;
476 }
477 default:
478 SkDEBUGFAIL("unknown text encoding");
479 }
480 return gptr - glyphs;
481 }
482
483 #endif
484
textToGlyphs(const void * textData,size_t byteLength,uint16_t glyphs[]) const485 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
486 uint16_t glyphs[]) const {
487 if (byteLength == 0) {
488 return 0;
489 }
490
491 SkASSERT(textData != NULL);
492
493 if (NULL == glyphs) {
494 switch (this->getTextEncoding()) {
495 case kUTF8_TextEncoding:
496 return SkUTF8_CountUnichars((const char*)textData, byteLength);
497 case kUTF16_TextEncoding:
498 return SkUTF16_CountUnichars((const uint16_t*)textData,
499 byteLength >> 1);
500 case kGlyphID_TextEncoding:
501 return byteLength >> 1;
502 default:
503 SkDEBUGFAIL("unknown text encoding");
504 }
505 return 0;
506 }
507
508 // if we get here, we have a valid glyphs[] array, so time to fill it in
509
510 // handle this encoding before the setup for the glyphcache
511 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
512 // we want to ignore the low bit of byteLength
513 memcpy(glyphs, textData, byteLength >> 1 << 1);
514 return byteLength >> 1;
515 }
516
517 SkAutoGlyphCache autoCache(*this, NULL);
518 SkGlyphCache* cache = autoCache.getCache();
519
520 const char* text = (const char*)textData;
521 const char* stop = text + byteLength;
522 uint16_t* gptr = glyphs;
523
524 switch (this->getTextEncoding()) {
525 case SkPaint::kUTF8_TextEncoding:
526 while (text < stop) {
527 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
528 }
529 break;
530 case SkPaint::kUTF16_TextEncoding: {
531 const uint16_t* text16 = (const uint16_t*)text;
532 const uint16_t* stop16 = (const uint16_t*)stop;
533 while (text16 < stop16) {
534 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
535 }
536 break;
537 }
538 default:
539 SkDEBUGFAIL("unknown text encoding");
540 }
541 return gptr - glyphs;
542 }
543
containsText(const void * textData,size_t byteLength) const544 bool SkPaint::containsText(const void* textData, size_t byteLength) const {
545 if (0 == byteLength) {
546 return true;
547 }
548
549 SkASSERT(textData != NULL);
550
551 // handle this encoding before the setup for the glyphcache
552 if (this->getTextEncoding() == kGlyphID_TextEncoding) {
553 const uint16_t* glyphID = static_cast<const uint16_t*>(textData);
554 size_t count = byteLength >> 1;
555 for (size_t i = 0; i < count; i++) {
556 if (0 == glyphID[i]) {
557 return false;
558 }
559 }
560 return true;
561 }
562
563 SkAutoGlyphCache autoCache(*this, NULL);
564 SkGlyphCache* cache = autoCache.getCache();
565
566 switch (this->getTextEncoding()) {
567 case SkPaint::kUTF8_TextEncoding: {
568 const char* text = static_cast<const char*>(textData);
569 const char* stop = text + byteLength;
570 while (text < stop) {
571 if (0 == cache->unicharToGlyph(SkUTF8_NextUnichar(&text))) {
572 return false;
573 }
574 }
575 break;
576 }
577 case SkPaint::kUTF16_TextEncoding: {
578 const uint16_t* text = static_cast<const uint16_t*>(textData);
579 const uint16_t* stop = text + (byteLength >> 1);
580 while (text < stop) {
581 if (0 == cache->unicharToGlyph(SkUTF16_NextUnichar(&text))) {
582 return false;
583 }
584 }
585 break;
586 }
587 default:
588 SkDEBUGFAIL("unknown text encoding");
589 return false;
590 }
591 return true;
592 }
593
glyphsToUnichars(const uint16_t glyphs[],int count,SkUnichar textData[]) const594 void SkPaint::glyphsToUnichars(const uint16_t glyphs[], int count,
595 SkUnichar textData[]) const {
596 if (count <= 0) {
597 return;
598 }
599
600 SkASSERT(glyphs != NULL);
601 SkASSERT(textData != NULL);
602
603 SkAutoGlyphCache autoCache(*this, NULL);
604 SkGlyphCache* cache = autoCache.getCache();
605
606 for (int index = 0; index < count; index++) {
607 textData[index] = cache->glyphToUnichar(glyphs[index]);
608 }
609 }
610
611 ///////////////////////////////////////////////////////////////////////////////
612
sk_getMetrics_utf8_next(SkGlyphCache * cache,const char ** text)613 static const SkGlyph& sk_getMetrics_utf8_next(SkGlyphCache* cache,
614 const char** text) {
615 SkASSERT(cache != NULL);
616 SkASSERT(text != NULL);
617
618 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
619 }
620
sk_getMetrics_utf8_prev(SkGlyphCache * cache,const char ** text)621 static const SkGlyph& sk_getMetrics_utf8_prev(SkGlyphCache* cache,
622 const char** text) {
623 SkASSERT(cache != NULL);
624 SkASSERT(text != NULL);
625
626 return cache->getUnicharMetrics(SkUTF8_PrevUnichar(text));
627 }
628
sk_getMetrics_utf16_next(SkGlyphCache * cache,const char ** text)629 static const SkGlyph& sk_getMetrics_utf16_next(SkGlyphCache* cache,
630 const char** text) {
631 SkASSERT(cache != NULL);
632 SkASSERT(text != NULL);
633
634 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
635 }
636
sk_getMetrics_utf16_prev(SkGlyphCache * cache,const char ** text)637 static const SkGlyph& sk_getMetrics_utf16_prev(SkGlyphCache* cache,
638 const char** text) {
639 SkASSERT(cache != NULL);
640 SkASSERT(text != NULL);
641
642 return cache->getUnicharMetrics(SkUTF16_PrevUnichar((const uint16_t**)text));
643 }
644
sk_getMetrics_glyph_next(SkGlyphCache * cache,const char ** text)645 static const SkGlyph& sk_getMetrics_glyph_next(SkGlyphCache* cache,
646 const char** text) {
647 SkASSERT(cache != NULL);
648 SkASSERT(text != NULL);
649
650 const uint16_t* ptr = *(const uint16_t**)text;
651 unsigned glyphID = *ptr;
652 ptr += 1;
653 *text = (const char*)ptr;
654 return cache->getGlyphIDMetrics(glyphID);
655 }
656
sk_getMetrics_glyph_prev(SkGlyphCache * cache,const char ** text)657 static const SkGlyph& sk_getMetrics_glyph_prev(SkGlyphCache* cache,
658 const char** text) {
659 SkASSERT(cache != NULL);
660 SkASSERT(text != NULL);
661
662 const uint16_t* ptr = *(const uint16_t**)text;
663 ptr -= 1;
664 unsigned glyphID = *ptr;
665 *text = (const char*)ptr;
666 return cache->getGlyphIDMetrics(glyphID);
667 }
668
sk_getAdvance_utf8_next(SkGlyphCache * cache,const char ** text)669 static const SkGlyph& sk_getAdvance_utf8_next(SkGlyphCache* cache,
670 const char** text) {
671 SkASSERT(cache != NULL);
672 SkASSERT(text != NULL);
673
674 return cache->getUnicharAdvance(SkUTF8_NextUnichar(text));
675 }
676
sk_getAdvance_utf8_prev(SkGlyphCache * cache,const char ** text)677 static const SkGlyph& sk_getAdvance_utf8_prev(SkGlyphCache* cache,
678 const char** text) {
679 SkASSERT(cache != NULL);
680 SkASSERT(text != NULL);
681
682 return cache->getUnicharAdvance(SkUTF8_PrevUnichar(text));
683 }
684
sk_getAdvance_utf16_next(SkGlyphCache * cache,const char ** text)685 static const SkGlyph& sk_getAdvance_utf16_next(SkGlyphCache* cache,
686 const char** text) {
687 SkASSERT(cache != NULL);
688 SkASSERT(text != NULL);
689
690 return cache->getUnicharAdvance(SkUTF16_NextUnichar((const uint16_t**)text));
691 }
692
sk_getAdvance_utf16_prev(SkGlyphCache * cache,const char ** text)693 static const SkGlyph& sk_getAdvance_utf16_prev(SkGlyphCache* cache,
694 const char** text) {
695 SkASSERT(cache != NULL);
696 SkASSERT(text != NULL);
697
698 return cache->getUnicharAdvance(SkUTF16_PrevUnichar((const uint16_t**)text));
699 }
700
sk_getAdvance_glyph_next(SkGlyphCache * cache,const char ** text)701 static const SkGlyph& sk_getAdvance_glyph_next(SkGlyphCache* cache,
702 const char** text) {
703 SkASSERT(cache != NULL);
704 SkASSERT(text != NULL);
705
706 const uint16_t* ptr = *(const uint16_t**)text;
707 unsigned glyphID = *ptr;
708 ptr += 1;
709 *text = (const char*)ptr;
710 return cache->getGlyphIDAdvance(glyphID);
711 }
712
sk_getAdvance_glyph_prev(SkGlyphCache * cache,const char ** text)713 static const SkGlyph& sk_getAdvance_glyph_prev(SkGlyphCache* cache,
714 const char** text) {
715 SkASSERT(cache != NULL);
716 SkASSERT(text != NULL);
717
718 const uint16_t* ptr = *(const uint16_t**)text;
719 ptr -= 1;
720 unsigned glyphID = *ptr;
721 *text = (const char*)ptr;
722 return cache->getGlyphIDAdvance(glyphID);
723 }
724
getMeasureCacheProc(TextBufferDirection tbd,bool needFullMetrics) const725 SkMeasureCacheProc SkPaint::getMeasureCacheProc(TextBufferDirection tbd,
726 bool needFullMetrics) const {
727 static const SkMeasureCacheProc gMeasureCacheProcs[] = {
728 sk_getMetrics_utf8_next,
729 sk_getMetrics_utf16_next,
730 sk_getMetrics_glyph_next,
731
732 sk_getMetrics_utf8_prev,
733 sk_getMetrics_utf16_prev,
734 sk_getMetrics_glyph_prev,
735
736 sk_getAdvance_utf8_next,
737 sk_getAdvance_utf16_next,
738 sk_getAdvance_glyph_next,
739
740 sk_getAdvance_utf8_prev,
741 sk_getAdvance_utf16_prev,
742 sk_getAdvance_glyph_prev
743 };
744
745 unsigned index = this->getTextEncoding();
746
747 if (kBackward_TextBufferDirection == tbd) {
748 index += 3;
749 }
750 if (!needFullMetrics && !this->isDevKernText()) {
751 index += 6;
752 }
753
754 SkASSERT(index < SK_ARRAY_COUNT(gMeasureCacheProcs));
755 return gMeasureCacheProcs[index];
756 }
757
758 ///////////////////////////////////////////////////////////////////////////////
759
sk_getMetrics_utf8_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)760 static const SkGlyph& sk_getMetrics_utf8_00(SkGlyphCache* cache,
761 const char** text, SkFixed, SkFixed) {
762 SkASSERT(cache != NULL);
763 SkASSERT(text != NULL);
764
765 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text));
766 }
767
sk_getMetrics_utf8_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)768 static const SkGlyph& sk_getMetrics_utf8_xy(SkGlyphCache* cache,
769 const char** text, SkFixed x, SkFixed y) {
770 SkASSERT(cache != NULL);
771 SkASSERT(text != NULL);
772
773 return cache->getUnicharMetrics(SkUTF8_NextUnichar(text), x, y);
774 }
775
sk_getMetrics_utf16_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)776 static const SkGlyph& sk_getMetrics_utf16_00(SkGlyphCache* cache,
777 const char** text, SkFixed, SkFixed) {
778 SkASSERT(cache != NULL);
779 SkASSERT(text != NULL);
780
781 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text));
782 }
783
sk_getMetrics_utf16_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)784 static const SkGlyph& sk_getMetrics_utf16_xy(SkGlyphCache* cache,
785 const char** text, SkFixed x, SkFixed y) {
786 SkASSERT(cache != NULL);
787 SkASSERT(text != NULL);
788
789 return cache->getUnicharMetrics(SkUTF16_NextUnichar((const uint16_t**)text),
790 x, y);
791 }
792
sk_getMetrics_glyph_00(SkGlyphCache * cache,const char ** text,SkFixed,SkFixed)793 static const SkGlyph& sk_getMetrics_glyph_00(SkGlyphCache* cache,
794 const char** text, SkFixed, SkFixed) {
795 SkASSERT(cache != NULL);
796 SkASSERT(text != NULL);
797
798 const uint16_t* ptr = *(const uint16_t**)text;
799 unsigned glyphID = *ptr;
800 ptr += 1;
801 *text = (const char*)ptr;
802 return cache->getGlyphIDMetrics(glyphID);
803 }
804
sk_getMetrics_glyph_xy(SkGlyphCache * cache,const char ** text,SkFixed x,SkFixed y)805 static const SkGlyph& sk_getMetrics_glyph_xy(SkGlyphCache* cache,
806 const char** text, SkFixed x, SkFixed y) {
807 SkASSERT(cache != NULL);
808 SkASSERT(text != NULL);
809
810 const uint16_t* ptr = *(const uint16_t**)text;
811 unsigned glyphID = *ptr;
812 ptr += 1;
813 *text = (const char*)ptr;
814 return cache->getGlyphIDMetrics(glyphID, x, y);
815 }
816
getDrawCacheProc() const817 SkDrawCacheProc SkPaint::getDrawCacheProc() const {
818 static const SkDrawCacheProc gDrawCacheProcs[] = {
819 sk_getMetrics_utf8_00,
820 sk_getMetrics_utf16_00,
821 sk_getMetrics_glyph_00,
822
823 sk_getMetrics_utf8_xy,
824 sk_getMetrics_utf16_xy,
825 sk_getMetrics_glyph_xy
826 };
827
828 unsigned index = this->getTextEncoding();
829 if (fFlags & kSubpixelText_Flag) {
830 index += 3;
831 }
832
833 SkASSERT(index < SK_ARRAY_COUNT(gDrawCacheProcs));
834 return gDrawCacheProcs[index];
835 }
836
837 ///////////////////////////////////////////////////////////////////////////////
838
839 class SkAutoRestorePaintTextSizeAndFrame {
840 public:
SkAutoRestorePaintTextSizeAndFrame(const SkPaint * paint)841 SkAutoRestorePaintTextSizeAndFrame(const SkPaint* paint)
842 : fPaint((SkPaint*)paint) {
843 fTextSize = paint->getTextSize();
844 fStyle = paint->getStyle();
845 fPaint->setStyle(SkPaint::kFill_Style);
846 }
847
~SkAutoRestorePaintTextSizeAndFrame()848 ~SkAutoRestorePaintTextSizeAndFrame() {
849 fPaint->setStyle(fStyle);
850 fPaint->setTextSize(fTextSize);
851 }
852
853 private:
854 SkPaint* fPaint;
855 SkScalar fTextSize;
856 SkPaint::Style fStyle;
857 };
858
set_bounds(const SkGlyph & g,SkRect * bounds)859 static void set_bounds(const SkGlyph& g, SkRect* bounds) {
860 bounds->set(SkIntToScalar(g.fLeft),
861 SkIntToScalar(g.fTop),
862 SkIntToScalar(g.fLeft + g.fWidth),
863 SkIntToScalar(g.fTop + g.fHeight));
864 }
865
866 // 64bits wide, with a 16bit bias. Useful when accumulating lots of 16.16 so
867 // we don't overflow along the way
868 typedef int64_t Sk48Dot16;
869
870 #ifdef SK_SCALAR_IS_FLOAT
Sk48Dot16ToScalar(Sk48Dot16 x)871 static inline float Sk48Dot16ToScalar(Sk48Dot16 x) {
872 return (float) (x * 1.5258789e-5); // x * (1 / 65536.0f)
873 }
874 #else
Sk48Dot16ToScalar(Sk48Dot16 x)875 static inline SkFixed Sk48Dot16ToScalar(Sk48Dot16 x) {
876 // just return the low 32bits
877 return static_cast<SkFixed>(x);
878 }
879 #endif
880
join_bounds_x(const SkGlyph & g,SkRect * bounds,Sk48Dot16 dx)881 static void join_bounds_x(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dx) {
882 SkScalar sx = Sk48Dot16ToScalar(dx);
883 bounds->join(SkIntToScalar(g.fLeft) + sx,
884 SkIntToScalar(g.fTop),
885 SkIntToScalar(g.fLeft + g.fWidth) + sx,
886 SkIntToScalar(g.fTop + g.fHeight));
887 }
888
join_bounds_y(const SkGlyph & g,SkRect * bounds,Sk48Dot16 dy)889 static void join_bounds_y(const SkGlyph& g, SkRect* bounds, Sk48Dot16 dy) {
890 SkScalar sy = Sk48Dot16ToScalar(dy);
891 bounds->join(SkIntToScalar(g.fLeft),
892 SkIntToScalar(g.fTop) + sy,
893 SkIntToScalar(g.fLeft + g.fWidth),
894 SkIntToScalar(g.fTop + g.fHeight) + sy);
895 }
896
897 typedef void (*JoinBoundsProc)(const SkGlyph&, SkRect*, Sk48Dot16);
898
899 // xyIndex is 0 for fAdvanceX or 1 for fAdvanceY
advance(const SkGlyph & glyph,int xyIndex)900 static SkFixed advance(const SkGlyph& glyph, int xyIndex) {
901 SkASSERT(0 == xyIndex || 1 == xyIndex);
902 return (&glyph.fAdvanceX)[xyIndex];
903 }
904
measure_text(SkGlyphCache * cache,const char * text,size_t byteLength,int * count,SkRect * bounds) const905 SkScalar SkPaint::measure_text(SkGlyphCache* cache,
906 const char* text, size_t byteLength,
907 int* count, SkRect* bounds) const {
908 SkASSERT(count);
909 if (byteLength == 0) {
910 *count = 0;
911 if (bounds) {
912 bounds->setEmpty();
913 }
914 return 0;
915 }
916
917 SkMeasureCacheProc glyphCacheProc;
918 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
919 NULL != bounds);
920
921 int xyIndex;
922 JoinBoundsProc joinBoundsProc;
923 if (this->isVerticalText()) {
924 xyIndex = 1;
925 joinBoundsProc = join_bounds_y;
926 } else {
927 xyIndex = 0;
928 joinBoundsProc = join_bounds_x;
929 }
930
931 int n = 1;
932 const char* stop = (const char*)text + byteLength;
933 const SkGlyph* g = &glyphCacheProc(cache, &text);
934 // our accumulated fixed-point advances might overflow 16.16, so we use
935 // a 48.16 (64bit) accumulator, and then convert that to scalar at the
936 // very end.
937 Sk48Dot16 x = advance(*g, xyIndex);
938
939 SkAutoKern autokern;
940
941 if (NULL == bounds) {
942 if (this->isDevKernText()) {
943 int rsb;
944 for (; text < stop; n++) {
945 rsb = g->fRsbDelta;
946 g = &glyphCacheProc(cache, &text);
947 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta) + advance(*g, xyIndex);
948 }
949 } else {
950 for (; text < stop; n++) {
951 x += advance(glyphCacheProc(cache, &text), xyIndex);
952 }
953 }
954 } else {
955 set_bounds(*g, bounds);
956 if (this->isDevKernText()) {
957 int rsb;
958 for (; text < stop; n++) {
959 rsb = g->fRsbDelta;
960 g = &glyphCacheProc(cache, &text);
961 x += SkAutoKern_AdjustF(rsb, g->fLsbDelta);
962 joinBoundsProc(*g, bounds, x);
963 x += advance(*g, xyIndex);
964 }
965 } else {
966 for (; text < stop; n++) {
967 g = &glyphCacheProc(cache, &text);
968 joinBoundsProc(*g, bounds, x);
969 x += advance(*g, xyIndex);
970 }
971 }
972 }
973 SkASSERT(text == stop);
974
975 *count = n;
976 return Sk48Dot16ToScalar(x);
977 }
978
measureText(const void * textData,size_t length,SkRect * bounds,SkScalar zoom) const979 SkScalar SkPaint::measureText(const void* textData, size_t length,
980 SkRect* bounds, SkScalar zoom) const {
981 const char* text = (const char*)textData;
982 SkASSERT(text != NULL || length == 0);
983
984 SkScalar scale = 0;
985 SkAutoRestorePaintTextSizeAndFrame restore(this);
986
987 if (this->isLinearText()) {
988 scale = fTextSize / kCanonicalTextSizeForPaths;
989 // this gets restored by restore
990 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
991 }
992
993 SkMatrix zoomMatrix, *zoomPtr = NULL;
994 if (zoom) {
995 zoomMatrix.setScale(zoom, zoom);
996 zoomPtr = &zoomMatrix;
997 }
998
999 SkAutoGlyphCache autoCache(*this, zoomPtr);
1000 SkGlyphCache* cache = autoCache.getCache();
1001
1002 SkScalar width = 0;
1003
1004 if (length > 0) {
1005 int tempCount;
1006
1007 width = this->measure_text(cache, text, length, &tempCount, bounds);
1008 if (scale) {
1009 width = SkScalarMul(width, scale);
1010 if (bounds) {
1011 bounds->fLeft = SkScalarMul(bounds->fLeft, scale);
1012 bounds->fTop = SkScalarMul(bounds->fTop, scale);
1013 bounds->fRight = SkScalarMul(bounds->fRight, scale);
1014 bounds->fBottom = SkScalarMul(bounds->fBottom, scale);
1015 }
1016 }
1017 }
1018 return width;
1019 }
1020
1021 typedef bool (*SkTextBufferPred)(const char* text, const char* stop);
1022
forward_textBufferPred(const char * text,const char * stop)1023 static bool forward_textBufferPred(const char* text, const char* stop) {
1024 return text < stop;
1025 }
1026
backward_textBufferPred(const char * text,const char * stop)1027 static bool backward_textBufferPred(const char* text, const char* stop) {
1028 return text > stop;
1029 }
1030
chooseTextBufferPred(SkPaint::TextBufferDirection tbd,const char ** text,size_t length,const char ** stop)1031 static SkTextBufferPred chooseTextBufferPred(SkPaint::TextBufferDirection tbd,
1032 const char** text, size_t length,
1033 const char** stop) {
1034 if (SkPaint::kForward_TextBufferDirection == tbd) {
1035 *stop = *text + length;
1036 return forward_textBufferPred;
1037 } else {
1038 // text should point to the end of the buffer, and stop to the beginning
1039 *stop = *text;
1040 *text += length;
1041 return backward_textBufferPred;
1042 }
1043 }
1044
breakText(const void * textD,size_t length,SkScalar maxWidth,SkScalar * measuredWidth,TextBufferDirection tbd) const1045 size_t SkPaint::breakText(const void* textD, size_t length, SkScalar maxWidth,
1046 SkScalar* measuredWidth,
1047 TextBufferDirection tbd) const {
1048 if (0 == length || 0 >= maxWidth) {
1049 if (measuredWidth) {
1050 *measuredWidth = 0;
1051 }
1052 return 0;
1053 }
1054
1055 if (0 == fTextSize) {
1056 if (measuredWidth) {
1057 *measuredWidth = 0;
1058 }
1059 return length;
1060 }
1061
1062 SkASSERT(textD != NULL);
1063 const char* text = (const char*)textD;
1064
1065 SkScalar scale = 0;
1066 SkAutoRestorePaintTextSizeAndFrame restore(this);
1067
1068 if (this->isLinearText()) {
1069 scale = fTextSize / kCanonicalTextSizeForPaths;
1070 maxWidth = SkScalarMulDiv(maxWidth, kCanonicalTextSizeForPaths, fTextSize);
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
1078 SkMeasureCacheProc glyphCacheProc = this->getMeasureCacheProc(tbd, false);
1079 const char* stop;
1080 SkTextBufferPred pred = chooseTextBufferPred(tbd, &text, length, &stop);
1081 const int xyIndex = this->isVerticalText() ? 1 : 0;
1082 // use 64bits for our accumulator, to avoid overflowing 16.16
1083 Sk48Dot16 max = SkScalarToFixed(maxWidth);
1084 Sk48Dot16 width = 0;
1085
1086 SkAutoKern autokern;
1087
1088 if (this->isDevKernText()) {
1089 int rsb = 0;
1090 while (pred(text, stop)) {
1091 const char* curr = text;
1092 const SkGlyph& g = glyphCacheProc(cache, &text);
1093 SkFixed x = SkAutoKern_AdjustF(rsb, g.fLsbDelta) + advance(g, xyIndex);
1094 if ((width += x) > max) {
1095 width -= x;
1096 text = curr;
1097 break;
1098 }
1099 rsb = g.fRsbDelta;
1100 }
1101 } else {
1102 while (pred(text, stop)) {
1103 const char* curr = text;
1104 SkFixed x = advance(glyphCacheProc(cache, &text), xyIndex);
1105 if ((width += x) > max) {
1106 width -= x;
1107 text = curr;
1108 break;
1109 }
1110 }
1111 }
1112
1113 if (measuredWidth) {
1114 SkScalar scalarWidth = Sk48Dot16ToScalar(width);
1115 if (scale) {
1116 scalarWidth = SkScalarMul(scalarWidth, scale);
1117 }
1118 *measuredWidth = scalarWidth;
1119 }
1120
1121 // return the number of bytes measured
1122 return (kForward_TextBufferDirection == tbd) ?
1123 text - stop + length : stop - text + length;
1124 }
1125
1126 ///////////////////////////////////////////////////////////////////////////////
1127
FontMetricsCacheProc(const SkGlyphCache * cache,void * context)1128 static bool FontMetricsCacheProc(const SkGlyphCache* cache, void* context) {
1129 *(SkPaint::FontMetrics*)context = cache->getFontMetricsY();
1130 return false; // don't detach the cache
1131 }
1132
FontMetricsDescProc(const SkDescriptor * desc,void * context)1133 static void FontMetricsDescProc(const SkDescriptor* desc, void* context) {
1134 SkGlyphCache::VisitCache(desc, FontMetricsCacheProc, context);
1135 }
1136
getFontMetrics(FontMetrics * metrics,SkScalar zoom) const1137 SkScalar SkPaint::getFontMetrics(FontMetrics* metrics, SkScalar zoom) const {
1138 SkScalar scale = 0;
1139 SkAutoRestorePaintTextSizeAndFrame restore(this);
1140
1141 if (this->isLinearText()) {
1142 scale = fTextSize / kCanonicalTextSizeForPaths;
1143 // this gets restored by restore
1144 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
1145 }
1146
1147 SkMatrix zoomMatrix, *zoomPtr = NULL;
1148 if (zoom) {
1149 zoomMatrix.setScale(zoom, zoom);
1150 zoomPtr = &zoomMatrix;
1151 }
1152
1153 #if 0
1154 SkAutoGlyphCache autoCache(*this, zoomPtr);
1155 SkGlyphCache* cache = autoCache.getCache();
1156 const FontMetrics& my = cache->getFontMetricsY();
1157 #endif
1158 FontMetrics storage;
1159 if (NULL == metrics) {
1160 metrics = &storage;
1161 }
1162
1163 this->descriptorProc(zoomPtr, FontMetricsDescProc, metrics, true);
1164
1165 if (scale) {
1166 metrics->fTop = SkScalarMul(metrics->fTop, scale);
1167 metrics->fAscent = SkScalarMul(metrics->fAscent, scale);
1168 metrics->fDescent = SkScalarMul(metrics->fDescent, scale);
1169 metrics->fBottom = SkScalarMul(metrics->fBottom, scale);
1170 metrics->fLeading = SkScalarMul(metrics->fLeading, scale);
1171 }
1172 return metrics->fDescent - metrics->fAscent + metrics->fLeading;
1173 }
1174
1175 ///////////////////////////////////////////////////////////////////////////////
1176
set_bounds(const SkGlyph & g,SkRect * bounds,SkScalar scale)1177 static void set_bounds(const SkGlyph& g, SkRect* bounds, SkScalar scale) {
1178 bounds->set(g.fLeft * scale,
1179 g.fTop * scale,
1180 (g.fLeft + g.fWidth) * scale,
1181 (g.fTop + g.fHeight) * scale);
1182 }
1183
getTextWidths(const void * textData,size_t byteLength,SkScalar widths[],SkRect bounds[]) const1184 int SkPaint::getTextWidths(const void* textData, size_t byteLength,
1185 SkScalar widths[], SkRect bounds[]) const {
1186 if (0 == byteLength) {
1187 return 0;
1188 }
1189
1190 SkASSERT(NULL != textData);
1191
1192 if (NULL == widths && NULL == bounds) {
1193 return this->countText(textData, byteLength);
1194 }
1195
1196 SkAutoRestorePaintTextSizeAndFrame restore(this);
1197 SkScalar scale = 0;
1198
1199 if (this->isLinearText()) {
1200 scale = fTextSize / kCanonicalTextSizeForPaths;
1201 // this gets restored by restore
1202 ((SkPaint*)this)->setTextSize(SkIntToScalar(kCanonicalTextSizeForPaths));
1203 }
1204
1205 SkAutoGlyphCache autoCache(*this, NULL);
1206 SkGlyphCache* cache = autoCache.getCache();
1207 SkMeasureCacheProc glyphCacheProc;
1208 glyphCacheProc = this->getMeasureCacheProc(kForward_TextBufferDirection,
1209 NULL != bounds);
1210
1211 const char* text = (const char*)textData;
1212 const char* stop = text + byteLength;
1213 int count = 0;
1214 const int xyIndex = this->isVerticalText() ? 1 : 0;
1215
1216 if (this->isDevKernText()) {
1217 // we adjust the widths returned here through auto-kerning
1218 SkAutoKern autokern;
1219 SkFixed prevWidth = 0;
1220
1221 if (scale) {
1222 while (text < stop) {
1223 const SkGlyph& g = glyphCacheProc(cache, &text);
1224 if (widths) {
1225 SkFixed adjust = autokern.adjust(g);
1226
1227 if (count > 0) {
1228 SkScalar w = SkFixedToScalar(prevWidth + adjust);
1229 *widths++ = SkScalarMul(w, scale);
1230 }
1231 prevWidth = advance(g, xyIndex);
1232 }
1233 if (bounds) {
1234 set_bounds(g, bounds++, scale);
1235 }
1236 ++count;
1237 }
1238 if (count > 0 && widths) {
1239 *widths = SkScalarMul(SkFixedToScalar(prevWidth), scale);
1240 }
1241 } else {
1242 while (text < stop) {
1243 const SkGlyph& g = glyphCacheProc(cache, &text);
1244 if (widths) {
1245 SkFixed adjust = autokern.adjust(g);
1246
1247 if (count > 0) {
1248 *widths++ = SkFixedToScalar(prevWidth + adjust);
1249 }
1250 prevWidth = advance(g, xyIndex);
1251 }
1252 if (bounds) {
1253 set_bounds(g, bounds++);
1254 }
1255 ++count;
1256 }
1257 if (count > 0 && widths) {
1258 *widths = SkFixedToScalar(prevWidth);
1259 }
1260 }
1261 } else { // no devkern
1262 if (scale) {
1263 while (text < stop) {
1264 const SkGlyph& g = glyphCacheProc(cache, &text);
1265 if (widths) {
1266 *widths++ = SkScalarMul(SkFixedToScalar(advance(g, xyIndex)),
1267 scale);
1268 }
1269 if (bounds) {
1270 set_bounds(g, bounds++, scale);
1271 }
1272 ++count;
1273 }
1274 } else {
1275 while (text < stop) {
1276 const SkGlyph& g = glyphCacheProc(cache, &text);
1277 if (widths) {
1278 *widths++ = SkFixedToScalar(advance(g, xyIndex));
1279 }
1280 if (bounds) {
1281 set_bounds(g, bounds++);
1282 }
1283 ++count;
1284 }
1285 }
1286 }
1287
1288 SkASSERT(text == stop);
1289 return count;
1290 }
1291
1292 ///////////////////////////////////////////////////////////////////////////////
1293
1294 #include "SkDraw.h"
1295
getTextPath(const void * textData,size_t length,SkScalar x,SkScalar y,SkPath * path) const1296 void SkPaint::getTextPath(const void* textData, size_t length,
1297 SkScalar x, SkScalar y, SkPath* path) const {
1298 SkASSERT(length == 0 || textData != NULL);
1299
1300 const char* text = (const char*)textData;
1301 if (text == NULL || length == 0 || path == NULL) {
1302 return;
1303 }
1304
1305 SkTextToPathIter iter(text, length, *this, false, true);
1306 SkMatrix matrix;
1307 SkScalar prevXPos = 0;
1308
1309 matrix.setScale(iter.getPathScale(), iter.getPathScale());
1310 matrix.postTranslate(x, y);
1311 path->reset();
1312
1313 SkScalar xpos;
1314 const SkPath* iterPath;
1315 while ((iterPath = iter.next(&xpos)) != NULL) {
1316 matrix.postTranslate(xpos - prevXPos, 0);
1317 path->addPath(*iterPath, matrix);
1318 prevXPos = xpos;
1319 }
1320 }
1321
add_flattenable(SkDescriptor * desc,uint32_t tag,SkFlattenableWriteBuffer * buffer)1322 static void add_flattenable(SkDescriptor* desc, uint32_t tag,
1323 SkFlattenableWriteBuffer* buffer) {
1324 buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
1325 }
1326
1327 // SkFontHost can override this choice in FilterRec()
computeMaskFormat(const SkPaint & paint)1328 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
1329 uint32_t flags = paint.getFlags();
1330
1331 // Antialiasing being disabled trumps all other settings.
1332 if (!(flags & SkPaint::kAntiAlias_Flag)) {
1333 return SkMask::kBW_Format;
1334 }
1335
1336 if (flags & SkPaint::kLCDRenderText_Flag) {
1337 return SkMask::kLCD16_Format;
1338 }
1339
1340 return SkMask::kA8_Format;
1341 }
1342
1343 // if linear-text is on, then we force hinting to be off (since that's sort of
1344 // the point of linear-text.
computeHinting(const SkPaint & paint)1345 static SkPaint::Hinting computeHinting(const SkPaint& paint) {
1346 SkPaint::Hinting h = paint.getHinting();
1347 if (paint.isLinearText()) {
1348 h = SkPaint::kNo_Hinting;
1349 }
1350 return h;
1351 }
1352
1353 // return true if the paint is just a single color (i.e. not a shader). If its
1354 // a shader, then we can't compute a const luminance for it :(
justAColor(const SkPaint & paint,SkColor * color)1355 static bool justAColor(const SkPaint& paint, SkColor* color) {
1356 if (paint.getShader()) {
1357 return false;
1358 }
1359 SkColor c = paint.getColor();
1360 if (paint.getColorFilter()) {
1361 c = paint.getColorFilter()->filterColor(c);
1362 }
1363 if (color) {
1364 *color = c;
1365 }
1366 return true;
1367 }
1368
1369 #ifdef SK_USE_COLOR_LUMINANCE
computeLuminanceColor(const SkPaint & paint)1370 static SkColor computeLuminanceColor(const SkPaint& paint) {
1371 SkColor c;
1372 if (!justAColor(paint, &c)) {
1373 c = SkColorSetRGB(0x7F, 0x80, 0x7F);
1374 }
1375 return c;
1376 }
1377
1378 #define assert_byte(x) SkASSERT(0 == ((x) >> 8))
1379
reduce_lumbits(U8CPU x)1380 static U8CPU reduce_lumbits(U8CPU x) {
1381 static const uint8_t gReduceBits[] = {
1382 0x0, 0x55, 0xAA, 0xFF
1383 };
1384 assert_byte(x);
1385 return gReduceBits[x >> 6];
1386 }
1387
computeLuminance(SkColor c)1388 static unsigned computeLuminance(SkColor c) {
1389 int r = SkColorGetR(c);
1390 int g = SkColorGetG(c);
1391 int b = SkColorGetB(c);
1392 // compute luminance
1393 // R=0.2126 G=0.7152 B=0.0722
1394 // scaling by 127 yields 27, 92, 9
1395 int luminance = r * 27 + g * 92 + b * 9;
1396 luminance >>= 7;
1397 assert_byte(luminance);
1398 return luminance;
1399 }
1400
1401 #else
1402 // returns 0..kLuminance_Max
computeLuminance(const SkPaint & paint)1403 static unsigned computeLuminance(const SkPaint& paint) {
1404 SkColor c;
1405 if (justAColor(paint, &c)) {
1406 int r = SkColorGetR(c);
1407 int g = SkColorGetG(c);
1408 int b = SkColorGetB(c);
1409 // compute luminance
1410 // R=0.2126 G=0.7152 B=0.0722
1411 // scaling by 127 yields 27, 92, 9
1412 #if 1
1413 int luminance = r * 27 + g * 92 + b * 9;
1414 luminance >>= 15 - SkScalerContext::kLuminance_Bits;
1415 #else
1416 int luminance = r * 2 + g * 5 + b * 1;
1417 luminance >>= 11 - SkScalerContext::kLuminance_Bits;
1418 #endif
1419 SkASSERT(luminance <= SkScalerContext::kLuminance_Max);
1420 return luminance;
1421 }
1422 // if we're not a single color, return the middle of the luminance range
1423 return SkScalerContext::kLuminance_Max >> 1;
1424 }
1425 #endif
1426
1427 // Beyond this size, LCD doesn't appreciably improve quality, but it always
1428 // cost more RAM and draws slower, so we set a cap.
1429 #ifndef SK_MAX_SIZE_FOR_LCDTEXT
1430 #define SK_MAX_SIZE_FOR_LCDTEXT 48
1431 #endif
1432
tooBigForLCD(const SkScalerContext::Rec & rec)1433 static bool tooBigForLCD(const SkScalerContext::Rec& rec) {
1434 SkScalar area = SkScalarMul(rec.fPost2x2[0][0], rec.fPost2x2[1][1]) -
1435 SkScalarMul(rec.fPost2x2[1][0], rec.fPost2x2[0][1]);
1436 SkScalar size = SkScalarMul(area, rec.fTextSize);
1437 return SkScalarAbs(size) > SkIntToScalar(SK_MAX_SIZE_FOR_LCDTEXT);
1438 }
1439
1440 /*
1441 * Return the scalar with only limited fractional precision. Used to consolidate matrices
1442 * that vary only slightly when we create our key into the font cache, since the font scaler
1443 * typically returns the same looking resuts for tiny changes in the matrix.
1444 */
sk_relax(SkScalar x)1445 static SkScalar sk_relax(SkScalar x) {
1446 #ifdef SK_SCALAR_IS_FLOAT
1447 int n = sk_float_round2int(x * 1024);
1448 return n / 1024.0f;
1449 #else
1450 // round to the nearest 10 fractional bits
1451 return (x + (1 << 5)) & ~(1024 - 1);
1452 #endif
1453 }
1454
MakeRec(const SkPaint & paint,const SkMatrix * deviceMatrix,Rec * rec)1455 void SkScalerContext::MakeRec(const SkPaint& paint,
1456 const SkMatrix* deviceMatrix, Rec* rec) {
1457 SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective());
1458
1459 SkTypeface* typeface = paint.getTypeface();
1460 rec->fOrigFontID = SkTypeface::UniqueID(typeface);
1461 rec->fFontID = rec->fOrigFontID;
1462 rec->fTextSize = paint.getTextSize();
1463 rec->fPreScaleX = paint.getTextScaleX();
1464 rec->fPreSkewX = paint.getTextSkewX();
1465
1466 if (deviceMatrix) {
1467 rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
1468 rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
1469 rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
1470 rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
1471 } else {
1472 rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
1473 rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
1474 }
1475
1476 SkPaint::Style style = paint.getStyle();
1477 SkScalar strokeWidth = paint.getStrokeWidth();
1478
1479 unsigned flags = 0;
1480
1481 #ifdef SK_USE_FREETYPE_EMBOLDEN
1482 // It is possible that the SkTypeface used to draw glyphs has
1483 // different properties than the SkTypeface set in the SkPaint.
1484 // If we are asked to render bold text with a bold font, and are
1485 // forced to fall back to a font with normal weight for some
1486 // glyphs, we need to use fake bold to render those glyphs. In
1487 // order to do that, we set SkScalerContext's "embolden" flag
1488 // here if we are trying to draw bold text via any means, and
1489 // ignore it at the glyph outline generation stage if the font
1490 // actually being used is already bold.
1491 if (paint.isFakeBoldText() || (typeface && typeface->isBold())) {
1492 flags |= SkScalerContext::kEmbolden_Flag;
1493 }
1494 #else
1495 if (paint.isFakeBoldText()) {
1496 SkScalar fakeBoldScale = SkScalarInterpFunc(paint.getTextSize(),
1497 kStdFakeBoldInterpKeys,
1498 kStdFakeBoldInterpValues,
1499 kStdFakeBoldInterpLength);
1500 SkScalar extra = SkScalarMul(paint.getTextSize(), fakeBoldScale);
1501
1502 if (style == SkPaint::kFill_Style) {
1503 style = SkPaint::kStrokeAndFill_Style;
1504 strokeWidth = extra; // ignore paint's strokeWidth if it was "fill"
1505 } else {
1506 strokeWidth += extra;
1507 }
1508 }
1509 #endif
1510
1511 if (paint.isDevKernText()) {
1512 flags |= SkScalerContext::kDevKernText_Flag;
1513 }
1514
1515 if (style != SkPaint::kFill_Style && strokeWidth > 0) {
1516 rec->fFrameWidth = strokeWidth;
1517 rec->fMiterLimit = paint.getStrokeMiter();
1518 rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
1519
1520 if (style == SkPaint::kStrokeAndFill_Style) {
1521 flags |= SkScalerContext::kFrameAndFill_Flag;
1522 }
1523 } else {
1524 rec->fFrameWidth = 0;
1525 rec->fMiterLimit = 0;
1526 rec->fStrokeJoin = 0;
1527 }
1528
1529 rec->fMaskFormat = SkToU8(computeMaskFormat(paint));
1530
1531 if (SkMask::kLCD16_Format == rec->fMaskFormat ||
1532 SkMask::kLCD32_Format == rec->fMaskFormat)
1533 {
1534 SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
1535 SkFontHost::LCDOrientation orient = SkFontHost::GetSubpixelOrientation();
1536 if (SkFontHost::kNONE_LCDOrder == order || tooBigForLCD(*rec)) {
1537 // eeek, can't support LCD
1538 rec->fMaskFormat = SkMask::kA8_Format;
1539 } else {
1540 if (SkFontHost::kVertical_LCDOrientation == orient) {
1541 flags |= SkScalerContext::kLCD_Vertical_Flag;
1542 }
1543 if (SkFontHost::kBGR_LCDOrder == order) {
1544 flags |= SkScalerContext::kLCD_BGROrder_Flag;
1545 }
1546 }
1547 }
1548
1549 if (paint.isEmbeddedBitmapText()) {
1550 flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
1551 }
1552 if (paint.isSubpixelText()) {
1553 flags |= SkScalerContext::kSubpixelPositioning_Flag;
1554 }
1555 if (paint.isAutohinted()) {
1556 flags |= SkScalerContext::kAutohinting_Flag;
1557 }
1558 if (paint.isVerticalText()) {
1559 flags |= SkScalerContext::kVertical_Flag;
1560 }
1561 if (paint.getFlags() & SkPaint::kGenA8FromLCD_Flag) {
1562 flags |= SkScalerContext::kGenA8FromLCD_Flag;
1563 }
1564 rec->fFlags = SkToU16(flags);
1565
1566 // these modify fFlags, so do them after assigning fFlags
1567 rec->setHinting(computeHinting(paint));
1568 #ifdef SK_USE_COLOR_LUMINANCE
1569 rec->setLuminanceColor(computeLuminanceColor(paint));
1570 #else
1571 rec->setLuminanceBits(computeLuminance(paint));
1572 #endif
1573 #ifdef SK_BUILD_FOR_ANDROID
1574 rec->fLanguage = paint.getLanguage();
1575 rec->fFontVariant = paint.getFontVariant();
1576 #endif //SK_BUILD_FOR_ANDROID
1577
1578 /* Allow the fonthost to modify our rec before we use it as a key into the
1579 cache. This way if we're asking for something that they will ignore,
1580 they can modify our rec up front, so we don't create duplicate cache
1581 entries.
1582 */
1583 SkFontHost::FilterRec(rec);
1584
1585 // be sure to call PostMakeRec(rec) before you actually use it!
1586 }
1587
1588 /**
1589 * We ensure that the rec is self-consistent and efficient (where possible)
1590 */
PostMakeRec(SkScalerContext::Rec * rec)1591 void SkScalerContext::PostMakeRec(SkScalerContext::Rec* rec) {
1592
1593 /**
1594 * If we're asking for A8, we force the colorlum to be gray, since that
1595 * that limits the number of unique entries, and the scaler will only
1596 * look at the lum of one of them.
1597 */
1598 switch (rec->fMaskFormat) {
1599 case SkMask::kLCD16_Format:
1600 case SkMask::kLCD32_Format: {
1601 #ifdef SK_USE_COLOR_LUMINANCE
1602 // filter down the luminance color to a finite number of bits
1603 SkColor c = rec->getLuminanceColor();
1604 c = SkColorSetRGB(reduce_lumbits(SkColorGetR(c)),
1605 reduce_lumbits(SkColorGetG(c)),
1606 reduce_lumbits(SkColorGetB(c)));
1607 rec->setLuminanceColor(c);
1608 #endif
1609 break;
1610 }
1611 case SkMask::kA8_Format: {
1612 #ifdef SK_USE_COLOR_LUMINANCE
1613 // filter down the luminance to a single component, since A8 can't
1614 // use per-component information
1615 unsigned lum = computeLuminance(rec->getLuminanceColor());
1616 // reduce to our finite number of bits
1617 lum = reduce_lumbits(lum);
1618 rec->setLuminanceColor(SkColorSetRGB(lum, lum, lum));
1619 #endif
1620 break;
1621 }
1622 case SkMask::kBW_Format:
1623 // No need to differentiate gamma if we're BW
1624 #ifdef SK_USE_COLOR_LUMINANCE
1625 rec->setLuminanceColor(0);
1626 #else
1627 rec->setLuminanceBits(0);
1628 #endif
1629 break;
1630 }
1631 }
1632
1633 #define MIN_SIZE_FOR_EFFECT_BUFFER 1024
1634
1635 #ifdef SK_DEBUG
1636 #define TEST_DESC
1637 #endif
1638
1639 /*
1640 * ignoreGamma tells us that the caller just wants metrics that are unaffected
1641 * by gamma correction, so we jam the luminance field to 0 (most common value
1642 * for black text) in hopes that we get a cache hit easier. A better solution
1643 * would be for the fontcache lookup to know to ignore the luminance field
1644 * entirely, but not sure how to do that and keep it fast.
1645 */
descriptorProc(const SkMatrix * deviceMatrix,void (* proc)(const SkDescriptor *,void *),void * context,bool ignoreGamma) const1646 void SkPaint::descriptorProc(const SkMatrix* deviceMatrix,
1647 void (*proc)(const SkDescriptor*, void*),
1648 void* context, bool ignoreGamma) const {
1649 SkScalerContext::Rec rec;
1650
1651 SkScalerContext::MakeRec(*this, deviceMatrix, &rec);
1652 if (ignoreGamma) {
1653 #ifdef SK_USE_COLOR_LUMINANCE
1654 rec.setLuminanceColor(0);
1655 #else
1656 rec.setLuminanceBits(0);
1657 #endif
1658 }
1659
1660 size_t descSize = sizeof(rec);
1661 int entryCount = 1;
1662 SkPathEffect* pe = this->getPathEffect();
1663 SkMaskFilter* mf = this->getMaskFilter();
1664 SkRasterizer* ra = this->getRasterizer();
1665
1666 SkFlattenableWriteBuffer peBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1667 SkFlattenableWriteBuffer mfBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1668 SkFlattenableWriteBuffer raBuffer(MIN_SIZE_FOR_EFFECT_BUFFER);
1669
1670 if (pe) {
1671 peBuffer.writeFlattenable(pe);
1672 descSize += peBuffer.size();
1673 entryCount += 1;
1674 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1675 // seems like we could support kLCD as well at this point...
1676 }
1677 if (mf) {
1678 mfBuffer.writeFlattenable(mf);
1679 descSize += mfBuffer.size();
1680 entryCount += 1;
1681 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing with maskfilters
1682 }
1683 if (ra) {
1684 raBuffer.writeFlattenable(ra);
1685 descSize += raBuffer.size();
1686 entryCount += 1;
1687 rec.fMaskFormat = SkMask::kA8_Format; // force antialiasing when we do the scan conversion
1688 }
1689
1690 ///////////////////////////////////////////////////////////////////////////
1691 // Now that we're done tweaking the rec, call the PostMakeRec cleanup
1692 SkScalerContext::PostMakeRec(&rec);
1693
1694 descSize += SkDescriptor::ComputeOverhead(entryCount);
1695
1696 SkAutoDescriptor ad(descSize);
1697 SkDescriptor* desc = ad.getDesc();
1698
1699 desc->init();
1700 desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1701
1702 if (pe) {
1703 add_flattenable(desc, kPathEffect_SkDescriptorTag, &peBuffer);
1704 }
1705 if (mf) {
1706 add_flattenable(desc, kMaskFilter_SkDescriptorTag, &mfBuffer);
1707 }
1708 if (ra) {
1709 add_flattenable(desc, kRasterizer_SkDescriptorTag, &raBuffer);
1710 }
1711
1712 SkASSERT(descSize == desc->getLength());
1713 desc->computeChecksum();
1714
1715 #ifdef TEST_DESC
1716 {
1717 // Check that we completely write the bytes in desc (our key), and that
1718 // there are no uninitialized bytes. If there were, then we would get
1719 // false-misses (or worse, false-hits) in our fontcache.
1720 //
1721 // We do this buy filling 2 others, one with 0s and the other with 1s
1722 // and create those, and then check that all 3 are identical.
1723 SkAutoDescriptor ad1(descSize);
1724 SkAutoDescriptor ad2(descSize);
1725 SkDescriptor* desc1 = ad1.getDesc();
1726 SkDescriptor* desc2 = ad2.getDesc();
1727
1728 memset(desc1, 0x00, descSize);
1729 memset(desc2, 0xFF, descSize);
1730
1731 desc1->init();
1732 desc2->init();
1733 desc1->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1734 desc2->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
1735
1736 if (pe) {
1737 add_flattenable(desc1, kPathEffect_SkDescriptorTag, &peBuffer);
1738 add_flattenable(desc2, kPathEffect_SkDescriptorTag, &peBuffer);
1739 }
1740 if (mf) {
1741 add_flattenable(desc1, kMaskFilter_SkDescriptorTag, &mfBuffer);
1742 add_flattenable(desc2, kMaskFilter_SkDescriptorTag, &mfBuffer);
1743 }
1744 if (ra) {
1745 add_flattenable(desc1, kRasterizer_SkDescriptorTag, &raBuffer);
1746 add_flattenable(desc2, kRasterizer_SkDescriptorTag, &raBuffer);
1747 }
1748
1749 SkASSERT(descSize == desc1->getLength());
1750 SkASSERT(descSize == desc2->getLength());
1751 desc1->computeChecksum();
1752 desc2->computeChecksum();
1753 SkASSERT(!memcmp(desc, desc1, descSize));
1754 SkASSERT(!memcmp(desc, desc2, descSize));
1755 }
1756 #endif
1757
1758 proc(desc, context);
1759 }
1760
detachCache(const SkMatrix * deviceMatrix) const1761 SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const {
1762 SkGlyphCache* cache;
1763 this->descriptorProc(deviceMatrix, DetachDescProc, &cache);
1764 return cache;
1765 }
1766
1767 ///////////////////////////////////////////////////////////////////////////////
1768
1769 #include "SkStream.h"
1770
asint(const void * p)1771 static uintptr_t asint(const void* p) {
1772 return reinterpret_cast<uintptr_t>(p);
1773 }
1774
1775 union Scalar32 {
1776 SkScalar fScalar;
1777 uint32_t f32;
1778 };
1779
write_scalar(uint32_t * ptr,SkScalar value)1780 static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
1781 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1782 Scalar32 tmp;
1783 tmp.fScalar = value;
1784 *ptr = tmp.f32;
1785 return ptr + 1;
1786 }
1787
read_scalar(const uint32_t * & ptr)1788 static SkScalar read_scalar(const uint32_t*& ptr) {
1789 SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
1790 Scalar32 tmp;
1791 tmp.f32 = *ptr++;
1792 return tmp.fScalar;
1793 }
1794
pack_4(unsigned a,unsigned b,unsigned c,unsigned d)1795 static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
1796 SkASSERT(a == (uint8_t)a);
1797 SkASSERT(b == (uint8_t)b);
1798 SkASSERT(c == (uint8_t)c);
1799 SkASSERT(d == (uint8_t)d);
1800 return (a << 24) | (b << 16) | (c << 8) | d;
1801 }
1802
1803 enum FlatFlags {
1804 kHasTypeface_FlatFlag = 0x01,
1805 kHasEffects_FlatFlag = 0x02
1806 };
1807
1808 // The size of a flat paint's POD fields
1809 static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1810 1 * sizeof(SkColor) +
1811 1 * sizeof(uint16_t) +
1812 6 * sizeof(uint8_t);
1813
1814 /* To save space/time, we analyze the paint, and write a truncated version of
1815 it if there are not tricky elements like shaders, etc.
1816 */
flatten(SkFlattenableWriteBuffer & buffer) const1817 void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
1818 uint8_t flatFlags = 0;
1819 if (this->getTypeface()) {
1820 flatFlags |= kHasTypeface_FlatFlag;
1821 }
1822 if (asint(this->getPathEffect()) |
1823 asint(this->getShader()) |
1824 asint(this->getXfermode()) |
1825 asint(this->getMaskFilter()) |
1826 asint(this->getColorFilter()) |
1827 asint(this->getRasterizer()) |
1828 asint(this->getLooper()) |
1829 asint(this->getImageFilter())) {
1830 flatFlags |= kHasEffects_FlatFlag;
1831 }
1832
1833 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1834 uint32_t* ptr = buffer.reserve(kPODPaintSize);
1835
1836 ptr = write_scalar(ptr, this->getTextSize());
1837 ptr = write_scalar(ptr, this->getTextScaleX());
1838 ptr = write_scalar(ptr, this->getTextSkewX());
1839 ptr = write_scalar(ptr, this->getStrokeWidth());
1840 ptr = write_scalar(ptr, this->getStrokeMiter());
1841 *ptr++ = this->getColor();
1842 // previously flags:16, textAlign:8, flatFlags:8
1843 // now flags:16, hinting:4, textAlign:4, flatFlags:8
1844 *ptr++ = (this->getFlags() << 16) |
1845 // hinting added later. 0 in this nibble means use the default.
1846 ((this->getHinting()+1) << 12) |
1847 (this->getTextAlign() << 8) |
1848 flatFlags;
1849 *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
1850 this->getStyle(), this->getTextEncoding());
1851
1852 #ifdef SK_BUILD_FOR_ANDROID
1853 buffer.writeInt(this->getFontVariant());
1854 const SkString& langTag = this->getLanguage().getTag();
1855 buffer.writeString(langTag.c_str(), langTag.size());
1856 #endif
1857
1858 // now we're done with ptr and the (pre)reserved space. If we need to write
1859 // additional fields, use the buffer directly
1860 if (flatFlags & kHasTypeface_FlatFlag) {
1861 buffer.writeTypeface(this->getTypeface());
1862 }
1863 if (flatFlags & kHasEffects_FlatFlag) {
1864 buffer.writeFlattenable(this->getPathEffect());
1865 buffer.writeFlattenable(this->getShader());
1866 buffer.writeFlattenable(this->getXfermode());
1867 buffer.writeFlattenable(this->getMaskFilter());
1868 buffer.writeFlattenable(this->getColorFilter());
1869 buffer.writeFlattenable(this->getRasterizer());
1870 buffer.writeFlattenable(this->getLooper());
1871 buffer.writeFlattenable(this->getImageFilter());
1872 }
1873 }
1874
unflatten(SkFlattenableReadBuffer & buffer)1875 void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
1876 SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
1877 const void* podData = buffer.skip(kPODPaintSize);
1878 const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
1879
1880 // the order we read must match the order we wrote in flatten()
1881 this->setTextSize(read_scalar(pod));
1882 this->setTextScaleX(read_scalar(pod));
1883 this->setTextSkewX(read_scalar(pod));
1884 this->setStrokeWidth(read_scalar(pod));
1885 this->setStrokeMiter(read_scalar(pod));
1886 this->setColor(*pod++);
1887
1888 // previously flags:16, textAlign:8, flatFlags:8
1889 // now flags:16, hinting:4, textAlign:4, flatFlags:8
1890 uint32_t tmp = *pod++;
1891 this->setFlags(tmp >> 16);
1892
1893 if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
1894 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
1895 this->setHinting(SkPaintDefaults_Hinting);
1896 } else {
1897 // hinting added later. 0 in this nibble means use the default.
1898 uint32_t hinting = (tmp >> 12) & 0xF;
1899 this->setHinting(0 == hinting ? kNormal_Hinting : static_cast<Hinting>(hinting-1));
1900
1901 this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xF));
1902 }
1903
1904 uint8_t flatFlags = tmp & 0xFF;
1905
1906 tmp = *pod++;
1907 this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
1908 this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
1909 this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
1910 this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
1911
1912 #ifdef SK_BUILD_FOR_ANDROID
1913 this->setFontVariant(SkPaint::FontVariant(buffer.readInt()));
1914 this->setLanguage(SkLanguage(buffer.readString()));
1915 #endif
1916
1917 if (flatFlags & kHasTypeface_FlatFlag) {
1918 this->setTypeface(buffer.readTypeface());
1919 } else {
1920 this->setTypeface(NULL);
1921 }
1922
1923 if (flatFlags & kHasEffects_FlatFlag) {
1924 SkSafeUnref(this->setPathEffect((SkPathEffect*) buffer.readFlattenable()));
1925 SkSafeUnref(this->setShader((SkShader*) buffer.readFlattenable()));
1926 SkSafeUnref(this->setXfermode((SkXfermode*) buffer.readFlattenable()));
1927 SkSafeUnref(this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable()));
1928 SkSafeUnref(this->setColorFilter((SkColorFilter*) buffer.readFlattenable()));
1929 SkSafeUnref(this->setRasterizer((SkRasterizer*) buffer.readFlattenable()));
1930 SkSafeUnref(this->setLooper((SkDrawLooper*) buffer.readFlattenable()));
1931 if (buffer.getPictureVersion() != PICTURE_VERSION_ICS)
1932 SkSafeUnref(this->setImageFilter((SkImageFilter*) buffer.readFlattenable()));
1933 else
1934 this->setImageFilter(NULL);
1935 } else {
1936 this->setPathEffect(NULL);
1937 this->setShader(NULL);
1938 this->setXfermode(NULL);
1939 this->setMaskFilter(NULL);
1940 this->setColorFilter(NULL);
1941 this->setRasterizer(NULL);
1942 this->setLooper(NULL);
1943 this->setImageFilter(NULL);
1944 }
1945 }
1946
1947 ///////////////////////////////////////////////////////////////////////////////
1948
setShader(SkShader * shader)1949 SkShader* SkPaint::setShader(SkShader* shader) {
1950 GEN_ID_INC_EVAL(shader != fShader);
1951 SkRefCnt_SafeAssign(fShader, shader);
1952 return shader;
1953 }
1954
setColorFilter(SkColorFilter * filter)1955 SkColorFilter* SkPaint::setColorFilter(SkColorFilter* filter) {
1956 GEN_ID_INC_EVAL(filter != fColorFilter);
1957 SkRefCnt_SafeAssign(fColorFilter, filter);
1958 return filter;
1959 }
1960
setXfermode(SkXfermode * mode)1961 SkXfermode* SkPaint::setXfermode(SkXfermode* mode) {
1962 GEN_ID_INC_EVAL(mode != fXfermode);
1963 SkRefCnt_SafeAssign(fXfermode, mode);
1964 return mode;
1965 }
1966
setXfermodeMode(SkXfermode::Mode mode)1967 SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) {
1968 SkSafeUnref(fXfermode);
1969 fXfermode = SkXfermode::Create(mode);
1970 GEN_ID_INC;
1971 return fXfermode;
1972 }
1973
setPathEffect(SkPathEffect * effect)1974 SkPathEffect* SkPaint::setPathEffect(SkPathEffect* effect) {
1975 GEN_ID_INC_EVAL(effect != fPathEffect);
1976 SkRefCnt_SafeAssign(fPathEffect, effect);
1977 return effect;
1978 }
1979
setMaskFilter(SkMaskFilter * filter)1980 SkMaskFilter* SkPaint::setMaskFilter(SkMaskFilter* filter) {
1981 GEN_ID_INC_EVAL(filter != fMaskFilter);
1982 SkRefCnt_SafeAssign(fMaskFilter, filter);
1983 return filter;
1984 }
1985
1986 ///////////////////////////////////////////////////////////////////////////////
1987
getFillPath(const SkPath & src,SkPath * dst) const1988 bool SkPaint::getFillPath(const SkPath& src, SkPath* dst) const {
1989 SkPath effectPath, strokePath;
1990 const SkPath* path = &src;
1991
1992 SkScalar width = this->getStrokeWidth();
1993
1994 switch (this->getStyle()) {
1995 case SkPaint::kFill_Style:
1996 width = -1; // mark it as no-stroke
1997 break;
1998 case SkPaint::kStrokeAndFill_Style:
1999 if (width == 0) {
2000 width = -1; // mark it as no-stroke
2001 }
2002 break;
2003 case SkPaint::kStroke_Style:
2004 break;
2005 default:
2006 SkDEBUGFAIL("unknown paint style");
2007 }
2008
2009 if (this->getPathEffect()) {
2010 // lie to the pathEffect if our style is strokeandfill, so that it treats us as just fill
2011 if (this->getStyle() == SkPaint::kStrokeAndFill_Style) {
2012 width = -1; // mark it as no-stroke
2013 }
2014
2015 if (this->getPathEffect()->filterPath(&effectPath, src, &width)) {
2016 path = &effectPath;
2017 }
2018
2019 // restore the width if we earlier had to lie, and if we're still set to no-stroke
2020 // note: if we're now stroke (width >= 0), then the pathEffect asked for that change
2021 // and we want to respect that (i.e. don't overwrite their setting for width)
2022 if (this->getStyle() == SkPaint::kStrokeAndFill_Style && width < 0) {
2023 width = this->getStrokeWidth();
2024 if (width == 0) {
2025 width = -1;
2026 }
2027 }
2028 }
2029
2030 if (width > 0 && !path->isEmpty()) {
2031 SkStroke stroker(*this, width);
2032 stroker.strokePath(*path, &strokePath);
2033 path = &strokePath;
2034 }
2035
2036 if (path == &src) {
2037 *dst = src;
2038 } else {
2039 SkASSERT(path == &effectPath || path == &strokePath);
2040 dst->swap(*(SkPath*)path);
2041 }
2042
2043 return width != 0; // return true if we're filled, or false if we're hairline (width == 0)
2044 }
2045
doComputeFastBounds(const SkRect & src,SkRect * storage) const2046 const SkRect& SkPaint::doComputeFastBounds(const SkRect& src,
2047 SkRect* storage) const {
2048 SkASSERT(storage);
2049
2050 if (this->getLooper()) {
2051 SkASSERT(this->getLooper()->canComputeFastBounds(*this));
2052 this->getLooper()->computeFastBounds(*this, src, storage);
2053 return *storage;
2054 }
2055
2056 if (this->getStyle() != SkPaint::kFill_Style) {
2057 // since we're stroked, outset the rect by the radius (and join type)
2058 SkScalar radius = SkScalarHalf(this->getStrokeWidth());
2059 if (0 == radius) { // hairline
2060 radius = SK_Scalar1;
2061 } else if (this->getStrokeJoin() == SkPaint::kMiter_Join) {
2062 SkScalar scale = this->getStrokeMiter();
2063 if (scale > SK_Scalar1) {
2064 radius = SkScalarMul(radius, scale);
2065 }
2066 }
2067 storage->set(src.fLeft - radius, src.fTop - radius,
2068 src.fRight + radius, src.fBottom + radius);
2069 } else {
2070 *storage = src;
2071 }
2072
2073 // check the mask filter
2074 if (this->getMaskFilter()) {
2075 this->getMaskFilter()->computeFastBounds(*storage, storage);
2076 }
2077
2078 return *storage;
2079 }
2080
2081 ///////////////////////////////////////////////////////////////////////////////
2082
has_thick_frame(const SkPaint & paint)2083 static bool has_thick_frame(const SkPaint& paint) {
2084 return paint.getStrokeWidth() > 0 &&
2085 paint.getStyle() != SkPaint::kFill_Style;
2086 }
2087
SkTextToPathIter(const char text[],size_t length,const SkPaint & paint,bool applyStrokeAndPathEffects,bool forceLinearTextOn)2088 SkTextToPathIter::SkTextToPathIter( const char text[], size_t length,
2089 const SkPaint& paint,
2090 bool applyStrokeAndPathEffects,
2091 bool forceLinearTextOn) : fPaint(paint) {
2092 fGlyphCacheProc = paint.getMeasureCacheProc(SkPaint::kForward_TextBufferDirection,
2093 true);
2094
2095 if (forceLinearTextOn) {
2096 fPaint.setLinearText(true);
2097 }
2098 fPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2099
2100 if (fPaint.getPathEffect() == NULL && !has_thick_frame(fPaint)) {
2101 applyStrokeAndPathEffects = false;
2102 }
2103
2104 // can't use our canonical size if we need to apply patheffects/strokes
2105 if (fPaint.getPathEffect() == NULL) {
2106 fPaint.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));
2107 fScale = paint.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
2108 if (has_thick_frame(fPaint)) {
2109 fPaint.setStrokeWidth(SkScalarDiv(fPaint.getStrokeWidth(), fScale));
2110 }
2111 } else {
2112 fScale = SK_Scalar1;
2113 }
2114
2115 if (!applyStrokeAndPathEffects) {
2116 fPaint.setStyle(SkPaint::kFill_Style);
2117 fPaint.setPathEffect(NULL);
2118 }
2119
2120 fCache = fPaint.detachCache(NULL);
2121
2122 SkPaint::Style style = SkPaint::kFill_Style;
2123 SkPathEffect* pe = NULL;
2124
2125 if (!applyStrokeAndPathEffects) {
2126 style = paint.getStyle(); // restore
2127 pe = paint.getPathEffect(); // restore
2128 }
2129 fPaint.setStyle(style);
2130 fPaint.setPathEffect(pe);
2131 fPaint.setMaskFilter(paint.getMaskFilter()); // restore
2132
2133 // now compute fXOffset if needed
2134
2135 SkScalar xOffset = 0;
2136 if (paint.getTextAlign() != SkPaint::kLeft_Align) { // need to measure first
2137 int count;
2138 SkScalar width = SkScalarMul(fPaint.measure_text(fCache, text, length,
2139 &count, NULL), fScale);
2140 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2141 width = SkScalarHalf(width);
2142 }
2143 xOffset = -width;
2144 }
2145 fXPos = xOffset;
2146 fPrevAdvance = 0;
2147
2148 fText = text;
2149 fStop = text + length;
2150
2151 fXYIndex = paint.isVerticalText() ? 1 : 0;
2152 }
2153
~SkTextToPathIter()2154 SkTextToPathIter::~SkTextToPathIter() {
2155 SkGlyphCache::AttachCache(fCache);
2156 }
2157
next(SkScalar * xpos)2158 const SkPath* SkTextToPathIter::next(SkScalar* xpos) {
2159 while (fText < fStop) {
2160 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
2161
2162 fXPos += SkScalarMul(SkFixedToScalar(fPrevAdvance + fAutoKern.adjust(glyph)), fScale);
2163 fPrevAdvance = advance(glyph, fXYIndex); // + fPaint.getTextTracking();
2164
2165 if (glyph.fWidth) {
2166 if (xpos) {
2167 *xpos = fXPos;
2168 }
2169 return fCache->findPath(glyph);
2170 }
2171 }
2172 return NULL;
2173 }
2174
2175 ///////////////////////////////////////////////////////////////////////////////
2176
nothingToDraw() const2177 bool SkPaint::nothingToDraw() const {
2178 if (fLooper) {
2179 return false;
2180 }
2181 SkXfermode::Mode mode;
2182 if (SkXfermode::AsMode(fXfermode, &mode)) {
2183 switch (mode) {
2184 case SkXfermode::kSrcOver_Mode:
2185 case SkXfermode::kSrcATop_Mode:
2186 case SkXfermode::kDstOut_Mode:
2187 case SkXfermode::kDstOver_Mode:
2188 case SkXfermode::kPlus_Mode:
2189 return 0 == this->getAlpha();
2190 case SkXfermode::kDst_Mode:
2191 return true;
2192 default:
2193 break;
2194 }
2195 }
2196 return false;
2197 }
2198
2199
2200 //////////// Move these to their own file soon.
2201
filterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * result,SkIPoint * loc)2202 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
2203 const SkMatrix& ctm,
2204 SkBitmap* result, SkIPoint* loc) {
2205 SkASSERT(proxy);
2206 SkASSERT(result);
2207 SkASSERT(loc);
2208 /*
2209 * Give the proxy first shot at the filter. If it returns false, ask
2210 * the filter to do it.
2211 */
2212 return proxy->filterImage(this, src, ctm, result, loc) ||
2213 this->onFilterImage(proxy, src, ctm, result, loc);
2214 }
2215
filterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst)2216 bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
2217 SkIRect* dst) {
2218 SkASSERT(&src);
2219 SkASSERT(dst);
2220 return this->onFilterBounds(src, ctm, dst);
2221 }
2222
onFilterImage(Proxy *,const SkBitmap &,const SkMatrix &,SkBitmap *,SkIPoint *)2223 bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
2224 SkBitmap*, SkIPoint*) {
2225 return false;
2226 }
2227
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst)2228 bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
2229 SkIRect* dst) {
2230 *dst = src;
2231 return true;
2232 }
2233
asABlur(SkSize * sigma) const2234 bool SkImageFilter::asABlur(SkSize* sigma) const {
2235 return false;
2236 }
2237
asAnErode(SkISize * radius) const2238 bool SkImageFilter::asAnErode(SkISize* radius) const {
2239 return false;
2240 }
2241
asADilate(SkISize * radius) const2242 bool SkImageFilter::asADilate(SkISize* radius) const {
2243 return false;
2244 }
2245
2246 //////
2247
canComputeFastBounds(const SkPaint & paint)2248 bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) {
2249 SkCanvas canvas;
2250
2251 this->init(&canvas);
2252 for (;;) {
2253 SkPaint p(paint);
2254 if (this->next(&canvas, &p)) {
2255 p.setLooper(NULL);
2256 if (!p.canComputeFastBounds()) {
2257 return false;
2258 }
2259 } else {
2260 break;
2261 }
2262 }
2263 return true;
2264 }
2265
computeFastBounds(const SkPaint & paint,const SkRect & src,SkRect * dst)2266 void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
2267 SkRect* dst) {
2268 SkCanvas canvas;
2269
2270 this->init(&canvas);
2271 for (bool firstTime = true;; firstTime = false) {
2272 SkPaint p(paint);
2273 if (this->next(&canvas, &p)) {
2274 SkRect r(src);
2275
2276 p.setLooper(NULL);
2277 p.computeFastBounds(r, &r);
2278 canvas.getTotalMatrix().mapRect(&r);
2279
2280 if (firstTime) {
2281 *dst = r;
2282 } else {
2283 dst->join(r);
2284 }
2285 } else {
2286 break;
2287 }
2288 }
2289 }
2290
2291