Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/inspector/InspectorFontFace.cpp
Line
Count
Source (jump to first uncovered line)
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
#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"
15
#include "zlib.h"
16
#include "mozilla/dom/CSSFontFaceRule.h"
17
#include "mozilla/dom/FontFaceSet.h"
18
#include "mozilla/ServoBindings.h"
19
#include "mozilla/Unused.h"
20
21
namespace mozilla {
22
namespace dom {
23
24
bool
25
InspectorFontFace::FromFontGroup()
26
0
{
27
0
  return bool(mMatchType & gfxTextRange::MatchType::kFontGroup);
28
0
}
29
30
bool
31
InspectorFontFace::FromLanguagePrefs()
32
0
{
33
0
  return bool(mMatchType & gfxTextRange::MatchType::kPrefsFallback);
34
0
}
35
36
bool
37
InspectorFontFace::FromSystemFallback()
38
0
{
39
0
  return bool(mMatchType & gfxTextRange::MatchType::kSystemFallback);
40
0
}
41
42
void
43
InspectorFontFace::GetName(nsAString& aName)
44
0
{
45
0
  if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
46
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
47
0
    aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mRealName));
48
0
  } else {
49
0
    aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->RealFaceName()));
50
0
  }
51
0
}
52
53
void
54
InspectorFontFace::GetCSSFamilyName(nsAString& aCSSFamilyName)
55
0
{
56
0
  aCSSFamilyName.Append(NS_ConvertUTF8toUTF16(mFontEntry->FamilyName()));
57
0
}
58
59
void
60
InspectorFontFace::GetCSSGeneric(nsAString& aName)
61
0
{
62
0
  auto genericType =
63
0
    FontFamilyType(mMatchType & gfxTextRange::MatchType::kGenericMask);
64
0
  if (genericType >= FontFamilyType::eFamily_generic_first &&
65
0
      genericType <= FontFamilyType::eFamily_generic_last) {
66
0
    aName.AssignASCII(gfxPlatformFontList::GetGenericName(genericType));
67
0
  } else {
68
0
    aName.Truncate(0);
69
0
  }
70
0
}
71
72
CSSFontFaceRule*
73
InspectorFontFace::GetRule()
74
0
{
75
0
  if (!mRule) {
76
0
    // check whether this font entry is associated with an @font-face rule
77
0
    // in the relevant font group's user font set
78
0
    RawServoFontFaceRule* rule = nullptr;
79
0
    if (mFontEntry->IsUserFont()) {
80
0
      FontFaceSet::UserFontSet* fontSet =
81
0
        static_cast<FontFaceSet::UserFontSet*>(mFontGroup->GetUserFontSet());
82
0
      if (fontSet) {
83
0
        FontFaceSet* fontFaceSet = fontSet->GetFontFaceSet();
84
0
        if (fontFaceSet) {
85
0
          rule = fontFaceSet->FindRuleForEntry(mFontEntry);
86
0
        }
87
0
      }
88
0
    }
89
0
    if (rule) {
90
0
      // XXX It would be better if we can share this with CSSOM tree,
91
0
      // but that may require us to create another map, which is not
92
0
      // great either. As far as they would use the same backend, and
93
0
      // we don't really support mutating @font-face rule via CSSOM,
94
0
      // it's probably fine for now.
95
0
      uint32_t line, column;
96
0
      Servo_FontFaceRule_GetSourceLocation(rule, &line, &column);
97
0
      mRule = new CSSFontFaceRule(do_AddRef(rule), nullptr, nullptr,
98
0
                                  line, column);
99
0
    }
100
0
  }
101
0
  return mRule;
102
0
}
103
104
int32_t
105
InspectorFontFace::SrcIndex()
106
0
{
107
0
  if (mFontEntry->IsUserFont()) {
108
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
109
0
    return mFontEntry->mUserFontData->mSrcIndex;
110
0
  }
111
0
112
0
  return -1;
113
0
}
114
115
void
116
InspectorFontFace::GetURI(nsAString& aURI)
117
0
{
118
0
  aURI.Truncate();
119
0
  if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
120
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
121
0
    if (mFontEntry->mUserFontData->mURI) {
122
0
      nsAutoCString spec;
123
0
      mFontEntry->mUserFontData->mURI->GetSpec(spec);
124
0
      AppendUTF8toUTF16(spec, aURI);
125
0
    }
126
0
  }
