gecko-dev/layout/inspector/InspectorFontFace.cpp

336 строки
10 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* 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 {
bool
InspectorFontFace::FromFontGroup()
{
return bool(mMatchType & gfxTextRange::MatchType::kFontGroup);
}
bool
InspectorFontFace::FromLanguagePrefs()
{
return bool(mMatchType & gfxTextRange::MatchType::kPrefsFallback);
}
bool
InspectorFontFace::FromSystemFallback()
{
return bool(mMatchType & gfxTextRange::MatchType::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)
{
auto genericType =
FontFamilyType(mMatchType & gfxTextRange::MatchType::kGenericMask);
if (genericType >= FontFamilyType::eFamily_generic_first &&
genericType <= FontFamilyType::eFamily_generic_last) {
aName.AssignASCII(gfxPlatformFontList::GetGenericName(genericType));
} else {
aName.Truncate(0);
}
}
CSSFontFaceRule*
InspectorFontFace::GetRule()
{
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio This patch does the following things: * Create a new class ServoFontFaceRule for CSSOM of @font-face rule which mostly follows how nsCSSFontFaceRule was implemented. * Remove the old nsCSSFontFaceRule and binding code to create it. * Have FontFace backed by Servo data via making mRule and mDescriptors of the class hold RawServoFontFaceRule like ServoFontFaceRule. To keep this patch small, it effectively just delays the conversion from Servo data to nsCSSValue from parsing to using. This may cause worse performance if the font set is flushed repeatedly. Supposing we don't flush font set very frequently, it may not be a big deal. We may still want to remove the intermediate nsCSSValue conversion at some point, and have everything converted to their final form directly when used, but that can happen in followups. There are some unfortunate bits from this change: * We lose style sheet for logging in FontFaceSet. This is probably not all that worse, because we wouldn't have that before either if the page doesn't use CSSOM to visit it. But we should figure out some approach to fix it anyway. * InspectorFontFace no longer shares the same rule object as CSSOM. This isn't really a problem if the @font-face rule isn't very mutable. Unless we want to make the rule returned from InspectorFontFace to be mutable (i.e. via inspector), not using the same object probably isn't too bad. This patch switches the code we use to serialize stuff in FontFace and CSSFontFaceRule, which leads to some failures in tests. Specifically, the expected changes including: * Value of font-family now can be serialized to identifier sequence like font-family property. The old code always serializes it to string, but it doesn't seem to have different requirement than the property. Blink can serialize to identifier as well. * Family name inside local() is also changed to use the same way as family names elsewhere (i.e. can be identifier sequence). Blink has the same behavior as the old code, but I don't think it's a big deal. * The order of descriptors serialized gets changed. I don't think it matters at all. * Empty string as font-family via using string syntax is no longer considered invalid for FontFace. I don't find it is mentioned anywhere that it should be specifically treated invalid. MozReview-Commit-ID: 32Fk3Fi9uTs --HG-- extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
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);
}
}
}
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio This patch does the following things: * Create a new class ServoFontFaceRule for CSSOM of @font-face rule which mostly follows how nsCSSFontFaceRule was implemented. * Remove the old nsCSSFontFaceRule and binding code to create it. * Have FontFace backed by Servo data via making mRule and mDescriptors of the class hold RawServoFontFaceRule like ServoFontFaceRule. To keep this patch small, it effectively just delays the conversion from Servo data to nsCSSValue from parsing to using. This may cause worse performance if the font set is flushed repeatedly. Supposing we don't flush font set very frequently, it may not be a big deal. We may still want to remove the intermediate nsCSSValue conversion at some point, and have everything converted to their final form directly when used, but that can happen in followups. There are some unfortunate bits from this change: * We lose style sheet for logging in FontFaceSet. This is probably not all that worse, because we wouldn't have that before either if the page doesn't use CSSOM to visit it. But we should figure out some approach to fix it anyway. * InspectorFontFace no longer shares the same rule object as CSSOM. This isn't really a problem if the @font-face rule isn't very mutable. Unless we want to make the rule returned from InspectorFontFace to be mutable (i.e. via inspector), not using the same object probably isn't too bad. This patch switches the code we use to serialize stuff in FontFace and CSSFontFaceRule, which leads to some failures in tests. Specifically, the expected changes including: * Value of font-family now can be serialized to identifier sequence like font-family property. The old code always serializes it to string, but it doesn't seem to have different requirement than the property. Blink can serialize to identifier as well. * Family name inside local() is also changed to use the same way as family names elsewhere (i.e. can be identifier sequence). Blink has the same behavior as the old code, but I don't think it's a big deal. * The order of descriptors serialized gets changed. I don't think it matters at all. * Empty string as font-family via using string syntax is no longer considered invalid for FontFace. I don't find it is mentioned anywhere that it should be specifically treated invalid. MozReview-Commit-ID: 32Fk3Fi9uTs --HG-- extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
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);
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio This patch does the following things: * Create a new class ServoFontFaceRule for CSSOM of @font-face rule which mostly follows how nsCSSFontFaceRule was implemented. * Remove the old nsCSSFontFaceRule and binding code to create it. * Have FontFace backed by Servo data via making mRule and mDescriptors of the class hold RawServoFontFaceRule like ServoFontFaceRule. To keep this patch small, it effectively just delays the conversion from Servo data to nsCSSValue from parsing to using. This may cause worse performance if the font set is flushed repeatedly. Supposing we don't flush font set very frequently, it may not be a big deal. We may still want to remove the intermediate nsCSSValue conversion at some point, and have everything converted to their final form directly when used, but that can happen in followups. There are some unfortunate bits from this change: * We lose style sheet for logging in FontFaceSet. This is probably not all that worse, because we wouldn't have that before either if the page doesn't use CSSOM to visit it. But we should figure out some approach to fix it anyway. * InspectorFontFace no longer shares the same rule object as CSSOM. This isn't really a problem if the @font-face rule isn't very mutable. Unless we want to make the rule returned from InspectorFontFace to be mutable (i.e. via inspector), not using the same object probably isn't too bad. This patch switches the code we use to serialize stuff in FontFace and CSSFontFaceRule, which leads to some failures in tests. Specifically, the expected changes including: * Value of font-family now can be serialized to identifier sequence like font-family property. The old code always serializes it to string, but it doesn't seem to have different requirement than the property. Blink can serialize to identifier as well. * Family name inside local() is also changed to use the same way as family names elsewhere (i.e. can be identifier sequence). Blink has the same behavior as the old code, but I don't think it's a big deal. * The order of descriptors serialized gets changed. I don't think it matters at all. * Empty string as font-family via using string syntax is no longer considered invalid for FontFace. I don't find it is mentioned anywhere that it should be specifically treated invalid. MozReview-Commit-ID: 32Fk3Fi9uTs --HG-- extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
}
}
Bug 1449087 part 2 - Use Servo data to back @font-face rule. r=emilio This patch does the following things: * Create a new class ServoFontFaceRule for CSSOM of @font-face rule which mostly follows how nsCSSFontFaceRule was implemented. * Remove the old nsCSSFontFaceRule and binding code to create it. * Have FontFace backed by Servo data via making mRule and mDescriptors of the class hold RawServoFontFaceRule like ServoFontFaceRule. To keep this patch small, it effectively just delays the conversion from Servo data to nsCSSValue from parsing to using. This may cause worse performance if the font set is flushed repeatedly. Supposing we don't flush font set very frequently, it may not be a big deal. We may still want to remove the intermediate nsCSSValue conversion at some point, and have everything converted to their final form directly when used, but that can happen in followups. There are some unfortunate bits from this change: * We lose style sheet for logging in FontFaceSet. This is probably not all that worse, because we wouldn't have that before either if the page doesn't use CSSOM to visit it. But we should figure out some approach to fix it anyway. * InspectorFontFace no longer shares the same rule object as CSSOM. This isn't really a problem if the @font-face rule isn't very mutable. Unless we want to make the rule returned from InspectorFontFace to be mutable (i.e. via inspector), not using the same object probably isn't too bad. This patch switches the code we use to serialize stuff in FontFace and CSSFontFaceRule, which leads to some failures in tests. Specifically, the expected changes including: * Value of font-family now can be serialized to identifier sequence like font-family property. The old code always serializes it to string, but it doesn't seem to have different requirement than the property. Blink can serialize to identifier as well. * Family name inside local() is also changed to use the same way as family names elsewhere (i.e. can be identifier sequence). Blink has the same behavior as the old code, but I don't think it's a big deal. * The order of descriptors serialized gets changed. I don't think it matters at all. * Empty string as font-family via using string syntax is no longer considered invalid for FontFace. I don't find it is mentioned anywhere that it should be specifically treated invalid. MozReview-Commit-ID: 32Fk3Fi9uTs --HG-- extra : rebase_source : 6221ec8fc56de357b06dd27e770fb175348a2f77
2018-04-04 01:42:10 +03:00
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 (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 (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;
}
void
InspectorFontFace::AddRange(nsRange* aRange)
{
mRanges.AppendElement(aRange);
}
} // namespace dom
} // namespace mozilla