Extract UTI mapping and allow for additions
[WebKit-https.git] / Source / WebCore / css / FontVariantBuilder.cpp
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
34 namespace WebCore {
35
36 FontVariantLigaturesValues 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
94 FontVariantNumericValues 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
140 FontVariantEastAsianValues 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
187 Ref<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