mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 13:56:29 +00:00
Bug 1711479 - Support various metrics (not only ex-height) as the basis for font-size-adjust calculations in the gfx font implementations. r=layout-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D115211
This commit is contained in:
parent
00a8f91ec3
commit
553fdd24fc
@ -6336,6 +6336,9 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"cap",
|
||||
"ch",
|
||||
"ic",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
|
@ -119,8 +119,7 @@ nsFontMetrics::nsFontMetrics(const nsFont& aFont, const Params& aParams,
|
||||
mVertical(false),
|
||||
mTextOrientation(mozilla::StyleTextOrientation::Mixed) {
|
||||
gfxFontStyle style(aFont.style, aFont.weight, aFont.stretch,
|
||||
gfxFloat(aFont.size.ToAppUnits()) / mP2A,
|
||||
aFont.sizeAdjust.IsEx() ? aFont.sizeAdjust.AsEx() : -1.0f,
|
||||
gfxFloat(aFont.size.ToAppUnits()) / mP2A, aFont.sizeAdjust,
|
||||
aFont.systemFont, mDeviceContext->IsPrinterContext(),
|
||||
aFont.synthesis & NS_FONT_SYNTHESIS_WEIGHT,
|
||||
aFont.synthesis & NS_FONT_SYNTHESIS_STYLE,
|
||||
|
@ -153,14 +153,53 @@ void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) {
|
||||
mFontFace->GetMetrics(&fontMetrics);
|
||||
}
|
||||
|
||||
if (mStyle.sizeAdjust >= 0.0) {
|
||||
gfxFloat aspect =
|
||||
(gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm;
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
} else {
|
||||
mAdjustedSize = GetAdjustedSize();
|
||||
if (GetAdjustedSize() > 0.0 && mStyle.sizeAdjust >= 0.0 &&
|
||||
FontSizeAdjust::Tag(mStyle.sizeAdjustBasis) !=
|
||||
FontSizeAdjust::Tag::None) {
|
||||
// For accurate measurement during the font-size-adjust computations;
|
||||
// these may be reset later according to the adjusted size.
|
||||
mUseSubpixelPositions = true;
|
||||
mFUnitsConvFactor = float(mAdjustedSize / fontMetrics.designUnitsPerEm);
|
||||
gfxFloat aspect;
|
||||
switch (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis)) {
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unhandled sizeAdjustBasis?");
|
||||
aspect = 0.0;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
aspect = (gfxFloat)fontMetrics.xHeight / fontMetrics.designUnitsPerEm;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
aspect = (gfxFloat)fontMetrics.capHeight / fontMetrics.designUnitsPerEm;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ch: {
|
||||
aspect = GetCharAdvance('0');
|
||||
if (aspect < 0.0) {
|
||||
// '0' not found, default to 0.5em.
|
||||
aspect = 0.5;
|
||||
} else {
|
||||
aspect /= mAdjustedSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FontSizeAdjust::Tag::Ic:
|
||||
aspect = GetCharAdvance(0x6C34);
|
||||
if (aspect < 0.0) {
|
||||
// U+6C34 not found, default to 1em.
|
||||
aspect = 1.0;
|
||||
} else {
|
||||
aspect /= mAdjustedSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (aspect > 0.0) {
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
}
|
||||
}
|
||||
|
||||
// Update now that we've adjusted the size if necessary.
|
||||
mFUnitsConvFactor = float(mAdjustedSize / fontMetrics.designUnitsPerEm);
|
||||
|
||||
// Note that GetMeasuringMode depends on mAdjustedSize
|
||||
if ((anAAOption == gfxFont::kAntialiasDefault && UsingClearType() &&
|
||||
GetMeasuringMode() == DWRITE_MEASURING_MODE_NATURAL) ||
|
||||
@ -168,6 +207,8 @@ void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) {
|
||||
mUseSubpixelPositions = true;
|
||||
// note that this may be reset to FALSE if we determine that a bitmap
|
||||
// strike is going to be used
|
||||
} else {
|
||||
mUseSubpixelPositions = false;
|
||||
}
|
||||
|
||||
gfxDWriteFontEntry* fe = static_cast<gfxDWriteFontEntry*>(mFontEntry.get());
|
||||
@ -185,8 +226,6 @@ void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) {
|
||||
mMetrics = new gfxFont::Metrics;
|
||||
::memset(mMetrics, 0, sizeof(*mMetrics));
|
||||
|
||||
mFUnitsConvFactor = float(mAdjustedSize / fontMetrics.designUnitsPerEm);
|
||||
|
||||
mMetrics->xHeight = fontMetrics.xHeight * mFUnitsConvFactor;
|
||||
mMetrics->capHeight = fontMetrics.capHeight * mFUnitsConvFactor;
|
||||
|
||||
@ -248,22 +287,14 @@ void gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption) {
|
||||
}
|
||||
|
||||
if (mMetrics->aveCharWidth < 1) {
|
||||
ucs = L'x';
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndices(&ucs, 1, &glyph)) && glyph != 0) {
|
||||
mMetrics->aveCharWidth = MeasureGlyphWidth(glyph);
|
||||
}
|
||||
mMetrics->aveCharWidth = GetCharAdvance('x');
|
||||
if (mMetrics->aveCharWidth < 1) {
|
||||
// Let's just assume the X is square.
|
||||
mMetrics->aveCharWidth = fontMetrics.xHeight * mFUnitsConvFactor;
|
||||
}
|
||||
}
|
||||
|
||||
ucs = L'0';
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndices(&ucs, 1, &glyph)) && glyph != 0) {
|
||||
mMetrics->zeroWidth = MeasureGlyphWidth(glyph);
|
||||
} else {
|
||||
mMetrics->zeroWidth = -1.0; // indicates not found
|
||||
}
|
||||
mMetrics->zeroWidth = GetCharAdvance('0');
|
||||
|
||||
mMetrics->underlineOffset = fontMetrics.underlinePosition * mFUnitsConvFactor;
|
||||
mMetrics->underlineSize = fontMetrics.underlineThickness * mFUnitsConvFactor;
|
||||
|
@ -212,14 +212,15 @@ static double FindClosestSize(FT_Face aFace, double aSize) {
|
||||
void gfxFT2FontBase::InitMetrics() {
|
||||
mFUnitsConvFactor = 0.0;
|
||||
|
||||
if (MOZ_UNLIKELY(GetStyle()->size <= 0.0) ||
|
||||
MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0)) {
|
||||
if (MOZ_UNLIKELY(mStyle.AdjustedSizeMustBeZero())) {
|
||||
memset(&mMetrics, 0, sizeof(mMetrics)); // zero initialize
|
||||
mSpaceGlyph = GetGlyph(' ');
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetStyle()->sizeAdjust > 0.0 && mFTSize == 0.0) {
|
||||
if (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis) !=
|
||||
FontSizeAdjust::Tag::None &&
|
||||
mStyle.sizeAdjust >= 0.0 && mFTSize == 0.0) {
|
||||
// If font-size-adjust is in effect, we need to get metrics in order to
|
||||
// determine the aspect ratio, then compute the final adjusted size and
|
||||
// re-initialize metrics.
|
||||
@ -228,11 +229,37 @@ void gfxFT2FontBase::InitMetrics() {
|
||||
mFTSize = 1.0;
|
||||
InitMetrics();
|
||||
// Now do the font-size-adjust calculation and set the final size.
|
||||
gfxFloat aspect = mMetrics.xHeight / mMetrics.emHeight;
|
||||
mAdjustedSize = GetStyle()->GetAdjustedSize(aspect);
|
||||
// Ensure the FT_Face will be reconfigured for the new size next time we
|
||||
// need to use it.
|
||||
mFTFace->ForgetLockOwner(this);
|
||||
gfxFloat aspect;
|
||||
switch (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis)) {
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unhandled sizeAdjustBasis?");
|
||||
aspect = 0.0;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
aspect = mMetrics.xHeight / mAdjustedSize;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
aspect = mMetrics.capHeight / mAdjustedSize;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ch:
|
||||
aspect =
|
||||
mMetrics.zeroWidth > 0.0 ? mMetrics.zeroWidth / mAdjustedSize : 0.5;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ic: {
|
||||
// We might want to add an icWidth field to the Metrics struct,
|
||||
// especially when we implement 'ic' as a CSS unit, but for now
|
||||
// we can look it up here if required.
|
||||
gfxFloat advance = GetCharAdvance(0x6C34);
|
||||
aspect = advance > 0 ? advance / mAdjustedSize : 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (aspect > 0.0) {
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
// Ensure the FT_Face will be reconfigured for the new size next time we
|
||||
// need to use it.
|
||||
mFTFace->ForgetLockOwner(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Set mAdjustedSize if it hasn't already been set by a font-size-adjust
|
||||
@ -438,19 +465,27 @@ void gfxFT2FontBase::InitMetrics() {
|
||||
mMetrics.zeroWidth = -1.0; // indicates not found
|
||||
}
|
||||
|
||||
// Prefering a measured x over sxHeight because sxHeight doesn't consider
|
||||
// hinting, but maybe the x extents are not quite right in some fancy
|
||||
// script fonts. CSS 2.1 suggests possibly using the height of an "o",
|
||||
// which would have a more consistent glyph across fonts.
|
||||
// If we didn't get a usable x-height or cap-height above, try measuring
|
||||
// specific glyphs. This can be affected by hinting, leading to erratic
|
||||
// behavior across font sizes and system configuration, so we prefer to
|
||||
// use the metrics directly from the font if possible.
|
||||
// Using glyph bounds for x-height or cap-height may not really be right,
|
||||
// if fonts have fancy swashes etc. For x-height, CSS 2.1 suggests possibly
|
||||
// using the height of an "o", which may be more consistent across fonts,
|
||||
// but then curve-overshoot should also be accounted for.
|
||||
gfxFloat xWidth;
|
||||
gfxRect xBounds;
|
||||
if (GetCharExtents('x', &xWidth, &xBounds) && xBounds.y < 0.0) {
|
||||
mMetrics.xHeight = -xBounds.y;
|
||||
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, xWidth);
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
if (GetCharExtents('x', &xWidth, &xBounds) && xBounds.y < 0.0) {
|
||||
mMetrics.xHeight = -xBounds.y;
|
||||
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, xWidth);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetCharExtents('H', nullptr, &xBounds) && xBounds.y < 0.0) {
|
||||
mMetrics.capHeight = -xBounds.y;
|
||||
if (mMetrics.capHeight == 0.0) {
|
||||
if (GetCharExtents('H', nullptr, &xBounds) && xBounds.y < 0.0) {
|
||||
mMetrics.capHeight = -xBounds.y;
|
||||
}
|
||||
}
|
||||
|
||||
mMetrics.aveCharWidth = std::max(mMetrics.aveCharWidth, mMetrics.zeroWidth);
|
||||
|
@ -259,8 +259,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
mFontPattern(aFontPattern),
|
||||
mFTFaceInitialized(false),
|
||||
mIgnoreFcCharmap(aIgnoreFcCharmap),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0) {
|
||||
mHasVariationsInitialized(false) {
|
||||
GetFontProperties(aFontPattern, &mWeightRange, &mStretchRange, &mStyleRange);
|
||||
}
|
||||
|
||||
@ -318,8 +317,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
mFTFace(std::move(aFace)),
|
||||
mFTFaceInitialized(true),
|
||||
mIgnoreFcCharmap(true),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0) {
|
||||
mHasVariationsInitialized(false) {
|
||||
mWeightRange = aWeight;
|
||||
mStyleRange = aStyle;
|
||||
mStretchRange = aStretch;
|
||||
@ -336,8 +334,7 @@ gfxFontconfigFontEntry::gfxFontconfigFontEntry(const nsACString& aFaceName,
|
||||
: gfxFT2FontEntryBase(aFaceName),
|
||||
mFontPattern(aFontPattern),
|
||||
mFTFaceInitialized(false),
|
||||
mHasVariationsInitialized(false),
|
||||
mAspect(0.0) {
|
||||
mHasVariationsInitialized(false) {
|
||||
mWeightRange = aWeight;
|
||||
mStyleRange = aStyle;
|
||||
mStretchRange = aStretch;
|
||||
@ -492,49 +489,70 @@ hb_blob_t* gfxFontconfigFontEntry::GetFontTable(uint32_t aTableTag) {
|
||||
return gfxFontEntry::GetFontTable(aTableTag);
|
||||
}
|
||||
|
||||
double gfxFontconfigFontEntry::GetAspect() {
|
||||
if (mAspect != 0.0) {
|
||||
return mAspect;
|
||||
}
|
||||
|
||||
// try to compute aspect from OS/2 metrics if available
|
||||
AutoTable os2Table(this, TRUETYPE_TAG('O', 'S', '/', '2'));
|
||||
if (os2Table) {
|
||||
uint16_t upem = UnitsPerEm();
|
||||
if (upem != kInvalidUPEM) {
|
||||
uint32_t len;
|
||||
auto os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (uint16_t(os2->version) >= 2) {
|
||||
if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
|
||||
int16_t(os2->sxHeight) > 0.1 * upem) {
|
||||
mAspect = double(int16_t(os2->sxHeight)) / upem;
|
||||
return mAspect;
|
||||
double gfxFontconfigFontEntry::GetAspect(uint8_t aSizeAdjustBasis) {
|
||||
using FontSizeAdjust = gfxFont::FontSizeAdjust;
|
||||
if (FontSizeAdjust::Tag(aSizeAdjustBasis) == FontSizeAdjust::Tag::Ex ||
|
||||
FontSizeAdjust::Tag(aSizeAdjustBasis) == FontSizeAdjust::Tag::Cap) {
|
||||
// try to compute aspect from OS/2 metrics if available
|
||||
AutoTable os2Table(this, TRUETYPE_TAG('O', 'S', '/', '2'));
|
||||
if (os2Table) {
|
||||
uint16_t upem = UnitsPerEm();
|
||||
if (upem != kInvalidUPEM) {
|
||||
uint32_t len;
|
||||
const auto* os2 =
|
||||
reinterpret_cast<const OS2Table*>(hb_blob_get_data(os2Table, &len));
|
||||
if (uint16_t(os2->version) >= 2) {
|
||||
// XXX(jfkthame) Other implementations don't have the check for
|
||||
// values <= 0.1em; should we drop that here? Just require it to be
|
||||
// a positive number?
|
||||
if (FontSizeAdjust::Tag(aSizeAdjustBasis) ==
|
||||
FontSizeAdjust::Tag::Ex) {
|
||||
if (len >= offsetof(OS2Table, sxHeight) + sizeof(int16_t) &&
|
||||
int16_t(os2->sxHeight) > 0.1 * upem) {
|
||||
return double(int16_t(os2->sxHeight)) / upem;
|
||||
}
|
||||
}
|
||||
if (FontSizeAdjust::Tag(aSizeAdjustBasis) ==
|
||||
FontSizeAdjust::Tag::Cap) {
|
||||
if (len >= offsetof(OS2Table, sCapHeight) + sizeof(int16_t) &&
|
||||
int16_t(os2->sCapHeight) > 0.1 * upem) {
|
||||
return double(int16_t(os2->sCapHeight)) / upem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default to aspect = 0.5 if the code below fails
|
||||
mAspect = 0.5;
|
||||
|
||||
// create a font to calculate x-height / em-height
|
||||
// create a font to calculate the requested aspect
|
||||
gfxFontStyle s;
|
||||
s.size = 100.0; // pick large size to avoid possible hinting artifacts
|
||||
s.size = 256.0; // pick large size to reduce hinting artifacts
|
||||
RefPtr<gfxFont> font = FindOrMakeFont(&s);
|
||||
if (font) {
|
||||
const gfxFont::Metrics& metrics =
|
||||
font->GetMetrics(nsFontMetrics::eHorizontal);
|
||||
|
||||
// The factor of 0.1 ensures that xHeight is sane so fonts don't
|
||||
// become huge. Strictly ">" ensures that xHeight and emHeight are
|
||||
// not both zero.
|
||||
if (metrics.xHeight > 0.1 * metrics.emHeight) {
|
||||
mAspect = metrics.xHeight / metrics.emHeight;
|
||||
if (metrics.emHeight == 0) {
|
||||
return 0;
|
||||
}
|
||||
switch (FontSizeAdjust::Tag(aSizeAdjustBasis)) {
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
return metrics.xHeight / metrics.emHeight;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
return metrics.capHeight / metrics.emHeight;
|
||||
case FontSizeAdjust::Tag::Ch:
|
||||
return metrics.zeroWidth > 0 ? metrics.zeroWidth / metrics.emHeight
|
||||
: 0.5;
|
||||
case FontSizeAdjust::Tag::Ic: {
|
||||
gfxFloat advance = font->GetCharAdvance(0x6C34);
|
||||
return advance > 0 ? advance / metrics.emHeight : 1.0;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mAspect;
|
||||
MOZ_ASSERT_UNREACHABLE("failed to compute size-adjust aspect");
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
static void PrepareFontOptions(FcPattern* aPattern, int* aOutLoadFlags,
|
||||
@ -759,8 +777,10 @@ gfxFontconfigFontEntry::UnscaledFontCache::Lookup(const std::string& aFile,
|
||||
|
||||
static inline gfxFloat SizeForStyle(gfxFontconfigFontEntry* aEntry,
|
||||
const gfxFontStyle& aStyle) {
|
||||
return aStyle.sizeAdjust >= 0.0 ? aStyle.GetAdjustedSize(aEntry->GetAspect())
|
||||
: aStyle.size * aEntry->mSizeAdjust;
|
||||
return StyleFontSizeAdjust::Tag(aStyle.sizeAdjustBasis) !=
|
||||
StyleFontSizeAdjust::Tag::None
|
||||
? aStyle.GetAdjustedSize(aEntry->GetAspect(aStyle.sizeAdjustBasis))
|
||||
: aStyle.size * aEntry->mSizeAdjust;
|
||||
}
|
||||
|
||||
static double ChooseFontSize(gfxFontconfigFontEntry* aEntry,
|
||||
|
@ -107,7 +107,7 @@ class gfxFontconfigFontEntry final : public gfxFT2FontEntryBase {
|
||||
nsresult CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>&) override;
|
||||
hb_blob_t* GetFontTable(uint32_t aTableTag) override;
|
||||
|
||||
double GetAspect();
|
||||
double GetAspect(uint8_t aSizeAdjustBasis);
|
||||
|
||||
protected:
|
||||
virtual ~gfxFontconfigFontEntry();
|
||||
@ -135,8 +135,6 @@ class gfxFontconfigFontEntry final : public gfxFT2FontEntryBase {
|
||||
bool mHasVariations;
|
||||
bool mHasVariationsInitialized;
|
||||
|
||||
double mAspect;
|
||||
|
||||
class UnscaledFontCache {
|
||||
public:
|
||||
already_AddRefed<mozilla::gfx::UnscaledFontFontconfig> Lookup(
|
||||
|
@ -878,7 +878,7 @@ gfxFont::RoundingFlags gfxFont::GetRoundOffsetsToPixels(
|
||||
}
|
||||
}
|
||||
|
||||
gfxFloat gfxFont::GetGlyphHAdvance(DrawTarget* aDrawTarget, uint16_t aGID) {
|
||||
gfxFloat gfxFont::GetGlyphHAdvance(uint16_t aGID) {
|
||||
if (ProvidesGlyphWidths()) {
|
||||
return GetGlyphWidth(aGID) / 65536.0;
|
||||
}
|
||||
@ -898,6 +898,27 @@ gfxFloat gfxFont::GetGlyphHAdvance(DrawTarget* aDrawTarget, uint16_t aGID) {
|
||||
return shaper->GetGlyphHAdvance(aGID) / 65536.0;
|
||||
}
|
||||
|
||||
gfxFloat gfxFont::GetCharAdvance(uint32_t aUnicode) {
|
||||
uint32_t gid = 0;
|
||||
if (ProvidesGetGlyph()) {
|
||||
gid = GetGlyph(aUnicode, 0);
|
||||
} else {
|
||||
if (!mHarfBuzzShaper) {
|
||||
mHarfBuzzShaper = MakeUnique<gfxHarfBuzzShaper>(this);
|
||||
}
|
||||
gfxHarfBuzzShaper* shaper =
|
||||
static_cast<gfxHarfBuzzShaper*>(mHarfBuzzShaper.get());
|
||||
if (!shaper->Initialize()) {
|
||||
return -1.0;
|
||||
}
|
||||
gid = shaper->GetNominalGlyph(aUnicode);
|
||||
}
|
||||
if (!gid) {
|
||||
return -1.0;
|
||||
}
|
||||
return GetGlyphHAdvance(gid);
|
||||
}
|
||||
|
||||
static void CollectLookupsByFeature(hb_face_t* aFace, hb_tag_t aTableTag,
|
||||
uint32_t aFeatureIndex,
|
||||
hb_set_t* aLookups) {
|
||||
@ -2543,8 +2564,7 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun,
|
||||
gfxGlyphExtents* extents =
|
||||
((aBoundingBoxType == LOOSE_INK_EXTENTS && !needsGlyphExtents &&
|
||||
!aTextRun->HasDetailedGlyphs()) ||
|
||||
(MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0)) ||
|
||||
(MOZ_UNLIKELY(GetStyle()->size == 0)))
|
||||
MOZ_UNLIKELY(GetStyle()->AdjustedSizeMustBeZero()))
|
||||
? nullptr
|
||||
: GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit());
|
||||
double x = 0;
|
||||
@ -3665,8 +3685,7 @@ void gfxFont::SanitizeMetrics(gfxFont::Metrics* aMetrics,
|
||||
// Even if this font size is zero, this font is created with non-zero size.
|
||||
// However, for layout and others, we should return the metrics of zero size
|
||||
// font.
|
||||
if (mStyle.size == 0.0 || mStyle.sizeAdjust == 0.0 ||
|
||||
mFontEntry->mSizeAdjust == 0.0) {
|
||||
if (mStyle.AdjustedSizeMustBeZero()) {
|
||||
memset(aMetrics, 0, sizeof(gfxFont::Metrics));
|
||||
return;
|
||||
}
|
||||
@ -3996,7 +4015,7 @@ void gfxFont::RemoveGlyphChangeObserver(GlyphChangeObserver* aObserver) {
|
||||
|
||||
gfxFontStyle::gfxFontStyle()
|
||||
: size(DEFAULT_PIXEL_FONT_SIZE),
|
||||
sizeAdjust(-1.0f),
|
||||
sizeAdjust(0.0f),
|
||||
baselineOffset(0.0f),
|
||||
languageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
|
||||
@ -4005,6 +4024,7 @@ gfxFontStyle::gfxFontStyle()
|
||||
style(FontSlantStyle::Normal()),
|
||||
variantCaps(NS_FONT_VARIANT_CAPS_NORMAL),
|
||||
variantSubSuper(NS_FONT_VARIANT_POSITION_NORMAL),
|
||||
sizeAdjustBasis(uint8_t(FontSizeAdjust::Tag::None)),
|
||||
systemFont(true),
|
||||
printerFont(false),
|
||||
useGrayscaleAntialiasing(false),
|
||||
@ -4014,12 +4034,11 @@ gfxFontStyle::gfxFontStyle()
|
||||
|
||||
gfxFontStyle::gfxFontStyle(FontSlantStyle aStyle, FontWeight aWeight,
|
||||
FontStretch aStretch, gfxFloat aSize,
|
||||
float aSizeAdjust, bool aSystemFont,
|
||||
const FontSizeAdjust& aSizeAdjust, bool aSystemFont,
|
||||
bool aPrinterFont, bool aAllowWeightSynthesis,
|
||||
bool aAllowStyleSynthesis,
|
||||
uint32_t aLanguageOverride)
|
||||
: size(aSize),
|
||||
sizeAdjust(aSizeAdjust),
|
||||
baselineOffset(0.0f),
|
||||
languageOverride(aLanguageOverride),
|
||||
fontSmoothingBackgroundColor(NS_RGBA(0, 0, 0, 0)),
|
||||
@ -4035,8 +4054,32 @@ gfxFontStyle::gfxFontStyle(FontSlantStyle aStyle, FontWeight aWeight,
|
||||
allowSyntheticStyle(aAllowStyleSynthesis),
|
||||
noFallbackVariantFeatures(true) {
|
||||
MOZ_ASSERT(!mozilla::IsNaN(size));
|
||||
|
||||
switch (aSizeAdjust.tag) {
|
||||
case FontSizeAdjust::Tag::None:
|
||||
sizeAdjust = 0.0f;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
sizeAdjust = aSizeAdjust.AsEx();
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
sizeAdjust = aSizeAdjust.AsCap();
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ch:
|
||||
sizeAdjust = aSizeAdjust.AsCh();
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ic:
|
||||
sizeAdjust = aSizeAdjust.AsIc();
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(!mozilla::IsNaN(sizeAdjust));
|
||||
|
||||
sizeAdjustBasis = uint8_t(aSizeAdjust.tag);
|
||||
// sizeAdjustBasis is currently a small bitfield, so let's assert that the
|
||||
// tag value was not truncated.
|
||||
MOZ_ASSERT(FontSizeAdjust::Tag(sizeAdjustBasis) == aSizeAdjust.tag,
|
||||
"gfxFontStyle.sizeAdjustBasis too small?");
|
||||
|
||||
if (weight > FontWeight(1000)) {
|
||||
weight = FontWeight(1000);
|
||||
}
|
||||
@ -4046,7 +4089,8 @@ gfxFontStyle::gfxFontStyle(FontSlantStyle aStyle, FontWeight aWeight,
|
||||
|
||||
if (size >= FONT_MAX_SIZE) {
|
||||
size = FONT_MAX_SIZE;
|
||||
sizeAdjust = -1.0f;
|
||||
sizeAdjust = 0.0f;
|
||||
sizeAdjustBasis = uint8_t(FontSizeAdjust::Tag::None);
|
||||
} else if (size < 0.0) {
|
||||
NS_WARNING("negative font size");
|
||||
size = 0.0;
|
||||
|
@ -94,15 +94,16 @@ typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
#endif
|
||||
|
||||
struct gfxFontStyle {
|
||||
typedef mozilla::FontStretch FontStretch;
|
||||
typedef mozilla::FontSlantStyle FontSlantStyle;
|
||||
typedef mozilla::FontWeight FontWeight;
|
||||
using FontStretch = mozilla::FontStretch;
|
||||
using FontSlantStyle = mozilla::FontSlantStyle;
|
||||
using FontWeight = mozilla::FontWeight;
|
||||
using FontSizeAdjust = mozilla::StyleFontSizeAdjust;
|
||||
|
||||
gfxFontStyle();
|
||||
gfxFontStyle(FontSlantStyle aStyle, FontWeight aWeight, FontStretch aStretch,
|
||||
gfxFloat aSize, float aSizeAdjust, bool aSystemFont,
|
||||
bool aPrinterFont, bool aWeightSynthesis, bool aStyleSynthesis,
|
||||
uint32_t aLanguageOverride);
|
||||
gfxFloat aSize, const FontSizeAdjust& aSizeAdjust,
|
||||
bool aSystemFont, bool aPrinterFont, bool aWeightSynthesis,
|
||||
bool aStyleSynthesis, uint32_t aLanguageOverride);
|
||||
// Features are composed of (1) features from style rules (2) features
|
||||
// from feature settings rules and (3) family-specific features. (1) and
|
||||
// (3) are guaranteed to be mutually exclusive
|
||||
@ -170,15 +171,18 @@ struct gfxFontStyle {
|
||||
return weight.IsNormal() && style.IsNormal() && stretch.IsNormal();
|
||||
}
|
||||
|
||||
// We pack these two small-integer fields into a single byte to avoid
|
||||
// We pack these three small-integer fields into a single byte to avoid
|
||||
// overflowing an 8-byte boundary [in a 64-bit build] and ending up with
|
||||
// 7 bytes of padding at the end of the struct.
|
||||
|
||||
// caps variant (small-caps, petite-caps, etc.)
|
||||
uint8_t variantCaps : 4; // uses range 0..6
|
||||
uint8_t variantCaps : 3; // uses range 0..6
|
||||
|
||||
// sub/superscript variant
|
||||
uint8_t variantSubSuper : 4; // uses range 0..2
|
||||
uint8_t variantSubSuper : 2; // uses range 0..2
|
||||
|
||||
// font metric used as basis of font-size-adjust
|
||||
uint8_t sizeAdjustBasis : 3; // uses range 0..4
|
||||
|
||||
// Say that this font is a system font and therefore does not
|
||||
// require certain fixup that we do for fonts from untrusted
|
||||
@ -200,15 +204,24 @@ struct gfxFontStyle {
|
||||
bool noFallbackVariantFeatures : 1;
|
||||
|
||||
// Return the final adjusted font size for the given aspect ratio.
|
||||
// Not meant to be called when sizeAdjust = -1.0.
|
||||
// Not meant to be called when sizeAdjustBasis is NONE.
|
||||
gfxFloat GetAdjustedSize(gfxFloat aspect) const {
|
||||
NS_ASSERTION(sizeAdjust >= 0.0,
|
||||
"Not meant to be called when sizeAdjust = -1.0");
|
||||
MOZ_ASSERT(
|
||||
FontSizeAdjust::Tag(sizeAdjustBasis) != FontSizeAdjust::Tag::None,
|
||||
"Not meant to be called when sizeAdjustBasis is none");
|
||||
gfxFloat adjustedSize =
|
||||
std::max(NS_round(size * (sizeAdjust / aspect)), 1.0);
|
||||
return std::min(adjustedSize, FONT_MAX_SIZE);
|
||||
}
|
||||
|
||||
// Some callers want to take a short-circuit path if they can be sure the
|
||||
// adjusted size will be zero.
|
||||
bool AdjustedSizeMustBeZero() const {
|
||||
return size == 0.0 ||
|
||||
(FontSizeAdjust::Tag(sizeAdjustBasis) != FontSizeAdjust::Tag::None &&
|
||||
sizeAdjust == 0.0);
|
||||
}
|
||||
|
||||
PLDHashNumber Hash() const;
|
||||
|
||||
// Adjust this style to simulate sub/superscript (as requested in the
|
||||
@ -233,6 +246,7 @@ struct gfxFontStyle {
|
||||
(useGrayscaleAntialiasing == other.useGrayscaleAntialiasing) &&
|
||||
(baselineOffset == other.baselineOffset) &&
|
||||
mozilla::NumbersAreBitwiseIdentical(sizeAdjust, other.sizeAdjust) &&
|
||||
(sizeAdjustBasis == other.sizeAdjustBasis) &&
|
||||
(featureSettings == other.featureSettings) &&
|
||||
(variantAlternates == other.variantAlternates) &&
|
||||
(featureValueLookup == other.featureValueLookup) &&
|
||||
@ -1392,14 +1406,15 @@ class gfxFont {
|
||||
friend class gfxGraphiteShaper;
|
||||
|
||||
protected:
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::unicode::Script Script;
|
||||
typedef mozilla::SVGContextPaint SVGContextPaint;
|
||||
using DrawTarget = mozilla::gfx::DrawTarget;
|
||||
using Script = mozilla::unicode::Script;
|
||||
using SVGContextPaint = mozilla::SVGContextPaint;
|
||||
|
||||
typedef gfxFontShaper::RoundingFlags RoundingFlags;
|
||||
using RoundingFlags = gfxFontShaper::RoundingFlags;
|
||||
|
||||
public:
|
||||
typedef mozilla::FontSlantStyle FontSlantStyle;
|
||||
using FontSlantStyle = mozilla::FontSlantStyle;
|
||||
using FontSizeAdjust = mozilla::StyleFontSizeAdjust;
|
||||
|
||||
nsrefcnt AddRef(void) {
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
|
||||
@ -1497,7 +1512,7 @@ class gfxFont {
|
||||
// but it may be overridden by a value computed in metrics initialization
|
||||
// from font-size-adjust.
|
||||
if (mAdjustedSize < 0.0) {
|
||||
mAdjustedSize = mStyle.sizeAdjust == 0.0
|
||||
mAdjustedSize = mStyle.AdjustedSizeMustBeZero()
|
||||
? 0.0
|
||||
: mStyle.size * mFontEntry->mSizeAdjust;
|
||||
}
|
||||
@ -1558,8 +1573,13 @@ class gfxFont {
|
||||
virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector) {
|
||||
return 0;
|
||||
}
|
||||
// Return the horizontal advance of a glyph.
|
||||
gfxFloat GetGlyphHAdvance(DrawTarget* aDrawTarget, uint16_t aGID);
|
||||
|
||||
// Return the advance of a glyph.
|
||||
gfxFloat GetGlyphHAdvance(uint16_t aGID);
|
||||
|
||||
// Return the advance of a given Unicode char in isolation.
|
||||
// Returns -1.0 if the char is not supported.
|
||||
gfxFloat GetCharAdvance(uint32_t aUnicode);
|
||||
|
||||
gfxFloat SynthesizeSpaceWidth(uint32_t aCh);
|
||||
|
||||
|
@ -119,29 +119,67 @@ void gfxGDIFont::Initialize() {
|
||||
|
||||
if (mAdjustedSize == 0.0) {
|
||||
mAdjustedSize = GetAdjustedSize();
|
||||
if (mStyle.sizeAdjust > 0.0 && mAdjustedSize > 0.0) {
|
||||
// to implement font-size-adjust, we first create the "unadjusted" font
|
||||
FillLogFont(logFont, mAdjustedSize);
|
||||
mFont = ::CreateFontIndirectW(&logFont);
|
||||
if (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis) !=
|
||||
FontSizeAdjust::Tag::None) {
|
||||
if (mStyle.sizeAdjust > 0.0 && mAdjustedSize > 0.0) {
|
||||
// to implement font-size-adjust, we first create the "unadjusted" font
|
||||
FillLogFont(logFont, mAdjustedSize);
|
||||
mFont = ::CreateFontIndirectW(&logFont);
|
||||
|
||||
// initialize its metrics so we can calculate size adjustment
|
||||
Initialize();
|
||||
// initialize its metrics so we can calculate size adjustment
|
||||
Initialize();
|
||||
|
||||
// Unless the font was so small that GDI metrics rounded to zero,
|
||||
// calculate the properly adjusted size, and then proceed
|
||||
// to recreate mFont and recalculate metrics
|
||||
if (mMetrics->xHeight > 0.0 && mMetrics->emHeight > 0.0) {
|
||||
gfxFloat aspect = mMetrics->xHeight / mMetrics->emHeight;
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
// Unless the font was so small that GDI metrics rounded to zero,
|
||||
// calculate the properly adjusted size, and then proceed
|
||||
// to recreate mFont and recalculate metrics
|
||||
if (mMetrics->emHeight > 0.0) {
|
||||
gfxFloat aspect;
|
||||
switch (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis)) {
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unhandled sizeAdjustBasis?");
|
||||
aspect = 0.0;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
aspect = mMetrics->xHeight / mMetrics->emHeight;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
aspect = mMetrics->capHeight / mMetrics->emHeight;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ch:
|
||||
aspect = GetCharAdvance('0');
|
||||
if (aspect < 0.0) {
|
||||
// '0' not found, default to 0.5em.
|
||||
aspect = 0.5;
|
||||
} else {
|
||||
aspect /= mMetrics->emHeight;
|
||||
}
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ic:
|
||||
// We might want to add an icWidth field to the Metrics struct,
|
||||
// especially when we implement 'ic' as a CSS unit, but for now
|
||||
// we can look it up here if required.
|
||||
aspect = GetCharAdvance(0x6C34);
|
||||
if (aspect < 0.0) {
|
||||
// U+6C34 not found, default to 1em.
|
||||
aspect = 1.0;
|
||||
} else {
|
||||
aspect /= mMetrics->emHeight;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (aspect > 0.0) {
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
}
|
||||
}
|
||||
|
||||
// delete the temporary font and metrics
|
||||
::DeleteObject(mFont);
|
||||
mFont = nullptr;
|
||||
delete mMetrics;
|
||||
mMetrics = nullptr;
|
||||
} else {
|
||||
mAdjustedSize = 0.0;
|
||||
}
|
||||
|
||||
// delete the temporary font and metrics
|
||||
::DeleteObject(mFont);
|
||||
mFont = nullptr;
|
||||
delete mMetrics;
|
||||
mMetrics = nullptr;
|
||||
} else if (mStyle.sizeAdjust == 0.0) {
|
||||
mAdjustedSize = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,9 +87,6 @@ hb_codepoint_t gfxHarfBuzzShaper::GetNominalGlyph(
|
||||
gid = mFont->GetGlyph(unicode, 0);
|
||||
} else {
|
||||
// we only instantiate a harfbuzz shaper if there's a cmap available
|
||||
NS_ASSERTION(mFont->GetFontEntry()->HasCmapTable(),
|
||||
"we cannot be using this font!");
|
||||
|
||||
NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0),
|
||||
"cmap data not correctly set up, expect disaster");
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "gfxTextRun.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsCocoaFeatures.h"
|
||||
#include "AppleUtils.h"
|
||||
#include "cairo-quartz.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -219,7 +220,7 @@ void gfxMacFont::InitMetrics() {
|
||||
// return the true value for OpenType/CFF fonts (it normalizes to 1000,
|
||||
// which then leads to metrics errors when we read the 'hmtx' table to
|
||||
// get glyph advances for HarfBuzz, see bug 580863)
|
||||
CFDataRef headData =
|
||||
AutoCFRelease<CFDataRef> headData =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('h', 'e', 'a', 'd'));
|
||||
if (headData) {
|
||||
if (size_t(::CFDataGetLength(headData)) >= sizeof(HeadTable)) {
|
||||
@ -227,7 +228,6 @@ void gfxMacFont::InitMetrics() {
|
||||
reinterpret_cast<const HeadTable*>(::CFDataGetBytePtr(headData));
|
||||
upem = head->unitsPerEm;
|
||||
}
|
||||
::CFRelease(headData);
|
||||
}
|
||||
if (!upem) {
|
||||
upem = ::CGFontGetUnitsPerEm(mCGFont);
|
||||
@ -273,33 +273,82 @@ void gfxMacFont::InitMetrics() {
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
|
||||
}
|
||||
|
||||
if (mMetrics.capHeight == 0.0) {
|
||||
mMetrics.capHeight = ::CGFontGetCapHeight(mCGFont) * cgConvFactor;
|
||||
}
|
||||
|
||||
if (mStyle.sizeAdjust > 0.0 && mMetrics.xHeight > 0.0) {
|
||||
AutoCFRelease<CFDataRef> cmap =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('c', 'm', 'a', 'p'));
|
||||
|
||||
uint32_t glyphID;
|
||||
mMetrics.zeroWidth = GetCharWidth(cmap, '0', &glyphID, cgConvFactor);
|
||||
if (glyphID == 0) {
|
||||
mMetrics.zeroWidth = -1.0; // indicates not found
|
||||
}
|
||||
|
||||
if (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis) !=
|
||||
FontSizeAdjust::Tag::None &&
|
||||
mStyle.sizeAdjust >= 0.0) {
|
||||
// apply font-size-adjust, and recalculate metrics
|
||||
gfxFloat aspect = mMetrics.xHeight / mAdjustedSize;
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
mFUnitsConvFactor = mAdjustedSize / upem;
|
||||
if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
|
||||
cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
|
||||
} else {
|
||||
cgConvFactor = mFUnitsConvFactor;
|
||||
gfxFloat aspect;
|
||||
switch (FontSizeAdjust::Tag(mStyle.sizeAdjustBasis)) {
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("unhandled sizeAdjustBasis?");
|
||||
aspect = 0.0;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ex:
|
||||
aspect = mMetrics.xHeight / mAdjustedSize;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Cap:
|
||||
aspect = mMetrics.capHeight / mAdjustedSize;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ch:
|
||||
aspect =
|
||||
mMetrics.zeroWidth < 0.0 ? 0.5 : mMetrics.zeroWidth / mAdjustedSize;
|
||||
break;
|
||||
case FontSizeAdjust::Tag::Ic: {
|
||||
// We might want to add an icWidth field to the Metrics struct,
|
||||
// especially when we implement 'ic' as a CSS unit, but for now
|
||||
// we can look it up here if required.
|
||||
aspect = GetCharWidth(cmap, 0x6C34, nullptr, cgConvFactor);
|
||||
if (aspect <= 0.0) {
|
||||
// U+6C34 not found, default to 1em.
|
||||
aspect = 1.0;
|
||||
} else {
|
||||
aspect /= mAdjustedSize;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
mMetrics.xHeight = 0.0;
|
||||
if (!InitMetricsFromSfntTables(mMetrics) &&
|
||||
(!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
|
||||
InitMetricsFromPlatform();
|
||||
}
|
||||
if (!mIsValid) {
|
||||
// this shouldn't happen, as we succeeded earlier before applying
|
||||
// the size-adjust factor! But check anyway, for paranoia's sake.
|
||||
return;
|
||||
}
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
|
||||
if (aspect > 0.0) {
|
||||
mAdjustedSize = mStyle.GetAdjustedSize(aspect);
|
||||
mFUnitsConvFactor = mAdjustedSize / upem;
|
||||
if (static_cast<MacOSFontEntry*>(mFontEntry.get())->IsCFF()) {
|
||||
cgConvFactor = mAdjustedSize / ::CGFontGetUnitsPerEm(mCGFont);
|
||||
} else {
|
||||
cgConvFactor = mFUnitsConvFactor;
|
||||
}
|
||||
mMetrics.xHeight = 0.0;
|
||||
if (!InitMetricsFromSfntTables(mMetrics) &&
|
||||
(!mFontEntry->IsUserFont() || mFontEntry->IsLocalUserFont())) {
|
||||
InitMetricsFromPlatform();
|
||||
}
|
||||
if (!mIsValid) {
|
||||
// this shouldn't happen, as we succeeded earlier before applying
|
||||
// the size-adjust factor! But check anyway, for paranoia's sake.
|
||||
return;
|
||||
}
|
||||
// Update metrics from the re-scaled font.
|
||||
if (mMetrics.xHeight == 0.0) {
|
||||
mMetrics.xHeight = ::CGFontGetXHeight(mCGFont) * cgConvFactor;
|
||||
}
|
||||
if (mMetrics.capHeight == 0.0) {
|
||||
mMetrics.capHeight = ::CGFontGetCapHeight(mCGFont) * cgConvFactor;
|
||||
}
|
||||
mMetrics.zeroWidth = GetCharWidth(cmap, '0', &glyphID, cgConvFactor);
|
||||
if (glyphID == 0) {
|
||||
mMetrics.zeroWidth = -1.0; // indicates not found
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,10 +361,6 @@ void gfxMacFont::InitMetrics() {
|
||||
// Measure/calculate additional metrics, independent of whether we used
|
||||
// the tables directly or ATS metrics APIs
|
||||
|
||||
CFDataRef cmap =
|
||||
::CGFontCopyTableForTag(mCGFont, TRUETYPE_TAG('c', 'm', 'a', 'p'));
|
||||
|
||||
uint32_t glyphID;
|
||||
if (mMetrics.aveCharWidth <= 0) {
|
||||
mMetrics.aveCharWidth = GetCharWidth(cmap, 'x', &glyphID, cgConvFactor);
|
||||
if (glyphID == 0) {
|
||||
@ -323,10 +368,6 @@ void gfxMacFont::InitMetrics() {
|
||||
mMetrics.aveCharWidth = mMetrics.maxAdvance;
|
||||
}
|
||||
}
|
||||
if (IsSyntheticBold()) {
|
||||
mMetrics.aveCharWidth += GetSyntheticBoldOffset();
|
||||
mMetrics.maxAdvance += GetSyntheticBoldOffset();
|
||||
}
|
||||
|
||||
mMetrics.spaceWidth = GetCharWidth(cmap, ' ', &glyphID, cgConvFactor);
|
||||
if (glyphID == 0) {
|
||||
@ -335,13 +376,13 @@ void gfxMacFont::InitMetrics() {
|
||||
}
|
||||
mSpaceGlyph = glyphID;
|
||||
|
||||
mMetrics.zeroWidth = GetCharWidth(cmap, '0', &glyphID, cgConvFactor);
|
||||
if (glyphID == 0) {
|
||||
mMetrics.zeroWidth = -1.0; // indicates not found
|
||||
}
|
||||
|
||||
if (cmap) {
|
||||
::CFRelease(cmap);
|
||||
if (IsSyntheticBold()) {
|
||||
mMetrics.spaceWidth += GetSyntheticBoldOffset();
|
||||
mMetrics.aveCharWidth += GetSyntheticBoldOffset();
|
||||
mMetrics.maxAdvance += GetSyntheticBoldOffset();
|
||||
if (mMetrics.zeroWidth > 0) {
|
||||
mMetrics.zeroWidth += GetSyntheticBoldOffset();
|
||||
}
|
||||
}
|
||||
|
||||
CalculateDerivedMetrics(mMetrics);
|
||||
@ -415,22 +456,19 @@ CTFontRef gfxMacFont::CreateCTFontFromCGFontWithVariations(
|
||||
CTFontRef ctFont;
|
||||
if (nsCocoaFeatures::OnSierraExactly() ||
|
||||
(aInstalledFont && nsCocoaFeatures::OnHighSierraOrLater())) {
|
||||
CFDictionaryRef variations = ::CGFontCopyVariations(aCGFont);
|
||||
AutoCFRelease<CFDictionaryRef> variations = ::CGFontCopyVariations(aCGFont);
|
||||
if (variations) {
|
||||
CFDictionaryRef varAttr = ::CFDictionaryCreate(
|
||||
AutoCFRelease<CFDictionaryRef> varAttr = ::CFDictionaryCreate(
|
||||
nullptr, (const void**)&kCTFontVariationAttribute,
|
||||
(const void**)&variations, 1, &kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
::CFRelease(variations);
|
||||
|
||||
CTFontDescriptorRef varDesc =
|
||||
AutoCFRelease<CTFontDescriptorRef> varDesc =
|
||||
aFontDesc
|
||||
? ::CTFontDescriptorCreateCopyWithAttributes(aFontDesc, varAttr)
|
||||
: ::CTFontDescriptorCreateWithAttributes(varAttr);
|
||||
::CFRelease(varAttr);
|
||||
|
||||
ctFont = ::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, varDesc);
|
||||
::CFRelease(varDesc);
|
||||
} else {
|
||||
ctFont =
|
||||
::CTFontCreateWithGraphicsFont(aCGFont, aSize, nullptr, aFontDesc);
|
||||
@ -497,7 +535,7 @@ bool gfxMacFont::GetGlyphBounds(uint16_t aGID, gfxRect* aBounds, bool aTight) {
|
||||
// for sfnts, including ALL downloadable fonts, we prefer to use
|
||||
// InitMetricsFromSfntTables and avoid platform APIs.
|
||||
void gfxMacFont::InitMetricsFromPlatform() {
|
||||
CTFontRef ctFont =
|
||||
AutoCFRelease<CTFontRef> ctFont =
|
||||
::CTFontCreateWithGraphicsFont(mCGFont, mAdjustedSize, nullptr, nullptr);
|
||||
if (!ctFont) {
|
||||
return;
|
||||
@ -528,8 +566,6 @@ void gfxMacFont::InitMetricsFromPlatform() {
|
||||
mMetrics.xHeight = ::CTFontGetXHeight(ctFont);
|
||||
mMetrics.capHeight = ::CTFontGetCapHeight(ctFont);
|
||||
|
||||
::CFRelease(ctFont);
|
||||
|
||||
mIsValid = true;
|
||||
}
|
||||
|
||||
|
@ -1610,8 +1610,7 @@ void gfxTextRun::FetchGlyphExtents(DrawTarget* aRefDrawTarget) {
|
||||
for (uint32_t i = 0; i < runCount; ++i) {
|
||||
const GlyphRun& run = glyphRuns[i];
|
||||
gfxFont* font = run.mFont;
|
||||
if (MOZ_UNLIKELY(font->GetStyle()->size == 0) ||
|
||||
MOZ_UNLIKELY(font->GetStyle()->sizeAdjust == 0.0f)) {
|
||||
if (MOZ_UNLIKELY(font->GetStyle()->AdjustedSizeMustBeZero())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2352,8 +2351,7 @@ already_AddRefed<gfxTextRun> gfxFontGroup::MakeSpaceTextRun(
|
||||
}
|
||||
|
||||
gfxFont* font = GetFirstValidFont();
|
||||
if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
|
||||
MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
|
||||
if (MOZ_UNLIKELY(GetStyle()->AdjustedSizeMustBeZero())) {
|
||||
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
|
||||
// them, and always create at least size 1 fonts, i.e. they still
|
||||
// render something for size 0 fonts.
|
||||
@ -2453,8 +2451,7 @@ already_AddRefed<gfxTextRun> gfxFontGroup::MakeTextRun(
|
||||
|
||||
aFlags |= ShapedTextFlags::TEXT_IS_8BIT;
|
||||
|
||||
if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
|
||||
MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
|
||||
if (MOZ_UNLIKELY(GetStyle()->AdjustedSizeMustBeZero())) {
|
||||
// Short-circuit for size-0 fonts, as Windows and ATSUI can't handle
|
||||
// them, and always create at least size 1 fonts, i.e. they still
|
||||
// render something for size 0 fonts.
|
||||
@ -2484,8 +2481,7 @@ already_AddRefed<gfxTextRun> gfxFontGroup::MakeTextRun(
|
||||
if (aLength == 1 && aString[0] == ' ') {
|
||||
return MakeSpaceTextRun(aParams, aFlags, aFlags2);
|
||||
}
|
||||
if (MOZ_UNLIKELY(GetStyle()->size == 0) ||
|
||||
MOZ_UNLIKELY(GetStyle()->sizeAdjust == 0.0f)) {
|
||||
if (MOZ_UNLIKELY(GetStyle()->AdjustedSizeMustBeZero())) {
|
||||
return MakeBlankTextRun(aString, aLength, aParams, aFlags, aFlags2);
|
||||
}
|
||||
|
||||
|
@ -9708,9 +9708,23 @@ void nsLayoutUtils::ComputeSystemFont(nsFont* aSystemFont,
|
||||
aSystemFont->size = Length::FromPixels(fontStyle.size);
|
||||
|
||||
// aSystemFont->langGroup = fontStyle.langGroup;
|
||||
aSystemFont->sizeAdjust = fontStyle.sizeAdjust < 0.0
|
||||
? StyleFontSizeAdjust::None()
|
||||
: StyleFontSizeAdjust::Ex(fontStyle.sizeAdjust);
|
||||
switch (StyleFontSizeAdjust::Tag(fontStyle.sizeAdjustBasis)) {
|
||||
case StyleFontSizeAdjust::Tag::None:
|
||||
aSystemFont->sizeAdjust = StyleFontSizeAdjust::None();
|
||||
break;
|
||||
case StyleFontSizeAdjust::Tag::Ex:
|
||||
aSystemFont->sizeAdjust = StyleFontSizeAdjust::Ex(fontStyle.sizeAdjust);
|
||||
break;
|
||||
case StyleFontSizeAdjust::Tag::Cap:
|
||||
aSystemFont->sizeAdjust = StyleFontSizeAdjust::Cap(fontStyle.sizeAdjust);
|
||||
break;
|
||||
case StyleFontSizeAdjust::Tag::Ch:
|
||||
aSystemFont->sizeAdjust = StyleFontSizeAdjust::Ch(fontStyle.sizeAdjust);
|
||||
break;
|
||||
case StyleFontSizeAdjust::Tag::Ic:
|
||||
aSystemFont->sizeAdjust = StyleFontSizeAdjust::Ic(fontStyle.sizeAdjust);
|
||||
break;
|
||||
}
|
||||
|
||||
if (aFontID == LookAndFeel::FontID::MozField ||
|
||||
aFontID == LookAndFeel::FontID::MozButton ||
|
||||
|
@ -527,8 +527,8 @@ already_AddRefed<gfxTextRun> nsOpenTypeTable::MakeTextRun(
|
||||
gfxTextRun::DetailedGlyph detailedGlyph;
|
||||
detailedGlyph.mGlyphID = aGlyph.glyphID;
|
||||
detailedGlyph.mAdvance = NSToCoordRound(
|
||||
aAppUnitsPerDevPixel * aFontGroup->GetFirstValidFont()->GetGlyphHAdvance(
|
||||
aDrawTarget, aGlyph.glyphID));
|
||||
aAppUnitsPerDevPixel *
|
||||
aFontGroup->GetFirstValidFont()->GetGlyphHAdvance(aGlyph.glyphID));
|
||||
textRun->SetDetailedGlyphs(0, 1, &detailedGlyph);
|
||||
|
||||
return textRun.forget();
|
||||
|
Loading…
x
Reference in New Issue
Block a user