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