OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrTextContext.h" | 8 #include "GrTextContext.h" |
9 #include "GrContext.h" | |
10 #include "GrFontScaler.h" | 9 #include "GrFontScaler.h" |
11 #include "GrTextUtils.h" | |
12 | 10 |
13 #include "SkDrawFilter.h" | |
14 #include "SkGlyphCache.h" | 11 #include "SkGlyphCache.h" |
15 #include "SkGrPriv.h" | |
16 #include "SkTextBlobRunIterator.h" | |
17 | 12 |
18 GrTextContext::GrTextContext(GrContext* context, const SkSurfaceProps& surfacePr
ops) | 13 GrTextContext::GrTextContext(GrContext* context, const SkSurfaceProps& surfacePr
ops) |
19 : fFallbackTextContext(nullptr) | 14 : fContext(context) |
20 , fContext(context) | |
21 , fSurfaceProps(surfaceProps) { | 15 , fSurfaceProps(surfaceProps) { |
22 } | 16 } |
23 | 17 |
24 GrTextContext::~GrTextContext() { | |
25 delete fFallbackTextContext; | |
26 } | |
27 | |
28 void GrTextContext::drawText(GrDrawContext* dc, | |
29 const GrClip& clip, const GrPaint& paint, | |
30 const SkPaint& skPaint, const SkMatrix& viewMatrix, | |
31 const char text[], size_t byteLength, | |
32 SkScalar x, SkScalar y, const SkIRect& clipBounds)
{ | |
33 if (fContext->abandoned()) { | |
34 return; | |
35 } | |
36 | |
37 GrTextContext* textContext = this; | |
38 do { | |
39 if (textContext->canDraw(skPaint, viewMatrix)) { | |
40 textContext->onDrawText(dc, clip, paint, skPaint, viewMatrix, | |
41 text, byteLength, x, y, clipBounds); | |
42 return; | |
43 } | |
44 textContext = textContext->fFallbackTextContext; | |
45 } while (textContext); | |
46 | |
47 // fall back to drawing as a path | |
48 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b
yteLength, x, y, | |
49 clipBounds); | |
50 } | |
51 | |
52 void GrTextContext::drawPosText(GrDrawContext* dc, | |
53 const GrClip& clip, const GrPaint& paint, | |
54 const SkPaint& skPaint, const SkMatrix& viewMatr
ix, | |
55 const char text[], size_t byteLength, | |
56 const SkScalar pos[], int scalarsPerPosition, | |
57 const SkPoint& offset, const SkIRect& clipBounds
) { | |
58 if (fContext->abandoned()) { | |
59 return; | |
60 } | |
61 | |
62 GrTextContext* textContext = this; | |
63 do { | |
64 if (textContext->canDraw(skPaint, viewMatrix)) { | |
65 textContext->onDrawPosText(dc, clip, paint, skPaint, viewMatrix, | |
66 text, byteLength, pos, | |
67 scalarsPerPosition, offset, clipBounds); | |
68 return; | |
69 } | |
70 textContext = textContext->fFallbackTextContext; | |
71 } while (textContext); | |
72 | |
73 // fall back to drawing as a path | |
74 GrTextUtils::DrawPosTextAsPath(fContext, dc, fSurfaceProps, clip, skPaint, v
iewMatrix, text, | |
75 byteLength, pos, scalarsPerPosition, offset,
clipBounds); | |
76 } | |
77 | |
78 bool GrTextContext::ShouldDisableLCD(const SkPaint& paint) { | 18 bool GrTextContext::ShouldDisableLCD(const SkPaint& paint) { |
79 if (!SkXfermode::AsMode(paint.getXfermode(), nullptr) || | 19 if (!SkXfermode::AsMode(paint.getXfermode(), nullptr) || |
80 paint.getMaskFilter() || | 20 paint.getMaskFilter() || |
81 paint.getRasterizer() || | 21 paint.getRasterizer() || |
82 paint.getPathEffect() || | 22 paint.getPathEffect() || |
83 paint.isFakeBoldText() || | 23 paint.isFakeBoldText() || |
84 paint.getStyle() != SkPaint::kFill_Style) | 24 paint.getStyle() != SkPaint::kFill_Style) |
85 { | 25 { |
86 return true; | 26 return true; |
87 } | 27 } |
88 return false; | 28 return false; |
89 } | 29 } |
90 | 30 |
91 uint32_t GrTextContext::FilterTextFlags(const SkSurfaceProps& surfaceProps, cons
t SkPaint& paint) { | 31 uint32_t GrTextContext::FilterTextFlags(const SkSurfaceProps& surfaceProps, cons
t SkPaint& paint) { |
92 uint32_t flags = paint.getFlags(); | 32 uint32_t flags = paint.getFlags(); |
93 | 33 |
94 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { | 34 if (!paint.isLCDRenderText() || !paint.isAntiAlias()) { |
95 return flags; | 35 return flags; |
96 } | 36 } |
97 | 37 |
98 if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisabl
eLCD(paint)) { | 38 if (kUnknown_SkPixelGeometry == surfaceProps.pixelGeometry() || ShouldDisabl
eLCD(paint)) { |
99 flags &= ~SkPaint::kLCDRenderText_Flag; | 39 flags &= ~SkPaint::kLCDRenderText_Flag; |
100 flags |= SkPaint::kGenA8FromLCD_Flag; | 40 flags |= SkPaint::kGenA8FromLCD_Flag; |
101 } | 41 } |
102 | 42 |
103 return flags; | 43 return flags; |
104 } | 44 } |
105 | 45 |
106 void GrTextContext::drawTextBlob(GrDrawContext* dc, | |
107 const GrClip& clip, const SkPaint& skPaint, | |
108 const SkMatrix& viewMatrix, const SkTextBlob* b
lob, | |
109 SkScalar x, SkScalar y, | |
110 SkDrawFilter* drawFilter, const SkIRect& clipBo
unds) { | |
111 SkPaint runPaint = skPaint; | |
112 | |
113 SkTextBlobRunIterator it(blob); | |
114 for (;!it.done(); it.next()) { | |
115 size_t textLen = it.glyphCount() * sizeof(uint16_t); | |
116 const SkPoint& offset = it.offset(); | |
117 // applyFontToPaint() always overwrites the exact same attributes, | |
118 // so it is safe to not re-seed the paint for this reason. | |
119 it.applyFontToPaint(&runPaint); | |
120 | |
121 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ
e)) { | |
122 // A false return from filter() means we should abort the current dr
aw. | |
123 runPaint = skPaint; | |
124 continue; | |
125 } | |
126 | |
127 runPaint.setFlags(FilterTextFlags(fSurfaceProps, runPaint)); | |
128 | |
129 GrPaint grPaint; | |
130 if (!SkPaintToGrPaint(fContext, runPaint, viewMatrix, &grPaint)) { | |
131 return; | |
132 } | |
133 | |
134 switch (it.positioning()) { | |
135 case SkTextBlob::kDefault_Positioning: | |
136 this->drawText(dc, clip, grPaint, runPaint, viewMatrix, (const char
*)it.glyphs(), | |
137 textLen, x + offset.x(), y + offset.y(), clipBounds); | |
138 break; | |
139 case SkTextBlob::kHorizontal_Positioning: | |
140 this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const ch
ar*)it.glyphs(), | |
141 textLen, it.pos(), 1, SkPoint::Make(x, y + offset.
y()), clipBounds); | |
142 break; | |
143 case SkTextBlob::kFull_Positioning: | |
144 this->drawPosText(dc, clip, grPaint, runPaint, viewMatrix, (const ch
ar*)it.glyphs(), | |
145 textLen, it.pos(), 2, SkPoint::Make(x, y), clipBou
nds); | |
146 break; | |
147 default: | |
148 SkFAIL("unhandled positioning mode"); | |
149 } | |
150 | |
151 if (drawFilter) { | |
152 // A draw filter may change the paint arbitrarily, so we must re-see
d in this case. | |
153 runPaint = skPaint; | |
154 } | |
155 } | |
156 } | |
157 | |
158 static void GlyphCacheAuxProc(void* data) { | 46 static void GlyphCacheAuxProc(void* data) { |
159 GrFontScaler* scaler = (GrFontScaler*)data; | 47 GrFontScaler* scaler = (GrFontScaler*)data; |
160 SkSafeUnref(scaler); | 48 SkSafeUnref(scaler); |
161 } | 49 } |
162 | 50 |
163 GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) { | 51 GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) { |
164 void* auxData; | 52 void* auxData; |
165 GrFontScaler* scaler = nullptr; | 53 GrFontScaler* scaler = nullptr; |
166 | 54 |
167 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) { | 55 if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) { |
168 scaler = (GrFontScaler*)auxData; | 56 scaler = (GrFontScaler*)auxData; |
169 } | 57 } |
170 if (nullptr == scaler) { | 58 if (nullptr == scaler) { |
171 scaler = new GrFontScaler(cache); | 59 scaler = new GrFontScaler(cache); |
172 cache->setAuxProc(GlyphCacheAuxProc, scaler); | 60 cache->setAuxProc(GlyphCacheAuxProc, scaler); |
173 } | 61 } |
174 | 62 |
175 return scaler; | 63 return scaler; |
176 } | 64 } |
OLD | NEW |