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