| /* |
| * 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 "../private/SkTemplates.h" |
| #include "../private/SkAtomics.h" |
| #include "SkPaint.h" |
| #include "SkString.h" |
| #include "SkRefCnt.h" |
| |
| struct SkSerialProcs; |
| struct SkDeserialProcs; |
| |
| /** \class SkTextBlob |
| |
| SkTextBlob combines multiple text runs into an immutable, ref-counted structure. |
| */ |
| class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> { |
| public: |
| /** |
| * Returns a conservative blob bounding box. |
| */ |
| const SkRect& bounds() const { return fBounds; } |
| |
| /** |
| * Return a non-zero, unique value representing the text blob. |
| */ |
| uint32_t uniqueID() const { return fUniqueID; } |
| |
| static sk_sp<SkTextBlob> MakeFromText( |
| const void* text, size_t byteLength, const SkPaint& paint); |
| |
| static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkPaint& paint) { |
| if (!string) { |
| return nullptr; |
| } |
| return MakeFromText(string, strlen(string), paint); |
| } |
| |
| /** |
| * Similar to serialize above, but writes directly into |memory|. Returns bytes written or 0u |
| * if serialization failed due to insufficient size. |
| */ |
| size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const; |
| |
| sk_sp<SkData> serialize(const SkSerialProcs& procs) const; |
| |
| static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, |
| const SkDeserialProcs& procs); |
| |
| private: |
| friend class SkNVRefCnt<SkTextBlob>; |
| class RunRecord; |
| |
| enum GlyphPositioning : uint8_t; |
| |
| explicit SkTextBlob(const SkRect& bounds); |
| |
| ~SkTextBlob(); |
| |
| // Memory for objects of this class is created with sk_malloc rather than operator new and must |
| // be freed with sk_free. |
| void operator delete(void* p); |
| void* operator new(size_t); |
| void* operator new(size_t, void* p); |
| |
| static unsigned ScalarsPerGlyph(GlyphPositioning pos); |
| |
| // Call when this blob is part of the key to a cache entry. This allows the cache |
| // to know automatically those entries can be purged when this SkTextBlob is deleted. |
| void notifyAddedToCache(uint32_t cacheID) const { |
| fCacheID.store(cacheID); |
| } |
| |
| friend class SkGlyphRunList; |
| friend class GrTextBlobCache; |
| friend class SkTextBlobBuilder; |
| friend class SkTextBlobPriv; |
| friend class SkTextBlobRunIterator; |
| |
| const SkRect fBounds; |
| const uint32_t fUniqueID; |
| mutable SkAtomic<uint32_t> fCacheID; |
| |
| SkDEBUGCODE(size_t fStorageSize;) |
| |
| // The actual payload resides in externally-managed storage, following the object. |
| // (see the .cpp for more details) |
| |
| typedef SkRefCnt INHERITED; |
| }; |
| |
| /** \class SkTextBlobBuilder |
| |
| Helper class for constructing SkTextBlobs. |
| */ |
| class SK_API SkTextBlobBuilder { |
| public: |
| SkTextBlobBuilder(); |
| |
| ~SkTextBlobBuilder(); |
| |
| /** |
| * Returns an immutable SkTextBlob for the current runs/glyphs, |
| * or nullptr if no runs were allocated. |
| * |
| * The builder is reset and can be reused. |
| */ |
| sk_sp<SkTextBlob> make(); |
| |
| /** |
| * Glyph and position buffers associated with a run. |
| * |
| * A run is a sequence of glyphs sharing the same font metrics |
| * and positioning mode. |
| * |
| * If textByteCount is 0, utf8text and clusters will be NULL (no |
| * character information will be associated with the glyphs). |
| * |
| * utf8text will point to a buffer of size textByteCount bytes. |
| * |
| * clusters (if not NULL) will point to an array of size count. |
| * For each glyph, give the byte-offset into the text for the |
| * first byte in the first character in that glyph's cluster. |
| * Each value in the array should be an integer less than |
| * textByteCount. Values in the array should either be |
| * monotonically increasing (left-to-right text) or monotonically |
| * decreasing (right-to-left text). This definiton is conviently |
| * the same as used by Harfbuzz's hb_glyph_info_t::cluster field, |
| * except that Harfbuzz interleaves glyphs and clusters. |
| */ |
| struct RunBuffer { |
| SkGlyphID* glyphs; |
| SkScalar* pos; |
| char* utf8text; |
| uint32_t* clusters; |
| }; |
| |
| /** |
| * 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 = nullptr) { |
| return this->allocRunText(font, count, x, y, 0, SkString(), bounds); |
| } |
| |
| /** |
| * 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 = nullptr) { |
| return this->allocRunTextPosH(font, count, y, 0, SkString(), bounds); |
| } |
| |
| /** |
| * 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 = nullptr) { |
| return this->allocRunTextPos(font, count, 0, SkString(), bounds); |
| } |
| |
| private: |
| const RunBuffer& allocRunText(const SkPaint& font, |
| int count, |
| SkScalar x, |
| SkScalar y, |
| int textByteCount, |
| SkString lang, |
| const SkRect* bounds = nullptr); |
| const RunBuffer& allocRunTextPosH(const SkPaint& font, int count, SkScalar y, |
| int textByteCount, SkString lang, |
| const SkRect* bounds = nullptr); |
| const RunBuffer& allocRunTextPos(const SkPaint& font, int count, |
| int textByteCount, SkString lang, |
| const SkRect* bounds = nullptr); |
| void reserve(size_t size); |
| void allocInternal(const SkPaint& font, SkTextBlob::GlyphPositioning positioning, |
| int count, int textBytes, SkPoint offset, const SkRect* bounds); |
| bool mergeRun(const SkPaint& font, SkTextBlob::GlyphPositioning positioning, |
| uint32_t count, SkPoint offset); |
| void updateDeferredBounds(); |
| |
| static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&); |
| static SkRect TightRunBounds(const SkTextBlob::RunRecord&); |
| |
| friend class SkTextBlobPriv; |
| friend class SkTextBlobBuilderPriv; |
| |
| SkAutoTMalloc<uint8_t> fStorage; |
| size_t fStorageSize; |
| size_t fStorageUsed; |
| |
| SkRect fBounds; |
| int fRunCount; |
| bool fDeferredBounds; |
| size_t fLastRun; // index into fStorage |
| |
| RunBuffer fCurrentRunBuffer; |
| }; |
| |
| #endif // SkTextBlob_DEFINED |