1/*
2 * Copyright (C) 2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FontVariantBuilder.h"
28
29#include "CSSPrimitiveValue.h"
30#include "CSSValueList.h"
31#include "CSSValuePool.h"
32#include "TextFlags.h"
33
34namespace WebCore {
35
36FontVariantLigaturesValues extractFontVariantLigatures(const CSSValue& value)
37{
38 FontVariantLigatures common = FontVariantLigatures::Normal;
39 FontVariantLigatures discretionary = FontVariantLigatures::Normal;
40 FontVariantLigatures historical = FontVariantLigatures::Normal;
41 FontVariantLigatures contextualAlternates = FontVariantLigatures::Normal;
42
43 if (is<CSSValueList>(value)) {
44 for (auto& item : downcast<CSSValueList>(value)) {
45 switch (downcast<CSSPrimitiveValue>(item.get()).valueID()) {
46 case CSSValueNoCommonLigatures:
47 common = FontVariantLigatures::No;
48 break;
49 case CSSValueCommonLigatures:
50 common = FontVariantLigatures::Yes;
51 break;
52 case CSSValueNoDiscretionaryLigatures:
53 discretionary = FontVariantLigatures::No;
54 break;
55 case CSSValueDiscretionaryLigatures:
56 discretionary = FontVariantLigatures::Yes;
57 break;
58 case CSSValueNoHistoricalLigatures:
59 historical = FontVariantLigatures::No;
60 break;
61 case CSSValueHistoricalLigatures:
62 historical = FontVariantLigatures::Yes;
63 break;
64 case CSSValueContextual:
65 contextualAlternates = FontVariantLigatures::Yes;
66 break;
67 case CSSValueNoContextual:
68 contextualAlternates = FontVariantLigatures::No;
69 break;
70 default:
71 ASSERT_NOT_REACHED();
72 break;
73 }
74 }
75 } else if (is<CSSPrimitiveValue>(value)) {
76 switch (downcast<CSSPrimitiveValue>(value).valueID()) {
77 case CSSValueNormal:
78 break;
79 case CSSValueNone:
80 common = FontVariantLigatures::No;
81 discretionary = FontVariantLigatures::No;
82 historical = FontVariantLigatures::No;
83 contextualAlternates = FontVariantLigatures::No;
84 break;
85 default:
86 ASSERT_NOT_REACHED();
87 break;
88 }
89 }
90
91 return FontVariantLigaturesValues(common, discretionary, historical, contextualAlternates);
92}
93
94FontVariantNumericValues extractFontVariantNumeric(const CSSValue& value)
95{
96 FontVariantNumericFigure figure = FontVariantNumericFigure::Normal;
97 FontVariantNumericSpacing spacing = FontVariantNumericSpacing::Normal;
98 FontVariantNumericFraction fraction = FontVariantNumericFraction::Normal;
99 FontVariantNumericOrdinal ordinal = FontVariantNumericOrdinal::Normal;
100 FontVariantNumericSlashedZero slashedZero = FontVariantNumericSlashedZero::Normal;
101
102 if (is<CSSValueList>(value)) {
103 for (auto& item : downcast<CSSValueList>(value)) {
104 switch (downcast<CSSPrimitiveValue>(item.get()).valueID()) {
105 case CSSValueLiningNums:
106 figure = FontVariantNumericFigure::LiningNumbers;
107 break;
108 case CSSValueOldstyleNums:
109 figure = FontVariantNumericFigure::OldStyleNumbers;
110 break;
111 case CSSValueProportionalNums:
112 spacing = FontVariantNumericSpacing::ProportionalNumbers;
113 break;
114 case CSSValueTabularNums:
115 spacing = FontVariantNumericSpacing::TabularNumbers;
116 break;
117 case CSSValueDiagonalFractions:
118 fraction = FontVariantNumericFraction::DiagonalFractions;
119 break;
120 case CSSValueStackedFractions:
121 fraction = FontVariantNumericFraction::StackedFractions;
122 break;
123 case CSSValueOrdinal:
124 ordinal = FontVariantNumericOrdinal::Yes;
125 break;
126 case CSSValueSlashedZero:
127 slashedZero = FontVariantNumericSlashedZero::Yes;
128 break;
129 default:
130 ASSERT_NOT_REACHED();
131 break;
132 }
133 }
134 } else if (is<CSSPrimitiveValue>(value))
135 ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal);
136
137 return FontVariantNumericValues(figure, spacing, fraction, ordinal, slashedZero);
138}
139
140FontVariantEastAsianValues extractFontVariantEastAsian(const CSSValue& value)
141{
142 FontVariantEastAsianVariant variant = FontVariantEastAsianVariant::Normal;
143 FontVariantEastAsianWidth width = FontVariantEastAsianWidth::Normal;
144 FontVariantEastAsianRuby ruby = FontVariantEastAsianRuby::Normal;
145
146 if (is<CSSValueList>(value)) {
147 for (auto& item : downcast<CSSValueList>(value)) {
148 switch (downcast<CSSPrimitiveValue>(item.get()).valueID()) {
149 case CSSValueJis78:
150 variant = FontVariantEastAsianVariant::Jis78;
151 break;
152 case CSSValueJis83:
153 variant = FontVariantEastAsianVariant::Jis83;
154 break;
155 case CSSValueJis90:
156 variant = FontVariantEastAsianVariant::Jis90;
157 break;
158 case CSSValueJis04:
159 variant = FontVariantEastAsianVariant::Jis04;
160 break;
161 case CSSValueSimplified:
162 variant = FontVariantEastAsianVariant::Simplified;
163 break;
164 case CSSValueTraditional:
165 variant = FontVariantEastAsianVariant::Traditional;
166 break;
167 case CSSValueFullWidth:
168 width = FontVariantEastAsianWidth::Full;
169 break;
170 case CSSValueProportionalWidth:
171 width = FontVariantEastAsianWidth::Proportional;
172 break;
173 case CSSValueRuby:
174 ruby = FontVariantEastAsianRuby::Yes;
175 break;
176 default:
177 ASSERT_NOT_REACHED();
178 break;
179 }
180 }
181 } else if (is<CSSPrimitiveValue>(value))
182 ASSERT(downcast<CSSPrimitiveValue>(value).valueID() == CSSValueNormal);
183
184 return FontVariantEastAsianValues(variant, width, ruby);
185}
186
187Ref<CSSValue> computeFontVariant(const FontVariantSettings& variantSettings)
188{
189 if (variantSettings.isAllNormal())
190 return CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
191
192 auto list = CSSValueList::createSpaceSeparated();
193
194 switch (variantSettings.commonLigatures) {
195 case FontVariantLigatures::Normal:
196 break;
197 case FontVariantLigatures::Yes:
198 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueCommonLigatures));
199 break;
200 case FontVariantLigatures::No:
201 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoCommonLigatures));
202 break;
203 }
204
205 switch (variantSettings.discretionaryLigatures) {
206 case FontVariantLigatures::Normal:
207 break;
208 case FontVariantLigatures::Yes:
209 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiscretionaryLigatures));
210 break;
211 case FontVariantLigatures::No:
212 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoDiscretionaryLigatures));
213 break;
214 }
215
216 switch (variantSettings.historicalLigatures) {
217 case FontVariantLigatures::Normal:
218 break;
219 case FontVariantLigatures::Yes:
220 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalLigatures));
221 break;
222 case FontVariantLigatures::No:
223 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoHistoricalLigatures));
224 break;
225 }
226
227 switch (variantSettings.contextualAlternates) {
228 case FontVariantLigatures::Normal:
229 break;
230 case FontVariantLigatures::Yes:
231 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueContextual));
232 break;
233 case FontVariantLigatures::No:
234 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueNoContextual));
235 break;
236 }
237
238 switch (variantSettings.position) {
239 case FontVariantPosition::Normal:
240 break;
241 case FontVariantPosition::Subscript:
242 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSub));
243 break;
244 case FontVariantPosition::Superscript:
245 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSuper));
246 break;
247 }
248
249 switch (variantSettings.caps) {
250 case FontVariantCaps::Normal:
251 break;
252 case FontVariantCaps::Small:
253 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSmallCaps));
254 break;
255 case FontVariantCaps::AllSmall:
256 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllSmallCaps));
257 break;
258 case FontVariantCaps::Petite:
259 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValuePetiteCaps));
260 break;
261 case FontVariantCaps::AllPetite:
262 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueAllPetiteCaps));
263 break;
264 case FontVariantCaps::Unicase:
265 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueUnicase));
266 break;
267 case FontVariantCaps::Titling:
268 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTitlingCaps));
269 break;
270 }
271
272 switch (variantSettings.numericFigure) {
273 case FontVariantNumericFigure::Normal:
274 break;
275 case FontVariantNumericFigure::LiningNumbers:
276 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueLiningNums));
277 break;
278 case FontVariantNumericFigure::OldStyleNumbers:
279 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueOldstyleNums));
280 break;
281 }
282
283 switch (variantSettings.numericSpacing) {
284 case FontVariantNumericSpacing::Normal:
285 break;
286 case FontVariantNumericSpacing::ProportionalNumbers:
287 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalNums));
288 break;
289 case FontVariantNumericSpacing::TabularNumbers:
290 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTabularNums));
291 break;
292 }
293
294 switch (variantSettings.numericFraction) {
295 case FontVariantNumericFraction::Normal:
296 break;
297 case FontVariantNumericFraction::DiagonalFractions:
298 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueDiagonalFractions));
299 break;
300 case FontVariantNumericFraction::StackedFractions:
301 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueStackedFractions));
302 break;
303 }
304
305 switch (variantSettings.numericOrdinal) {
306 case FontVariantNumericOrdinal::Normal:
307 break;
308 case FontVariantNumericOrdinal::Yes:
309 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueOrdinal));
310 break;
311 }
312
313 switch (variantSettings.numericSlashedZero) {
314 case FontVariantNumericSlashedZero::Normal:
315 break;
316 case FontVariantNumericSlashedZero::Yes:
317 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSlashedZero));
318 break;
319 }
320
321 switch (variantSettings.alternates) {
322 case FontVariantAlternates::Normal:
323 break;
324 case FontVariantAlternates::HistoricalForms:
325 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueHistoricalForms));
326 break;
327 }
328
329 switch (variantSettings.eastAsianVariant) {
330 case FontVariantEastAsianVariant::Normal:
331 break;
332 case FontVariantEastAsianVariant::Jis78:
333 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis78));
334 break;
335 case FontVariantEastAsianVariant::Jis83:
336 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis83));
337 break;
338 case FontVariantEastAsianVariant::Jis90:
339 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis90));
340 break;
341 case FontVariantEastAsianVariant::Jis04:
342 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueJis04));
343 break;
344 case FontVariantEastAsianVariant::Simplified:
345 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueSimplified));
346 break;
347 case FontVariantEastAsianVariant::Traditional:
348 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueTraditional));
349 break;
350 }
351
352 switch (variantSettings.eastAsianWidth) {
353 case FontVariantEastAsianWidth::Normal:
354 break;
355 case FontVariantEastAsianWidth::Full:
356 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueFullWidth));
357 break;
358 case FontVariantEastAsianWidth::Proportional:
359 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueProportionalWidth));
360 break;
361 }
362
363 switch (variantSettings.eastAsianRuby) {
364 case FontVariantEastAsianRuby::Normal:
365 break;
366 case FontVariantEastAsianRuby::Yes:
367 list.get().append(CSSValuePool::singleton().createIdentifierValue(CSSValueRuby));
368 break;
369 }
370
371 return list;
372}
373
374}
375
376