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