diff options
author | fmalita <fmalita@chromium.org> | 2014-09-19 18:37:00 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-19 18:37:00 -0700 |
commit | 13645ea0ea87038ebd71be3bd6d53b313069a9e4 (patch) | |
tree | 2cdb9acb1219abed808d06edce88f547ece4ea6c /include/core/SkTextBlob.h | |
parent | d49226cff368419c4a0fed7ba7f0383d46d9b2ac (diff) |
Souped-up SkTextBlob.
Refactored text blob backend for improved performance: instead of using
separate buffers for runs/positions/glyphs, everything is now packed in
a consolidated slab (including the SkTextBlob object itself!).
Benefits:
* number of allocations per blob construction reduced from ~4 to 1
(also minimizes internal fragmentation)
* run record size reduced by 8 bytes
This takes the blob construction overhead down to negligible levels
(for the current Blink uncached textblob implementation).
Unfortunately, the code is much more finicky (run merging in
particular) -- hence the assert spree.
Multi-run blobs are vulnerable to realloc storms but this is not a
problem at the moment because Blink is using one-run blobs 99% of the
time. Will be addressed in the future.
R=mtklein@google.com, reed@google.com, robertphillips@google.com
Author: fmalita@chromium.org
Review URL: https://codereview.chromium.org/581173003
Diffstat (limited to 'include/core/SkTextBlob.h')
-rw-r--r-- | include/core/SkTextBlob.h | 58 |
1 files changed, 27 insertions, 31 deletions
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h index 8e67723494..8ee1d19196 100644 --- a/include/core/SkTextBlob.h +++ b/include/core/SkTextBlob.h @@ -53,6 +53,8 @@ private: kFull_Positioning = 2 // Point positioning -- two scalars per glyph. }; + class RunRecord; + class RunIterator { public: RunIterator(const SkTextBlob* blob); @@ -68,21 +70,16 @@ private: GlyphPositioning positioning() const; private: - const SkTextBlob* fBlob; - int fIndex; - }; + const RunRecord* fCurrentRun; + int fRemainingRuns; - // A run is a sequence of glyphs sharing the same font metrics and positioning mode. - struct Run { - uint32_t count; - uint32_t glyphStart; // index into fGlyphBuffer - uint32_t posStart; // index into fPosBuffer - SkPoint offset; // run offset (unsued for fully positioned glyphs) - SkPaint font; - GlyphPositioning positioning; + SkDEBUGCODE(uint8_t* fStorageTop;) }; - SkTextBlob(uint16_t* glyphs, SkScalar* pos, const SkTArray<Run>* runs, const SkRect& bounds); + SkTextBlob(int runCount, const SkRect& bounds); + + virtual ~SkTextBlob(); + virtual void internal_dispose() const SK_OVERRIDE; static unsigned ScalarsPerGlyph(GlyphPositioning pos); @@ -90,14 +87,14 @@ private: friend class SkTextBlobBuilder; friend class TextBlobTester; - const SkAutoTMalloc<uint16_t> fGlyphBuffer; - const SkAutoTMalloc<SkScalar> fPosBuffer; + const int fRunCount; + const SkRect fBounds; + mutable uint32_t fUniqueID; - // SkTArray required here for run font destruction. - SkAutoTDelete<const SkTArray<Run> > fRuns; - const SkRect fBounds; + SkDEBUGCODE(size_t fStorageSize;) - mutable uint32_t fUniqueID; + // The actual payload resides in externally-managed storage, following the object. + // (see the .cpp for more details) typedef SkRefCnt INHERITED; }; @@ -108,11 +105,7 @@ private: */ class SK_API SkTextBlobBuilder { public: - /** - * @param runs The number of runs to be added, if known. This is a storage hint and - * not a limit. - */ - SkTextBlobBuilder(unsigned runs = 0); + SkTextBlobBuilder(); ~SkTextBlobBuilder(); @@ -180,20 +173,23 @@ public: const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL); private: + void reserve(size_t size); void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning, int count, SkPoint offset, const SkRect* bounds); - void ensureRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning, - const SkPoint& offset); + bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning, + int count, SkPoint offset); void updateDeferredBounds(); - SkTDArray<uint16_t> fGlyphBuffer; - SkTDArray<SkScalar> fPosBuffer; - SkTArray<SkTextBlob::Run>* fRuns; + SkAutoTMalloc<uint8_t> fStorage; + size_t fStorageSize; + size_t fStorageUsed; - SkRect fBounds; - bool fDeferredBounds; + SkRect fBounds; + int fRunCount; + bool fDeferredBounds; + size_t fLastRun; // index into fStorage - RunBuffer fCurrentRunBuffer; + RunBuffer fCurrentRunBuffer; }; #endif // SkTextBlob_DEFINED |