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