Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: skia/sgl/SkPaint.cpp

Issue 113827: Remove the remainder of the skia source code from the Chromium repo.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « skia/sgl/SkPackBits.cpp ('k') | skia/sgl/SkPath.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « skia/sgl/SkPackBits.cpp ('k') | skia/sgl/SkPath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698