xref: /third_party/skia/src/core/SkFont_serial.cpp (revision cb93a386)
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