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