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