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 "GrAtlas.h" | 9 #include "GrAtlas.h" |
10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props)); | 83 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props)); |
84 } | 84 } |
85 | 85 |
86 bool GrAtlasTextContext::canDraw(const GrRenderTarget*, | 86 bool GrAtlasTextContext::canDraw(const GrRenderTarget*, |
87 const GrClip&, | 87 const GrClip&, |
88 const GrPaint&, | 88 const GrPaint&, |
89 const SkPaint& skPaint, | 89 const SkPaint& skPaint, |
90 const SkMatrix& viewMatrix) { | 90 const SkMatrix& viewMatrix) { |
91 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); | 91 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); |
92 } | 92 } |
93 | 93 |
robertphillips
2015/04/09 13:15:32
kMinDiscernableTranslation ?
Can this be moved int
joshualitt
2015/04/09 14:59:00
Acknowledged.
| |
94 bool GrAtlasTextContext::MustRegenerateBlob(const BitmapTextBlob& blob, const Sk Paint& paint, | 94 static const SkScalar kThreshold = 0.0625; |
95 | |
96 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* transX, SkScalar* transY, | |
97 const BitmapTextBlob& blob, const Sk Paint& paint, | |
95 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { | 98 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { |
96 // We always regenerate blobs with patheffects or mask filters we could cach e these | 99 // Color can affect the mask |
97 // TODO find some way to cache the maskfilter / patheffects on the textblob | 100 // TODO we can adjust the color within specific gamma slots |
98 return !blob.fViewMatrix.cheapEqualTo(viewMatrix) || blob.fX != x || blob.fY != y || | 101 if (blob.fColor != paint.getColor()) { |
99 paint.getMaskFilter() || paint.getPathEffect() || paint.getStyle() ! = blob.fStyle; | 102 return true; |
103 } | |
104 | |
105 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { | |
106 return true; | |
107 } | |
108 | |
109 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view Matrix)) { | |
110 return true; | |
111 } | |
112 | |
113 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || | |
114 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || | |
115 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || | |
116 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { | |
117 return true; | |
118 } | |
119 | |
120 // We can update the positions in the cachedtextblobs without regenerating t he whole blob, but | |
121 // only for integer translations. | |
robertphillips
2015/04/09 13:15:32
That's an ominous todo
Shouldn't this be something
joshualitt
2015/04/09 14:59:00
I took another stab at it. I *think* I can allow
| |
122 // TODO I think this is wrong | |
123 if (SkScalarFraction(blob.fViewMatrix.getTranslateX() - | |
124 viewMatrix.getTranslateX()) > kThreshold || | |
125 SkScalarFraction(x - blob.fX) > kThreshold || | |
126 SkScalarFraction(blob.fViewMatrix.getTranslateX() - | |
127 viewMatrix.getTranslateX()) > kThreshold || | |
128 SkScalarFraction(y - blob.fY) > kThreshold) { | |
129 return true; | |
130 } | |
131 | |
robertphillips
2015/04/09 13:15:32
// This cool math does the following ...
?
joshualitt
2015/04/09 14:59:00
Acknowledged.
| |
132 (*transX) = viewMatrix.getTranslateX() + | |
133 viewMatrix.getScaleX() * (x - blob.fX) + | |
134 viewMatrix.getSkewX() * (y - blob.fY) - | |
135 blob.fViewMatrix.getTranslateX(); | |
136 | |
137 (*transY) = viewMatrix.getTranslateY() + | |
138 viewMatrix.getSkewY() * (x - blob.fX) + | |
139 viewMatrix.getScaleY() * (y - blob.fY) - | |
140 blob.fViewMatrix.getTranslateY(); | |
141 return false; | |
100 } | 142 } |
101 | 143 |
102 | 144 |
103 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, | 145 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, |
104 const SkPaint& skPaint, | 146 const SkPaint& skPaint, |
105 const SkMatrix& viewMatrix) { | 147 const SkMatrix& viewMatrix) { |
106 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); | 148 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); |
107 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); | 149 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); |
108 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; | 150 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; |
109 } | 151 } |
110 | 152 |
111 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, | 153 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, |
112 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, | 154 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, |
113 const SkTextBlob* blob, SkScalar x, SkScal ar y, | 155 const SkTextBlob* blob, SkScalar x, SkScal ar y, |
114 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { | 156 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { |
115 uint32_t uniqueID = blob->uniqueID(); | 157 uint32_t uniqueID = blob->uniqueID(); |
116 BitmapTextBlob* cacheBlob = fCache->find(uniqueID); | 158 SkAutoTUnref<BitmapTextBlob> cacheBlob; |
159 // TODO start caching these, mix bits into the key | |
robertphillips
2015/04/09 13:15:32
Would this be more natural as "canCache" ?
joshualitt
2015/04/09 14:59:00
Acknowledged.
| |
160 bool mustNotCache = skPaint.getPathEffect() || | |
161 skPaint.getMaskFilter() || | |
162 skPaint.getColorFilter() || | |
163 skPaint.getStyle() != SkPaint::kFill_Style || | |
164 drawFilter; | |
165 | |
166 if (!mustNotCache) { | |
167 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID))); | |
168 } | |
169 | |
117 SkIRect clipRect; | 170 SkIRect clipRect; |
118 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); | 171 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); |
119 | 172 |
173 SkScalar transX = 0.f; | |
174 SkScalar transY = 0.f; | |
175 | |
120 if (cacheBlob) { | 176 if (cacheBlob) { |
121 if (MustRegenerateBlob(*cacheBlob, skPaint, viewMatrix, x, y)) { | 177 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix , x, y)) { |
122 // We have to remake the blob because changes may invalidate our mas ks. | 178 // We have to remake the blob because changes may invalidate our mas ks. |
123 // TODO we could probably get away reuse most of the time if the poi nter is unique, | 179 // TODO we could probably get away reuse most of the time if the poi nter is unique, |
124 // but we'd have to clear the subrun information | 180 // but we'd have to clear the subrun information |
125 fCache->remove(cacheBlob); | 181 fCache->remove(cacheBlob); |
126 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); | 182 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize ))); |
127 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, | 183 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, |
128 clipRect); | 184 clipRect); |
129 } else { | 185 } else { |
186 // If we can reuse the blob, then make sure we update the blob's vie wmatrix and x/y | |
187 // offsets to reflect the results of any translations we may apply i n generateGeometry | |
188 cacheBlob->fViewMatrix = viewMatrix; | |
189 cacheBlob->fX = x; | |
190 cacheBlob->fY = y; | |
130 fCache->makeMRU(cacheBlob); | 191 fCache->makeMRU(cacheBlob); |
131 } | 192 } |
132 } else { | 193 } else { |
133 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); | 194 if (mustNotCache) { |
195 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); | |
196 } else { | |
197 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize ))); | |
198 } | |
134 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); | 199 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); |
135 } | 200 } |
136 | 201 |
137 // Though for the time being runs in the textblob can override the paint, th ey only touch font | 202 // Though for the time being runs in the textblob can override the paint, th ey only touch font |
138 // info. | 203 // info. |
139 GrPaint grPaint; | 204 GrPaint grPaint; |
140 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); | 205 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); |
141 | 206 |
142 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, | 207 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, |
143 clip, viewMatrix, clipBounds, x, y); | 208 clip, viewMatrix, clipBounds, x, y, transX, transY); |
144 } | 209 } |
145 | 210 |
146 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, | 211 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, |
147 const SkPaint& skPaint, const SkMatr ix& viewMatrix, | 212 const SkPaint& skPaint, const SkMatr ix& viewMatrix, |
148 const SkTextBlob* blob, SkScalar x, SkScalar y, | 213 const SkTextBlob* blob, SkScalar x, SkScalar y, |
149 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { | 214 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { |
150 cacheBlob->fViewMatrix = viewMatrix; | 215 cacheBlob->fViewMatrix = viewMatrix; |
151 cacheBlob->fX = x; | 216 cacheBlob->fX = x; |
152 cacheBlob->fY = y; | 217 cacheBlob->fY = y; |
218 cacheBlob->fColor = skPaint.getColor(); | |
153 cacheBlob->fStyle = skPaint.getStyle(); | 219 cacheBlob->fStyle = skPaint.getStyle(); |
154 | 220 |
155 // Regenerate textblob | 221 // Regenerate textblob |
156 SkPaint runPaint = skPaint; | 222 SkPaint runPaint = skPaint; |
157 SkTextBlob::RunIterator it(blob); | 223 SkTextBlob::RunIterator it(blob); |
158 for (int run = 0; !it.done(); it.next(), run++) { | 224 for (int run = 0; !it.done(); it.next(), run++) { |
159 int glyphCount = it.glyphCount(); | 225 int glyphCount = it.glyphCount(); |
160 size_t textLen = glyphCount * sizeof(uint16_t); | 226 size_t textLen = glyphCount * sizeof(uint16_t); |
161 const SkPoint& offset = it.offset(); | 227 const SkPoint& offset = it.offset(); |
162 // applyFontToPaint() always overwrites the exact same attributes, | 228 // applyFontToPaint() always overwrites the exact same attributes, |
(...skipping 15 matching lines...) Expand all Loading... | |
178 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); | 244 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); |
179 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( ); | 245 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( ); |
180 | 246 |
181 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; | 247 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; |
182 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; | 248 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; |
183 | 249 |
184 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; | 250 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; |
185 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; | 251 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; |
186 } | 252 } |
187 | 253 |
188 if (SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix)) { | 254 if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) { |
189 cacheBlob->fRuns[run].fDrawAsPaths = true; | 255 cacheBlob->fRuns[run].fDrawAsPaths = true; |
190 continue; | 256 continue; |
191 } | 257 } |
192 cacheBlob->fRuns[run].fDrawAsPaths = false; | 258 cacheBlob->fRuns[run].fDrawAsPaths = false; |
193 | 259 |
194 switch (it.positioning()) { | 260 switch (it.positioning()) { |
195 case SkTextBlob::kDefault_Positioning: | 261 case SkTextBlob::kDefault_Positioning: |
196 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix, | 262 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix, |
197 (const char *)it.glyphs(), textLen, | 263 (const char *)it.glyphs(), textLen, |
198 x + offset.x(), y + offset.y(), clipRect) ; | 264 x + offset.x(), y + offset.y(), clipRect) ; |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
529 return; | 595 return; |
530 } | 596 } |
531 | 597 |
532 int x = vx + glyph->fBounds.fLeft; | 598 int x = vx + glyph->fBounds.fLeft; |
533 int y = vy + glyph->fBounds.fTop; | 599 int y = vy + glyph->fBounds.fTop; |
534 | 600 |
535 // keep them as ints until we've done the clip-test | 601 // keep them as ints until we've done the clip-test |
536 int width = glyph->fBounds.width(); | 602 int width = glyph->fBounds.width(); |
537 int height = glyph->fBounds.height(); | 603 int height = glyph->fBounds.height(); |
538 | 604 |
539 // check if we clipped out | |
540 if (clipRect.quickReject(x, y, x + width, y + height)) { | |
541 return; | |
542 } | |
543 | |
544 // If the glyph is too large we fall back to paths | 605 // If the glyph is too large we fall back to paths |
545 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) { | 606 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) { |
546 if (NULL == glyph->fPath) { | 607 if (NULL == glyph->fPath) { |
547 SkPath* path = SkNEW(SkPath); | 608 SkPath* path = SkNEW(SkPath); |
548 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { | 609 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { |
549 // flag the glyph as being dead? | 610 // flag the glyph as being dead? |
550 SkDELETE(path); | 611 SkDELETE(path); |
551 return; | 612 return; |
552 } | 613 } |
553 glyph->fPath = path; | 614 glyph->fPath = path; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
591 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex); | 652 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex); |
592 | 653 |
593 // V0 | 654 // V0 |
594 SkPoint* position = reinterpret_cast<SkPoint*>(vertex); | 655 SkPoint* position = reinterpret_cast<SkPoint*>(vertex); |
595 position->set(r.fLeft, r.fTop); | 656 position->set(r.fLeft, r.fTop); |
596 if (kA8_GrMaskFormat == format) { | 657 if (kA8_GrMaskFormat == format) { |
597 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; | 658 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; |
598 *colorPtr = color; | 659 *colorPtr = color; |
599 } | 660 } |
600 vertex += vertexStride; | 661 vertex += vertexStride; |
601 | |
602 // V1 | 662 // V1 |
603 position = reinterpret_cast<SkPoint*>(vertex); | 663 position = reinterpret_cast<SkPoint*>(vertex); |
604 position->set(r.fLeft, r.fBottom); | 664 position->set(r.fLeft, r.fBottom); |
605 if (kA8_GrMaskFormat == format) { | 665 if (kA8_GrMaskFormat == format) { |
606 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; | 666 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; |
607 *colorPtr = color; | 667 *colorPtr = color; |
608 } | 668 } |
609 vertex += vertexStride; | 669 vertex += vertexStride; |
610 | 670 |
611 // V2 | 671 // V2 |
(...skipping 21 matching lines...) Expand all Loading... | |
633 public: | 693 public: |
634 typedef GrAtlasTextContext::BitmapTextBlob Blob; | 694 typedef GrAtlasTextContext::BitmapTextBlob Blob; |
635 typedef Blob::Run Run; | 695 typedef Blob::Run Run; |
636 typedef Run::SubRunInfo TextInfo; | 696 typedef Run::SubRunInfo TextInfo; |
637 struct Geometry { | 697 struct Geometry { |
638 Geometry() {} | 698 Geometry() {} |
639 Geometry(const Geometry& geometry) | 699 Geometry(const Geometry& geometry) |
640 : fBlob(SkRef(geometry.fBlob.get())) | 700 : fBlob(SkRef(geometry.fBlob.get())) |
641 , fRun(geometry.fRun) | 701 , fRun(geometry.fRun) |
642 , fSubRun(geometry.fSubRun) | 702 , fSubRun(geometry.fSubRun) |
643 , fColor(geometry.fColor) {} | 703 , fColor(geometry.fColor) |
704 , fTransX(geometry.fTransX) | |
705 , fTransY(geometry.fTransY) {} | |
644 SkAutoTUnref<Blob> fBlob; | 706 SkAutoTUnref<Blob> fBlob; |
645 int fRun; | 707 int fRun; |
646 int fSubRun; | 708 int fSubRun; |
647 GrColor fColor; | 709 GrColor fColor; |
710 SkScalar fTransX; | |
711 SkScalar fTransY; | |
648 }; | 712 }; |
649 | 713 |
650 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat, | 714 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat, |
651 int glyphCount, GrBatchFontCache* fontCache) { | 715 int glyphCount, GrBatchFontCache* fontCache) { |
652 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache)); | 716 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache)); |
653 } | 717 } |
654 | 718 |
655 const char* name() const override { return "BitmapTextBatch"; } | 719 const char* name() const override { return "BitmapTextBatch"; } |
656 | 720 |
657 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { | 721 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
751 int instancesToFlush = 0; | 815 int instancesToFlush = 0; |
752 for (int i = 0; i < instanceCount; i++) { | 816 for (int i = 0; i < instanceCount; i++) { |
753 Geometry& args = fGeoData[i]; | 817 Geometry& args = fGeoData[i]; |
754 Blob* blob = args.fBlob; | 818 Blob* blob = args.fBlob; |
755 Run& run = blob->fRuns[args.fRun]; | 819 Run& run = blob->fRuns[args.fRun]; |
756 TextInfo& info = run.fSubRunInfo[args.fSubRun]; | 820 TextInfo& info = run.fSubRunInfo[args.fSubRun]; |
757 | 821 |
758 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); | 822 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); |
759 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen; | 823 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen; |
760 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor; | 824 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor; |
825 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0. f; | |
761 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; | 826 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; |
762 | 827 |
763 // We regenerate both texture coords and colors in the blob itself, and update the | 828 // We regenerate both texture coords and colors in the blob itself, and update the |
764 // atlas generation. If we don't end up purging any unused plots, w e can avoid | 829 // atlas generation. If we don't end up purging any unused plots, w e can avoid |
765 // regenerating the coords. We could take a finer grained approach to updating texture | 830 // regenerating the coords. We could take a finer grained approach to updating texture |
766 // coords but its not clear if the extra bookkeeping would offset an y gains. | 831 // coords but its not clear if the extra bookkeeping would offset an y gains. |
767 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color | 832 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color |
768 // or coords as needed. One final note, if we have to break a run f or an atlas eviction | 833 // or coords as needed. One final note, if we have to break a run f or an atlas eviction |
769 // then we can't really trust the atlas has all of the correct data. Atlas evictions | 834 // then we can't really trust the atlas has all of the correct data. Atlas evictions |
770 // should be pretty rare, so we just always regenerate in those case s | 835 // should be pretty rare, so we just always regenerate in those case s |
771 if (regenerateTextureCoords || regenerateColors) { | 836 if (regenerateTextureCoords || regenerateColors || regeneratePositio ns) { |
772 // first regenerate texture coordinates / colors if need be | 837 // first regenerate texture coordinates / colors if need be |
773 const SkDescriptor* desc = NULL; | 838 const SkDescriptor* desc = NULL; |
774 SkGlyphCache* cache = NULL; | 839 SkGlyphCache* cache = NULL; |
775 GrFontScaler* scaler = NULL; | 840 GrFontScaler* scaler = NULL; |
776 GrBatchTextStrike* strike = NULL; | 841 GrBatchTextStrike* strike = NULL; |
777 bool brokenRun = false; | 842 bool brokenRun = false; |
778 if (regenerateTextureCoords) { | 843 if (regenerateTextureCoords) { |
779 info.fBulkUseToken.reset(); | 844 info.fBulkUseToken.reset(); |
780 desc = run.fDescriptor.getDesc(); | 845 desc = run.fDescriptor.getDesc(); |
781 cache = SkGlyphCache::DetachCache(run.fTypeface, desc); | 846 cache = SkGlyphCache::DetachCache(run.fTypeface, desc); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 this->regenerateTextureCoords(glyph, vertex, vertexStrid e); | 880 this->regenerateTextureCoords(glyph, vertex, vertexStrid e); |
816 } | 881 } |
817 | 882 |
818 if (regenerateColors) { | 883 if (regenerateColors) { |
819 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); | 884 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); |
820 vertex += info.fVertexStartIndex; | 885 vertex += info.fVertexStartIndex; |
821 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); | 886 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); |
822 this->regenerateColors(vertex, vertexStride, args.fColor ); | 887 this->regenerateColors(vertex, vertexStride, args.fColor ); |
823 } | 888 } |
824 | 889 |
890 if (regeneratePositions) { | |
891 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); | |
892 vertex += info.fVertexStartIndex; | |
893 vertex += vertexStride * glyphIdx * kVerticesPerGlyph; | |
894 SkScalar transX = args.fTransX; | |
895 SkScalar transY = args.fTransY; | |
896 this->regeneratePositions(vertex, vertexStride, transX, transY); | |
897 } | |
825 instancesToFlush++; | 898 instancesToFlush++; |
826 } | 899 } |
827 | 900 |
901 // We my have changed the color so update it here | |
902 run.fColor = args.fColor; | |
828 if (regenerateTextureCoords) { | 903 if (regenerateTextureCoords) { |
829 SkGlyphCache::AttachCache(cache); | 904 SkGlyphCache::AttachCache(cache); |
830 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration : | 905 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration : |
831 fFontCache->atlasGenerat ion(fMaskFormat); | 906 fFontCache->atlasGenerat ion(fMaskFormat); |
832 } | 907 } |
833 } else { | 908 } else { |
834 instancesToFlush += glyphCount; | 909 instancesToFlush += glyphCount; |
835 | 910 |
836 // set use tokens for all of the glyphs in our subrun. This is only valid if we | 911 // set use tokens for all of the glyphs in our subrun. This is only valid if we |
837 // have a valid atlas generation | 912 // have a valid atlas generation |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
897 } | 972 } |
898 | 973 |
899 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { | 974 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { |
900 for (int i = 0; i < kVerticesPerGlyph; i++) { | 975 for (int i = 0; i < kVerticesPerGlyph; i++) { |
901 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); | 976 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); |
902 *vcolor = color; | 977 *vcolor = color; |
903 vertex += vertexStride; | 978 vertex += vertexStride; |
904 } | 979 } |
905 } | 980 } |
906 | 981 |
982 void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar tran sX, | |
983 SkScalar transY) { | |
984 for (int i = 0; i < kVerticesPerGlyph; i++) { | |
985 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | |
986 point->fX += transX; | |
987 point->fY += transY; | |
988 vertex += vertexStride; | |
989 } | |
990 } | |
991 | |
907 void initDraw(GrBatchTarget* batchTarget, | 992 void initDraw(GrBatchTarget* batchTarget, |
908 const GrGeometryProcessor* gp, | 993 const GrGeometryProcessor* gp, |
909 const GrPipeline* pipeline) { | 994 const GrPipeline* pipeline) { |
910 batchTarget->initDraw(gp, pipeline); | 995 batchTarget->initDraw(gp, pipeline); |
911 | 996 |
912 // TODO remove this when batch is everywhere | 997 // TODO remove this when batch is everywhere |
913 GrPipelineInfo init; | 998 GrPipelineInfo init; |
914 init.fColorIgnored = fBatch.fColorIgnored; | 999 init.fColorIgnored = fBatch.fColorIgnored; |
915 init.fOverrideColor = GrColor_ILLEGAL; | 1000 init.fOverrideColor = GrColor_ILLEGAL; |
916 init.fCoverageIgnored = fBatch.fCoverageIgnored; | 1001 init.fCoverageIgnored = fBatch.fCoverageIgnored; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1003 break; | 1088 break; |
1004 case SkTextBlob::kFull_Positioning: | 1089 case SkTextBlob::kFull_Positioning: |
1005 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (), | 1090 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (), |
1006 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds); | 1091 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds); |
1007 break; | 1092 break; |
1008 } | 1093 } |
1009 } | 1094 } |
1010 | 1095 |
1011 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder, | 1096 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder, |
1012 BitmapTextBlob* cacheBlob, int run, GrC olor color, | 1097 BitmapTextBlob* cacheBlob, int run, GrC olor color, |
1013 uint8_t paintAlpha) { | 1098 uint8_t paintAlpha, SkScalar transX, Sk Scalar transY) { |
1014 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) { | 1099 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) { |
1015 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; | 1100 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; |
1016 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; | 1101 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; |
1017 if (0 == glyphCount) { | 1102 if (0 == glyphCount) { |
1018 continue; | 1103 continue; |
1019 } | 1104 } |
1020 | 1105 |
1021 GrMaskFormat format = info.fMaskFormat; | 1106 GrMaskFormat format = info.fMaskFormat; |
1022 GrColor subRunColor = kARGB_GrMaskFormat == format ? | 1107 GrColor subRunColor = kARGB_GrMaskFormat == format ? |
1023 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) : | 1108 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) : |
1024 color; | 1109 color; |
1025 | 1110 |
1026 BitmapTextBatch::Geometry geometry; | 1111 BitmapTextBatch::Geometry geometry; |
1027 geometry.fBlob.reset(SkRef(cacheBlob)); | 1112 geometry.fBlob.reset(SkRef(cacheBlob)); |
1028 geometry.fRun = run; | 1113 geometry.fRun = run; |
1029 geometry.fSubRun = subRun; | 1114 geometry.fSubRun = subRun; |
1030 geometry.fColor = subRunColor; | 1115 geometry.fColor = subRunColor; |
1116 geometry.fTransX = transX; | |
1117 geometry.fTransY = transY; | |
1031 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount, | 1118 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount, |
1032 fContext->getBatchFo ntCache())); | 1119 fContext->getBatchFo ntCache())); |
1033 | 1120 |
1034 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds); | 1121 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds); |
1035 } | 1122 } |
1036 } | 1123 } |
1037 | 1124 |
1038 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt, | 1125 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt, |
1039 const GrPaint& grPaint, const GrC lip& clip) { | 1126 const GrPaint& grPaint, const GrC lip& clip, |
1127 SkScalar transX, SkScalar transY) { | |
1040 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { | 1128 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { |
1041 const BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; | 1129 BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; |
1130 bigGlyph.fVx += transX; | |
1131 bigGlyph.fVy += transY; | |
1042 SkMatrix translate; | 1132 SkMatrix translate; |
1043 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy)); | 1133 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), |
1134 SkIntToScalar(bigGlyph.fVy)); | |
1044 SkPath tmpPath(bigGlyph.fPath); | 1135 SkPath tmpPath(bigGlyph.fPath); |
1045 tmpPath.transform(translate); | 1136 tmpPath.transform(translate); |
1046 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); | 1137 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); |
1047 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo ); | 1138 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo ); |
1048 } | 1139 } |
1049 } | 1140 } |
1050 | 1141 |
1051 void GrAtlasTextContext::flush(GrDrawTarget* target, | 1142 void GrAtlasTextContext::flush(GrDrawTarget* target, |
1052 const SkTextBlob* blob, | 1143 const SkTextBlob* blob, |
1053 BitmapTextBlob* cacheBlob, | 1144 BitmapTextBlob* cacheBlob, |
1054 GrRenderTarget* rt, | 1145 GrRenderTarget* rt, |
1055 const SkPaint& skPaint, | 1146 const SkPaint& skPaint, |
1056 const GrPaint& grPaint, | 1147 const GrPaint& grPaint, |
1057 SkDrawFilter* drawFilter, | 1148 SkDrawFilter* drawFilter, |
1058 const GrClip& clip, | 1149 const GrClip& clip, |
1059 const SkMatrix& viewMatrix, | 1150 const SkMatrix& viewMatrix, |
1060 const SkIRect& clipBounds, | 1151 const SkIRect& clipBounds, |
1061 SkScalar x, | 1152 SkScalar x, SkScalar y, |
1062 SkScalar y) { | 1153 SkScalar transX, SkScalar transY) { |
1063 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush | 1154 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush |
1064 // it as paths | 1155 // it as paths |
1065 GrPipelineBuilder pipelineBuilder; | 1156 GrPipelineBuilder pipelineBuilder; |
1066 pipelineBuilder.setFromPaint(grPaint, rt, clip); | 1157 pipelineBuilder.setFromPaint(grPaint, rt, clip); |
1067 | 1158 |
1068 GrColor color = grPaint.getColor(); | 1159 GrColor color = grPaint.getColor(); |
1069 uint8_t paintAlpha = skPaint.getAlpha(); | 1160 uint8_t paintAlpha = skPaint.getAlpha(); |
1070 | 1161 |
1071 SkTextBlob::RunIterator it(blob); | 1162 SkTextBlob::RunIterator it(blob); |
1072 for (int run = 0; !it.done(); it.next(), run++) { | 1163 for (int run = 0; !it.done(); it.next(), run++) { |
1073 if (cacheBlob->fRuns[run].fDrawAsPaths) { | 1164 if (cacheBlob->fRuns[run].fDrawAsPaths) { |
1074 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y); | 1165 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y); |
1075 continue; | 1166 continue; |
1076 } | 1167 } |
1077 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); | 1168 cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY); |
1169 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, transX, transY); | |
1078 } | 1170 } |
1079 | 1171 |
1080 // Now flush big glyphs | 1172 // Now flush big glyphs |
1081 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); | 1173 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, transX, transY); |
1082 } | 1174 } |
1083 | 1175 |
1084 void GrAtlasTextContext::flush(GrDrawTarget* target, | 1176 void GrAtlasTextContext::flush(GrDrawTarget* target, |
1085 BitmapTextBlob* cacheBlob, | 1177 BitmapTextBlob* cacheBlob, |
1086 GrRenderTarget* rt, | 1178 GrRenderTarget* rt, |
1087 const SkPaint& skPaint, | 1179 const SkPaint& skPaint, |
1088 const GrPaint& grPaint, | 1180 const GrPaint& grPaint, |
1089 const GrClip& clip, | 1181 const GrClip& clip, |
1090 const SkMatrix& viewMatrix) { | 1182 const SkMatrix& viewMatrix) { |
1091 GrPipelineBuilder pipelineBuilder; | 1183 GrPipelineBuilder pipelineBuilder; |
1092 pipelineBuilder.setFromPaint(grPaint, rt, clip); | 1184 pipelineBuilder.setFromPaint(grPaint, rt, clip); |
1093 | 1185 |
1094 GrColor color = grPaint.getColor(); | 1186 GrColor color = grPaint.getColor(); |
1095 uint8_t paintAlpha = skPaint.getAlpha(); | 1187 uint8_t paintAlpha = skPaint.getAlpha(); |
1096 for (int run = 0; run < cacheBlob->fRunCount; run++) { | 1188 for (int run = 0; run < cacheBlob->fRunCount; run++) { |
1097 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); | 1189 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0); |
1098 } | 1190 } |
1099 | 1191 |
1100 // Now flush big glyphs | 1192 // Now flush big glyphs |
1101 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); | 1193 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); |
1102 } | 1194 } |
OLD | NEW |