127
0
}
128
129
void
130
InspectorFontFace::GetLocalName(nsAString& aLocalName)
131
0
{
132
0
  aLocalName.Truncate();
133
0
  if (mFontEntry->IsLocalUserFont()) {
134
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
135
0
    aLocalName.Append(NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mLocalName));
136
0
  }
137
0
}
138
139
static void
140
AppendToFormat(nsAString& aResult, const char* aFormat)
141
0
{
142
0
  if (!aResult.IsEmpty()) {
143
0
    aResult.Append(',');
144
0
  }
145
0
  aResult.AppendASCII(aFormat);
146
0
}
147
148
void
149
InspectorFontFace::GetFormat(nsAString& aFormat)
150
0
{
151
0
  aFormat.Truncate();
152
0
  if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
153
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
154
0
    uint32_t formatFlags = mFontEntry->mUserFontData->mFormat;
155
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE) {
156
0
      AppendToFormat(aFormat, "opentype");
157
0
    }
158
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE) {
159
0
      AppendToFormat(aFormat, "truetype");
160
0
    }
161
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) {
162
0
      AppendToFormat(aFormat, "truetype-aat");
163
0
    }
164
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_EOT) {
165
0
      AppendToFormat(aFormat, "embedded-opentype");
166
0
    }
167
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_SVG) {
168
0
      AppendToFormat(aFormat, "svg");
169
0
    }
170
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF) {
171
0
      AppendToFormat(aFormat, "woff");
172
0
    }
173
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2) {
174
0
      AppendToFormat(aFormat, "woff2");
175
0
    }
176
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS) {
177
0
      AppendToFormat(aFormat, "opentype-variations");
178
0
    }
179
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS) {
180
0
      AppendToFormat(aFormat, "truetype-variations");
181
0
    }
182
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS) {
183
0
      AppendToFormat(aFormat, "woff-variations");
184
0
    }
185
0
    if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS) {
186
0
      AppendToFormat(aFormat, "woff2-variations");
187
0
    }
188
0
  }
189
0
}
190
191
void
192
InspectorFontFace::GetMetadata(nsAString& aMetadata)
193
0
{
194
0
  aMetadata.Truncate();
195
0
  if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
196
0
    NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
197
0
    const gfxUserFontData* userFontData = mFontEntry->mUserFontData.get();
198
0
    if (userFontData->mMetadata.Length() && userFontData->mMetaOrigLen) {
199
0
      nsAutoCString str;
200
0
      str.SetLength(userFontData->mMetaOrigLen);
201
0
      if (str.Length() == userFontData->mMetaOrigLen) {
202
0
        switch (userFontData->mCompression) {
203
0
        case gfxUserFontData::kZlibCompression:
204
0
          {
205
0
            uLongf destLen = userFontData->mMetaOrigLen;
206
0
            if (uncompress((Bytef *)(str.BeginWriting()), &destLen,
207
0
                           (const Bytef *)(userFontData->mMetadata.Elements()),
208
0
                           userFontData->mMetadata.Length()) == Z_OK &&
209
0
                destLen == userFontData->mMetaOrigLen) {
210
0
              AppendUTF8toUTF16(str, aMetadata);
211
0
            }
212
0
          }
213
0
          break;
214
0
        case gfxUserFontData::kBrotliCompression:
215
0
          {
216
0
            size_t decodedSize = userFontData->mMetaOrigLen;
217
0
            if (BrotliDecoderDecompress(userFontData->mMetadata.Length(),
218
0
                                        userFontData->mMetadata.Elements(),
219
0
                                        &decodedSize,
220
0
                                        (uint8_t*)str.BeginWriting()) == 1 &&
221
0
                decodedSize == userFontData->mMetaOrigLen) {
222
0
              AppendUTF8toUTF16(str, aMetadata);
223
0
            }
224
0
          }
225
0
          break;
226
0
        }
227
0
      }
228
0
    }
229
0
  }
