зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1464094 - print font variations as paths for PDF/PS output. r=jfkthame
MozReview-Commit-ID: 3sPKD4pNwdy
This commit is contained in:
Родитель
67537a721b
Коммит
50e6372cf9
|
@ -881,6 +881,8 @@ public:
|
|||
|
||||
virtual bool CanSerialize() { return false; }
|
||||
|
||||
virtual bool HasVariationSettings() { return false; }
|
||||
|
||||
void AddUserData(UserDataKey *key, void *userData, void (*destroy)(void*)) {
|
||||
mUserData.Add(key, userData, destroy);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/Scoped.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
#include "cairo.h"
|
||||
#include "cairo-tee.h"
|
||||
|
@ -1348,6 +1349,19 @@ DrawTargetCairo::SetPermitSubpixelAA(bool aPermitSubpixelAA)
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
SupportsVariationSettings(cairo_surface_t* surface)
|
||||
{
|
||||
switch (cairo_surface_get_type(surface))
|
||||
{
|
||||
case CAIRO_SURFACE_TYPE_PDF:
|
||||
case CAIRO_SURFACE_TYPE_PS:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetCairo::FillGlyphs(ScaledFont *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
|
@ -1403,7 +1417,17 @@ DrawTargetCairo::FillGlyphs(ScaledFont *aFont,
|
|||
glyphs[i].y = aBuffer.mGlyphs[i].mPosition.y;
|
||||
}
|
||||
|
||||
cairo_show_glyphs(mContext, &glyphs[0], aBuffer.mNumGlyphs);
|
||||
if (!SupportsVariationSettings(mSurface) &&
|
||||
aFont->HasVariationSettings() &&
|
||||
gfxPrefs::PrintFontVariationsAsPaths()) {
|
||||
cairo_set_fill_rule(mContext, CAIRO_FILL_RULE_WINDING);
|
||||
cairo_new_path(mContext);
|
||||
cairo_glyph_path(mContext, &glyphs[0], aBuffer.mNumGlyphs);
|
||||
cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
|
||||
cairo_fill(mContext);
|
||||
} else {
|
||||
cairo_show_glyphs(mContext, &glyphs[0], aBuffer.mNumGlyphs);
|
||||
}
|
||||
|
||||
if (cairo_surface_status(cairo_get_group_target(mContext))) {
|
||||
gfxDebug() << "Ending FillGlyphs with a bad surface " << cairo_surface_status(cairo_get_group_target(mContext));
|
||||
|
|
|
@ -12,9 +12,12 @@
|
|||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
NativeFontResourceFontconfig::NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace)
|
||||
: mFontData(std::move(aFontData)),
|
||||
mFace(aFace)
|
||||
NativeFontResourceFontconfig::NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData,
|
||||
uint32_t aDataLength,
|
||||
FT_Face aFace)
|
||||
: mFontData(std::move(aFontData))
|
||||
, mDataLength(aDataLength)
|
||||
, mFace(aFace)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,7 +51,7 @@ NativeFontResourceFontconfig::Create(uint8_t *aFontData, uint32_t aDataLength, F
|
|||
}
|
||||
|
||||
RefPtr<NativeFontResourceFontconfig> resource =
|
||||
new NativeFontResourceFontconfig(std::move(fontData), face);
|
||||
new NativeFontResourceFontconfig(std::move(fontData), aDataLength, face);
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
|
@ -60,5 +63,11 @@ NativeFontResourceFontconfig::CreateUnscaledFont(uint32_t aIndex,
|
|||
return unscaledFont.forget();
|
||||
}
|
||||
|
||||
FT_Face
|
||||
NativeFontResourceFontconfig::CloneFace()
|
||||
{
|
||||
return Factory::NewFTFaceFromData(mFace->glyph->library, mFontData.get(), mDataLength, 0);
|
||||
}
|
||||
|
||||
} // gfx
|
||||
} // mozilla
|
||||
|
|
|
@ -29,10 +29,15 @@ public:
|
|||
|
||||
~NativeFontResourceFontconfig();
|
||||
|
||||
FT_Face CloneFace();
|
||||
|
||||
private:
|
||||
NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData, FT_Face aFace);
|
||||
NativeFontResourceFontconfig(UniquePtr<uint8_t[]>&& aFontData,
|
||||
uint32_t aDataLength,
|
||||
FT_Face aFace);
|
||||
|
||||
UniquePtr<uint8_t[]> mFontData;
|
||||
uint32_t mDataLength;
|
||||
FT_Face mFace;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include "ScaledFontFontconfig.h"
|
||||
#include "UnscaledFontFreeType.h"
|
||||
#include "NativeFontResourceFontconfig.h"
|
||||
#include "Logging.h"
|
||||
#include "StackArray.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
|
||||
#ifdef USE_SKIA
|
||||
|
@ -14,6 +16,9 @@
|
|||
#endif
|
||||
|
||||
#include <fontconfig/fcfreetype.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -224,12 +229,67 @@ ScaledFontFontconfig::InstanceData::SetupFontMatrix(cairo_matrix_t* aFontMatrix)
|
|||
cairo_matrix_init(aFontMatrix, mScale, 0, mSkew, mScale, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
ScaledFontFontconfig::GetVariationSettings(std::vector<FontVariation>* aVariations)
|
||||
{
|
||||
aVariations->clear();
|
||||
|
||||
typedef FT_Error (*GetVarFunc)(FT_Face, FT_MM_Var**);
|
||||
typedef FT_Error (*DoneVarFunc)(FT_Library, FT_MM_Var*);
|
||||
typedef FT_Error (*GetVarDesignCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||
static GetVarFunc getVar;
|
||||
static DoneVarFunc doneVar;
|
||||
static GetVarDesignCoordsFunc getCoords;
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
getVar = (GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
|
||||
doneVar = (DoneVarFunc)dlsym(RTLD_DEFAULT, "FT_Done_MM_Var");
|
||||
getCoords = (GetVarDesignCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Get_Var_Design_Coordinates");
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* sf = GetCairoScaledFont();
|
||||
FT_Face face = cairo_ft_scaled_font_lock_face(sf);
|
||||
if (face && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
FT_MM_Var* mmVar;
|
||||
if ((*getVar)(face, &mmVar) == FT_Err_Ok) {
|
||||
aVariations->reserve(mmVar->num_axis);
|
||||
StackArray<FT_Fixed, 32> coords(mmVar->num_axis);
|
||||
if ((*getCoords)(face, mmVar->num_axis, coords.data()) == FT_Err_Ok) {
|
||||
bool changed = false;
|
||||
for (uint32_t i = 0; i < mmVar->num_axis; i++) {
|
||||
if (coords[i] != mmVar->axis[i].def) {
|
||||
changed = true;
|
||||
}
|
||||
aVariations->push_back(FontVariation{uint32_t(mmVar->axis[i].tag),
|
||||
float(coords[i] / 65536.0)});
|
||||
}
|
||||
if (!changed) {
|
||||
aVariations->clear();
|
||||
}
|
||||
}
|
||||
if (doneVar) {
|
||||
(*doneVar)(face->glyph->library, mmVar);
|
||||
} else {
|
||||
free(mmVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
cairo_ft_scaled_font_unlock_face(sf);
|
||||
}
|
||||
|
||||
bool
|
||||
ScaledFontFontconfig::GetFontInstanceData(FontInstanceDataOutput aCb, void* aBaton)
|
||||
{
|
||||
InstanceData instance(GetCairoScaledFont(), mPattern);
|
||||
|
||||
aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance), nullptr, 0, aBaton);
|
||||
std::vector<FontVariation> variations;
|
||||
if (HasVariationSettings()) {
|
||||
GetVariationSettings(&variations);
|
||||
}
|
||||
|
||||
aCb(reinterpret_cast<uint8_t*>(&instance), sizeof(instance),
|
||||
variations.data(), variations.size(), aBaton);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -348,6 +408,11 @@ ScaledFontFontconfig::GetWRFontInstanceOptions(Maybe<wr::FontInstanceOptions>* a
|
|||
|
||||
*aOutOptions = Some(options);
|
||||
*aOutPlatformOptions = Some(platformOptions);
|
||||
|
||||
if (HasVariationSettings()) {
|
||||
GetVariationSettings(aOutVariations);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -364,8 +429,12 @@ UnscaledFontFontconfig::CreateScaledFont(Float aGlyphSize,
|
|||
}
|
||||
const ScaledFontFontconfig::InstanceData *instanceData =
|
||||
reinterpret_cast<const ScaledFontFontconfig::InstanceData*>(aInstanceData);
|
||||
return ScaledFontFontconfig::CreateFromInstanceData(*instanceData, this, aGlyphSize,
|
||||
mNativeFontResource.get());
|
||||
RefPtr<ScaledFont> scaledFont =
|
||||
ScaledFontFontconfig::CreateFromInstanceData(*instanceData, this, aGlyphSize,
|
||||
aVariations, aNumVariations,
|
||||
static_cast<NativeFontResourceFontconfig*>(
|
||||
mNativeFontResource.get()));
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t sNativeFontResourceKey;
|
||||
|
@ -376,20 +445,37 @@ ReleaseNativeFontResource(void* aData)
|
|||
static_cast<NativeFontResource*>(aData)->Release();
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t sFaceKey;
|
||||
|
||||
static void
|
||||
ReleaseFace(void* aData)
|
||||
{
|
||||
Factory::ReleaseFTFace(static_cast<FT_Face>(aData));
|
||||
}
|
||||
|
||||
already_AddRefed<ScaledFont>
|
||||
ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
||||
UnscaledFontFontconfig* aUnscaledFont,
|
||||
Float aSize,
|
||||
NativeFontResource* aNativeFontResource)
|
||||
const FontVariation* aVariations,
|
||||
uint32_t aNumVariations,
|
||||
NativeFontResourceFontconfig* aNativeFontResource)
|
||||
{
|
||||
FcPattern* pattern = FcPatternCreate();
|
||||
if (!pattern) {
|
||||
gfxWarning() << "Failing initializing Fontconfig pattern for scaled font";
|
||||
gfxWarning() << "Failed initializing Fontconfig pattern for scaled font";
|
||||
return nullptr;
|
||||
}
|
||||
FT_Face face = aUnscaledFont->GetFace();
|
||||
FT_Face varFace = nullptr;
|
||||
if (face) {
|
||||
FcPatternAddFTFace(pattern, FC_FT_FACE, face);
|
||||
if (aNativeFontResource && aNumVariations > 0) {
|
||||
varFace = aNativeFontResource->CloneFace();
|
||||
if (!varFace) {
|
||||
gfxWarning() << "Failed cloning face for variations";
|
||||
}
|
||||
}
|
||||
FcPatternAddFTFace(pattern, FC_FT_FACE, varFace ? varFace : face);
|
||||
} else {
|
||||
FcPatternAddString(pattern, FC_FILE, reinterpret_cast<const FcChar8*>(aUnscaledFont->GetFile()));
|
||||
FcPatternAddInteger(pattern, FC_INDEX, aUnscaledFont->GetIndex());
|
||||
|
@ -397,10 +483,18 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
|||
FcPatternAddDouble(pattern, FC_PIXEL_SIZE, aSize);
|
||||
aInstanceData.SetupPattern(pattern);
|
||||
|
||||
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern, nullptr, 0);
|
||||
StackArray<FT_Fixed, 32> coords(aNumVariations);
|
||||
for (uint32_t i = 0; i < aNumVariations; i++) {
|
||||
coords[i] = std::round(aVariations[i].mValue * 65536.0);
|
||||
}
|
||||
|
||||
cairo_font_face_t* font = cairo_ft_font_face_create_for_pattern(pattern, coords.data(), aNumVariations);
|
||||
if (cairo_font_face_status(font) != CAIRO_STATUS_SUCCESS) {
|
||||
gfxWarning() << "Failed creating Cairo font face for Fontconfig pattern";
|
||||
FcPatternDestroy(pattern);
|
||||
if (varFace) {
|
||||
Factory::ReleaseFTFace(varFace);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -414,13 +508,28 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
|||
// to prevent races if multiple threads are thus sharing the same Cairo face.
|
||||
FT_Library library = face ? face->glyph->library : Factory::GetFTLibrary();
|
||||
Factory::LockFTLibrary(library);
|
||||
cairo_status_t err = cairo_font_face_set_user_data(font,
|
||||
&sNativeFontResourceKey,
|
||||
aNativeFontResource,
|
||||
ReleaseNativeFontResource);
|
||||
cairo_status_t err = CAIRO_STATUS_SUCCESS;
|
||||
bool cleanupFace = false;
|
||||
if (varFace) {
|
||||
err = cairo_font_face_set_user_data(font,
|
||||
&sFaceKey,
|
||||
varFace,
|
||||
ReleaseFace);
|
||||
}
|
||||
if (err != CAIRO_STATUS_SUCCESS) {
|
||||
cleanupFace = true;
|
||||
} else {
|
||||
err = cairo_font_face_set_user_data(font,
|
||||
&sNativeFontResourceKey,
|
||||
aNativeFontResource,
|
||||
ReleaseNativeFontResource);
|
||||
}
|
||||
Factory::UnlockFTLibrary(library);
|
||||
if (err != CAIRO_STATUS_SUCCESS) {
|
||||
gfxWarning() << "Failed binding NativeFontResource to Cairo font face";
|
||||
if (varFace && cleanupFace) {
|
||||
Factory::ReleaseFTFace(varFace);
|
||||
}
|
||||
aNativeFontResource->Release();
|
||||
cairo_font_face_destroy(font);
|
||||
FcPatternDestroy(pattern);
|
||||
|
@ -455,9 +564,51 @@ ScaledFontFontconfig::CreateFromInstanceData(const InstanceData& aInstanceData,
|
|||
cairo_scaled_font_destroy(cairoScaledFont);
|
||||
FcPatternDestroy(pattern);
|
||||
|
||||
// Only apply variations if we have an explicitly cloned face. Otherwise,
|
||||
// if the pattern holds the pathname, Cairo will handle setting of variations.
|
||||
if (varFace) {
|
||||
scaledFont->ApplyVariations(aVariations, aNumVariations);
|
||||
}
|
||||
|
||||
return scaledFont.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ScaledFontFontconfig::ApplyVariations(const FontVariation* aVariations,
|
||||
uint32_t aNumVariations)
|
||||
{
|
||||
typedef FT_Error (*SetVarDesignCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
||||
static SetVarDesignCoordsFunc setCoords;
|
||||
static bool firstTime = true;
|
||||
if (firstTime) {
|
||||
firstTime = false;
|
||||
setCoords = (SetVarDesignCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* sf = GetCairoScaledFont();
|
||||
FT_Face face = cairo_ft_scaled_font_lock_face(sf);
|
||||
if (face && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
|
||||
StackArray<FT_Fixed, 32> coords(aNumVariations);
|
||||
for (uint32_t i = 0; i < aNumVariations; i++) {
|
||||
coords[i] = std::round(aVariations[i].mValue * 65536.0f);
|
||||
}
|
||||
if ((*setCoords)(face, aNumVariations, coords.data()) != FT_Err_Ok) {
|
||||
// ignore the problem?
|
||||
}
|
||||
}
|
||||
cairo_ft_scaled_font_unlock_face(sf);
|
||||
}
|
||||
|
||||
bool
|
||||
ScaledFontFontconfig::HasVariationSettings()
|
||||
{
|
||||
// Check if the FT face has been cloned.
|
||||
FT_Face face = nullptr;
|
||||
return FcPatternGetFTFace(mPattern, FC_FT_FACE, 0, &face) == FcResultMatch &&
|
||||
face && face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS &&
|
||||
face != static_cast<UnscaledFontFontconfig*>(mUnscaledFont.get())->GetFace();
|
||||
}
|
||||
|
||||
already_AddRefed<UnscaledFont>
|
||||
UnscaledFontFontconfig::CreateFromFontDescriptor(const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex)
|
||||
{
|
||||
|
|
|
@ -39,10 +39,16 @@ public:
|
|||
Maybe<wr::FontInstancePlatformOptions>* aOutPlatformOptions,
|
||||
std::vector<FontVariation>* aOutVariations) override;
|
||||
|
||||
void ApplyVariations(const FontVariation* aVariations, uint32_t aNumVariations);
|
||||
|
||||
bool HasVariationSettings() override;
|
||||
|
||||
private:
|
||||
friend class NativeFontResourceFontconfig;
|
||||
friend class UnscaledFontFontconfig;
|
||||
|
||||
void GetVariationSettings(std::vector<FontVariation>* aVariations);
|
||||
|
||||
struct InstanceData
|
||||
{
|
||||
enum {
|
||||
|
@ -72,7 +78,9 @@ private:
|
|||
CreateFromInstanceData(const InstanceData& aInstanceData,
|
||||
UnscaledFontFontconfig* aUnscaledFont,
|
||||
Float aSize,
|
||||
NativeFontResource* aNativeFontResource = nullptr);
|
||||
const FontVariation* aVariations,
|
||||
uint32_t aNumVariations,
|
||||
NativeFontResourceFontconfig* aNativeFontResource = nullptr);
|
||||
|
||||
FcPattern* mPattern;
|
||||
};
|
||||
|
|
|
@ -749,10 +749,19 @@ ReleaseFTUserFontData(void* aData)
|
|||
static_cast<FTUserFontData*>(aData)->Release();
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t sFcFontlistFTFaceKey;
|
||||
|
||||
static void
|
||||
ReleaseFTFace(void* aData)
|
||||
{
|
||||
Factory::ReleaseFTFace(static_cast<FT_Face>(aData));
|
||||
}
|
||||
|
||||
cairo_scaled_font_t*
|
||||
gfxFontconfigFontEntry::CreateScaledFont(FcPattern* aRenderPattern,
|
||||
gfxFloat aAdjustedSize,
|
||||
const gfxFontStyle *aStyle)
|
||||
const gfxFontStyle *aStyle,
|
||||
FT_Face aFTFace)
|
||||
{
|
||||
if (aStyle->NeedsSyntheticBold(this)) {
|
||||
FcPatternAddBool(aRenderPattern, FC_EMBOLDEN, FcTrue);
|
||||
|
@ -784,9 +793,21 @@ gfxFontconfigFontEntry::CreateScaledFont(FcPattern* aRenderPattern,
|
|||
coords.Elements(),
|
||||
coords.Length());
|
||||
|
||||
if (aFTFace) {
|
||||
if (cairo_font_face_set_user_data(face,
|
||||
&sFcFontlistFTFaceKey,
|
||||
aFTFace,
|
||||
ReleaseFTFace) != CAIRO_STATUS_SUCCESS) {
|
||||
NS_WARNING("Failed binding FT_Face to Cairo font face");
|
||||
cairo_font_face_destroy(face);
|
||||
Factory::ReleaseFTFace(aFTFace);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (mFontData) {
|
||||
// for data fonts, add the face/data pointer to the cairo font face
|
||||
// so that it gets deleted whenever cairo decides
|
||||
// so that it ges deleted whenever cairo decides
|
||||
NS_ASSERTION(mFTFace, "FT_Face is null when setting user data");
|
||||
NS_ASSERTION(mUserFontData, "user font data is null when setting user data");
|
||||
mUserFontData.get()->AddRef();
|
||||
|
@ -1009,11 +1030,14 @@ gfxFontconfigFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle)
|
|||
}
|
||||
if (!renderPattern) {
|
||||
NS_WARNING("Failed to prepare Fontconfig pattern for font instance");
|
||||
if (face != mFTFace) {
|
||||
Factory::ReleaseFTFace(face);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
cairo_scaled_font_t* scaledFont =
|
||||
CreateScaledFont(renderPattern, size, aFontStyle);
|
||||
CreateScaledFont(renderPattern, size, aFontStyle, face != mFTFace ? face : nullptr);
|
||||
|
||||
const FcChar8* file = ToFcChar8Ptr("");
|
||||
int index = 0;
|
||||
|
|
|
@ -139,7 +139,8 @@ protected:
|
|||
cairo_scaled_font_t*
|
||||
CreateScaledFont(FcPattern* aRenderPattern,
|
||||
gfxFloat aAdjustedSize,
|
||||
const gfxFontStyle *aStyle);
|
||||
const gfxFontStyle *aStyle,
|
||||
FT_Face aFTFace);
|
||||
|
||||
// override to pull data from FTFace
|
||||
virtual nsresult
|
||||
|
|
|
@ -725,6 +725,8 @@ private:
|
|||
|
||||
DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "print.font-variations-as-paths", PrintFontVariationsAsPaths, bool, true);
|
||||
|
||||
DECL_GFX_PREF(Once, "slider.snapMultiplier", SliderSnapMultiplier, int32_t, 0);
|
||||
|
||||
DECL_GFX_PREF(Live, "test.events.async.enabled", TestEventsAsyncEnabled, bool, false);
|
||||
|
|
|
@ -1138,6 +1138,11 @@ pref("print.print_via_parent", true);
|
|||
pref("print.print_via_parent", false);
|
||||
#endif
|
||||
|
||||
// Variation fonts can't always be embedded in certain output formats
|
||||
// such as PDF. To work around this, draw the variation fonts using
|
||||
// paths instead of using font embedding.
|
||||
pref("print.font-variations-as-paths", true);
|
||||
|
||||
// Pref used by the spellchecker extension to control the
|
||||
// maximum number of misspelled words that will be underlined
|
||||
// in a document.
|
||||
|
|
Загрузка…
Ссылка в новой задаче