1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "InspectorFontFace.h"
8
9 #ifdef MOZ_OLD_STYLE
10 #include "nsCSSRules.h"
11 #endif
12 #include "gfxTextRun.h"
13 #include "gfxUserFontSet.h"
14 #include "nsFontFaceLoader.h"
15 #include "mozilla/gfx/2D.h"
16 #include "brotli/decode.h"
17 #include "zlib.h"
18 #include "mozilla/dom/FontFaceSet.h"
19 #include "mozilla/Unused.h"
20
21 namespace mozilla {
22 namespace dom {
23
FromFontGroup()24 bool InspectorFontFace::FromFontGroup() {
25 return mMatchType & gfxTextRange::kFontGroup;
26 }
27
FromLanguagePrefs()28 bool InspectorFontFace::FromLanguagePrefs() {
29 return mMatchType & gfxTextRange::kPrefsFallback;
30 }
31
FromSystemFallback()32 bool InspectorFontFace::FromSystemFallback() {
33 return mMatchType & gfxTextRange::kSystemFallback;
34 }
35
GetName(nsAString & aName)36 void InspectorFontFace::GetName(nsAString& aName) {
37 if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
38 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
39 aName = mFontEntry->mUserFontData->mRealName;
40 } else {
41 aName = mFontEntry->RealFaceName();
42 }
43 }
44
GetCSSFamilyName(nsAString & aCSSFamilyName)45 void InspectorFontFace::GetCSSFamilyName(nsAString& aCSSFamilyName) {
46 aCSSFamilyName = mFontEntry->FamilyName();
47 }
48
GetRule()49 nsCSSFontFaceRule* InspectorFontFace::GetRule() {
50 // check whether this font entry is associated with an @font-face rule
51 // in the relevant font group's user font set
52 nsCSSFontFaceRule* rule = nullptr;
53 if (mFontEntry->IsUserFont()) {
54 FontFaceSet::UserFontSet* fontSet =
55 static_cast<FontFaceSet::UserFontSet*>(mFontGroup->GetUserFontSet());
56 if (fontSet) {
57 FontFaceSet* fontFaceSet = fontSet->GetFontFaceSet();
58 if (fontFaceSet) {
59 rule = fontFaceSet->FindRuleForEntry(mFontEntry);
60 }
61 }
62 }
63 return rule;
64 }
65
SrcIndex()66 int32_t InspectorFontFace::SrcIndex() {
67 if (mFontEntry->IsUserFont()) {
68 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
69 return mFontEntry->mUserFontData->mSrcIndex;
70 }
71
72 return -1;
73 }
74
GetURI(nsAString & aURI)75 void InspectorFontFace::GetURI(nsAString& aURI) {
76 aURI.Truncate();
77 if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
78 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
79 if (mFontEntry->mUserFontData->mURI) {
80 nsAutoCString spec;
81 mFontEntry->mUserFontData->mURI->GetSpec(spec);
82 AppendUTF8toUTF16(spec, aURI);
83 }
84 }
85 }
86
GetLocalName(nsAString & aLocalName)87 void InspectorFontFace::GetLocalName(nsAString& aLocalName) {
88 if (mFontEntry->IsLocalUserFont()) {
89 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
90 aLocalName = mFontEntry->mUserFontData->mLocalName;
91 } else {
92 aLocalName.Truncate();
93 }
94 }
95
AppendToFormat(nsAString & aResult,const char * aFormat)96 static void AppendToFormat(nsAString& aResult, const char* aFormat) {
97 if (!aResult.IsEmpty()) {
98 aResult.Append(',');
99 }
100 aResult.AppendASCII(aFormat);
101 }
102
GetFormat(nsAString & aFormat)103 void InspectorFontFace::GetFormat(nsAString& aFormat) {
104 aFormat.Truncate();
105 if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
106 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
107 uint32_t formatFlags = mFontEntry->mUserFontData->mFormat;
108 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE) {
109 AppendToFormat(aFormat, "opentype");
110 }
111 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE) {
112 AppendToFormat(aFormat, "truetype");
113 }
114 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) {
115 AppendToFormat(aFormat, "truetype-aat");
116 }
117 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_EOT) {
118 AppendToFormat(aFormat, "embedded-opentype");
119 }
120 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_SVG) {
121 AppendToFormat(aFormat, "svg");
122 }
123 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF) {
124 AppendToFormat(aFormat, "woff");
125 }
126 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2) {
127 AppendToFormat(aFormat, "woff2");
128 }
129 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS) {
130 AppendToFormat(aFormat, "opentype-variations");
131 }
132 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS) {
133 AppendToFormat(aFormat, "truetype-variations");
134 }
135 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS) {
136 AppendToFormat(aFormat, "woff-variations");
137 }
138 if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS) {
139 AppendToFormat(aFormat, "woff2-variations");
140 }
141 }
142 }
143
GetMetadata(nsAString & aMetadata)144 void InspectorFontFace::GetMetadata(nsAString& aMetadata) {
145 aMetadata.Truncate();
146 if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
147 NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
148 const gfxUserFontData* userFontData = mFontEntry->mUserFontData.get();
149 if (userFontData->mMetadata.Length() && userFontData->mMetaOrigLen) {
150 nsAutoCString str;
151 str.SetLength(userFontData->mMetaOrigLen);
152 if (str.Length() == userFontData->mMetaOrigLen) {
153 switch (userFontData->mCompression) {
154 case gfxUserFontData::kZlibCompression: {
155 uLongf destLen = userFontData->mMetaOrigLen;
156 if (uncompress((Bytef*)(str.BeginWriting()), &destLen,
157 (const Bytef*)(userFontData->mMetadata.Elements()),
158 userFontData->mMetadata.Length()) == Z_OK &&
159 destLen == userFontData->mMetaOrigLen) {
160 AppendUTF8toUTF16(str, aMetadata);
161 }
162 } break;
163 case gfxUserFontData::kBrotliCompression: {
164 size_t decodedSize = userFontData->mMetaOrigLen;
165 if (BrotliDecoderDecompress(userFontData->mMetadata.Length(),
166 userFontData->mMetadata.Elements(),
167 &decodedSize,
168 (uint8_t*)str.BeginWriting()) == 1 &&
169 decodedSize == userFontData->mMetaOrigLen) {
170 AppendUTF8toUTF16(str, aMetadata);
171 }
172 } break;
173 }
174 }
175 }
176 }
177 }
178
179 // Append an OpenType tag to a string as a 4-ASCII-character code.
AppendTagAsASCII(nsAString & aString,uint32_t aTag)180 static void AppendTagAsASCII(nsAString& aString, uint32_t aTag) {
181 aString.AppendPrintf("%c%c%c%c", (aTag >> 24) & 0xff, (aTag >> 16) & 0xff,
182 (aTag >> 8) & 0xff, aTag & 0xff);
183 }
184
GetVariationAxes(nsTArray<InspectorVariationAxis> & aResult,ErrorResult & aRV)185 void InspectorFontFace::GetVariationAxes(
186 nsTArray<InspectorVariationAxis>& aResult, ErrorResult& aRV) {
187 if (!mFontEntry->HasVariations()) {
188 return;
189 }
190 AutoTArray<gfxFontVariationAxis, 4> axes;
191 mFontEntry->GetVariationAxes(axes);
192 MOZ_ASSERT(!axes.IsEmpty());
193 if (!aResult.SetCapacity(axes.Length(), mozilla::fallible)) {
194 aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
195 return;
196 }
197 for (auto a : axes) {
198 InspectorVariationAxis& axis = *aResult.AppendElement();
199 AppendTagAsASCII(axis.mTag, a.mTag);
200 axis.mName = a.mName;
201 axis.mMinValue = a.mMinValue;
202 axis.mMaxValue = a.mMaxValue;
203 axis.mDefaultValue = a.mDefaultValue;
204 }
205 }
206
GetVariationInstances(nsTArray<InspectorVariationInstance> & aResult,ErrorResult & aRV)207 void InspectorFontFace::GetVariationInstances(
208 nsTArray<InspectorVariationInstance>& aResult, ErrorResult& aRV) {
209 if (!mFontEntry->HasVariations()) {
210 return;
211 }
212 AutoTArray<gfxFontVariationInstance, 16> instances;
213 mFontEntry->GetVariationInstances(instances);
214 if (!aResult.SetCapacity(instances.Length(), mozilla::fallible)) {
215 aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
216 return;
217 }
218 for (auto i : instances) {
219 InspectorVariationInstance& inst = *aResult.AppendElement();
220 inst.mName = i.mName;
221 // inst.mValues is a webidl sequence<>, which is a fallible array,
222 // so we are required to use fallible SetCapacity and AppendElement calls,
223 // and check the result. In practice we don't expect failure here; the
224 // list of values cannot get huge because of limits in the font format.
225 if (!inst.mValues.SetCapacity(i.mValues.Length(), mozilla::fallible)) {
226 aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
227 return;
228 }
229 for (auto v : i.mValues) {
230 InspectorVariationValue value;
231 AppendTagAsASCII(value.mAxis, v.mAxis);
232 value.mValue = v.mValue;
233 // This won't fail, because of SetCapacity above.
234 Unused << inst.mValues.AppendElement(value, mozilla::fallible);
235 }
236 }
237 }
238
GetFeatures(nsTArray<InspectorFontFeature> & aResult,ErrorResult & aRV)239 void InspectorFontFace::GetFeatures(nsTArray<InspectorFontFeature>& aResult,
240 ErrorResult& aRV) {
241 AutoTArray<gfxFontFeatureInfo, 64> features;
242 mFontEntry->GetFeatureInfo(features);
243 if (features.IsEmpty()) {
244 return;
245 }
246 if (!aResult.SetCapacity(features.Length(), mozilla::fallible)) {
247 aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
248 return;
249 }
250 for (auto& f : features) {
251 InspectorFontFeature& feat = *aResult.AppendElement();
252 AppendTagAsASCII(feat.mTag, f.mTag);
253 AppendTagAsASCII(feat.mScript, f.mScript);
254 AppendTagAsASCII(feat.mLanguageSystem, f.mLangSys);
255 }
256 }
257
GetRanges(nsTArray<RefPtr<nsRange>> & aResult)258 void InspectorFontFace::GetRanges(nsTArray<RefPtr<nsRange>>& aResult) {
259 aResult = mRanges;
260 }
261
AddRange(nsRange * aRange)262 void InspectorFontFace::AddRange(nsRange* aRange) {
263 mRanges.AppendElement(aRange);
264 }
265
266 } // namespace dom
267 } // namespace mozilla
268