| 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 SkFontPriv_DEFINED | 
|---|
| 9 | #define SkFontPriv_DEFINED | 
|---|
| 10 |  | 
|---|
| 11 | #include "include/core/SkFont.h" | 
|---|
| 12 | #include "include/core/SkMatrix.h" | 
|---|
| 13 | #include "include/core/SkTypeface.h" | 
|---|
| 14 |  | 
|---|
| 15 | class SkReadBuffer; | 
|---|
| 16 | class SkWriteBuffer; | 
|---|
| 17 |  | 
|---|
| 18 | class SkFontPriv { | 
|---|
| 19 | public: | 
|---|
| 20 | /*  This is the size we use when we ask for a glyph's path. We then | 
|---|
| 21 | *  post-transform it as we draw to match the request. | 
|---|
| 22 | *  This is done to try to re-use cache entries for the path. | 
|---|
| 23 | * | 
|---|
| 24 | *  This value is somewhat arbitrary. In theory, it could be 1, since | 
|---|
| 25 | *  we store paths as floats. However, we get the path from the font | 
|---|
| 26 | *  scaler, and it may represent its paths as fixed-point (or 26.6), | 
|---|
| 27 | *  so we shouldn't ask for something too big (might overflow 16.16) | 
|---|
| 28 | *  or too small (underflow 26.6). | 
|---|
| 29 | * | 
|---|
| 30 | *  This value could track kMaxSizeForGlyphCache, assuming the above | 
|---|
| 31 | *  constraints, but since we ask for unhinted paths, the two values | 
|---|
| 32 | *  need not match per-se. | 
|---|
| 33 | */ | 
|---|
| 34 | static constexpr int kCanonicalTextSizeForPaths  = 64; | 
|---|
| 35 |  | 
|---|
| 36 | /** | 
|---|
| 37 | *  Return a matrix that applies the paint's text values: size, scale, skew | 
|---|
| 38 | */ | 
|---|
| 39 | static SkMatrix MakeTextMatrix(SkScalar size, SkScalar scaleX, SkScalar skewX) { | 
|---|
| 40 | SkMatrix m = SkMatrix::MakeScale(size * scaleX, size); | 
|---|
| 41 | if (skewX) { | 
|---|
| 42 | m.postSkew(skewX, 0); | 
|---|
| 43 | } | 
|---|
| 44 | return m; | 
|---|
| 45 | } | 
|---|
| 46 |  | 
|---|
| 47 | static SkMatrix MakeTextMatrix(const SkFont& font) { | 
|---|
| 48 | return MakeTextMatrix(font.getSize(), font.getScaleX(), font.getSkewX()); | 
|---|
| 49 | } | 
|---|
| 50 |  | 
|---|
| 51 | static void ScaleFontMetrics(SkFontMetrics*, SkScalar); | 
|---|
| 52 |  | 
|---|
| 53 | /** | 
|---|
| 54 | Returns the union of bounds of all glyphs. | 
|---|
| 55 | Returned dimensions are computed by font manager from font data, | 
|---|
| 56 | ignoring SkPaint::Hinting. Includes font metrics, but not fake bold or SkPathEffect. | 
|---|
| 57 |  | 
|---|
| 58 | If text size is large, text scale is one, and text skew is zero, | 
|---|
| 59 | returns the bounds as: | 
|---|
| 60 | { SkFontMetrics::fXMin, SkFontMetrics::fTop, SkFontMetrics::fXMax, SkFontMetrics::fBottom }. | 
|---|
| 61 |  | 
|---|
| 62 | @return  union of bounds of all glyphs | 
|---|
| 63 | */ | 
|---|
| 64 | static SkRect GetFontBounds(const SkFont&); | 
|---|
| 65 |  | 
|---|
| 66 | static bool IsFinite(const SkFont& font) { | 
|---|
| 67 | return SkScalarIsFinite(font.getSize()) && | 
|---|
| 68 | SkScalarIsFinite(font.getScaleX()) && | 
|---|
| 69 | SkScalarIsFinite(font.getSkewX()); | 
|---|
| 70 | } | 
|---|
| 71 |  | 
|---|
| 72 | // Returns the number of elements (characters or glyphs) in the array. | 
|---|
| 73 | static int CountTextElements(const void* text, size_t byteLength, SkTextEncoding); | 
|---|
| 74 |  | 
|---|
| 75 | static void GlyphsToUnichars(const SkFont&, const uint16_t glyphs[], int count, SkUnichar[]); | 
|---|
| 76 |  | 
|---|
| 77 | static void Flatten(const SkFont&, SkWriteBuffer& buffer); | 
|---|
| 78 | static bool Unflatten(SkFont*, SkReadBuffer& buffer); | 
|---|
| 79 |  | 
|---|
| 80 | static inline uint8_t Flags(const SkFont& font) { return font.fFlags; } | 
|---|
| 81 | }; | 
|---|
| 82 |  | 
|---|
| 83 | class SkAutoToGlyphs { | 
|---|
| 84 | public: | 
|---|
| 85 | SkAutoToGlyphs(const SkFont& font, const void* text, size_t length, SkTextEncoding encoding) { | 
|---|
| 86 | if (encoding == SkTextEncoding::kGlyphID || length == 0) { | 
|---|
| 87 | fGlyphs = reinterpret_cast<const uint16_t*>(text); | 
|---|
| 88 | fCount = length >> 1; | 
|---|
| 89 | } else { | 
|---|
| 90 | fCount = font.countText(text, length, encoding); | 
|---|
| 91 | if (fCount < 0) { | 
|---|
| 92 | fCount = 0; | 
|---|
| 93 | } | 
|---|
| 94 | fStorage.reset(fCount); | 
|---|
| 95 | font.textToGlyphs(text, length, encoding, fStorage.get(), fCount); | 
|---|
| 96 | fGlyphs = fStorage.get(); | 
|---|
| 97 | } | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | int count() const { return fCount; } | 
|---|
| 101 | const uint16_t* glyphs() const { return fGlyphs; } | 
|---|
| 102 |  | 
|---|
| 103 | private: | 
|---|
| 104 | SkAutoSTArray<32, uint16_t> fStorage; | 
|---|
| 105 | const uint16_t* fGlyphs; | 
|---|
| 106 | int             fCount; | 
|---|
| 107 | }; | 
|---|
| 108 |  | 
|---|
| 109 | #endif | 
|---|
| 110 |  | 
|---|