Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 #include "GrAtlasTextContext.h" | 7 #include "GrAtlasTextContext.h" |
| 8 | 8 |
| 9 #include "GrDrawContext.h" | 9 #include "GrDrawContext.h" |
| 10 #include "GrDrawTarget.h" | 10 #include "GrDrawTarget.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "SkGpuDevice.h" | 27 #include "SkGpuDevice.h" |
| 28 #include "SkGrPriv.h" | 28 #include "SkGrPriv.h" |
| 29 #include "SkPath.h" | 29 #include "SkPath.h" |
| 30 #include "SkRTConf.h" | 30 #include "SkRTConf.h" |
| 31 #include "SkStrokeRec.h" | 31 #include "SkStrokeRec.h" |
| 32 #include "SkTextBlob.h" | 32 #include "SkTextBlob.h" |
| 33 #include "SkTextMapStateProc.h" | 33 #include "SkTextMapStateProc.h" |
| 34 | 34 |
| 35 #include "batches/GrAtlasTextBatch.h" | 35 #include "batches/GrAtlasTextBatch.h" |
| 36 | 36 |
| 37 GrAtlasTextContext::GrAtlasTextContext(GrContext* context) | 37 GrAtlasTextContext::GrAtlasTextContext() |
| 38 : INHERITED(context) | 38 : fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { |
| 39 , fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { | |
| 40 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest | |
| 41 // vertexStride | |
| 42 static_assert(GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kColorTex tVASize && | |
| 43 GrAtlasTextBlob::kGrayTextVASize >= GrAtlasTextBlob::kLCDTextV ASize, | |
| 44 "vertex_attribute_changed"); | |
| 45 fCache = context->getTextBlobCache(); | |
| 46 } | 39 } |
| 47 | 40 |
| 48 | 41 |
| 49 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context) { | 42 GrAtlasTextContext* GrAtlasTextContext::Create() { |
| 50 return new GrAtlasTextContext(context); | 43 return new GrAtlasTextContext(); |
| 51 } | 44 } |
| 52 | 45 |
| 53 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, | 46 bool GrAtlasTextContext::canDraw(const SkPaint& skPaint, |
| 54 const SkMatrix& viewMatrix, | 47 const SkMatrix& viewMatrix, |
| 55 const SkSurfaceProps& props) { | 48 const SkSurfaceProps& props, |
| 56 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, | 49 const GrShaderCaps& shaderCaps) { |
| 57 *fContext->caps()->shaderCaps()) || | 50 return GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shad erCaps) || |
| 58 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); | 51 !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); |
| 59 } | 52 } |
| 60 | 53 |
| 61 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd ) { | 54 GrColor GrAtlasTextContext::ComputeCanonicalColor(const SkPaint& paint, bool lcd ) { |
| 62 GrColor canonicalColor = paint.computeLuminanceColor(); | 55 GrColor canonicalColor = paint.computeLuminanceColor(); |
| 63 if (lcd) { | 56 if (lcd) { |
| 64 // This is the correct computation, but there are tons of cases where LC D can be overridden. | 57 // This is the correct computation, but there are tons of cases where LC D can be overridden. |
| 65 // For now we just regenerate if any run in a textblob has LCD. | 58 // For now we just regenerate if any run in a textblob has LCD. |
| 66 // TODO figure out where all of these overrides are and see if we can in corporate that logic | 59 // TODO figure out where all of these overrides are and see if we can in corporate that logic |
| 67 // at a higher level *OR* use sRGB | 60 // at a higher level *OR* use sRGB |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 85 bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { | 78 bool GrAtlasTextContext::HasLCD(const SkTextBlob* blob) { |
| 86 SkTextBlobRunIterator it(blob); | 79 SkTextBlobRunIterator it(blob); |
| 87 for (; !it.done(); it.next()) { | 80 for (; !it.done(); it.next()) { |
| 88 if (it.isLCD()) { | 81 if (it.isLCD()) { |
| 89 return true; | 82 return true; |
| 90 } | 83 } |
| 91 } | 84 } |
| 92 return false; | 85 return false; |
| 93 } | 86 } |
| 94 | 87 |
| 95 void GrAtlasTextContext::drawTextBlob(GrDrawContext* dc, | 88 void GrAtlasTextContext::drawTextBlob(GrContext* context, GrDrawContext* dc, |
| 96 const GrClip& clip, const SkPaint& skPaint , | 89 const GrClip& clip, const SkPaint& skPaint , |
| 97 const SkMatrix& viewMatrix, | 90 const SkMatrix& viewMatrix, |
| 98 const SkSurfaceProps& props, const SkTextB lob* blob, | 91 const SkSurfaceProps& props, const SkTextB lob* blob, |
| 99 SkScalar x, SkScalar y, | 92 SkScalar x, SkScalar y, |
| 100 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { | 93 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { |
| 101 // If we have been abandoned, then don't draw | 94 // If we have been abandoned, then don't draw |
| 102 if (fContext->abandoned()) { | 95 if (context->abandoned()) { |
| 103 return; | 96 return; |
| 104 } | 97 } |
| 105 | 98 |
| 106 SkAutoTUnref<GrAtlasTextBlob> cacheBlob; | 99 SkAutoTUnref<GrAtlasTextBlob> cacheBlob; |
| 107 SkMaskFilter::BlurRec blurRec; | 100 SkMaskFilter::BlurRec blurRec; |
| 108 GrAtlasTextBlob::Key key; | 101 GrAtlasTextBlob::Key key; |
| 109 // It might be worth caching these things, but its not clear at this time | 102 // It might be worth caching these things, but its not clear at this time |
| 110 // TODO for animated mask filters, this will fill up our cache. We need a s afeguard here | 103 // TODO for animated mask filters, this will fill up our cache. We need a s afeguard here |
| 111 const SkMaskFilter* mf = skPaint.getMaskFilter(); | 104 const SkMaskFilter* mf = skPaint.getMaskFilter(); |
| 112 bool canCache = !(skPaint.getPathEffect() || | 105 bool canCache = !(skPaint.getPathEffect() || |
| 113 (mf && !mf->asABlur(&blurRec)) || | 106 (mf && !mf->asABlur(&blurRec)) || |
| 114 drawFilter); | 107 drawFilter); |
| 115 | 108 |
| 109 GrTextBlobCache* cache = context->getTextBlobCache(); | |
| 116 if (canCache) { | 110 if (canCache) { |
| 117 bool hasLCD = HasLCD(blob); | 111 bool hasLCD = HasLCD(blob); |
| 118 | 112 |
| 119 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry | 113 // We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry |
| 120 SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : | 114 SkPixelGeometry pixelGeometry = hasLCD ? props.pixelGeometry() : |
| 121 kUnknown_SkPixelGeometry; | 115 kUnknown_SkPixelGeometry; |
| 122 | 116 |
| 123 // TODO we want to figure out a way to be able to use the canonical colo r on LCD text, | 117 // TODO we want to figure out a way to be able to use the canonical colo r on LCD text, |
| 124 // see the note on ComputeCanonicalColor above. We pick a dummy value f or LCD text to | 118 // see the note on ComputeCanonicalColor above. We pick a dummy value f or LCD text to |
| 125 // ensure we always match the same key | 119 // ensure we always match the same key |
| 126 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : | 120 GrColor canonicalColor = hasLCD ? SK_ColorTRANSPARENT : |
| 127 ComputeCanonicalColor(skPaint, hasLCD) ; | 121 ComputeCanonicalColor(skPaint, hasLCD) ; |
| 128 | 122 |
| 129 key.fPixelGeometry = pixelGeometry; | 123 key.fPixelGeometry = pixelGeometry; |
| 130 key.fUniqueID = blob->uniqueID(); | 124 key.fUniqueID = blob->uniqueID(); |
| 131 key.fStyle = skPaint.getStyle(); | 125 key.fStyle = skPaint.getStyle(); |
| 132 key.fHasBlur = SkToBool(mf); | 126 key.fHasBlur = SkToBool(mf); |
| 133 key.fCanonicalColor = canonicalColor; | 127 key.fCanonicalColor = canonicalColor; |
| 134 cacheBlob.reset(SkSafeRef(fCache->find(key))); | 128 cacheBlob.reset(SkSafeRef(cache->find(key))); |
| 135 } | 129 } |
| 136 | 130 |
| 137 SkScalar transX = 0.f; | 131 SkScalar transX = 0.f; |
| 138 SkScalar transY = 0.f; | 132 SkScalar transY = 0.f; |
| 139 | 133 |
| 140 // Though for the time being runs in the textblob can override the paint, th ey only touch font | 134 // Though for the time being runs in the textblob can override the paint, th ey only touch font |
| 141 // info. | 135 // info. |
| 142 GrPaint grPaint; | 136 GrPaint grPaint; |
| 143 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &grPaint)) { | 137 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { |
| 144 return; | 138 return; |
| 145 } | 139 } |
| 146 | 140 |
| 147 if (cacheBlob) { | 141 if (cacheBlob) { |
| 148 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColo r(), blurRec, | 142 if (cacheBlob->mustRegenerate(&transX, &transY, skPaint, grPaint.getColo r(), blurRec, |
| 149 viewMatrix, x, y)) { | 143 viewMatrix, x, y)) { |
| 150 // We have to remake the blob because changes may invalidate our mas ks. | 144 // We have to remake the blob because changes may invalidate our mas ks. |
| 151 // TODO we could probably get away reuse most of the time if the poi nter is unique, | 145 // TODO we could probably get away reuse most of the time if the poi nter is unique, |
| 152 // but we'd have to clear the subrun information | 146 // but we'd have to clear the subrun information |
| 153 fCache->remove(cacheBlob); | 147 cache->remove(cacheBlob); |
| 154 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint))); | 148 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, sk Paint))); |
| 155 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie wMatrix, props, | 149 this->regenerateTextBlob(cacheBlob, context->getBatchFontCache(), |
| 150 *context->caps()->shaderCaps(), skPaint, gr Paint.getColor(), | |
| 151 viewMatrix, props, | |
| 156 blob, x, y, drawFilter); | 152 blob, x, y, drawFilter); |
| 157 } else { | 153 } else { |
| 158 fCache->makeMRU(cacheBlob); | 154 cache->makeMRU(cacheBlob); |
| 159 | 155 |
| 160 if (CACHE_SANITY_CHECK) { | 156 if (CACHE_SANITY_CHECK) { |
| 161 int glyphCount = 0; | 157 int glyphCount = 0; |
| 162 int runCount = 0; | 158 int runCount = 0; |
| 163 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); | 159 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); |
| 164 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp hCount, runCount)); | 160 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(cache->createBlob(glyph Count, runCount)); |
| 165 sanityBlob->setupKey(key, blurRec, skPaint); | 161 sanityBlob->setupKey(key, blurRec, skPaint); |
| 166 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor() , viewMatrix, props, | 162 this->regenerateTextBlob(sanityBlob, context->getBatchFontCache( ), |
| 163 *context->caps()->shaderCaps(), skPaint , | |
| 164 grPaint.getColor(), viewMatrix, props, | |
| 167 blob, x, y, drawFilter); | 165 blob, x, y, drawFilter); |
| 168 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); | 166 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); |
| 169 } | 167 } |
| 170 } | 168 } |
| 171 } else { | 169 } else { |
| 172 if (canCache) { | 170 if (canCache) { |
| 173 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint))); | 171 cacheBlob.reset(SkRef(cache->createCachedBlob(blob, key, blurRec, sk Paint))); |
| 174 } else { | 172 } else { |
| 175 cacheBlob.reset(fCache->createBlob(blob)); | 173 cacheBlob.reset(cache->createBlob(blob)); |
| 176 } | 174 } |
| 177 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat rix, props, | 175 this->regenerateTextBlob(cacheBlob, context->getBatchFontCache(), |
| 176 *context->caps()->shaderCaps(), skPaint, grPain t.getColor(), | |
| 177 viewMatrix, props, | |
| 178 blob, x, y, drawFilter); | 178 blob, x, y, drawFilter); |
| 179 } | 179 } |
| 180 | 180 |
| 181 cacheBlob->flushCached(fContext, dc, blob, props, fDistanceAdjustTable, skPa int, | 181 cacheBlob->flushCached(context, dc, blob, props, fDistanceAdjustTable, skPai nt, |
| 182 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY); | 182 grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY); |
| 183 } | 183 } |
| 184 | 184 |
| 185 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, | 185 void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, |
| 186 GrBatchFontCache* fontCache, | |
| 187 const GrShaderCaps& shaderCaps, | |
| 186 const SkPaint& skPaint, GrColor colo r, | 188 const SkPaint& skPaint, GrColor colo r, |
| 187 const SkMatrix& viewMatrix, | 189 const SkMatrix& viewMatrix, |
| 188 const SkSurfaceProps& props, | 190 const SkSurfaceProps& props, |
| 189 const SkTextBlob* blob, SkScalar x, SkScalar y, | 191 const SkTextBlob* blob, SkScalar x, SkScalar y, |
| 190 SkDrawFilter* drawFilter) { | 192 SkDrawFilter* drawFilter) { |
| 191 cacheBlob->initReusableBlob(color, viewMatrix, x, y); | 193 cacheBlob->initReusableBlob(color, viewMatrix, x, y); |
| 192 | 194 |
| 193 // Regenerate textblob | 195 // Regenerate textblob |
| 194 SkPaint runPaint = skPaint; | 196 SkPaint runPaint = skPaint; |
| 195 SkTextBlobRunIterator it(blob); | 197 SkTextBlobRunIterator it(blob); |
| 196 for (int run = 0; !it.done(); it.next(), run++) { | 198 for (int run = 0; !it.done(); it.next(), run++) { |
| 197 int glyphCount = it.glyphCount(); | 199 int glyphCount = it.glyphCount(); |
| 198 size_t textLen = glyphCount * sizeof(uint16_t); | 200 size_t textLen = glyphCount * sizeof(uint16_t); |
| 199 const SkPoint& offset = it.offset(); | 201 const SkPoint& offset = it.offset(); |
| 200 // applyFontToPaint() always overwrites the exact same attributes, | 202 // applyFontToPaint() always overwrites the exact same attributes, |
| 201 // so it is safe to not re-seed the paint for this reason. | 203 // so it is safe to not re-seed the paint for this reason. |
| 202 it.applyFontToPaint(&runPaint); | 204 it.applyFontToPaint(&runPaint); |
| 203 | 205 |
| 204 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ e)) { | 206 if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Typ e)) { |
| 205 // A false return from filter() means we should abort the current dr aw. | 207 // A false return from filter() means we should abort the current dr aw. |
| 206 runPaint = skPaint; | 208 runPaint = skPaint; |
| 207 continue; | 209 continue; |
| 208 } | 210 } |
| 209 | 211 |
| 210 runPaint.setFlags(FilterTextFlags(props, runPaint)); | 212 runPaint.setFlags(FilterTextFlags(props, runPaint)); |
| 211 | 213 |
| 212 cacheBlob->push_back_run(run); | 214 cacheBlob->push_back_run(run); |
| 213 | 215 |
| 214 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, | 216 if (GrTextUtils::CanDrawAsDistanceFields(runPaint, viewMatrix, props, sh aderCaps)) { |
| 215 *fContext->caps()->shaderCaps() )) { | |
| 216 switch (it.positioning()) { | 217 switch (it.positioning()) { |
| 217 case SkTextBlob::kDefault_Positioning: { | 218 case SkTextBlob::kDefault_Positioning: { |
| 218 GrTextUtils::DrawDFText(cacheBlob, run, fContext->getBatchFo ntCache(), | 219 GrTextUtils::DrawDFText(cacheBlob, run, fontCache, |
| 219 props, runPaint, color, viewMatrix, | 220 props, runPaint, color, viewMatrix, |
| 220 (const char *)it.glyphs(), textLen, | 221 (const char *)it.glyphs(), textLen, |
| 221 x + offset.x(), y + offset.y()); | 222 x + offset.x(), y + offset.y()); |
| 222 break; | 223 break; |
| 223 } | 224 } |
| 224 case SkTextBlob::kHorizontal_Positioning: { | 225 case SkTextBlob::kHorizontal_Positioning: { |
| 225 SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); | 226 SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); |
| 226 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBatc hFontCache(), | 227 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache, |
| 227 props, runPaint, color, viewMatri x, | 228 props, runPaint, color, viewMatri x, |
| 228 (const char*)it.glyphs(), textLen , it.pos(), | 229 (const char*)it.glyphs(), textLen , it.pos(), |
| 229 1, dfOffset); | 230 1, dfOffset); |
| 230 break; | 231 break; |
| 231 } | 232 } |
| 232 case SkTextBlob::kFull_Positioning: { | 233 case SkTextBlob::kFull_Positioning: { |
| 233 SkPoint dfOffset = SkPoint::Make(x, y); | 234 SkPoint dfOffset = SkPoint::Make(x, y); |
| 234 GrTextUtils::DrawDFPosText(cacheBlob, run, fContext->getBat chFontCache(), | 235 GrTextUtils::DrawDFPosText(cacheBlob, run, fontCache, |
| 235 props, runPaint, color, viewMatri x, | 236 props, runPaint, color, viewMatri x, |
| 236 (const char*)it.glyphs(), textLen , it.pos(), | 237 (const char*)it.glyphs(), textLen , it.pos(), |
| 237 2, dfOffset); | 238 2, dfOffset); |
| 238 break; | 239 break; |
| 239 } | 240 } |
| 240 } | 241 } |
| 241 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { | 242 } else if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { |
| 242 cacheBlob->setRunDrawAsPaths(run); | 243 cacheBlob->setRunDrawAsPaths(run); |
| 243 } else { | 244 } else { |
| 244 switch (it.positioning()) { | 245 switch (it.positioning()) { |
| 245 case SkTextBlob::kDefault_Positioning: | 246 case SkTextBlob::kDefault_Positioning: |
| 246 GrTextUtils::DrawBmpText(cacheBlob, run, fContext->getBatchF ontCache(), | 247 GrTextUtils::DrawBmpText(cacheBlob, run, fontCache, |
| 247 props, runPaint, color, viewMatrix, | 248 props, runPaint, color, viewMatrix, |
| 248 (const char *)it.glyphs(), textLen, | 249 (const char *)it.glyphs(), textLen, |
| 249 x + offset.x(), y + offset.y()); | 250 x + offset.x(), y + offset.y()); |
| 250 break; | 251 break; |
| 251 case SkTextBlob::kHorizontal_Positioning: | 252 case SkTextBlob::kHorizontal_Positioning: |
| 252 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat chFontCache(), | 253 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache, |
| 253 props, runPaint, color, viewMatr ix, | 254 props, runPaint, color, viewMatr ix, |
| 254 (const char*)it.glyphs(), textLe n, it.pos(), 1, | 255 (const char*)it.glyphs(), textLe n, it.pos(), 1, |
| 255 SkPoint::Make(x, y + offset.y()) ); | 256 SkPoint::Make(x, y + offset.y()) ); |
| 256 break; | 257 break; |
| 257 case SkTextBlob::kFull_Positioning: | 258 case SkTextBlob::kFull_Positioning: |
| 258 GrTextUtils::DrawBmpPosText(cacheBlob, run, fContext->getBat chFontCache(), | 259 GrTextUtils::DrawBmpPosText(cacheBlob, run, fontCache, |
| 259 props, runPaint, color, viewMatr ix, | 260 props, runPaint, color, viewMatr ix, |
| 260 (const char*)it.glyphs(), textLe n, it.pos(), 2, | 261 (const char*)it.glyphs(), textLe n, it.pos(), 2, |
| 261 SkPoint::Make(x, y)); | 262 SkPoint::Make(x, y)); |
| 262 break; | 263 break; |
| 263 } | 264 } |
| 264 } | 265 } |
| 265 | 266 |
| 266 if (drawFilter) { | 267 if (drawFilter) { |
| 267 // A draw filter may change the paint arbitrarily, so we must re-see d in this case. | 268 // A draw filter may change the paint arbitrarily, so we must re-see d in this case. |
| 268 runPaint = skPaint; | 269 runPaint = skPaint; |
| 269 } | 270 } |
| 270 } | 271 } |
| 271 } | 272 } |
| 272 | 273 |
|
robertphillips
2016/02/10 19:44:39
can this be static now ?
| |
| 273 inline GrAtlasTextBlob* | 274 inline GrAtlasTextBlob* |
| 274 GrAtlasTextContext::createDrawTextBlob(const GrPaint& paint, | 275 GrAtlasTextContext::createDrawTextBlob(GrTextBlobCache* blobCache, |
| 276 GrBatchFontCache* fontCache, | |
| 277 const GrShaderCaps& shaderCaps, | |
| 278 const GrPaint& paint, | |
| 275 const SkPaint& skPaint, | 279 const SkPaint& skPaint, |
| 276 const SkMatrix& viewMatrix, | 280 const SkMatrix& viewMatrix, |
| 277 const SkSurfaceProps& props, | 281 const SkSurfaceProps& props, |
| 278 const char text[], size_t byteLength, | 282 const char text[], size_t byteLength, |
| 279 SkScalar x, SkScalar y) { | 283 SkScalar x, SkScalar y) { |
| 280 int glyphCount = skPaint.countText(text, byteLength); | 284 int glyphCount = skPaint.countText(text, byteLength); |
| 281 | 285 |
| 282 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); | 286 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1); |
| 283 blob->initThrowawayBlob(viewMatrix, x, y); | 287 blob->initThrowawayBlob(viewMatrix, x, y); |
| 284 | 288 |
| 285 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, | 289 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderC aps)) { |
| 286 *fContext->caps()->shaderCaps())) { | 290 GrTextUtils::DrawDFText(blob, 0, fontCache, props, |
| 287 GrTextUtils::DrawDFText(blob, 0, fContext->getBatchFontCache(), props, | |
| 288 skPaint, paint.getColor(), viewMatrix, text, | 291 skPaint, paint.getColor(), viewMatrix, text, |
| 289 byteLength, x, y); | 292 byteLength, x, y); |
| 290 } else { | 293 } else { |
| 291 GrTextUtils::DrawBmpText(blob, 0, fContext->getBatchFontCache(), props, skPaint, | 294 GrTextUtils::DrawBmpText(blob, 0, fontCache, props, skPaint, |
| 292 paint.getColor(), viewMatrix, text, byteLength, x, y); | 295 paint.getColor(), viewMatrix, text, byteLength, x, y); |
| 293 } | 296 } |
| 294 return blob; | 297 return blob; |
| 295 } | 298 } |
| 296 | 299 |
|
robertphillips
2016/02/10 19:44:39
this too ?
| |
| 297 inline GrAtlasTextBlob* | 300 inline GrAtlasTextBlob* |
| 298 GrAtlasTextContext::createDrawPosTextBlob(const GrPaint& paint, const SkPaint& s kPaint, | 301 GrAtlasTextContext::createDrawPosTextBlob(GrTextBlobCache* blobCache, GrBatchFon tCache* fontCache, |
| 302 const GrShaderCaps& shaderCaps, const GrPaint& paint, | |
| 303 const SkPaint& skPaint, | |
| 299 const SkMatrix& viewMatrix, const SkSu rfaceProps& props, | 304 const SkMatrix& viewMatrix, const SkSu rfaceProps& props, |
| 300 const char text[], size_t byteLength, | 305 const char text[], size_t byteLength, |
| 301 const SkScalar pos[], int scalarsPerPo sition, | 306 const SkScalar pos[], int scalarsPerPo sition, |
| 302 const SkPoint& offset) { | 307 const SkPoint& offset) { |
| 303 int glyphCount = skPaint.countText(text, byteLength); | 308 int glyphCount = skPaint.countText(text, byteLength); |
| 304 | 309 |
| 305 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1); | 310 GrAtlasTextBlob* blob = blobCache->createBlob(glyphCount, 1); |
| 306 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); | 311 blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); |
| 307 | 312 |
| 308 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, | 313 if (GrTextUtils::CanDrawAsDistanceFields(skPaint, viewMatrix, props, shaderC aps)) { |
| 309 *fContext->caps()->shaderCaps())) { | 314 GrTextUtils::DrawDFPosText(blob, 0, fontCache, props, |
| 310 GrTextUtils::DrawDFPosText(blob, 0, fContext->getBatchFontCache(), props , | |
| 311 skPaint, paint.getColor(), viewMatrix, text, | 315 skPaint, paint.getColor(), viewMatrix, text, |
| 312 byteLength, pos, scalarsPerPosition, offset); | 316 byteLength, pos, scalarsPerPosition, offset); |
| 313 } else { | 317 } else { |
| 314 GrTextUtils::DrawBmpPosText(blob, 0, fContext->getBatchFontCache(), prop s, skPaint, | 318 GrTextUtils::DrawBmpPosText(blob, 0, fontCache, props, skPaint, |
| 315 paint.getColor(), viewMatrix, text, | 319 paint.getColor(), viewMatrix, text, |
| 316 byteLength, pos, scalarsPerPosition, offset) ; | 320 byteLength, pos, scalarsPerPosition, offset) ; |
| 317 } | 321 } |
| 318 return blob; | 322 return blob; |
| 319 } | 323 } |
| 320 | 324 |
| 321 void GrAtlasTextContext::drawText(GrDrawContext* dc, | 325 void GrAtlasTextContext::drawText(GrContext* context, |
| 326 GrDrawContext* dc, | |
| 322 const GrClip& clip, | 327 const GrClip& clip, |
| 323 const GrPaint& paint, const SkPaint& skPaint, | 328 const GrPaint& paint, const SkPaint& skPaint, |
| 324 const SkMatrix& viewMatrix, | 329 const SkMatrix& viewMatrix, |
| 325 const SkSurfaceProps& props, | 330 const SkSurfaceProps& props, |
| 326 const char text[], size_t byteLength, | 331 const char text[], size_t byteLength, |
| 327 SkScalar x, SkScalar y, const SkIRect& regionC lipBounds) { | 332 SkScalar x, SkScalar y, const SkIRect& regionC lipBounds) { |
|
robertphillips
2016/02/10 19:44:39
These are already guarded against abandonment in t
| |
| 328 if (fContext->abandoned()) { | 333 if (context->abandoned()) { |
| 329 return; | 334 return; |
| 330 } else if (this->canDraw(skPaint, viewMatrix, props)) { | 335 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shade rCaps())) { |
| 331 SkAutoTUnref<GrAtlasTextBlob> blob( | 336 SkAutoTUnref<GrAtlasTextBlob> blob( |
| 332 this->createDrawTextBlob(paint, skPaint, viewMatrix, props, text, by teLength, x, y)); | 337 this->createDrawTextBlob(context->getTextBlobCache(), context->getBa tchFontCache(), |
| 333 blob->flushThrowaway(fContext, dc, props, fDistanceAdjustTable, skPaint, paint, | 338 *context->caps()->shaderCaps(), |
| 339 paint, skPaint, | |
| 340 viewMatrix, props, | |
| 341 text, byteLength, x, y)); | |
| 342 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint, | |
| 334 clip, regionClipBounds); | 343 clip, regionClipBounds); |
| 335 return; | 344 return; |
| 336 } | 345 } |
| 337 | 346 |
| 338 // fall back to drawing as a path | 347 // fall back to drawing as a path |
| 339 GrTextUtils::DrawTextAsPath(fContext, dc, clip, skPaint, viewMatrix, text, b yteLength, x, y, | 348 GrTextUtils::DrawTextAsPath(context, dc, clip, skPaint, viewMatrix, text, by teLength, x, y, |
| 340 regionClipBounds); | 349 regionClipBounds); |
| 341 } | 350 } |
| 342 | 351 |
| 343 void GrAtlasTextContext::drawPosText(GrDrawContext* dc, | 352 void GrAtlasTextContext::drawPosText(GrContext* context, |
| 353 GrDrawContext* dc, | |
| 344 const GrClip& clip, | 354 const GrClip& clip, |
| 345 const GrPaint& paint, const SkPaint& skPain t, | 355 const GrPaint& paint, const SkPaint& skPain t, |
| 346 const SkMatrix& viewMatrix, | 356 const SkMatrix& viewMatrix, |
| 347 const SkSurfaceProps& props, | 357 const SkSurfaceProps& props, |
| 348 const char text[], size_t byteLength, | 358 const char text[], size_t byteLength, |
| 349 const SkScalar pos[], int scalarsPerPositio n, | 359 const SkScalar pos[], int scalarsPerPositio n, |
| 350 const SkPoint& offset, const SkIRect& regio nClipBounds) { | 360 const SkPoint& offset, const SkIRect& regio nClipBounds) { |
|
robertphillips
2016/02/10 19:44:39
same
| |
| 351 if (fContext->abandoned()) { | 361 if (context->abandoned()) { |
| 352 return; | 362 return; |
| 353 } else if (this->canDraw(skPaint, viewMatrix, props)) { | 363 } else if (this->canDraw(skPaint, viewMatrix, props, *context->caps()->shade rCaps())) { |
| 354 SkAutoTUnref<GrAtlasTextBlob> blob( | 364 SkAutoTUnref<GrAtlasTextBlob> blob( |
| 355 this->createDrawPosTextBlob(paint, skPaint, viewMatrix, props, | 365 this->createDrawPosTextBlob(context->getTextBlobCache(), |
| 366 context->getBatchFontCache(), | |
| 367 *context->caps()->shaderCaps(), | |
| 368 paint, skPaint, viewMatrix, props, | |
| 356 text, byteLength, | 369 text, byteLength, |
| 357 pos, scalarsPerPosition, | 370 pos, scalarsPerPosition, |
| 358 offset)); | 371 offset)); |
| 359 blob->flushThrowaway(fContext, dc, props, fDistanceAdjustTable, skPaint, paint, | 372 blob->flushThrowaway(context, dc, props, fDistanceAdjustTable, skPaint, paint, |
| 360 clip, regionClipBounds); | 373 clip, regionClipBounds); |
| 361 return; | 374 return; |
| 362 } | 375 } |
| 363 | 376 |
| 364 // fall back to drawing as a path | 377 // fall back to drawing as a path |
| 365 GrTextUtils::DrawPosTextAsPath(fContext, dc, props, clip, skPaint, viewMatri x, text, | 378 GrTextUtils::DrawPosTextAsPath(context, dc, props, clip, skPaint, viewMatrix , text, |
| 366 byteLength, pos, scalarsPerPosition, offset, regionClipBounds); | 379 byteLength, pos, scalarsPerPosition, offset, regionClipBounds); |
| 367 } | 380 } |
| 368 | 381 |
| 369 //////////////////////////////////////////////////////////////////////////////// /////////////////// | 382 //////////////////////////////////////////////////////////////////////////////// /////////////////// |
| 370 | 383 |
| 371 #ifdef GR_TEST_UTILS | 384 #ifdef GR_TEST_UTILS |
| 372 | 385 |
| 373 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { | 386 DRAW_BATCH_TEST_DEFINE(TextBlobBatch) { |
| 374 static uint32_t gContextID = SK_InvalidGenID; | 387 static uint32_t gContextID = SK_InvalidGenID; |
| 375 static GrAtlasTextContext* gTextContext = nullptr; | 388 static GrAtlasTextContext* gTextContext = nullptr; |
| 376 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType ); | 389 static SkSurfaceProps gSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType ); |
| 377 | 390 |
| 378 if (context->uniqueID() != gContextID) { | 391 if (context->uniqueID() != gContextID) { |
| 379 gContextID = context->uniqueID(); | 392 gContextID = context->uniqueID(); |
| 380 delete gTextContext; | 393 delete gTextContext; |
| 381 | 394 |
| 382 // We don't yet test the fall back to paths in the GrTextContext base cl ass. This is mostly | 395 // We don't yet test the fall back to paths in the GrTextContext base cl ass. This is mostly |
| 383 // because we don't really want to have a gpu device here. | 396 // because we don't really want to have a gpu device here. |
| 384 // We enable distance fields by twiddling a knob on the paint | 397 // We enable distance fields by twiddling a knob on the paint |
| 385 gTextContext = GrAtlasTextContext::Create(context); | 398 gTextContext = GrAtlasTextContext::Create(); |
| 386 } | 399 } |
| 387 | 400 |
| 388 // Setup dummy SkPaint / GrPaint | 401 // Setup dummy SkPaint / GrPaint |
| 389 GrColor color = GrRandomColor(random); | 402 GrColor color = GrRandomColor(random); |
| 390 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); | 403 SkMatrix viewMatrix = GrTest::TestMatrixInvertible(random); |
| 391 SkPaint skPaint; | 404 SkPaint skPaint; |
| 392 skPaint.setColor(color); | 405 skPaint.setColor(color); |
| 393 skPaint.setLCDRenderText(random->nextBool()); | 406 skPaint.setLCDRenderText(random->nextBool()); |
| 394 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); | 407 skPaint.setAntiAlias(skPaint.isLCDRenderText() ? true : random->nextBool()); |
| 395 skPaint.setSubpixelText(random->nextBool()); | 408 skPaint.setSubpixelText(random->nextBool()); |
| 396 | 409 |
| 397 GrPaint grPaint; | 410 GrPaint grPaint; |
| 398 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { | 411 if (!SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)) { |
| 399 SkFAIL("couldn't convert paint\n"); | 412 SkFAIL("couldn't convert paint\n"); |
| 400 } | 413 } |
| 401 | 414 |
| 402 const char* text = "The quick brown fox jumps over the lazy dog."; | 415 const char* text = "The quick brown fox jumps over the lazy dog."; |
| 403 int textLen = (int)strlen(text); | 416 int textLen = (int)strlen(text); |
| 404 | 417 |
| 405 // Setup clip | 418 // Setup clip |
| 406 GrClip clip; | 419 GrClip clip; |
| 407 | 420 |
| 408 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only | 421 // right now we don't handle textblobs, nor do we handle drawPosText. Since we only |
| 409 // intend to test the batch with this unit test, that is okay. | 422 // intend to test the batch with this unit test, that is okay. |
| 410 SkAutoTUnref<GrAtlasTextBlob> blob( | 423 SkAutoTUnref<GrAtlasTextBlob> blob( |
| 411 gTextContext->createDrawTextBlob(grPaint, skPaint, viewMatrix, gSurf aceProps, text, | 424 gTextContext->createDrawTextBlob(context->getTextBlobCache(), |
| 425 context->getBatchFontCache(), | |
| 426 *context->caps()->shaderCaps(), grP aint, skPaint, | |
| 427 viewMatrix, | |
| 428 gSurfaceProps, text, | |
| 412 static_cast<size_t>(textLen), 0, 0) ); | 429 static_cast<size_t>(textLen), 0, 0) ); |
| 413 | 430 |
| 414 // We'd like to be able to test this with random translations, but currently the vertex | 431 // We'd like to be able to test this with random translations, but currently the vertex |
| 415 // bounds and vertices will get out of sync | 432 // bounds and vertices will get out of sync |
| 416 SkScalar transX = 0.f;//SkIntToScalar(random->nextU()); | 433 SkScalar transX = 0.f;//SkIntToScalar(random->nextU()); |
| 417 SkScalar transY = 0.f;//SkIntToScalar(random->nextU()); | 434 SkScalar transY = 0.f;//SkIntToScalar(random->nextU()); |
| 418 return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint, | 435 return blob->test_createBatch(textLen, 0, 0, color, transX, transY, skPaint, |
| 419 gSurfaceProps, gTextContext->dfAdjustTable(), | 436 gSurfaceProps, gTextContext->dfAdjustTable(), |
| 420 context->getBatchFontCache()); | 437 context->getBatchFontCache()); |
| 421 } | 438 } |
| 422 | 439 |
| 423 #endif | 440 #endif |
| OLD | NEW |