1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkTextBlobPriv_DEFINED 9 #define SkTextBlobPriv_DEFINED 10 11 #include "SkColorFilter.h" 12 #include "SkDrawLooper.h" 13 #include "SkFont.h" 14 #include "SkImageFilter.h" 15 #include "SkMaskFilter.h" 16 #include "SkPaintPriv.h" 17 #include "SkPathEffect.h" 18 #include "SkSafeMath.h" 19 #include "SkShader.h" 20 #include "SkTextBlob.h" 21 #include "SkTypeface.h" 22 23 class SkReadBuffer; 24 class SkWriteBuffer; 25 26 class SkTextBlobPriv { 27 public: 28 /** 29 * Serialize to a buffer. 30 */ 31 static void Flatten(const SkTextBlob& , SkWriteBuffer&); 32 33 /** 34 * Recreate an SkTextBlob that was serialized into a buffer. 35 * 36 * @param SkReadBuffer Serialized blob data. 37 * @return A new SkTextBlob representing the serialized data, or NULL if the buffer is 38 * invalid. 39 */ 40 static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&); 41 }; 42 43 class SkTextBlobBuilderPriv { 44 public: 45 static const SkTextBlobBuilder::RunBuffer& AllocRunText(SkTextBlobBuilder* builder, 46 const SkFont& font, int count, SkScalar x, SkScalar y, int textByteCount, 47 SkString lang, const SkRect* bounds = nullptr) { 48 return builder->allocRunText(font, count, x, y, textByteCount, lang, bounds); 49 } 50 static const SkTextBlobBuilder::RunBuffer& AllocRunTextPosH(SkTextBlobBuilder* builder, 51 const SkFont& font, int count, SkScalar y, int textByteCount, SkString lang, 52 const SkRect* bounds = nullptr) { 53 return builder->allocRunTextPosH(font, count, y, textByteCount, lang, bounds); 54 } 55 static const SkTextBlobBuilder::RunBuffer& AllocRunTextPos(SkTextBlobBuilder* builder, 56 const SkFont& font, int count, int textByteCount, SkString lang, 57 const SkRect* bounds = nullptr) { 58 return builder->allocRunTextPos(font, count, textByteCount, lang, bounds); 59 } 60 }; 61 62 // 63 // Textblob data is laid out into externally-managed storage as follows: 64 // 65 // ----------------------------------------------------------------------------- 66 // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... 67 // ----------------------------------------------------------------------------- 68 // 69 // Each run record describes a text blob run, and can be used to determine the (implicit) 70 // location of the following record. 71 // 72 // Extended Textblob runs have more data after the Pos[] array: 73 // 74 // ------------------------------------------------------------------------- 75 // ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ... 76 // ------------------------------------------------------------------------- 77 // 78 // To determine the length of the extended run data, the TextSize must be read. 79 // 80 // Extended Textblob runs may be mixed with non-extended runs. 81 82 SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) 83 84 class SkTextBlob::RunRecord { 85 public: RunRecord(uint32_t count,uint32_t textSize,const SkPoint & offset,const SkFont & font,GlyphPositioning pos)86 RunRecord(uint32_t count, uint32_t textSize, const SkPoint& offset, const SkFont& font, GlyphPositioning pos) 87 : fFont(font) 88 , fCount(count) 89 , fOffset(offset) 90 , fFlags(pos) { 91 SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask); 92 93 SkDEBUGCODE(fMagic = kRunRecordMagic); 94 if (textSize > 0) { 95 fFlags |= kExtended_Flag; 96 *this->textSizePtr() = textSize; 97 } 98 } 99 glyphCount()100 uint32_t glyphCount() const { 101 return fCount; 102 } 103 offset()104 const SkPoint& offset() const { 105 return fOffset; 106 } 107 font()108 const SkFont& font() const { 109 return fFont; 110 } 111 positioning()112 GlyphPositioning positioning() const { 113 return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask); 114 } 115 glyphBuffer()116 uint16_t* glyphBuffer() const { 117 static_assert(SkIsAlignPtr(sizeof(RunRecord)), ""); 118 // Glyphs are stored immediately following the record. 119 return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); 120 } 121 122 // can be aliased with pointBuffer() or xformBuffer() posBuffer()123 SkScalar* posBuffer() const { 124 // Position scalars follow the (aligned) glyph buffer. 125 return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) + 126 SkAlign4(fCount * sizeof(uint16_t))); 127 } 128 129 // alias for posBuffer() pointBuffer()130 SkPoint* pointBuffer() const { 131 SkASSERT(this->positioning() == (GlyphPositioning)2); 132 return reinterpret_cast<SkPoint*>(this->posBuffer()); 133 } 134 135 // alias for posBuffer() xformBuffer()136 SkRSXform* xformBuffer() const { 137 SkASSERT(this->positioning() == (GlyphPositioning)3); 138 return reinterpret_cast<SkRSXform*>(this->posBuffer()); 139 } 140 textSize()141 uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; } 142 clusterBuffer()143 uint32_t* clusterBuffer() const { 144 // clusters follow the textSize. 145 return isExtended() ? 1 + this->textSizePtr() : nullptr; 146 } 147 textBuffer()148 char* textBuffer() const { 149 return isExtended() 150 ? reinterpret_cast<char*>(this->clusterBuffer() + fCount) 151 : nullptr; 152 } 153 154 static size_t StorageSize(uint32_t glyphCount, uint32_t textSize, 155 SkTextBlob::GlyphPositioning positioning, 156 SkSafeMath* safe); 157 158 static const RunRecord* First(const SkTextBlob* blob); 159 160 static const RunRecord* Next(const RunRecord* run); 161 162 void validate(const uint8_t* storageTop) const; 163 164 private: 165 friend class SkTextBlobBuilder; 166 167 enum Flags { 168 kPositioning_Mask = 0x03, // bits 0-1 reserved for positioning 169 kLast_Flag = 0x04, // set for the last blob run 170 kExtended_Flag = 0x08, // set for runs with text/cluster info 171 }; 172 173 static const RunRecord* NextUnchecked(const RunRecord* run); 174 175 static size_t PosCount(uint32_t glyphCount, 176 SkTextBlob::GlyphPositioning positioning, 177 SkSafeMath* safe); 178 179 uint32_t* textSizePtr() const; 180 181 void grow(uint32_t count); 182 isExtended()183 bool isExtended() const { 184 return fFlags & kExtended_Flag; 185 } 186 187 SkFont fFont; 188 uint32_t fCount; 189 SkPoint fOffset; 190 uint32_t fFlags; 191 192 SkDEBUGCODE(unsigned fMagic;) 193 }; 194 195 /** 196 * Iterate through all of the text runs of the text blob. For example: 197 * for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) { 198 * ..... 199 * } 200 */ 201 class SkTextBlobRunIterator { 202 public: 203 SkTextBlobRunIterator(const SkTextBlob* blob); 204 205 enum GlyphPositioning : uint8_t { 206 kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph. 207 kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph. 208 kFull_Positioning = 2, // Point positioning -- two scalars per glyph. 209 kRSXform_Positioning = 3, // RSXform positioning -- four scalars per glyph. 210 }; 211 done()212 bool done() const { 213 return !fCurrentRun; 214 } 215 void next(); 216 glyphCount()217 uint32_t glyphCount() const { 218 SkASSERT(!this->done()); 219 return fCurrentRun->glyphCount(); 220 } glyphs()221 const uint16_t* glyphs() const { 222 SkASSERT(!this->done()); 223 return fCurrentRun->glyphBuffer(); 224 } pos()225 const SkScalar* pos() const { 226 SkASSERT(!this->done()); 227 return fCurrentRun->posBuffer(); 228 } 229 // alias for pos() points()230 const SkPoint* points() const { 231 return fCurrentRun->pointBuffer(); 232 } 233 // alias for pos() xforms()234 const SkRSXform* xforms() const { 235 return fCurrentRun->xformBuffer(); 236 } offset()237 const SkPoint& offset() const { 238 SkASSERT(!this->done()); 239 return fCurrentRun->offset(); 240 } font()241 const SkFont& font() const { 242 SkASSERT(!this->done()); 243 return fCurrentRun->font(); 244 } 245 GlyphPositioning positioning() const; clusters()246 uint32_t* clusters() const { 247 SkASSERT(!this->done()); 248 return fCurrentRun->clusterBuffer(); 249 } textSize()250 uint32_t textSize() const { 251 SkASSERT(!this->done()); 252 return fCurrentRun->textSize(); 253 } text()254 char* text() const { 255 SkASSERT(!this->done()); 256 return fCurrentRun->textBuffer(); 257 } 258 259 bool isLCD() const; 260 261 private: 262 const SkTextBlob::RunRecord* fCurrentRun; 263 264 SkDEBUGCODE(uint8_t* fStorageTop;) 265 }; 266 267 #endif // SkTextBlobPriv_DEFINED 268