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 
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 
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 
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 
74 bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) {
75     return paint.getMaskFilter() || paint.getPathEffect() ||
76            paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style;
77 }
78 
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