230
0
}
231
232
// Append an OpenType tag to a string as a 4-ASCII-character code.
233
static void
234
AppendTagAsASCII(nsAString& aString, uint32_t aTag)
235
0
{
236
0
  aString.AppendPrintf("%c%c%c%c", (aTag >> 24) & 0xff,
237
0
                                   (aTag >> 16) & 0xff,
238
0
                                   (aTag >> 8) & 0xff,
239
0
                                   aTag & 0xff);
240
0
}
241
242
void
243
InspectorFontFace::GetVariationAxes(nsTArray<InspectorVariationAxis>& aResult,
244
                                    ErrorResult& aRV)
245
0
{
246
0
  if (!mFontEntry->HasVariations()) {
247
0
    return;
248
0
  }
249
0
  AutoTArray<gfxFontVariationAxis,4> axes;
250
0
  mFontEntry->GetVariationAxes(axes);
251
0
  MOZ_ASSERT(!axes.IsEmpty());
252
0
  if (!aResult.SetCapacity(axes.Length(), mozilla::fallible)) {
253
0
    aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
254
0
    return;
255
0
  }
256
0
  for (auto a : axes) {
257
0
    InspectorVariationAxis& axis = *aResult.AppendElement();
258
0
    AppendTagAsASCII(axis.mTag, a.mTag);
259
0
    axis.mName.Append(NS_ConvertUTF8toUTF16(a.mName));
260
0
    axis.mMinValue = a.mMinValue;
261
0
    axis.mMaxValue = a.mMaxValue;
262
0
    axis.mDefaultValue = a.mDefaultValue;
263
0
  }
264
0
}
265
266
void
267
InspectorFontFace::GetVariationInstances(
268
  nsTArray<InspectorVariationInstance>& aResult,
269
  ErrorResult& aRV)
270
0
{
271
0
  if (!mFontEntry->HasVariations()) {
272
0
    return;
273
0
  }
274
0
  AutoTArray<gfxFontVariationInstance,16> instances;
275
0
  mFontEntry->GetVariationInstances(instances);
276
0
  if (!aResult.SetCapacity(instances.Length(), mozilla::fallible)) {
277
0
    aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
278
0
    return;
279
0
  }
280
0
  for (auto i : instances) {
281
0
    InspectorVariationInstance& inst = *aResult.AppendElement();
282
0
    inst.mName.Append(NS_ConvertUTF8toUTF16(i.mName));
283
0
    // inst.mValues is a webidl sequence<>, which is a fallible array,
284
0
    // so we are required to use fallible SetCapacity and AppendElement calls,
285
0
    // and check the result. In practice we don't expect failure here; the
286
0
    // list of values cannot get huge because of limits in the font format.
287
0
    if (!inst.mValues.SetCapacity(i.mValues.Length(), mozilla::fallible)) {
288
0
      aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
289
0
      return;
290
0
    }
291
0
    for (auto v : i.mValues) {
292
0
      InspectorVariationValue value;
293
0
      AppendTagAsASCII(value.mAxis, v.mAxis);
294
0
      value.mValue = v.mValue;
295
0
      // This won't fail, because of SetCapacity above.
296
0
      Unused << inst.mValues.AppendElement(value, mozilla::fallible);
297
0
    }
298
0
  }
299
0
}
300
301
void
302
InspectorFontFace::GetFeatures(nsTArray<InspectorFontFeature>& aResult,
303
                               ErrorResult& aRV)
304
0
{
305
0
  AutoTArray<gfxFontFeatureInfo,64> features;
306
0
  mFontEntry->GetFeatureInfo(features);
307
0
  if (features.IsEmpty()) {
308
0
    return;
309
0
  }
310
0
  if (!aResult.SetCapacity(features.Length(), mozilla::fallible)) {
311
0
    aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
312
0
    return;
313
0
  }
314
0
  for (auto& f : features) {
315
0
    InspectorFontFeature& feat = *aResult.AppendElement();
316
0
    AppendTagAsASCII(feat.mTag, f.mTag);
317
0
    AppendTagAsASCII(feat.mScript, f.mScript);
318
0
    AppendTagAsASCII(feat.mLanguageSystem, f.mLangSys);
319
0
  }
320
0
}
321
322
void
323
InspectorFontFace::GetRanges(nsTArray<RefPtr<nsRange>>& aResult)
324
0
{
325
0
  aResult = mRanges;
326
0
}
327
328
void
329
InspectorFontFace::AddRange(nsRange* aRange)
330
0
{
331
0
  mRanges.AppendElement(aRange);
332
0
}
333
334
} // namespace dom
335
} // namespace mozilla