summaryrefslogtreecommitdiffstats
path: root/layout/inspector/InspectorFontFace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'layout/inspector/InspectorFontFace.cpp')
-rw-r--r--layout/inspector/InspectorFontFace.cpp297
1 files changed, 297 insertions, 0 deletions
diff --git a/layout/inspector/InspectorFontFace.cpp b/layout/inspector/InspectorFontFace.cpp
new file mode 100644
index 0000000000..0127b14282
--- /dev/null
+++ b/layout/inspector/InspectorFontFace.cpp
@@ -0,0 +1,297 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InspectorFontFace.h"
+
+#include "gfxPlatformFontList.h"
+#include "gfxTextRun.h"
+#include "gfxUserFontSet.h"
+#include "nsFontFaceLoader.h"
+#include "mozilla/gfx/2D.h"
+#include "brotli/decode.h"
+#include "zlib.h"
+#include "mozilla/dom/CSSFontFaceRule.h"
+#include "mozilla/dom/FontFaceSet.h"
+#include "mozilla/ServoBindings.h"
+#include "mozilla/Unused.h"
+
+namespace mozilla {
+namespace dom {
+
+InspectorFontFace::InspectorFontFace(gfxFontEntry* aFontEntry,
+ gfxFontGroup* aFontGroup,
+ FontMatchType aMatchType)
+ : mFontEntry(aFontEntry), mFontGroup(aFontGroup), mMatchType(aMatchType) {
+ MOZ_COUNT_CTOR(InspectorFontFace);
+}
+
+InspectorFontFace::~InspectorFontFace() { MOZ_COUNT_DTOR(InspectorFontFace); }
+
+bool InspectorFontFace::FromFontGroup() {
+ return bool(mMatchType.kind & FontMatchType::Kind::kFontGroup);
+}
+
+bool InspectorFontFace::FromLanguagePrefs() {
+ return bool(mMatchType.kind & FontMatchType::Kind::kPrefsFallback);
+}
+
+bool InspectorFontFace::FromSystemFallback() {
+ return bool(mMatchType.kind & FontMatchType::Kind::kSystemFallback);
+}
+
+void InspectorFontFace::GetName(nsAString& aName) {
+ if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mRealName));
+ } else {
+ aName.Append(NS_ConvertUTF8toUTF16(mFontEntry->RealFaceName()));
+ }
+}
+
+void InspectorFontFace::GetCSSFamilyName(nsAString& aCSSFamilyName) {
+ aCSSFamilyName.Append(NS_ConvertUTF8toUTF16(mFontEntry->FamilyName()));
+}
+
+void InspectorFontFace::GetCSSGeneric(nsAString& aName) {
+ if (mMatchType.generic != StyleGenericFontFamily::None) {
+ aName.AssignASCII(gfxPlatformFontList::GetGenericName(mMatchType.generic));
+ } else {
+ aName.Truncate(0);
+ }
+}
+
+CSSFontFaceRule* InspectorFontFace::GetRule() {
+ if (!mRule) {
+ // check whether this font entry is associated with an @font-face rule
+ // in the relevant font group's user font set
+ RawServoFontFaceRule* rule = nullptr;
+ if (mFontEntry->IsUserFont()) {
+ FontFaceSet::UserFontSet* fontSet =
+ static_cast<FontFaceSet::UserFontSet*>(mFontGroup->GetUserFontSet());
+ if (fontSet) {
+ FontFaceSet* fontFaceSet = fontSet->GetFontFaceSet();
+ if (fontFaceSet) {
+ rule = fontFaceSet->FindRuleForEntry(mFontEntry);
+ }
+ }
+ }
+ if (rule) {
+ // XXX It would be better if we can share this with CSSOM tree,
+ // but that may require us to create another map, which is not
+ // great either. As far as they would use the same backend, and
+ // we don't really support mutating @font-face rule via CSSOM,
+ // it's probably fine for now.
+ uint32_t line, column;
+ Servo_FontFaceRule_GetSourceLocation(rule, &line, &column);
+ mRule =
+ new CSSFontFaceRule(do_AddRef(rule), nullptr, nullptr, line, column);
+ }
+ }
+ return mRule;
+}
+
+int32_t InspectorFontFace::SrcIndex() {
+ if (mFontEntry->IsUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ return mFontEntry->mUserFontData->mSrcIndex;
+ }
+
+ return -1;
+}
+
+void InspectorFontFace::GetURI(nsAString& aURI) {
+ aURI.Truncate();
+ if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ if (mFontEntry->mUserFontData->mURI) {
+ nsAutoCString spec;
+ mFontEntry->mUserFontData->mURI->GetSpec(spec);
+ AppendUTF8toUTF16(spec, aURI);
+ }
+ }
+}
+
+void InspectorFontFace::GetLocalName(nsAString& aLocalName) {
+ aLocalName.Truncate();
+ if (mFontEntry->IsLocalUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ aLocalName.Append(
+ NS_ConvertUTF8toUTF16(mFontEntry->mUserFontData->mLocalName));
+ }
+}
+
+static void AppendToFormat(nsAString& aResult, const char* aFormat) {
+ if (!aResult.IsEmpty()) {
+ aResult.Append(',');
+ }
+ aResult.AppendASCII(aFormat);
+}
+
+void InspectorFontFace::GetFormat(nsAString& aFormat) {
+ aFormat.Truncate();
+ if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ uint32_t formatFlags = mFontEntry->mUserFontData->mFormat;
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE) {
+ AppendToFormat(aFormat, "opentype");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE) {
+ AppendToFormat(aFormat, "truetype");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT) {
+ AppendToFormat(aFormat, "truetype-aat");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_EOT) {
+ AppendToFormat(aFormat, "embedded-opentype");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_SVG) {
+ AppendToFormat(aFormat, "svg");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF) {
+ AppendToFormat(aFormat, "woff");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2) {
+ AppendToFormat(aFormat, "woff2");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_OPENTYPE_VARIATIONS) {
+ AppendToFormat(aFormat, "opentype-variations");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_TRUETYPE_VARIATIONS) {
+ AppendToFormat(aFormat, "truetype-variations");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF_VARIATIONS) {
+ AppendToFormat(aFormat, "woff-variations");
+ }
+ if (formatFlags & gfxUserFontSet::FLAG_FORMAT_WOFF2_VARIATIONS) {
+ AppendToFormat(aFormat, "woff2-variations");
+ }
+ }
+}
+
+void InspectorFontFace::GetMetadata(nsAString& aMetadata) {
+ aMetadata.Truncate();
+ if (mFontEntry->IsUserFont() && !mFontEntry->IsLocalUserFont()) {
+ NS_ASSERTION(mFontEntry->mUserFontData, "missing userFontData");
+ const gfxUserFontData* userFontData = mFontEntry->mUserFontData.get();
+ if (userFontData->mMetadata.Length() && userFontData->mMetaOrigLen) {
+ nsAutoCString str;
+ str.SetLength(userFontData->mMetaOrigLen);
+ if (str.Length() == userFontData->mMetaOrigLen) {
+ switch (userFontData->mCompression) {
+ case gfxUserFontData::kZlibCompression: {
+ uLongf destLen = userFontData->mMetaOrigLen;
+ if (uncompress((Bytef*)(str.BeginWriting()), &destLen,
+ (const Bytef*)(userFontData->mMetadata.Elements()),
+ userFontData->mMetadata.Length()) == Z_OK &&
+ destLen == userFontData->mMetaOrigLen) {
+ AppendUTF8toUTF16(str, aMetadata);
+ }
+ } break;
+ case gfxUserFontData::kBrotliCompression: {
+ size_t decodedSize = userFontData->mMetaOrigLen;
+ if (BrotliDecoderDecompress(userFontData->mMetadata.Length(),
+ userFontData->mMetadata.Elements(),
+ &decodedSize,
+ (uint8_t*)str.BeginWriting()) == 1 &&
+ decodedSize == userFontData->mMetaOrigLen) {
+ AppendUTF8toUTF16(str, aMetadata);
+ }
+ } break;
+ }
+ }
+ }
+ }
+}
+
+// Append an OpenType tag to a string as a 4-ASCII-character code.
+static void AppendTagAsASCII(nsAString& aString, uint32_t aTag) {
+ aString.AppendPrintf("%c%c%c%c", (aTag >> 24) & 0xff, (aTag >> 16) & 0xff,
+ (aTag >> 8) & 0xff, aTag & 0xff);
+}
+
+void InspectorFontFace::GetVariationAxes(
+ nsTArray<InspectorVariationAxis>& aResult, ErrorResult& aRV) {
+ if (!mFontEntry->HasVariations()) {
+ return;
+ }
+ AutoTArray<gfxFontVariationAxis, 4> axes;
+ mFontEntry->GetVariationAxes(axes);
+ MOZ_ASSERT(!axes.IsEmpty());
+ if (!aResult.SetCapacity(axes.Length(), mozilla::fallible)) {
+ aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ for (auto a : axes) {
+ InspectorVariationAxis& axis = *aResult.AppendElement();
+ AppendTagAsASCII(axis.mTag, a.mTag);
+ axis.mName.Append(NS_ConvertUTF8toUTF16(a.mName));
+ axis.mMinValue = a.mMinValue;
+ axis.mMaxValue = a.mMaxValue;
+ axis.mDefaultValue = a.mDefaultValue;
+ }
+}
+
+void InspectorFontFace::GetVariationInstances(
+ nsTArray<InspectorVariationInstance>& aResult, ErrorResult& aRV) {
+ if (!mFontEntry->HasVariations()) {
+ return;
+ }
+ AutoTArray<gfxFontVariationInstance, 16> instances;
+ mFontEntry->GetVariationInstances(instances);
+ if (!aResult.SetCapacity(instances.Length(), mozilla::fallible)) {
+ aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ for (const auto& i : instances) {
+ InspectorVariationInstance& inst = *aResult.AppendElement();
+ inst.mName.Append(NS_ConvertUTF8toUTF16(i.mName));
+ // inst.mValues is a webidl sequence<>, which is a fallible array,
+ // so we are required to use fallible SetCapacity and AppendElement calls,
+ // and check the result. In practice we don't expect failure here; the
+ // list of values cannot get huge because of limits in the font format.
+ if (!inst.mValues.SetCapacity(i.mValues.Length(), mozilla::fallible)) {
+ aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ for (const auto& v : i.mValues) {
+ InspectorVariationValue value;
+ AppendTagAsASCII(value.mAxis, v.mAxis);
+ value.mValue = v.mValue;
+ // This won't fail, because of SetCapacity above.
+ Unused << inst.mValues.AppendElement(value, mozilla::fallible);
+ }
+ }
+}
+
+void InspectorFontFace::GetFeatures(nsTArray<InspectorFontFeature>& aResult,
+ ErrorResult& aRV) {
+ AutoTArray<gfxFontFeatureInfo, 64> features;
+ mFontEntry->GetFeatureInfo(features);
+ if (features.IsEmpty()) {
+ return;
+ }
+ if (!aResult.SetCapacity(features.Length(), mozilla::fallible)) {
+ aRV.Throw(NS_ERROR_OUT_OF_MEMORY);
+ return;
+ }
+ for (auto& f : features) {
+ InspectorFontFeature& feat = *aResult.AppendElement();
+ AppendTagAsASCII(feat.mTag, f.mTag);
+ AppendTagAsASCII(feat.mScript, f.mScript);
+ AppendTagAsASCII(feat.mLanguageSystem, f.mLangSys);
+ }
+}
+
+void InspectorFontFace::GetRanges(nsTArray<RefPtr<nsRange>>& aResult) {
+ aResult = mRanges.Clone();
+}
+
+void InspectorFontFace::AddRange(nsRange* aRange) {
+ mRanges.AppendElement(aRange);
+}
+
+} // namespace dom
+} // namespace mozilla