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/. */
7 #include "InspectorFontFace.h"
9 #include "gfxPlatformFontList.h"
10 #include "gfxTextRun.h"
11 #include "gfxUserFontSet.h"
12 #include "nsFontFaceLoader.h"
13 #include "mozilla/gfx/2D.h"
14 #include "brotli/decode.h"
16 #include "mozilla/dom/CSSFontFaceRule.h"
17 #include "mozilla/dom/FontFaceSet.h"
18 #include "mozilla/ServoBindings.h"
19 #include "mozilla/Unused.h"
24 InspectorFontFace::InspectorFontFace(gfxFontEntry
* aFontEntry
,
25 gfxFontGroup
* aFontGroup
,
26 FontMatchType aMatchType
)
27 : mFontEntry(aFontEntry
), mFontGroup(aFontGroup
), mMatchType(aMatchType
) {
28 MOZ_COUNT_CTOR(InspectorFontFace
);
31 InspectorFontFace::~InspectorFontFace() { MOZ_COUNT_DTOR(InspectorFontFace
); }
33 bool InspectorFontFace::FromFontGroup() {
34 return bool(mMatchType
.kind
& FontMatchType::Kind::kFontGroup
);
37 bool InspectorFontFace::FromLanguagePrefs() {
38 return bool(mMatchType
.kind
& FontMatchType::Kind::kPrefsFallback
);
41 bool InspectorFontFace::FromSystemFallback() {
42 return bool(mMatchType
.kind
& FontMatchType::Kind::kSystemFallback
);
45 void InspectorFontFace::GetName(nsAString
& aName
) {
46 if (mFontEntry
->IsUserFont() && !mFontEntry
->IsLocalUserFont()) {
47 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
48 aName
.Append(NS_ConvertUTF8toUTF16(mFontEntry
->mUserFontData
->mRealName
));
50 aName
.Append(NS_ConvertUTF8toUTF16(mFontEntry
->RealFaceName()));
54 void InspectorFontFace::GetCSSFamilyName(nsAString
& aCSSFamilyName
) {
55 aCSSFamilyName
.Append(NS_ConvertUTF8toUTF16(mFontEntry
->FamilyName()));
58 void InspectorFontFace::GetCSSGeneric(nsAString
& aName
) {
59 if (mMatchType
.generic
!= StyleGenericFontFamily::None
) {
60 aName
.AssignASCII(gfxPlatformFontList::GetGenericName(mMatchType
.generic
));
66 CSSFontFaceRule
* InspectorFontFace::GetRule() {
68 // check whether this font entry is associated with an @font-face rule
69 // in the relevant font group's user font set
70 StyleLockedFontFaceRule
* rule
= nullptr;
71 if (mFontEntry
->IsUserFont()) {
73 static_cast<FontFaceSetImpl
*>(mFontGroup
->GetUserFontSet());
75 rule
= fontFaceSet
->FindRuleForEntry(mFontEntry
);
79 // XXX It would be better if we can share this with CSSOM tree,
80 // but that may require us to create another map, which is not
81 // great either. As far as they would use the same backend, and
82 // we don't really support mutating @font-face rule via CSSOM,
83 // it's probably fine for now.
84 uint32_t line
, column
;
85 Servo_FontFaceRule_GetSourceLocation(rule
, &line
, &column
);
87 new CSSFontFaceRule(do_AddRef(rule
), nullptr, nullptr, line
, column
);
93 int32_t InspectorFontFace::SrcIndex() {
94 if (mFontEntry
->IsUserFont()) {
95 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
96 return mFontEntry
->mUserFontData
->mSrcIndex
;
102 void InspectorFontFace::GetURI(nsAString
& aURI
) {
104 if (mFontEntry
->IsUserFont() && !mFontEntry
->IsLocalUserFont()) {
105 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
106 if (mFontEntry
->mUserFontData
->mURI
) {
108 mFontEntry
->mUserFontData
->mURI
->GetSpec(spec
);
109 AppendUTF8toUTF16(spec
, aURI
);
114 void InspectorFontFace::GetLocalName(nsAString
& aLocalName
) {
115 aLocalName
.Truncate();
116 if (mFontEntry
->IsLocalUserFont()) {
117 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
119 NS_ConvertUTF8toUTF16(mFontEntry
->mUserFontData
->mLocalName
));
123 void InspectorFontFace::GetFormat(nsAString
& aFormat
) {
125 if (mFontEntry
->IsUserFont() && !mFontEntry
->IsLocalUserFont()) {
126 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
127 switch (mFontEntry
->mUserFontData
->mFormatHint
) {
128 case StyleFontFaceSourceFormatKeyword::None
:
130 case StyleFontFaceSourceFormatKeyword::Collection
:
131 aFormat
.AssignLiteral("collection");
133 case StyleFontFaceSourceFormatKeyword::Opentype
:
134 aFormat
.AssignLiteral("opentype");
136 case StyleFontFaceSourceFormatKeyword::Truetype
:
137 aFormat
.AssignLiteral("truetype");
139 case StyleFontFaceSourceFormatKeyword::EmbeddedOpentype
:
140 aFormat
.AssignLiteral("embedded-opentype");
142 case StyleFontFaceSourceFormatKeyword::Svg
:
143 aFormat
.AssignLiteral("svg");
145 case StyleFontFaceSourceFormatKeyword::Woff
:
146 aFormat
.AssignLiteral("woff");
148 case StyleFontFaceSourceFormatKeyword::Woff2
:
149 aFormat
.AssignLiteral("woff2");
151 case StyleFontFaceSourceFormatKeyword::Unknown
:
152 aFormat
.AssignLiteral("unknown!");
158 void InspectorFontFace::GetMetadata(nsAString
& aMetadata
) {
159 aMetadata
.Truncate();
160 if (mFontEntry
->IsUserFont() && !mFontEntry
->IsLocalUserFont()) {
161 NS_ASSERTION(mFontEntry
->mUserFontData
, "missing userFontData");
162 const gfxUserFontData
* userFontData
= mFontEntry
->mUserFontData
.get();
163 if (userFontData
->mMetadata
.Length() && userFontData
->mMetaOrigLen
) {
165 str
.SetLength(userFontData
->mMetaOrigLen
);
166 if (str
.Length() == userFontData
->mMetaOrigLen
) {
167 switch (userFontData
->mCompression
) {
168 case gfxUserFontData::kZlibCompression
: {
169 uLongf destLen
= userFontData
->mMetaOrigLen
;
170 if (uncompress((Bytef
*)(str
.BeginWriting()), &destLen
,
171 (const Bytef
*)(userFontData
->mMetadata
.Elements()),
172 userFontData
->mMetadata
.Length()) == Z_OK
&&
173 destLen
== userFontData
->mMetaOrigLen
) {
174 AppendUTF8toUTF16(str
, aMetadata
);
177 case gfxUserFontData::kBrotliCompression
: {
178 size_t decodedSize
= userFontData
->mMetaOrigLen
;
179 if (BrotliDecoderDecompress(userFontData
->mMetadata
.Length(),
180 userFontData
->mMetadata
.Elements(),
182 (uint8_t*)str
.BeginWriting()) == 1 &&
183 decodedSize
== userFontData
->mMetaOrigLen
) {
184 AppendUTF8toUTF16(str
, aMetadata
);
193 // Append an OpenType tag to a string as a 4-ASCII-character code.
194 static void AppendTagAsASCII(nsAString
& aString
, uint32_t aTag
) {
195 aString
.AppendPrintf("%c%c%c%c", (aTag
>> 24) & 0xff, (aTag
>> 16) & 0xff,
196 (aTag
>> 8) & 0xff, aTag
& 0xff);
199 void InspectorFontFace::GetVariationAxes(
200 nsTArray
<InspectorVariationAxis
>& aResult
, ErrorResult
& aRV
) {
201 if (!mFontEntry
->HasVariations()) {
204 AutoTArray
<gfxFontVariationAxis
, 4> axes
;
205 mFontEntry
->GetVariationAxes(axes
);
206 MOZ_ASSERT(!axes
.IsEmpty());
207 if (!aResult
.SetCapacity(axes
.Length(), mozilla::fallible
)) {
208 aRV
.Throw(NS_ERROR_OUT_OF_MEMORY
);
211 for (auto a
: axes
) {
212 InspectorVariationAxis
& axis
= *aResult
.AppendElement();
213 AppendTagAsASCII(axis
.mTag
, a
.mTag
);
214 axis
.mName
.Append(NS_ConvertUTF8toUTF16(a
.mName
));
215 axis
.mMinValue
= a
.mMinValue
;
216 axis
.mMaxValue
= a
.mMaxValue
;
217 axis
.mDefaultValue
= a
.mDefaultValue
;
221 void InspectorFontFace::GetVariationInstances(
222 nsTArray
<InspectorVariationInstance
>& aResult
, ErrorResult
& aRV
) {
223 if (!mFontEntry
->HasVariations()) {
226 AutoTArray
<gfxFontVariationInstance
, 16> instances
;
227 mFontEntry
->GetVariationInstances(instances
);
228 if (!aResult
.SetCapacity(instances
.Length(), mozilla::fallible
)) {
229 aRV
.Throw(NS_ERROR_OUT_OF_MEMORY
);
232 for (const auto& i
: instances
) {
233 InspectorVariationInstance
& inst
= *aResult
.AppendElement();
234 inst
.mName
.Append(NS_ConvertUTF8toUTF16(i
.mName
));
235 // inst.mValues is a webidl sequence<>, which is a fallible array,
236 // so we are required to use fallible SetCapacity and AppendElement calls,
237 // and check the result. In practice we don't expect failure here; the
238 // list of values cannot get huge because of limits in the font format.
239 if (!inst
.mValues
.SetCapacity(i
.mValues
.Length(), mozilla::fallible
)) {
240 aRV
.Throw(NS_ERROR_OUT_OF_MEMORY
);
243 for (const auto& v
: i
.mValues
) {
244 InspectorVariationValue value
;
245 AppendTagAsASCII(value
.mAxis
, v
.mAxis
);
246 value
.mValue
= v
.mValue
;
247 // This won't fail, because of SetCapacity above.
248 Unused
<< inst
.mValues
.AppendElement(value
, mozilla::fallible
);
253 void InspectorFontFace::GetFeatures(nsTArray
<InspectorFontFeature
>& aResult
,
255 AutoTArray
<gfxFontFeatureInfo
, 64> features
;
256 mFontEntry
->GetFeatureInfo(features
);
257 if (features
.IsEmpty()) {
260 if (!aResult
.SetCapacity(features
.Length(), mozilla::fallible
)) {
261 aRV
.Throw(NS_ERROR_OUT_OF_MEMORY
);
264 for (auto& f
: features
) {
265 InspectorFontFeature
& feat
= *aResult
.AppendElement();
266 AppendTagAsASCII(feat
.mTag
, f
.mTag
);
267 AppendTagAsASCII(feat
.mScript
, f
.mScript
);
268 AppendTagAsASCII(feat
.mLanguageSystem
, f
.mLangSys
);
272 void InspectorFontFace::GetRanges(nsTArray
<RefPtr
<nsRange
>>& aResult
) {
273 aResult
= mRanges
.Clone();
276 void InspectorFontFace::AddRange(nsRange
* aRange
) {
277 mRanges
.AppendElement(aRange
);
281 } // namespace mozilla