123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*
- * Copyright 2018 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkTextBlobPriv_DEFINED
- #define SkTextBlobPriv_DEFINED
- #include "include/core/SkColorFilter.h"
- #include "include/core/SkDrawLooper.h"
- #include "include/core/SkFont.h"
- #include "include/core/SkImageFilter.h"
- #include "include/core/SkMaskFilter.h"
- #include "include/core/SkPathEffect.h"
- #include "include/core/SkShader.h"
- #include "include/core/SkTextBlob.h"
- #include "include/core/SkTypeface.h"
- #include "src/core/SkPaintPriv.h"
- #include "src/core/SkSafeMath.h"
- class SkReadBuffer;
- class SkWriteBuffer;
- class SkTextBlobPriv {
- public:
- /**
- * Serialize to a buffer.
- */
- static void Flatten(const SkTextBlob& , SkWriteBuffer&);
- /**
- * 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 sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&);
- };
- class SkTextBlobBuilderPriv {
- public:
- static const SkTextBlobBuilder::RunBuffer& AllocRunText(SkTextBlobBuilder* builder,
- const SkFont& font, int count, SkScalar x, SkScalar y, int textByteCount,
- SkString lang, const SkRect* bounds = nullptr) {
- return builder->allocRunText(font, count, x, y, textByteCount, lang, bounds);
- }
- static const SkTextBlobBuilder::RunBuffer& AllocRunTextPosH(SkTextBlobBuilder* builder,
- const SkFont& font, int count, SkScalar y, int textByteCount, SkString lang,
- const SkRect* bounds = nullptr) {
- return builder->allocRunTextPosH(font, count, y, textByteCount, lang, bounds);
- }
- static const SkTextBlobBuilder::RunBuffer& AllocRunTextPos(SkTextBlobBuilder* builder,
- const SkFont& font, int count, int textByteCount, SkString lang,
- const SkRect* bounds = nullptr) {
- return builder->allocRunTextPos(font, count, textByteCount, lang, bounds);
- }
- };
- //
- // Textblob data is laid out into externally-managed storage as follows:
- //
- // -----------------------------------------------------------------------------
- // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ...
- // -----------------------------------------------------------------------------
- //
- // Each run record describes a text blob run, and can be used to determine the (implicit)
- // location of the following record.
- //
- // Extended Textblob runs have more data after the Pos[] array:
- //
- // -------------------------------------------------------------------------
- // ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ...
- // -------------------------------------------------------------------------
- //
- // To determine the length of the extended run data, the TextSize must be read.
- //
- // Extended Textblob runs may be mixed with non-extended runs.
- SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;)
- class SkTextBlob::RunRecord {
- public:
- RunRecord(uint32_t count, uint32_t textSize, const SkPoint& offset, const SkFont& font, GlyphPositioning pos)
- : fFont(font)
- , fCount(count)
- , fOffset(offset)
- , fFlags(pos) {
- SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask);
- SkDEBUGCODE(fMagic = kRunRecordMagic);
- if (textSize > 0) {
- fFlags |= kExtended_Flag;
- *this->textSizePtr() = textSize;
- }
- }
- uint32_t glyphCount() const {
- return fCount;
- }
- const SkPoint& offset() const {
- return fOffset;
- }
- const SkFont& font() const {
- return fFont;
- }
- GlyphPositioning positioning() const {
- return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask);
- }
- uint16_t* glyphBuffer() const {
- static_assert(SkIsAlignPtr(sizeof(RunRecord)), "");
- // Glyphs are stored immediately following the record.
- return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1);
- }
- // can be aliased with pointBuffer() or xformBuffer()
- SkScalar* posBuffer() const {
- // Position scalars follow the (aligned) glyph buffer.
- return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) +
- SkAlign4(fCount * sizeof(uint16_t)));
- }
- // alias for posBuffer()
- SkPoint* pointBuffer() const {
- SkASSERT(this->positioning() == (GlyphPositioning)2);
- return reinterpret_cast<SkPoint*>(this->posBuffer());
- }
- // alias for posBuffer()
- SkRSXform* xformBuffer() const {
- SkASSERT(this->positioning() == (GlyphPositioning)3);
- return reinterpret_cast<SkRSXform*>(this->posBuffer());
- }
- uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; }
- uint32_t* clusterBuffer() const {
- // clusters follow the textSize.
- return isExtended() ? 1 + this->textSizePtr() : nullptr;
- }
- char* textBuffer() const {
- return isExtended()
- ? reinterpret_cast<char*>(this->clusterBuffer() + fCount)
- : nullptr;
- }
- static size_t StorageSize(uint32_t glyphCount, uint32_t textSize,
- SkTextBlob::GlyphPositioning positioning,
- SkSafeMath* safe);
- static const RunRecord* First(const SkTextBlob* blob);
- static const RunRecord* Next(const RunRecord* run);
- void validate(const uint8_t* storageTop) const;
- private:
- friend class SkTextBlobBuilder;
- enum Flags {
- kPositioning_Mask = 0x03, // bits 0-1 reserved for positioning
- kLast_Flag = 0x04, // set for the last blob run
- kExtended_Flag = 0x08, // set for runs with text/cluster info
- };
- static const RunRecord* NextUnchecked(const RunRecord* run);
- static size_t PosCount(uint32_t glyphCount,
- SkTextBlob::GlyphPositioning positioning,
- SkSafeMath* safe);
- uint32_t* textSizePtr() const;
- void grow(uint32_t count);
- bool isExtended() const {
- return fFlags & kExtended_Flag;
- }
- SkFont fFont;
- uint32_t fCount;
- SkPoint fOffset;
- uint32_t fFlags;
- SkDEBUGCODE(unsigned fMagic;)
- };
- /**
- * Iterate through all of the text runs of the text blob. For example:
- * for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) {
- * .....
- * }
- */
- class SkTextBlobRunIterator {
- public:
- SkTextBlobRunIterator(const SkTextBlob* blob);
- enum GlyphPositioning : uint8_t {
- 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.
- kRSXform_Positioning = 3, // RSXform positioning -- four scalars per glyph.
- };
- bool done() const {
- return !fCurrentRun;
- }
- void next();
- uint32_t glyphCount() const {
- SkASSERT(!this->done());
- return fCurrentRun->glyphCount();
- }
- const uint16_t* glyphs() const {
- SkASSERT(!this->done());
- return fCurrentRun->glyphBuffer();
- }
- const SkScalar* pos() const {
- SkASSERT(!this->done());
- return fCurrentRun->posBuffer();
- }
- // alias for pos()
- const SkPoint* points() const {
- return fCurrentRun->pointBuffer();
- }
- // alias for pos()
- const SkRSXform* xforms() const {
- return fCurrentRun->xformBuffer();
- }
- const SkPoint& offset() const {
- SkASSERT(!this->done());
- return fCurrentRun->offset();
- }
- const SkFont& font() const {
- SkASSERT(!this->done());
- return fCurrentRun->font();
- }
- GlyphPositioning positioning() const;
- uint32_t* clusters() const {
- SkASSERT(!this->done());
- return fCurrentRun->clusterBuffer();
- }
- uint32_t textSize() const {
- SkASSERT(!this->done());
- return fCurrentRun->textSize();
- }
- char* text() const {
- SkASSERT(!this->done());
- return fCurrentRun->textBuffer();
- }
- bool isLCD() const;
- private:
- const SkTextBlob::RunRecord* fCurrentRun;
- SkDEBUGCODE(uint8_t* fStorageTop;)
- };
- #endif // SkTextBlobPriv_DEFINED
|