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
18enum {
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
37static bool scalar_is_byte(SkScalar x) {
38 int ix = (int)x;
39 return ix == x && ix >= 0 && ix <= kMask_For_Size;
40}
41
42void 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
82bool 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