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