Index: src/gpu/GrBitmapTextContext.h |
diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h |
index 3bf3a941c646cb42d28464d1afbd6efbd4ffe897..1f8a82f35aae21690d556eac28ebc38eb50db74d 100644 |
--- a/src/gpu/GrBitmapTextContext.h |
+++ b/src/gpu/GrBitmapTextContext.h |
@@ -11,6 +11,8 @@ |
#include "GrTextContext.h" |
#include "GrGeometryProcessor.h" |
+#include "GrMemoryPool.h" |
+#include "SkDescriptor.h" |
#include "SkTHash.h" |
class GrBatchTextStrike; |
@@ -65,63 +67,108 @@ private: |
// this at a more fine grained level, but its not clear if this is worth it, as evictions |
// should be fairly rare. |
// One additional point, each run can contain glyphs with any of the three mask formats. |
- // We maintain separate arrays for each format type, and flush them separately. In practice |
- // most of the time a run will have the same format type |
+ // We call these SubRuns. Because a subrun must be a contiguous range, we have to create |
+ // a new subrun each time the mask format changes in a run. In theory, a run can have as |
+ // many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8. In |
+ // practice, the vast majority of runs have only a single subrun. |
+ |
struct Run { |
- Run() : fColor(GrColor_ILLEGAL) { fVertexBounds.setLargestInverted(); } |
- struct PerFormatInfo { |
- PerFormatInfo() : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration) {} |
- SkTDArray<unsigned char> fVertices; |
- SkTDArray<GrGlyph::PackedID> fGlyphIDs; |
+ Run() : fColor(GrColor_ILLEGAL), fInitialized(false) { |
+ fVertexBounds.setLargestInverted(); |
+ // We insert the first subrun to gurantee a run always has atleast one subrun. |
+ // We do this to simplify things when we 'hand off' data from one subrun to the |
+ // next |
+ fSubRunInfo.push_back(); |
+ } |
+ struct SubRunInfo { |
+ SubRunInfo() |
+ : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration) |
+ , fGlyphStartIndex(0) |
+ , fGlyphEndIndex(0) |
+ , fVertexStartIndex(0) |
+ , fVertexEndIndex(0) {} |
+ GrMaskFormat fMaskFormat; |
uint64_t fAtlasGeneration; |
+ uint32_t fGlyphStartIndex; |
+ uint32_t fGlyphEndIndex; |
+ size_t fVertexStartIndex; |
+ size_t fVertexEndIndex; |
}; |
- SkAutoTUnref<const SkData> fDescriptor; |
+ SkSTArray<1, SubRunInfo, true> fSubRunInfo; |
+ SkAutoDescriptor fDescriptor; |
SkAutoTUnref<SkTypeface> fTypeface; |
- PerFormatInfo fInfos[kMaskFormatCount]; |
SkRect fVertexBounds; |
GrColor fColor; |
+ bool fInitialized; |
}; |
- SkSTArray<1, Run, true> fRuns; |
+ |
struct BigGlyph { |
BigGlyph(const SkPath& path, int vx, int vy) : fPath(path), fVx(vx), fVy(vy) {} |
SkPath fPath; |
int fVx; |
int fVy; |
}; |
+ |
SkTArray<BigGlyph> fBigGlyphs; |
- SkTextBlob* fBlob; |
SkMatrix fViewMatrix; |
SkScalar fX; |
SkScalar fY; |
SkPaint::Style fStyle; |
+ uint32_t fRunCount; |
+ |
+ // all glyph / vertex offsets are into these pools. |
+ unsigned char* fVertices; |
+ GrGlyph::PackedID* fGlyphIDs; |
+ Run* fRuns; |
static uint32_t Hash(const uint32_t& key) { |
return SkChecksum::Mix(key); |
} |
+ |
+ void operator delete(void* p) { sk_free(p); } |
+ void* operator new(size_t) { |
+ SkFAIL("All blobs are created by placement new."); |
+ return sk_malloc_throw(0); |
+ } |
+ |
+ void* operator new(size_t, void* p) { return p; } |
+ void operator delete(void* target, void* placement) { |
+ ::operator delete(target, placement); |
+ } |
}; |
+ typedef BitmapTextBlob::Run Run; |
+ typedef Run::SubRunInfo PerSubRunInfo; |
+ |
+ BitmapTextBlob* CreateBlob(int glyphCount, int runCount); |
+ |
void appendGlyph(BitmapTextBlob*, int runIndex, GrGlyph::PackedID, int left, int top, |
GrFontScaler*, const SkIRect& clipRect); |
- void flushSubRun(GrDrawTarget*, BitmapTextBlob*, int i, GrPipelineBuilder*, GrMaskFormat, |
- GrColor color, int paintAlpha); |
void flush(GrDrawTarget*, BitmapTextBlob*, GrRenderTarget*, const GrPaint&, const GrClip&, |
const SkMatrix& viewMatrix, int paintAlpha); |
- void internalDrawText(BitmapTextBlob*, int runIndex, const SkPaint&, |
+ void internalDrawText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&, |
const SkMatrix& viewMatrix, const char text[], size_t byteLength, |
SkScalar x, SkScalar y, const SkIRect& clipRect); |
- void internalDrawPosText(BitmapTextBlob*, int runIndex, const SkPaint&, |
+ void internalDrawPosText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&, |
const SkMatrix& viewMatrix, |
const char text[], size_t byteLength, |
const SkScalar pos[], int scalarsPerPosition, |
const SkPoint& offset, const SkIRect& clipRect); |
+ // sets up the descriptor on the blob and returns a detached cache. Client must attach |
+ inline SkGlyphCache* setupCache(Run*, const SkPaint&, const SkMatrix& viewMatrix); |
static inline bool MustRegenerateBlob(const BitmapTextBlob&, const SkPaint&, |
const SkMatrix& viewMatrix, SkScalar x, SkScalar y); |
void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, const SkMatrix& viewMatrix, |
const SkTextBlob* blob, SkScalar x, SkScalar y, |
SkDrawFilter* drawFilter, const SkIRect& clipRect); |
+ // TODO this currently only uses the public interface of SkTextBlob, however, I may need to add |
+ // functionality to it while looping over the runs so I'm putting this here for the time being. |
+ // If this lands in Chrome without changes, move it to SkTextBlob. |
+ static inline void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob*); |
+ |
GrBatchTextStrike* fCurrStrike; |
// TODO use real cache |