1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "GrTextUtils.h"
9 #include "GrContext.h"
10 #include "SkDrawFilter.h"
11 #include "SkGlyphCache.h"
12 #include "SkGr.h"
13 #include "SkPaint.h"
14 #include "SkTextBlobRunIterator.h"
15
initFilteredColor()16 void GrTextUtils::Paint::initFilteredColor() {
17 // This mirrors the logic in skpaint_to_grpaint_impl for handling paint colors
18 if (fDstColorSpaceInfo->colorSpace()) {
19 GrColor4f filteredColor =
20 SkColorToUnpremulGrColor4f(fPaint->getColor(), *fDstColorSpaceInfo);
21 if (fPaint->getColorFilter()) {
22 filteredColor = GrColor4f::FromSkColor4f(
23 fPaint->getColorFilter()->filterColor4f(filteredColor.toSkColor4f()));
24 }
25 fFilteredPremulColor = filteredColor.premul().toGrColor();
26 } else {
27 SkColor filteredSkColor = fPaint->getColor();
28 if (fPaint->getColorFilter()) {
29 filteredSkColor = fPaint->getColorFilter()->filterColor(filteredSkColor);
30 }
31 fFilteredPremulColor = SkColorToPremulGrColor(filteredSkColor);
32 }
33 }
34
35
modifyForRun(std::function<void (SkPaint *)> paintModFunc)36 bool GrTextUtils::RunPaint::modifyForRun(std::function<void(SkPaint*)> paintModFunc) {
37 if (!fModifiedPaint.isValid()) {
38 fModifiedPaint.init(fOriginalPaint->skPaint());
39 fPaint = fModifiedPaint.get();
40 } else if (fFilter) {
41 // We have to reset before applying the run because the filter could have arbitrary
42 // changed the paint.
43 *fModifiedPaint.get() = fOriginalPaint->skPaint();
44 }
45 paintModFunc(fModifiedPaint.get());
46
47 if (fFilter) {
48 if (!fFilter->filter(fModifiedPaint.get(), SkDrawFilter::kText_Type)) {
49 // A false return from filter() means we should abort the current draw.
50 return false;
51 }
52 // The draw filter could have changed either the paint color or color filter.
53 this->initFilteredColor();
54 }
55 fModifiedPaint.get()->setFlags(FilterTextFlags(fProps, *fModifiedPaint.get()));
56 return true;
57 }
58
FilterTextFlags(const SkSurfaceProps & surfaceProps,const SkPaint & paint)59 uint32_t GrTextUtils::FilterTextFlags(const SkSurfaceProps& surfaceProps, const SkPaint& paint) {
60 uint32_t flags = paint.getFlags();
61
62 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) {
63 return flags;
64 }
65
66 if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisableLCD(paint)) {
67 flags &= ~SkPaint::kLCDRenderText_Flag;
68 flags |= SkPaint::kGenA8FromLCD_Flag;
69 }
70
71 return flags;
72 }
73
ShouldDisableLCD(const SkPaint & paint)74 bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
75 return paint.getMaskFilter() || paint.getPathEffect() ||
76 paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style;
77 }
78
next(const SkGlyph ** skGlyph,const SkPath ** path,SkScalar * xpos)79 bool GrTextUtils::PathTextIter::next(const SkGlyph** skGlyph, const SkPath** path, SkScalar* xpos) {
80 SkASSERT(skGlyph);
81 SkASSERT(path);
82 SkASSERT(xpos);
83 if (fText < fStop) {
84 const SkGlyph& glyph = fGlyphCacheProc(fCache, &fText);
85
86 fXPos += (fPrevAdvance + fAutoKern.adjust(glyph)) * fScale;
87 SkASSERT(0 == fXYIndex || 1 == fXYIndex);
88 fPrevAdvance = SkFloatToScalar((&glyph.fAdvanceX)[fXYIndex]);
89
90 if (glyph.fWidth) {
91 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
92 *skGlyph = &glyph;
93 *path = nullptr;
94 } else {
95 *skGlyph = nullptr;
96 *path = fCache->findPath(glyph);
97 }
98 } else {
99 *skGlyph = nullptr;
100 *path = nullptr;
101 }
102 *xpos = fXPos;
103 return true;
104 }
105 return false;
106 }
107