1 | /* |
2 | * Copyright 2012 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/SkData.h" |
9 | #include "include/core/SkStream.h" |
10 | #include "src/core/SkFontDescriptor.h" |
11 | |
12 | enum { |
13 | kInvalid = 0x00, |
14 | |
15 | // these must match the sfnt 'name' enums |
16 | kFontFamilyName = 0x01, |
17 | kFullName = 0x04, |
18 | kPostscriptName = 0x06, |
19 | |
20 | // These count backwards from 0xFF, so as not to collide with the SFNT |
21 | // defines for names in its 'name' table. |
22 | kFontVariation = 0xFA, |
23 | kFontAxes = 0xFB, // Only picture version 79 and eariler. |
24 | kFontIndex = 0xFD, |
25 | kSentinel = 0xFF, |
26 | }; |
27 | |
28 | SkFontDescriptor::SkFontDescriptor() { } |
29 | |
30 | static bool SK_WARN_UNUSED_RESULT read_string(SkStream* stream, SkString* string) { |
31 | size_t length; |
32 | if (!stream->readPackedUInt(&length)) { return false; } |
33 | if (length > 0) { |
34 | string->resize(length); |
35 | if (stream->read(string->writable_str(), length) != length) { return false; } |
36 | } |
37 | return true; |
38 | } |
39 | |
40 | static bool write_string(SkWStream* stream, const SkString& string, uint32_t id) { |
41 | if (string.isEmpty()) { return true; } |
42 | return stream->writePackedUInt(id) && |
43 | stream->writePackedUInt(string.size()) && |
44 | stream->write(string.c_str(), string.size()); |
45 | } |
46 | |
47 | static bool write_uint(SkWStream* stream, size_t n, uint32_t id) { |
48 | return stream->writePackedUInt(id) && |
49 | stream->writePackedUInt(n); |
50 | } |
51 | |
52 | static size_t SK_WARN_UNUSED_RESULT read_id(SkStream* stream) { |
53 | size_t i; |
54 | if (!stream->readPackedUInt(&i)) { return kInvalid; } |
55 | return i; |
56 | } |
57 | |
58 | std::unique_ptr<SkFontData> SkFontDescriptor::maybeAsSkFontData() { |
59 | if (!fVariationDataIsOldAndBad) { |
60 | return nullptr; |
61 | } |
62 | SkFontArguments args; |
63 | args.setCollectionIndex(this->getCollectionIndex()); |
64 | args.setVariationDesignPosition({this->getVariation(), this->getVariationCoordinateCount()}); |
65 | return std::make_unique<SkFontData>(this->dupStream(), args); |
66 | } |
67 | |
68 | bool SkFontDescriptor::Deserialize(SkStream* stream, SkFontDescriptor* result) { |
69 | size_t styleBits; |
70 | if (!stream->readPackedUInt(&styleBits)) { return false; } |
71 | result->fStyle = SkFontStyle((styleBits >> 16) & 0xFFFF, |
72 | (styleBits >> 8 ) & 0xFF, |
73 | static_cast<SkFontStyle::Slant>(styleBits & 0xFF)); |
74 | bool variationDataIsNewAndGood = false; |
75 | result->fVariationDataIsOldAndBad = false; |
76 | SkFixed oldBadVariationValue; |
77 | |
78 | size_t coordinateCount; |
79 | using CoordinateCountType = decltype(result->fCoordinateCount); |
80 | |
81 | size_t index; |
82 | using CollectionIndexType = decltype(result->fCollectionIndex); |
83 | |
84 | for (size_t id; (id = read_id(stream)) != kSentinel;) { |
85 | switch (id) { |
86 | case kFontFamilyName: |
87 | if (!read_string(stream, &result->fFamilyName)) { return false; } |
88 | break; |
89 | case kFullName: |
90 | if (!read_string(stream, &result->fFullName)) { return false; } |
91 | break; |
92 | case kPostscriptName: |
93 | if (!read_string(stream, &result->fPostscriptName)) { return false; } |
94 | break; |
95 | case kFontAxes: |
96 | if (variationDataIsNewAndGood) { |
97 | if (!stream->readPackedUInt(&coordinateCount)) { return false; } |
98 | for (size_t i = 0; i < coordinateCount; ++i) { |
99 | if (!stream->readS32(&oldBadVariationValue)) { return false; } |
100 | } |
101 | } else { |
102 | if (!stream->readPackedUInt(&coordinateCount)) { return false; } |
103 | if (!SkTFitsIn<CoordinateCountType>(coordinateCount)) { return false; } |
104 | result->fCoordinateCount = SkTo<CoordinateCountType>(coordinateCount); |
105 | |
106 | result->fVariation.reset(coordinateCount); |
107 | for (size_t i = 0; i < coordinateCount; ++i) { |
108 | if (!stream->readS32(&oldBadVariationValue)) { return false; } |
109 | result->fVariation[i].axis = 0; |
110 | result->fVariation[i].value = SkFixedToScalar(oldBadVariationValue); |
111 | } |
112 | result->fVariationDataIsOldAndBad = true; |
113 | } |
114 | break; |
115 | case kFontVariation: |
116 | if (!stream->readPackedUInt(&coordinateCount)) { return false; } |
117 | if (!SkTFitsIn<CoordinateCountType>(coordinateCount)) { return false; } |
118 | result->fCoordinateCount = SkTo<CoordinateCountType>(coordinateCount); |
119 | |
120 | result->fVariation.reset(coordinateCount); |
121 | for (size_t i = 0; i < coordinateCount; ++i) { |
122 | if (!stream->readU32(&result->fVariation[i].axis)) { return false; } |
123 | if (!stream->readScalar(&result->fVariation[i].value)) { return false; } |
124 | } |
125 | variationDataIsNewAndGood = true; |
126 | result->fVariationDataIsOldAndBad = false; |
127 | break; |
128 | case kFontIndex: |
129 | if (!stream->readPackedUInt(&index)) { return false; } |
130 | if (!SkTFitsIn<CollectionIndexType>(index)) { return false; } |
131 | result->fCollectionIndex = SkTo<CollectionIndexType>(index); |
132 | break; |
133 | default: |
134 | SkDEBUGFAIL("Unknown id used by a font descriptor" ); |
135 | return false; |
136 | } |
137 | } |
138 | |
139 | size_t length; |
140 | if (!stream->readPackedUInt(&length)) { return false; } |
141 | if (length > 0) { |
142 | sk_sp<SkData> data(SkData::MakeUninitialized(length)); |
143 | if (stream->read(data->writable_data(), length) != length) { |
144 | SkDEBUGFAIL("Could not read font data" ); |
145 | return false; |
146 | } |
147 | result->fStream = SkMemoryStream::Make(std::move(data)); |
148 | } |
149 | return true; |
150 | } |
151 | |
152 | void SkFontDescriptor::serialize(SkWStream* stream) const { |
153 | uint32_t styleBits = (fStyle.weight() << 16) | (fStyle.width() << 8) | (fStyle.slant()); |
154 | stream->writePackedUInt(styleBits); |
155 | |
156 | write_string(stream, fFamilyName, kFontFamilyName); |
157 | write_string(stream, fFullName, kFullName); |
158 | write_string(stream, fPostscriptName, kPostscriptName); |
159 | |
160 | if (fCollectionIndex) { |
161 | write_uint(stream, fCollectionIndex, kFontIndex); |
162 | } |
163 | if (fCoordinateCount) { |
164 | write_uint(stream, fCoordinateCount, kFontVariation); |
165 | for (int i = 0; i < fCoordinateCount; ++i) { |
166 | stream->write32(fVariation[i].axis); |
167 | stream->writeScalar(fVariation[i].value); |
168 | } |
169 | } |
170 | |
171 | stream->writePackedUInt(kSentinel); |
172 | |
173 | if (fStream) { |
174 | std::unique_ptr<SkStreamAsset> fontStream = fStream->duplicate(); |
175 | size_t length = fontStream->getLength(); |
176 | stream->writePackedUInt(length); |
177 | stream->writeStream(fontStream.get(), length); |
178 | } else { |
179 | stream->writePackedUInt(0); |
180 | } |
181 | } |
182 | |