Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "nsFont.h"
7 : #include "gfxFont.h" // for gfxFontStyle
8 : #include "gfxFontFeatures.h" // for gfxFontFeature, etc
9 : #include "gfxFontUtils.h" // for TRUETYPE_TAG
10 : #include "nsCRT.h" // for nsCRT
11 : #include "nsDebug.h" // for NS_ASSERTION
12 : #include "nsISupports.h"
13 : #include "nsUnicharUtils.h"
14 : #include "nscore.h" // for char16_t
15 : #include "mozilla/ArrayUtils.h"
16 : #include "mozilla/gfx/2D.h"
17 :
18 : using namespace mozilla;
19 :
20 0 : nsFont::nsFont(const FontFamilyList& aFontlist, nscoord aSize)
21 : : fontlist(aFontlist)
22 0 : , size(aSize)
23 : {
24 0 : }
25 :
26 217 : nsFont::nsFont(FontFamilyType aGenericType, nscoord aSize)
27 : : fontlist(aGenericType)
28 217 : , size(aSize)
29 : {
30 217 : }
31 :
32 : nsFont::nsFont(const nsFont& aOther) = default;
33 :
34 0 : nsFont::nsFont()
35 : {
36 0 : }
37 :
38 96 : nsFont::~nsFont()
39 : {
40 96 : }
41 :
42 445 : bool nsFont::Equals(const nsFont& aOther) const
43 : {
44 1335 : if ((style == aOther.style) &&
45 890 : (systemFont == aOther.systemFont) &&
46 890 : (weight == aOther.weight) &&
47 890 : (stretch == aOther.stretch) &&
48 890 : (size == aOther.size) &&
49 890 : (sizeAdjust == aOther.sizeAdjust) &&
50 890 : (fontlist == aOther.fontlist) &&
51 890 : (kerning == aOther.kerning) &&
52 890 : (synthesis == aOther.synthesis) &&
53 890 : (fontFeatureSettings == aOther.fontFeatureSettings) &&
54 890 : (fontVariationSettings == aOther.fontVariationSettings) &&
55 890 : (languageOverride == aOther.languageOverride) &&
56 890 : (variantAlternates == aOther.variantAlternates) &&
57 890 : (variantCaps == aOther.variantCaps) &&
58 890 : (variantEastAsian == aOther.variantEastAsian) &&
59 890 : (variantLigatures == aOther.variantLigatures) &&
60 890 : (variantNumeric == aOther.variantNumeric) &&
61 890 : (variantPosition == aOther.variantPosition) &&
62 890 : (variantWidth == aOther.variantWidth) &&
63 890 : (alternateValues == aOther.alternateValues) &&
64 1335 : (featureValueLookup == aOther.featureValueLookup) &&
65 445 : (smoothing == aOther.smoothing)) {
66 445 : return true;
67 : }
68 0 : return false;
69 : }
70 :
71 : nsFont& nsFont::operator=(const nsFont& aOther) = default;
72 :
73 : void
74 6 : nsFont::CopyAlternates(const nsFont& aOther)
75 : {
76 6 : variantAlternates = aOther.variantAlternates;
77 6 : alternateValues = aOther.alternateValues;
78 6 : featureValueLookup = aOther.featureValueLookup;
79 6 : }
80 :
81 : // mapping from bitflag to font feature tag/value pair
82 : //
83 : // these need to be kept in sync with the constants listed
84 : // in gfxFontConstants.h (e.g. NS_FONT_VARIANT_EAST_ASIAN_JIS78)
85 :
86 : // NS_FONT_VARIANT_EAST_ASIAN_xxx values
87 : const gfxFontFeature eastAsianDefaults[] = {
88 : { TRUETYPE_TAG('j','p','7','8'), 1 },
89 : { TRUETYPE_TAG('j','p','8','3'), 1 },
90 : { TRUETYPE_TAG('j','p','9','0'), 1 },
91 : { TRUETYPE_TAG('j','p','0','4'), 1 },
92 : { TRUETYPE_TAG('s','m','p','l'), 1 },
93 : { TRUETYPE_TAG('t','r','a','d'), 1 },
94 : { TRUETYPE_TAG('f','w','i','d'), 1 },
95 : { TRUETYPE_TAG('p','w','i','d'), 1 },
96 : { TRUETYPE_TAG('r','u','b','y'), 1 }
97 : };
98 :
99 : static_assert(MOZ_ARRAY_LENGTH(eastAsianDefaults) ==
100 : NS_FONT_VARIANT_EAST_ASIAN_COUNT,
101 : "eastAsianDefaults[] should be correct");
102 :
103 : // NS_FONT_VARIANT_LIGATURES_xxx values
104 : const gfxFontFeature ligDefaults[] = {
105 : { TRUETYPE_TAG('l','i','g','a'), 0 }, // none value means all off
106 : { TRUETYPE_TAG('l','i','g','a'), 1 },
107 : { TRUETYPE_TAG('l','i','g','a'), 0 },
108 : { TRUETYPE_TAG('d','l','i','g'), 1 },
109 : { TRUETYPE_TAG('d','l','i','g'), 0 },
110 : { TRUETYPE_TAG('h','l','i','g'), 1 },
111 : { TRUETYPE_TAG('h','l','i','g'), 0 },
112 : { TRUETYPE_TAG('c','a','l','t'), 1 },
113 : { TRUETYPE_TAG('c','a','l','t'), 0 }
114 : };
115 :
116 : static_assert(MOZ_ARRAY_LENGTH(ligDefaults) ==
117 : NS_FONT_VARIANT_LIGATURES_COUNT,
118 : "ligDefaults[] should be correct");
119 :
120 : // NS_FONT_VARIANT_NUMERIC_xxx values
121 : const gfxFontFeature numericDefaults[] = {
122 : { TRUETYPE_TAG('l','n','u','m'), 1 },
123 : { TRUETYPE_TAG('o','n','u','m'), 1 },
124 : { TRUETYPE_TAG('p','n','u','m'), 1 },
125 : { TRUETYPE_TAG('t','n','u','m'), 1 },
126 : { TRUETYPE_TAG('f','r','a','c'), 1 },
127 : { TRUETYPE_TAG('a','f','r','c'), 1 },
128 : { TRUETYPE_TAG('z','e','r','o'), 1 },
129 : { TRUETYPE_TAG('o','r','d','n'), 1 }
130 : };
131 :
132 : static_assert(MOZ_ARRAY_LENGTH(numericDefaults) ==
133 : NS_FONT_VARIANT_NUMERIC_COUNT,
134 : "numericDefaults[] should be correct");
135 :
136 : static void
137 0 : AddFontFeaturesBitmask(uint32_t aValue, uint32_t aMin, uint32_t aMax,
138 : const gfxFontFeature aFeatureDefaults[],
139 : nsTArray<gfxFontFeature>& aFeaturesOut)
140 :
141 : {
142 : uint32_t i, m;
143 :
144 0 : for (i = 0, m = aMin; m <= aMax; i++, m <<= 1) {
145 0 : if (m & aValue) {
146 0 : const gfxFontFeature& feature = aFeatureDefaults[i];
147 0 : aFeaturesOut.AppendElement(feature);
148 : }
149 : }
150 0 : }
151 :
152 : static uint32_t
153 6 : FontFeatureTagForVariantWidth(uint32_t aVariantWidth)
154 : {
155 6 : switch (aVariantWidth) {
156 : case NS_FONT_VARIANT_WIDTH_FULL:
157 0 : return TRUETYPE_TAG('f','w','i','d');
158 : case NS_FONT_VARIANT_WIDTH_HALF:
159 0 : return TRUETYPE_TAG('h','w','i','d');
160 : case NS_FONT_VARIANT_WIDTH_THIRD:
161 0 : return TRUETYPE_TAG('t','w','i','d');
162 : case NS_FONT_VARIANT_WIDTH_QUARTER:
163 0 : return TRUETYPE_TAG('q','w','i','d');
164 : default:
165 6 : return 0;
166 : }
167 : }
168 :
169 6 : void nsFont::AddFontFeaturesToStyle(gfxFontStyle *aStyle) const
170 : {
171 : // add in font-variant features
172 : gfxFontFeature setting;
173 :
174 : // -- kerning
175 6 : setting.mTag = TRUETYPE_TAG('k','e','r','n');
176 6 : switch (kerning) {
177 : case NS_FONT_KERNING_NONE:
178 0 : setting.mValue = 0;
179 0 : aStyle->featureSettings.AppendElement(setting);
180 0 : break;
181 : case NS_FONT_KERNING_NORMAL:
182 0 : setting.mValue = 1;
183 0 : aStyle->featureSettings.AppendElement(setting);
184 0 : break;
185 : default:
186 : // auto case implies use user agent default
187 6 : break;
188 : }
189 :
190 : // -- alternates
191 6 : if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_HISTORICAL) {
192 0 : setting.mValue = 1;
193 0 : setting.mTag = TRUETYPE_TAG('h','i','s','t');
194 0 : aStyle->featureSettings.AppendElement(setting);
195 : }
196 :
197 : // -- copy font-specific alternate info into style
198 : // (this will be resolved after font-matching occurs)
199 6 : aStyle->alternateValues.AppendElements(alternateValues);
200 6 : aStyle->featureValueLookup = featureValueLookup;
201 :
202 : // -- caps
203 6 : aStyle->variantCaps = variantCaps;
204 :
205 : // -- east-asian
206 6 : if (variantEastAsian) {
207 0 : AddFontFeaturesBitmask(variantEastAsian,
208 : NS_FONT_VARIANT_EAST_ASIAN_JIS78,
209 : NS_FONT_VARIANT_EAST_ASIAN_RUBY,
210 0 : eastAsianDefaults, aStyle->featureSettings);
211 : }
212 :
213 : // -- ligatures
214 6 : if (variantLigatures) {
215 0 : AddFontFeaturesBitmask(variantLigatures,
216 : NS_FONT_VARIANT_LIGATURES_NONE,
217 : NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
218 0 : ligDefaults, aStyle->featureSettings);
219 :
220 0 : if (variantLigatures & NS_FONT_VARIANT_LIGATURES_COMMON) {
221 : // liga already enabled, need to enable clig also
222 0 : setting.mTag = TRUETYPE_TAG('c','l','i','g');
223 0 : setting.mValue = 1;
224 0 : aStyle->featureSettings.AppendElement(setting);
225 0 : } else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NO_COMMON) {
226 : // liga already disabled, need to disable clig also
227 0 : setting.mTag = TRUETYPE_TAG('c','l','i','g');
228 0 : setting.mValue = 0;
229 0 : aStyle->featureSettings.AppendElement(setting);
230 0 : } else if (variantLigatures & NS_FONT_VARIANT_LIGATURES_NONE) {
231 : // liga already disabled, need to disable dlig, hlig, calt, clig
232 0 : setting.mValue = 0;
233 0 : setting.mTag = TRUETYPE_TAG('d','l','i','g');
234 0 : aStyle->featureSettings.AppendElement(setting);
235 0 : setting.mTag = TRUETYPE_TAG('h','l','i','g');
236 0 : aStyle->featureSettings.AppendElement(setting);
237 0 : setting.mTag = TRUETYPE_TAG('c','a','l','t');
238 0 : aStyle->featureSettings.AppendElement(setting);
239 0 : setting.mTag = TRUETYPE_TAG('c','l','i','g');
240 0 : aStyle->featureSettings.AppendElement(setting);
241 : }
242 : }
243 :
244 : // -- numeric
245 6 : if (variantNumeric) {
246 0 : AddFontFeaturesBitmask(variantNumeric,
247 : NS_FONT_VARIANT_NUMERIC_LINING,
248 : NS_FONT_VARIANT_NUMERIC_ORDINAL,
249 0 : numericDefaults, aStyle->featureSettings);
250 : }
251 :
252 : // -- position
253 6 : aStyle->variantSubSuper = variantPosition;
254 :
255 : // -- width
256 6 : setting.mTag = FontFeatureTagForVariantWidth(variantWidth);
257 6 : if (setting.mTag) {
258 0 : setting.mValue = 1;
259 0 : aStyle->featureSettings.AppendElement(setting);
260 : }
261 :
262 : // indicate common-path case when neither variantCaps or variantSubSuper are set
263 6 : aStyle->noFallbackVariantFeatures =
264 12 : (aStyle->variantCaps == NS_FONT_VARIANT_CAPS_NORMAL) &&
265 6 : (variantPosition == NS_FONT_VARIANT_POSITION_NORMAL);
266 :
267 : // add in features from font-feature-settings
268 6 : aStyle->featureSettings.AppendElements(fontFeatureSettings);
269 :
270 : // enable grayscale antialiasing for text
271 6 : if (smoothing == NS_FONT_SMOOTHING_GRAYSCALE) {
272 0 : aStyle->useGrayscaleAntialiasing = true;
273 : }
274 6 : }
275 :
276 6 : void nsFont::AddFontVariationsToStyle(gfxFontStyle *aStyle) const
277 : {
278 : // TODO: add variation settings from specific CSS properties
279 : // such as weight, width, optical-size
280 :
281 : // Add in arbitrary values from font-variation-settings
282 6 : aStyle->variationSettings.AppendElements(fontVariationSettings);
283 6 : }
|