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 | |
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 | |
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 | |
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 | |