/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkTextBlob_DEFINED #define SkTextBlob_DEFINED #include "SkPaint.h" #include "SkRefCnt.h" #include "SkTArray.h" #include "SkTDArray.h" class SkReadBuffer; class SkWriteBuffer; /** \class SkTextBlob SkTextBlob combines multiple text runs into an immutable, ref-counted structure. */ class SK_API SkTextBlob : public SkRefCnt { public: /** * Returns the blob bounding box. */ const SkRect& bounds() const { return fBounds; } /** * Return a non-zero, unique value representing the text blob. */ uint32_t uniqueID() const; /** * Serialize to a buffer. */ void flatten(SkWriteBuffer&) const; /** * Recreate an SkTextBlob that was serialized into a buffer. * * @param SkReadBuffer Serialized blob data. * @return A new SkTextBlob representing the serialized data, or NULL if the buffer is * invalid. */ static const SkTextBlob* CreateFromBuffer(SkReadBuffer&); private: enum GlyphPositioning { kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph. kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph. kFull_Positioning = 2 // Point positioning -- two scalars per glyph. }; class RunIterator { public: RunIterator(const SkTextBlob* blob); bool done() const; void next(); uint32_t glyphCount() const; const uint16_t* glyphs() const; const SkScalar* pos() const; const SkPoint& offset() const; void applyFontToPaint(SkPaint*) const; GlyphPositioning positioning() const; private: const SkTextBlob* fBlob; int fIndex; }; // 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; }; SkTextBlob(uint16_t* glyphs, SkScalar* pos, const SkTArray* runs, const SkRect& bounds); static unsigned ScalarsPerGlyph(GlyphPositioning pos); friend class SkBaseDevice; friend class SkTextBlobBuilder; friend class TextBlobTester; const SkAutoTMalloc fGlyphBuffer; const SkAutoTMalloc fPosBuffer; // SkTArray required here for run font destruction. SkAutoTDelete > fRuns; const SkRect fBounds; mutable uint32_t fUniqueID; typedef SkRefCnt INHERITED; }; /** \class SkTextBlobBuilder Helper class for constructing SkTextBlobs. */ 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(); /** * Returns an immutable SkTextBlob for the current runs/glyphs. The builder is reset and * can be reused. */ const SkTextBlob* build(); /** * Glyph and position buffers associated with a run. * * A run is a sequence of glyphs sharing the same font metrics and positioning mode. */ struct RunBuffer { uint16_t* glyphs; SkScalar* pos; }; /** * Allocates a new default-positioned run and returns its writable glyph buffer * for direct manipulation. * * @param font The font to be used for this run. * @param count Number of glyphs. * @param x,y Position within the blob. * @param bounds Optional run bounding box. If known in advance (!= NULL), it will * be used when computing the blob bounds, to avoid re-measuring. * * @return A writable glyph buffer, valid until the next allocRun() or * build() call. The buffer is guaranteed to hold @count@ glyphs. */ const RunBuffer& allocRun(const SkPaint& font, int count, SkScalar x, SkScalar y, const SkRect* bounds = NULL); /** * Allocates a new horizontally-positioned run and returns its writable glyph and position * buffers for direct manipulation. * * @param font The font to be used for this run. * @param count Number of glyphs. * @param y Vertical offset within the blob. * @param bounds Optional run bounding box. If known in advance (!= NULL), it will * be used when computing the blob bounds, to avoid re-measuring. * * @return Writable glyph and position buffers, valid until the next allocRun() * or build() call. The buffers are guaranteed to hold @count@ elements. */ const RunBuffer& allocRunPosH(const SkPaint& font, int count, SkScalar y, const SkRect* bounds = NULL); /** * Allocates a new fully-positioned run and returns its writable glyph and position * buffers for direct manipulation. * * @param font The font to be used for this run. * @param count Number of glyphs. * @param bounds Optional run bounding box. If known in advance (!= NULL), it will * be used when computing the blob bounds, to avoid re-measuring. * * @return Writable glyph and position buffers, valid until the next allocRun() * or build() call. The glyph buffer and position buffer are * guaranteed to hold @count@ and 2 * @count@ elements, respectively. */ const RunBuffer& allocRunPos(const SkPaint& font, int count, const SkRect* bounds = NULL); private: 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); void updateDeferredBounds(); SkTDArray fGlyphBuffer; SkTDArray fPosBuffer; SkTArray* fRuns; SkRect fBounds; bool fDeferredBounds; RunBuffer fCurrentRunBuffer; }; #endif // SkTextBlob_DEFINED