1 /* 2 * Copyright 2014 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 #include "include/core/SkTypeface.h" 9 #include "include/private/SkTo.h" 10 #include "src/core/SkFontPriv.h" 11 #include "src/core/SkReadBuffer.h" 12 #include "src/core/SkWriteBuffer.h" 13 14 // packed int at the beginning of the serialized font: 15 // 16 // control_bits:8 size_as_byte:8 flags:12 edging:2 hinting:2 17 18 enum { 19 kSize_Is_Byte_Bit = 1 << 31, 20 kHas_ScaleX_Bit = 1 << 30, 21 kHas_SkewX_Bit = 1 << 29, 22 kHas_Typeface_Bit = 1 << 28, 23 24 kShift_for_Size = 16, 25 kMask_For_Size = 0xFF, 26 27 kShift_For_Flags = 4, 28 kMask_For_Flags = 0xFFF, 29 30 kShift_For_Edging = 2, 31 kMask_For_Edging = 0x3, 32 33 kShift_For_Hinting = 0, 34 kMask_For_Hinting = 0x3 35 }; 36 scalar_is_byte(SkScalar x)37 static bool scalar_is_byte(SkScalar x) { 38 int ix = (int)x; 39 return ix == x && ix >= 0 && ix <= kMask_For_Size; 40 } 41 Flatten(const SkFont & font,SkWriteBuffer & buffer)42 void SkFontPriv::Flatten(const SkFont& font, SkWriteBuffer& buffer) { 43 SkASSERT(font.fFlags <= SkFont::kAllFlags); 44 SkASSERT((font.fFlags & ~kMask_For_Flags) == 0); 45 SkASSERT((font.fEdging & ~kMask_For_Edging) == 0); 46 SkASSERT((font.fHinting & ~kMask_For_Hinting) == 0); 47 48 uint32_t packed = 0; 49 packed |= font.fFlags << kShift_For_Flags; 50 packed |= font.fEdging << kShift_For_Edging; 51 packed |= font.fHinting << kShift_For_Hinting; 52 53 if (scalar_is_byte(font.fSize)) { 54 packed |= kSize_Is_Byte_Bit; 55 packed |= (int)font.fSize << kShift_for_Size; 56 } 57 if (font.fScaleX != 1) { 58 packed |= kHas_ScaleX_Bit; 59 } 60 if (font.fSkewX != 0) { 61 packed |= kHas_SkewX_Bit; 62 } 63 if (font.fTypeface) { 64 packed |= kHas_Typeface_Bit; 65 } 66 67 buffer.write32(packed); 68 if (!(packed & kSize_Is_Byte_Bit)) { 69 buffer.writeScalar(font.fSize); 70 } 71 if (packed & kHas_ScaleX_Bit) { 72 buffer.writeScalar(font.fScaleX); 73 } 74 if (packed & kHas_SkewX_Bit) { 75 buffer.writeScalar(font.fSkewX); 76 } 77 if (packed & kHas_Typeface_Bit) { 78 buffer.writeTypeface(font.fTypeface.get()); 79 } 80 } 81 Unflatten(SkFont * font,SkReadBuffer & buffer)82 bool SkFontPriv::Unflatten(SkFont* font, SkReadBuffer& buffer) { 83 const uint32_t packed = buffer.read32(); 84 85 if (packed & kSize_Is_Byte_Bit) { 86 font->fSize = (packed >> kShift_for_Size) & kMask_For_Size; 87 } else { 88 font->fSize = buffer.readScalar(); 89 } 90 if (packed & kHas_ScaleX_Bit) { 91 font->fScaleX = buffer.readScalar(); 92 } 93 if (packed & kHas_SkewX_Bit) { 94 font->fSkewX = buffer.readScalar(); 95 } 96 if (packed & kHas_Typeface_Bit) { 97 font->fTypeface = buffer.readTypeface(); 98 } 99 100 SkASSERT(SkFont::kAllFlags <= kMask_For_Flags); 101 // we & with kAllFlags, to clear out any unknown flag bits 102 font->fFlags = SkToU8((packed >> kShift_For_Flags) & SkFont::kAllFlags); 103 104 unsigned edging = (packed >> kShift_For_Edging) & kMask_For_Edging; 105 if (edging > (unsigned)SkFont::Edging::kSubpixelAntiAlias) { 106 edging = 0; 107 } 108 font->fEdging = SkToU8(edging); 109 110 unsigned hinting = (packed >> kShift_For_Hinting) & kMask_For_Hinting; 111 if (hinting > (unsigned)SkFontHinting::kFull) { 112 hinting = 0; 113 } 114 font->fHinting = SkToU8(hinting); 115 116 return buffer.isValid(); 117 } 118