| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "GrStencilAndCoverTextContext.h" | 8 #include "GrStencilAndCoverTextContext.h" |
| 9 #include "GrAtlasTextContext.h" | 9 #include "GrAtlasTextContext.h" |
| 10 #include "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 const GrClip& clip, | 74 const GrClip& clip, |
| 75 const GrPaint& paint, | 75 const GrPaint& paint, |
| 76 const SkPaint& skPaint, | 76 const SkPaint& skPaint, |
| 77 const SkMatrix& viewMatrix, | 77 const SkMatrix& viewMatrix, |
| 78 const char text[], | 78 const char text[], |
| 79 size_t byteLength, | 79 size_t byteLength, |
| 80 SkScalar x, SkScalar y, | 80 SkScalar x, SkScalar y, |
| 81 const SkIRect& clipBounds) { | 81 const SkIRect& clipBounds) { |
| 82 TextRun run(skPaint); | 82 TextRun run(skPaint); |
| 83 GrPipelineBuilder pipelineBuilder(paint, rt, clip); | 83 GrPipelineBuilder pipelineBuilder(paint, rt, clip); |
| 84 run.setText(text, byteLength, x, y, fContext, &fSurfaceProps); | 84 run.setText(text, byteLength, x, y); |
| 85 run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBound
s, | 85 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0,
clipBounds, |
| 86 fFallbackTextContext, skPaint); | 86 fFallbackTextContext, skPaint); |
| 87 } | 87 } |
| 88 | 88 |
| 89 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
et* rt, | 89 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg
et* rt, |
| 90 const GrClip& clip, | 90 const GrClip& clip, |
| 91 const GrPaint& paint, | 91 const GrPaint& paint, |
| 92 const SkPaint& skPaint, | 92 const SkPaint& skPaint, |
| 93 const SkMatrix& viewMatrix, | 93 const SkMatrix& viewMatrix, |
| 94 const char text[], | 94 const char text[], |
| 95 size_t byteLength, | 95 size_t byteLength, |
| 96 const SkScalar pos[], | 96 const SkScalar pos[], |
| 97 int scalarsPerPosition, | 97 int scalarsPerPosition, |
| 98 const SkPoint& offset, | 98 const SkPoint& offset, |
| 99 const SkIRect& clipBounds) { | 99 const SkIRect& clipBounds) { |
| 100 TextRun run(skPaint); | 100 TextRun run(skPaint); |
| 101 GrPipelineBuilder pipelineBuilder(paint, rt, clip); | 101 GrPipelineBuilder pipelineBuilder(paint, rt, clip); |
| 102 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext,
&fSurfaceProps); | 102 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset); |
| 103 run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBound
s, | 103 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0,
clipBounds, |
| 104 fFallbackTextContext, skPaint); | 104 fFallbackTextContext, skPaint); |
| 105 } | 105 } |
| 106 | 106 |
| 107 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarge
t* rt, | 107 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarge
t* rt, |
| 108 const GrClip& clip, const SkPain
t& skPaint, | 108 const GrClip& clip, const SkPain
t& skPaint, |
| 109 const SkMatrix& viewMatrix, | 109 const SkMatrix& viewMatrix, |
| 110 const SkTextBlob* skBlob, SkScal
ar x, SkScalar y, | 110 const SkTextBlob* skBlob, SkScal
ar x, SkScalar y, |
| 111 SkDrawFilter* drawFilter, | 111 SkDrawFilter* drawFilter, |
| 112 const SkIRect& clipBounds) { | 112 const SkIRect& clipBounds) { |
| 113 if (!this->internalCanDraw(skPaint)) { | 113 if (!this->internalCanDraw(skPaint)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 130 GrPaint paint; | 130 GrPaint paint; |
| 131 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) { | 131 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) { |
| 132 return; | 132 return; |
| 133 } | 133 } |
| 134 | 134 |
| 135 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); | 135 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); |
| 136 GrPipelineBuilder pipelineBuilder(paint, rt, clip); | 136 GrPipelineBuilder pipelineBuilder(paint, rt, clip); |
| 137 | 137 |
| 138 TextBlob::Iter iter(blob); | 138 TextBlob::Iter iter(blob); |
| 139 for (TextRun* run = iter.get(); run; run = iter.next()) { | 139 for (TextRun* run = iter.get(); run; run = iter.next()) { |
| 140 run->draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clip
Bounds, | 140 run->draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix,
x, y, clipBounds, |
| 141 fFallbackTextContext, skPaint); | 141 fFallbackTextContext, skPaint); |
| 142 run->releaseGlyphCache(); |
| 142 } | 143 } |
| 143 } | 144 } |
| 144 | 145 |
| 145 const GrStencilAndCoverTextContext::TextBlob& | 146 const GrStencilAndCoverTextContext::TextBlob& |
| 146 GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, | 147 GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, |
| 147 const SkPaint& skPaint) { | 148 const SkPaint& skPaint) { |
| 148 // The font-related parameters are baked into the text blob and will overrid
e this skPaint, so | 149 // The font-related parameters are baked into the text blob and will overrid
e this skPaint, so |
| 149 // the only remaining properties that can affect a TextBlob are the ones rel
ated to stroke. | 150 // the only remaining properties that can affect a TextBlob are the ones rel
ated to stroke. |
| 150 if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path. | 151 if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path. |
| 151 if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) { | 152 if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) { |
| 152 fLRUList.remove(*found); | 153 fLRUList.remove(*found); |
| 153 fLRUList.addToTail(*found); | 154 fLRUList.addToTail(*found); |
| 154 return **found; | 155 return **found; |
| 155 } | 156 } |
| 156 TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint, fCont
ext, | 157 TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint); |
| 157 &fSurfaceProps); | |
| 158 this->purgeToFit(*blob); | 158 this->purgeToFit(*blob); |
| 159 fBlobIdCache.set(skBlob->uniqueID(), blob); | 159 fBlobIdCache.set(skBlob->uniqueID(), blob); |
| 160 fLRUList.addToTail(blob); | 160 fLRUList.addToTail(blob); |
| 161 fCacheSize += blob->cpuMemorySize(); | 161 fCacheSize += blob->cpuMemorySize(); |
| 162 return *blob; | 162 return *blob; |
| 163 } else { | 163 } else { |
| 164 GrStrokeInfo stroke(skPaint); | 164 GrStrokeInfo stroke(skPaint); |
| 165 SkSTArray<4, uint32_t, true> key; | 165 SkSTArray<4, uint32_t, true> key; |
| 166 key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt()); | 166 key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt()); |
| 167 key[0] = skBlob->uniqueID(); | 167 key[0] = skBlob->uniqueID(); |
| 168 stroke.asUniqueKeyFragment(&key[1]); | 168 stroke.asUniqueKeyFragment(&key[1]); |
| 169 if (TextBlob** found = fBlobKeyCache.find(key)) { | 169 if (TextBlob** found = fBlobKeyCache.find(key)) { |
| 170 fLRUList.remove(*found); | 170 fLRUList.remove(*found); |
| 171 fLRUList.addToTail(*found); | 171 fLRUList.addToTail(*found); |
| 172 return **found; | 172 return **found; |
| 173 } | 173 } |
| 174 TextBlob* blob = new TextBlob(key, skBlob, skPaint, fContext, &fSurfaceP
rops); | 174 TextBlob* blob = new TextBlob(key, skBlob, skPaint); |
| 175 this->purgeToFit(*blob); | 175 this->purgeToFit(*blob); |
| 176 fBlobKeyCache.set(blob); | 176 fBlobKeyCache.set(blob); |
| 177 fLRUList.addToTail(blob); | 177 fLRUList.addToTail(blob); |
| 178 fCacheSize += blob->cpuMemorySize(); | 178 fCacheSize += blob->cpuMemorySize(); |
| 179 return *blob; | 179 return *blob; |
| 180 } | 180 } |
| 181 } | 181 } |
| 182 | 182 |
| 183 void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) { | 183 void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) { |
| 184 static const int maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for cac
hing text blobs. | 184 static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for
caching text blobs. |
| 185 | 185 |
| 186 int maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize(); | 186 size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize(); |
| 187 while (fCacheSize && fCacheSize > maxSizeForNewBlob) { | 187 while (fCacheSize && fCacheSize > maxSizeForNewBlob) { |
| 188 TextBlob* lru = fLRUList.head(); | 188 TextBlob* lru = fLRUList.head(); |
| 189 if (1 == lru->key().count()) { | 189 if (1 == lru->key().count()) { |
| 190 // 1-length keys are unterstood to be the blob id. | 190 // 1-length keys are unterstood to be the blob id. |
| 191 fBlobIdCache.remove(lru->key()[0]); | 191 fBlobIdCache.remove(lru->key()[0]); |
| 192 } else { | 192 } else { |
| 193 fBlobKeyCache.remove(lru->key()); | 193 fBlobKeyCache.remove(lru->key()); |
| 194 } | 194 } |
| 195 fLRUList.remove(lru); | 195 fLRUList.remove(lru); |
| 196 fCacheSize -= lru->cpuMemorySize(); | 196 fCacheSize -= lru->cpuMemorySize(); |
| 197 delete lru; | 197 delete lru; |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 201 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 202 | 202 |
| 203 void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, cons
t SkPaint& skPaint, | 203 void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, |
| 204 GrContext* ctx, const SkSurfac
eProps* props) { | 204 const SkPaint& skPaint) { |
| 205 fCpuMemorySize = sizeof(TextBlob); | 205 fCpuMemorySize = sizeof(TextBlob); |
| 206 SkPaint runPaint(skPaint); | 206 SkPaint runPaint(skPaint); |
| 207 for (SkTextBlob::RunIterator iter(skBlob); !iter.done(); iter.next()) { | 207 for (SkTextBlob::RunIterator iter(skBlob); !iter.done(); iter.next()) { |
| 208 iter.applyFontToPaint(&runPaint); // No need to re-seed the paint. | 208 iter.applyFontToPaint(&runPaint); // No need to re-seed the paint. |
| 209 TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint)); | 209 TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint)); |
| 210 | 210 |
| 211 const char* text = reinterpret_cast<const char*>(iter.glyphs()); | 211 const char* text = reinterpret_cast<const char*>(iter.glyphs()); |
| 212 size_t byteLength = sizeof(uint16_t) * iter.glyphCount(); | 212 size_t byteLength = sizeof(uint16_t) * iter.glyphCount(); |
| 213 const SkPoint& runOffset = iter.offset(); | 213 const SkPoint& runOffset = iter.offset(); |
| 214 | 214 |
| 215 switch (iter.positioning()) { | 215 switch (iter.positioning()) { |
| 216 case SkTextBlob::kDefault_Positioning: | 216 case SkTextBlob::kDefault_Positioning: |
| 217 run->setText(text, byteLength, runOffset.fX, runOffset.fY, ctx,
props); | 217 run->setText(text, byteLength, runOffset.fX, runOffset.fY); |
| 218 break; | 218 break; |
| 219 case SkTextBlob::kHorizontal_Positioning: | 219 case SkTextBlob::kHorizontal_Positioning: |
| 220 run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0
, runOffset.fY), | 220 run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0
, runOffset.fY)); |
| 221 ctx, props); | |
| 222 break; | 221 break; |
| 223 case SkTextBlob::kFull_Positioning: | 222 case SkTextBlob::kFull_Positioning: |
| 224 run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0
, 0), ctx, props); | 223 run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0
, 0)); |
| 225 break; | 224 break; |
| 226 } | 225 } |
| 227 | 226 |
| 228 fCpuMemorySize += run->cpuMemorySize(); | 227 fCpuMemorySize += run->computeSizeInCache(); |
| 229 } | 228 } |
| 230 } | 229 } |
| 231 | 230 |
| 232 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 231 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 233 | 232 |
| 234 class GrStencilAndCoverTextContext::FallbackBlobBuilder { | 233 class GrStencilAndCoverTextContext::FallbackBlobBuilder { |
| 235 public: | 234 public: |
| 236 FallbackBlobBuilder() : fBuffIdx(0) {} | 235 FallbackBlobBuilder() : fBuffIdx(0) {} |
| 237 | 236 |
| 238 bool isInitialized() const { return SkToBool(fBuilder); } | 237 bool isInitialized() const { return SkToBool(fBuilder); } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 253 int fBuffIdx; | 252 int fBuffIdx; |
| 254 uint16_t fGlyphIds[kWriteBufferSize]; | 253 uint16_t fGlyphIds[kWriteBufferSize]; |
| 255 SkPoint fPositions[kWriteBufferSize]; | 254 SkPoint fPositions[kWriteBufferSize]; |
| 256 }; | 255 }; |
| 257 | 256 |
| 258 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 257 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 259 | 258 |
| 260 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) | 259 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) |
| 261 : fStroke(fontAndStroke), | 260 : fStroke(fontAndStroke), |
| 262 fFont(fontAndStroke), | 261 fFont(fontAndStroke), |
| 263 fTotalGlyphCount(0) { | 262 fTotalGlyphCount(0), |
| 263 fDetachedGlyphCache(nullptr), |
| 264 fLastDrawnGlyphsID(SK_InvalidUniqueID) { |
| 264 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. | 265 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. |
| 265 | 266 |
| 266 // Setting to "fill" ensures that no strokes get baked into font outlines. (
We use the GPU path | 267 // Setting to "fill" ensures that no strokes get baked into font outlines. (
We use the GPU path |
| 267 // rendering API for stroking). | 268 // rendering API for stroking). |
| 268 fFont.setStyle(SkPaint::kFill_Style); | 269 fFont.setStyle(SkPaint::kFill_Style); |
| 269 | 270 |
| 270 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle
()) { | 271 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle
()) { |
| 271 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. | 272 // Instead of letting fake bold get baked into the glyph outlines, do it
with GPU stroke. |
| 272 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(), | 273 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(), |
| 273 kStdFakeBoldInterpKeys, | 274 kStdFakeBoldInterpKeys, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 300 | 301 |
| 301 fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() && | 302 fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() && |
| 302 0 == fFont.getTextSkewX() && | 303 0 == fFont.getTextSkewX() && |
| 303 !fFont.isFakeBoldText() && | 304 !fFont.isFakeBoldText() && |
| 304 !fFont.isVerticalText(); | 305 !fFont.isVerticalText(); |
| 305 } else { | 306 } else { |
| 306 fTextRatio = fTextInverseRatio = 1.0f; | 307 fTextRatio = fTextInverseRatio = 1.0f; |
| 307 fUsingRawGlyphPaths = false; | 308 fUsingRawGlyphPaths = false; |
| 308 } | 309 } |
| 309 | 310 |
| 311 // Generate the key that will be used to cache the GPU glyph path objects. |
| 312 if (fUsingRawGlyphPaths && fStroke.isFillStyle()) { |
| 313 static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::
GenerateDomain(); |
| 314 |
| 315 const SkTypeface* typeface = fFont.getTypeface(); |
| 316 GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1
); |
| 317 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID(
) : 0; |
| 318 } else { |
| 319 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::Generat
eDomain(); |
| 320 |
| 321 int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt(); |
| 322 if (fUsingRawGlyphPaths) { |
| 323 const SkTypeface* typeface = fFont.getTypeface(); |
| 324 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 +
strokeDataCount); |
| 325 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; |
| 326 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount; |
| 327 fStroke.asUniqueKeyFragment(&builder[2]); |
| 328 } else { |
| 329 SkGlyphCache* glyphCache = this->getGlyphCache(); |
| 330 const SkTypeface* typeface = glyphCache->getScalerContext()->getType
face(); |
| 331 const SkDescriptor* desc = &glyphCache->getDescriptor(); |
| 332 int descDataCount = (desc->getLength() + 3) / 4; |
| 333 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, |
| 334 2 + strokeDataCount + descDataCount); |
| 335 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu
eID() : 0; |
| 336 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDat
aCount << 16); |
| 337 fStroke.asUniqueKeyFragment(&builder[2]); |
| 338 memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); |
| 339 } |
| 340 } |
| 341 |
| 310 // When drawing from canonically sized paths, the actual local coords are fT
extRatio * coords. | 342 // When drawing from canonically sized paths, the actual local coords are fT
extRatio * coords. |
| 311 fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); | 343 fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); |
| 312 } | 344 } |
| 313 | 345 |
| 314 GrStencilAndCoverTextContext::TextRun::~TextRun() { | 346 GrStencilAndCoverTextContext::TextRun::~TextRun() { |
| 347 this->releaseGlyphCache(); |
| 315 } | 348 } |
| 316 | 349 |
| 317 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, | 350 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by
teLength, |
| 318 SkScalar x, SkScalar y, GrCo
ntext* ctx, | 351 SkScalar x, SkScalar y) { |
| 319 const SkSurfaceProps* surfac
eProps) { | |
| 320 SkASSERT(byteLength == 0 || text != nullptr); | 352 SkASSERT(byteLength == 0 || text != nullptr); |
| 321 | 353 |
| 322 SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr); | 354 SkGlyphCache* glyphCache = this->getGlyphCache(); |
| 323 SkGlyphCache* glyphCache = autoGlyphCache.getCache(); | 355 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); |
| 324 | 356 |
| 325 fTotalGlyphCount = fFont.countText(text, byteLength); | 357 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor
mType, |
| 326 fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache), | 358 fTotalGlyphCount = fFont.countText(text,
byteLength))); |
| 327 GrPathRendering::kTranslate_PathTransfor
mType, | |
| 328 fTotalGlyphCount)); | |
| 329 | |
| 330 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | |
| 331 | 359 |
| 332 const char* stop = text + byteLength; | 360 const char* stop = text + byteLength; |
| 333 | 361 |
| 334 // Measure first if needed. | 362 // Measure first if needed. |
| 335 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { | 363 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { |
| 336 SkFixed stopX = 0; | 364 SkFixed stopX = 0; |
| 337 SkFixed stopY = 0; | 365 SkFixed stopY = 0; |
| 338 | 366 |
| 339 const char* textPtr = text; | 367 const char* textPtr = text; |
| 340 while (textPtr < stop) { | 368 while (textPtr < stop) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 371 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); | 399 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); |
| 372 if (glyph.fWidth) { | 400 if (glyph.fWidth) { |
| 373 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy)), | 401 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT
oScalar(fy)), |
| 374 &fallback); | 402 &fallback); |
| 375 } | 403 } |
| 376 | 404 |
| 377 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); | 405 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); |
| 378 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); | 406 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); |
| 379 } | 407 } |
| 380 | 408 |
| 381 fDraw->loadGlyphPathsIfNeeded(); | |
| 382 | |
| 383 fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 409 fFallbackTextBlob.reset(fallback.buildIfInitialized()); |
| 384 } | 410 } |
| 385 | 411 |
| 386 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, | 412 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t
byteLength, |
| 387 const SkScalar pos[], int
scalarsPerPosition, | 413 const SkScalar pos[], int
scalarsPerPosition, |
| 388 const SkPoint& offset, Gr
Context* ctx, | 414 const SkPoint& offset) { |
| 389 const SkSurfaceProps* sur
faceProps) { | |
| 390 SkASSERT(byteLength == 0 || text != nullptr); | 415 SkASSERT(byteLength == 0 || text != nullptr); |
| 391 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); | 416 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); |
| 392 | 417 |
| 393 SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr); | 418 SkGlyphCache* glyphCache = this->getGlyphCache(); |
| 394 SkGlyphCache* glyphCache = autoGlyphCache.getCache(); | 419 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); |
| 395 | 420 |
| 396 fTotalGlyphCount = fFont.countText(text, byteLength); | 421 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor
mType, |
| 397 fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache), | 422 fTotalGlyphCount = fFont.countText(text,
byteLength))); |
| 398 GrPathRendering::kTranslate_PathTransfor
mType, | |
| 399 fTotalGlyphCount)); | |
| 400 | |
| 401 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | |
| 402 | 423 |
| 403 const char* stop = text + byteLength; | 424 const char* stop = text + byteLength; |
| 404 | 425 |
| 405 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); | 426 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); |
| 406 SkTextAlignProc alignProc(fFont.getTextAlign()); | 427 SkTextAlignProc alignProc(fFont.getTextAlign()); |
| 407 FallbackBlobBuilder fallback; | 428 FallbackBlobBuilder fallback; |
| 408 while (text < stop) { | 429 while (text < stop) { |
| 409 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0); | 430 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0); |
| 410 if (glyph.fWidth) { | 431 if (glyph.fWidth) { |
| 411 SkPoint tmsLoc; | 432 SkPoint tmsLoc; |
| 412 tmsProc(pos, &tmsLoc); | 433 tmsProc(pos, &tmsLoc); |
| 413 SkPoint loc; | 434 SkPoint loc; |
| 414 alignProc(tmsLoc, glyph, &loc); | 435 alignProc(tmsLoc, glyph, &loc); |
| 415 | 436 |
| 416 this->appendGlyph(glyph, loc, &fallback); | 437 this->appendGlyph(glyph, loc, &fallback); |
| 417 } | 438 } |
| 418 pos += scalarsPerPosition; | 439 pos += scalarsPerPosition; |
| 419 } | 440 } |
| 420 | 441 |
| 421 fDraw->loadGlyphPathsIfNeeded(); | |
| 422 | |
| 423 fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 442 fFallbackTextBlob.reset(fallback.buildIfInitialized()); |
| 424 } | 443 } |
| 425 | 444 |
| 426 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx, | 445 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx)
const { |
| 427 SkGlyphCache* g
lyphCache) { | 446 GrPathRange* glyphs = static_cast<GrPathRange*>( |
| 428 SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface() | 447 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe
y)); |
| 429 : glyphCache->getScalerContext()-
>getTypeface(); | 448 if (nullptr == glyphs) { |
| 430 const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getD
escriptor(); | 449 if (fUsingRawGlyphPaths) { |
| 431 | 450 glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(),
nullptr, fStroke); |
| 432 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDom
ain(); | 451 } else { |
| 433 int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt(); | 452 SkGlyphCache* cache = this->getGlyphCache(); |
| 434 GrUniqueKey glyphKey; | 453 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte
xt()->getTypeface(), |
| 435 GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCoun
t); | 454 &cache->getDescriptor
(), |
| 436 reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0; | 455 fStroke); |
| 437 reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() :
0; | 456 } |
| 438 if (strokeDataCount > 0) { | 457 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph
s); |
| 439 fStroke.asUniqueKeyFragment(&builder[2]); | |
| 440 } | 458 } |
| 441 builder.finish(); | 459 return glyphs; |
| 442 | |
| 443 SkAutoTUnref<GrPathRange> glyphs( | |
| 444 static_cast<GrPathRange*>( | |
| 445 ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey))); | |
| 446 if (nullptr == glyphs) { | |
| 447 glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStro
ke)); | |
| 448 ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs); | |
| 449 } else { | |
| 450 SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc)); | |
| 451 } | |
| 452 | |
| 453 return glyphs.detach(); | |
| 454 } | 460 } |
| 455 | 461 |
| 456 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl
yph, | 462 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl
yph, |
| 457 const SkPoint& po
s, | 463 const SkPoint& po
s, |
| 458 FallbackBlobBuild
er* fallback) { | 464 FallbackBlobBuild
er* fallback) { |
| 459 // Stick the glyphs we can't draw into the fallback text blob. | 465 // Stick the glyphs we can't draw into the fallback text blob. |
| 460 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { | 466 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { |
| 461 if (!fallback->isInitialized()) { | 467 if (!fallback->isInitialized()) { |
| 462 fallback->init(fFont, fTextRatio); | 468 fallback->init(fFont, fTextRatio); |
| 463 } | 469 } |
| 464 fallback->appendGlyph(glyph.getGlyphID(), pos); | 470 fallback->appendGlyph(glyph.getGlyphID(), pos); |
| 465 } else { | 471 } else { |
| 466 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p
os.y() }; | 472 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p
os.y() }; |
| 467 fDraw->append(glyph.getGlyphID(), translate); | 473 fDraw->append(glyph.getGlyphID(), translate); |
| 468 } | 474 } |
| 469 } | 475 } |
| 470 | 476 |
| 471 void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc, | 477 void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, |
| 478 GrDrawContext* dc, |
| 472 GrPipelineBuilder* pipelineBuil
der, | 479 GrPipelineBuilder* pipelineBuil
der, |
| 473 GrColor color, | 480 GrColor color, |
| 474 const SkMatrix& viewMatrix, | 481 const SkMatrix& viewMatrix, |
| 475 SkScalar x, SkScalar y, | 482 SkScalar x, SkScalar y, |
| 476 const SkIRect& clipBounds, | 483 const SkIRect& clipBounds, |
| 477 GrTextContext* fallbackTextCont
ext, | 484 GrTextContext* fallbackTextCont
ext, |
| 478 const SkPaint& originalSkPaint)
const { | 485 const SkPaint& originalSkPaint)
const { |
| 479 SkASSERT(fDraw); | 486 SkASSERT(fDraw); |
| 480 SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() |
| | 487 SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() |
| |
| 481 !fFont.isAntiAlias()); | 488 !fFont.isAntiAlias()); |
| 482 | 489 |
| 483 if (fDraw->count()) { | 490 if (fDraw->count()) { |
| 484 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is
AntiAlias()); | 491 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is
AntiAlias()); |
| 485 | 492 |
| 486 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | 493 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, |
| 487 kZero_StencilOp, | 494 kZero_StencilOp, |
| 488 kKeep_StencilOp, | 495 kKeep_StencilOp, |
| 489 kNotEqual_StencilFunc, | 496 kNotEqual_StencilFunc, |
| 490 0xffff, | 497 0xffff, |
| 491 0x0000, | 498 0x0000, |
| 492 0xffff); | 499 0xffff); |
| 493 | 500 |
| 494 *pipelineBuilder->stencil() = kStencilPass; | 501 *pipelineBuilder->stencil() = kStencilPass; |
| 495 | 502 |
| 503 SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); |
| 504 if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { |
| 505 // Either this is the first draw or the glyphs object was purged sin
ce last draw. |
| 506 glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count()); |
| 507 fLastDrawnGlyphsID = glyphs->getUniqueID(); |
| 508 } |
| 509 |
| 496 SkMatrix drawMatrix(viewMatrix); | 510 SkMatrix drawMatrix(viewMatrix); |
| 497 drawMatrix.preTranslate(x, y); | 511 drawMatrix.preTranslate(x, y); |
| 498 drawMatrix.preScale(fTextRatio, fTextRatio); | 512 drawMatrix.preScale(fTextRatio, fTextRatio); |
| 499 | 513 |
| 500 SkMatrix& localMatrix = fLocalMatrixTemplate; | 514 SkMatrix& localMatrix = fLocalMatrixTemplate; |
| 501 localMatrix.setTranslateX(x); | 515 localMatrix.setTranslateX(x); |
| 502 localMatrix.setTranslateY(y); | 516 localMatrix.setTranslateY(y); |
| 503 | 517 |
| 504 dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color,
fDraw, | 518 dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color,
glyphs, fDraw, |
| 505 GrPathRendering::kWinding_FillType); | 519 GrPathRendering::kWinding_FillType); |
| 506 } | 520 } |
| 507 | 521 |
| 508 if (fFallbackTextBlob) { | 522 if (fFallbackTextBlob) { |
| 509 SkPaint fallbackSkPaint(originalSkPaint); | 523 SkPaint fallbackSkPaint(originalSkPaint); |
| 510 fStroke.applyToPaint(&fallbackSkPaint); | 524 fStroke.applyToPaint(&fallbackSkPaint); |
| 511 if (!fStroke.isFillStyle()) { | 525 if (!fStroke.isFillStyle()) { |
| 512 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); | 526 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); |
| 513 } | 527 } |
| 514 | 528 |
| 515 fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget()
, | 529 fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget()
, |
| 516 pipelineBuilder->clip(), fallbackSkPai
nt, viewMatrix, | 530 pipelineBuilder->clip(), fallbackSkPai
nt, viewMatrix, |
| 517 fFallbackTextBlob, x, y, nullptr, clip
Bounds); | 531 fFallbackTextBlob, x, y, nullptr, clip
Bounds); |
| 518 } | 532 } |
| 519 } | 533 } |
| 520 | 534 |
| 521 int GrStencilAndCoverTextContext::TextRun::cpuMemorySize() const { | 535 SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const { |
| 522 int size = sizeof(TextRun) + fTotalGlyphCount * (sizeof(uint16_t) + 2 * size
of(float)); | 536 if (!fDetachedGlyphCache) { |
| 537 fDetachedGlyphCache = fFont.detachCache(nullptr, nullptr, true /*ignoreG
amma*/); |
| 538 } |
| 539 return fDetachedGlyphCache; |
| 540 } |
| 541 |
| 542 |
| 543 void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { |
| 544 if (fDetachedGlyphCache) { |
| 545 SkGlyphCache::AttachCache(fDetachedGlyphCache); |
| 546 fDetachedGlyphCache = nullptr; |
| 547 } |
| 548 } |
| 549 |
| 550 size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { |
| 551 size_t size = sizeof(TextRun) + |
| 552 fGlyphPathsKey.size() + |
| 553 fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float)); |
| 523 if (fDraw) { | 554 if (fDraw) { |
| 524 size += sizeof(GrPathRangeDraw); | 555 size += sizeof(GrPathRangeDraw); |
| 525 } | 556 } |
| 526 if (fFallbackTextBlob) { | 557 if (fFallbackTextBlob) { |
| 527 size += sizeof(SkTextBlob); | 558 size += sizeof(SkTextBlob); |
| 528 } | 559 } |
| 529 return size; | 560 return size; |
| 530 } | 561 } |
| 531 | 562 |
| 532 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 563 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 fBuffIdx = 0; | 600 fBuffIdx = 0; |
| 570 } | 601 } |
| 571 | 602 |
| 572 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInit
ialized() { | 603 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInit
ialized() { |
| 573 if (!this->isInitialized()) { | 604 if (!this->isInitialized()) { |
| 574 return nullptr; | 605 return nullptr; |
| 575 } | 606 } |
| 576 this->flush(); | 607 this->flush(); |
| 577 return fBuilder->build(); | 608 return fBuilder->build(); |
| 578 } | 609 } |
| OLD | NEW |