mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-24 05:44:10 +00:00
bug 916048 - SVG-in-OpenType glyphs should use the font's unitsPerEm value. r=roc
This commit is contained in:
parent
fa21bde76e
commit
c9f388d0f2
@ -111,6 +111,7 @@ gfxFontEntry::gfxFontEntry() :
|
|||||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||||
mUVSOffset(0), mUVSData(nullptr),
|
mUVSOffset(0), mUVSData(nullptr),
|
||||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||||
|
mUnitsPerEm(0),
|
||||||
mHBFace(nullptr),
|
mHBFace(nullptr),
|
||||||
mGrFace(nullptr),
|
mGrFace(nullptr),
|
||||||
mGrFaceRefCnt(0)
|
mGrFaceRefCnt(0)
|
||||||
@ -137,6 +138,7 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
|||||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||||
mUVSOffset(0), mUVSData(nullptr),
|
mUVSOffset(0), mUVSData(nullptr),
|
||||||
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
mLanguageOverride(NO_FONT_LANGUAGE_OVERRIDE),
|
||||||
|
mUnitsPerEm(0),
|
||||||
mHBFace(nullptr),
|
mHBFace(nullptr),
|
||||||
mGrFace(nullptr),
|
mGrFace(nullptr),
|
||||||
mGrFaceRefCnt(0)
|
mGrFaceRefCnt(0)
|
||||||
@ -264,6 +266,30 @@ gfxFontEntry::FindOrMakeFont(const gfxFontStyle *aStyle, bool aNeedsBold)
|
|||||||
return font.forget();
|
return font.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t
|
||||||
|
gfxFontEntry::UnitsPerEm()
|
||||||
|
{
|
||||||
|
if (!mUnitsPerEm) {
|
||||||
|
AutoTable headTable(this, TRUETYPE_TAG('h','e','a','d'));
|
||||||
|
if (headTable) {
|
||||||
|
uint32_t len;
|
||||||
|
const HeadTable* head =
|
||||||
|
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable,
|
||||||
|
&len));
|
||||||
|
if (len >= sizeof(HeadTable)) {
|
||||||
|
mUnitsPerEm = head->unitsPerEm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we didn't find a usable 'head' table, or if the value was
|
||||||
|
// outside the valid range, record it as invalid
|
||||||
|
if (mUnitsPerEm < kMinUPEM || mUnitsPerEm > kMaxUPEM) {
|
||||||
|
mUnitsPerEm = kInvalidUPEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mUnitsPerEm;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId)
|
gfxFontEntry::HasSVGGlyph(uint32_t aGlyphId)
|
||||||
{
|
{
|
||||||
@ -275,15 +301,17 @@ bool
|
|||||||
gfxFontEntry::GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
|
gfxFontEntry::GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
|
||||||
gfxRect *aResult)
|
gfxRect *aResult)
|
||||||
{
|
{
|
||||||
NS_ABORT_IF_FALSE(mSVGInitialized, "SVG data has not yet been loaded. TryGetSVGData() first.");
|
NS_ABORT_IF_FALSE(mSVGInitialized,
|
||||||
|
"SVG data has not yet been loaded. TryGetSVGData() first.");
|
||||||
|
NS_ABORT_IF_FALSE(mUnitsPerEm >= kMinUPEM && mUnitsPerEm <= kMaxUPEM,
|
||||||
|
"font has invalid unitsPerEm");
|
||||||
|
|
||||||
gfxContextAutoSaveRestore matrixRestore(aContext);
|
gfxContextAutoSaveRestore matrixRestore(aContext);
|
||||||
cairo_matrix_t fontMatrix;
|
cairo_matrix_t fontMatrix;
|
||||||
cairo_get_font_matrix(aContext->GetCairo(), &fontMatrix);
|
cairo_get_font_matrix(aContext->GetCairo(), &fontMatrix);
|
||||||
|
|
||||||
gfxMatrix svgToAppSpace = *reinterpret_cast<gfxMatrix*>(&fontMatrix);
|
gfxMatrix svgToAppSpace = *reinterpret_cast<gfxMatrix*>(&fontMatrix);
|
||||||
svgToAppSpace.Scale(1.0f / gfxSVGGlyphs::SVG_UNITS_PER_EM,
|
svgToAppSpace.Scale(1.0f / mUnitsPerEm, 1.0f / mUnitsPerEm);
|
||||||
1.0f / gfxSVGGlyphs::SVG_UNITS_PER_EM);
|
|
||||||
|
|
||||||
return mSVGGlyphs->GetGlyphExtents(aGlyphId, svgToAppSpace, aResult);
|
return mSVGGlyphs->GetGlyphExtents(aGlyphId, svgToAppSpace, aResult);
|
||||||
}
|
}
|
||||||
@ -307,8 +335,13 @@ gfxFontEntry::TryGetSVGData(gfxFont* aFont)
|
|||||||
if (!mSVGInitialized) {
|
if (!mSVGInitialized) {
|
||||||
mSVGInitialized = true;
|
mSVGInitialized = true;
|
||||||
|
|
||||||
// We don't use AutoTable here because we'll pass ownership of these
|
// If UnitsPerEm is not known/valid, we can't use SVG glyphs
|
||||||
// blobs to the gfxSVGGlyphs, once we've confirmed the tables exist
|
if (UnitsPerEm() == kInvalidUPEM) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't use AutoTable here because we'll pass ownership of this
|
||||||
|
// blob to the gfxSVGGlyphs, once we've confirmed the table exists
|
||||||
hb_blob_t *svgTable = GetFontTable(TRUETYPE_TAG('S','V','G',' '));
|
hb_blob_t *svgTable = GetFontTable(TRUETYPE_TAG('S','V','G',' '));
|
||||||
if (!svgTable) {
|
if (!svgTable) {
|
||||||
return false;
|
return false;
|
||||||
@ -2818,7 +2851,8 @@ gfxFont::RenderSVGGlyph(gfxContext *aContext, gfxPoint aPoint, DrawMode aDrawMod
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gfxFloat devUnitsPerSVGUnit = GetStyle()->size / gfxSVGGlyphs::SVG_UNITS_PER_EM;
|
const gfxFloat devUnitsPerSVGUnit =
|
||||||
|
GetAdjustedSize() / GetFontEntry()->UnitsPerEm();
|
||||||
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
|
gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
|
||||||
|
|
||||||
aContext->Translate(gfxPoint(aPoint.x, aPoint.y));
|
aContext->Translate(gfxPoint(aPoint.x, aPoint.y));
|
||||||
@ -3548,7 +3582,6 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
|||||||
{
|
{
|
||||||
mIsValid = false; // font is NOT valid in case of early return
|
mIsValid = false; // font is NOT valid in case of early return
|
||||||
|
|
||||||
const uint32_t kHeadTableTag = TRUETYPE_TAG('h','e','a','d');
|
|
||||||
const uint32_t kHheaTableTag = TRUETYPE_TAG('h','h','e','a');
|
const uint32_t kHheaTableTag = TRUETYPE_TAG('h','h','e','a');
|
||||||
const uint32_t kPostTableTag = TRUETYPE_TAG('p','o','s','t');
|
const uint32_t kPostTableTag = TRUETYPE_TAG('p','o','s','t');
|
||||||
const uint32_t kOS_2TableTag = TRUETYPE_TAG('O','S','/','2');
|
const uint32_t kOS_2TableTag = TRUETYPE_TAG('O','S','/','2');
|
||||||
@ -3557,21 +3590,11 @@ gfxFont::InitMetricsFromSfntTables(Metrics& aMetrics)
|
|||||||
|
|
||||||
if (mFUnitsConvFactor == 0.0) {
|
if (mFUnitsConvFactor == 0.0) {
|
||||||
// If the conversion factor from FUnits is not yet set,
|
// If the conversion factor from FUnits is not yet set,
|
||||||
// 'head' table is required; otherwise we cannot read any metrics
|
// get the unitsPerEm from the 'head' table via the font entry
|
||||||
// because we don't know unitsPerEm
|
uint16_t unitsPerEm = GetFontEntry()->UnitsPerEm();
|
||||||
gfxFontEntry::AutoTable headTable(mFontEntry, kHeadTableTag);
|
if (unitsPerEm == gfxFontEntry::kInvalidUPEM) {
|
||||||
if (!headTable) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const HeadTable* head =
|
|
||||||
reinterpret_cast<const HeadTable*>(hb_blob_get_data(headTable, &len));
|
|
||||||
if (len < sizeof(HeadTable)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uint32_t unitsPerEm = head->unitsPerEm;
|
|
||||||
if (!unitsPerEm) {
|
|
||||||
return true; // is an sfnt, but not valid
|
|
||||||
}
|
|
||||||
mFUnitsConvFactor = mAdjustedSize / unitsPerEm;
|
mFUnitsConvFactor = mAdjustedSize / unitsPerEm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,6 +375,16 @@ public:
|
|||||||
hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
|
hb_blob_t *ShareFontTableAndGetBlob(uint32_t aTag,
|
||||||
FallibleTArray<uint8_t>* aTable);
|
FallibleTArray<uint8_t>* aTable);
|
||||||
|
|
||||||
|
// Get the font's unitsPerEm from the 'head' table, in the case of an
|
||||||
|
// sfnt resource. Will return kInvalidUPEM for non-sfnt fonts,
|
||||||
|
// if present on the platform.
|
||||||
|
uint16_t UnitsPerEm();
|
||||||
|
enum {
|
||||||
|
kMinUPEM = 16, // Limits on valid unitsPerEm range, from the
|
||||||
|
kMaxUPEM = 16384, // OpenType spec
|
||||||
|
kInvalidUPEM = uint16_t(-1)
|
||||||
|
};
|
||||||
|
|
||||||
// Shaper face accessors:
|
// Shaper face accessors:
|
||||||
// NOTE that harfbuzz and graphite handle ownership/lifetime of the face
|
// NOTE that harfbuzz and graphite handle ownership/lifetime of the face
|
||||||
// object in completely different ways.
|
// object in completely different ways.
|
||||||
@ -473,6 +483,10 @@ protected:
|
|||||||
// caller is responsible to do any sanitization/validation necessary.
|
// caller is responsible to do any sanitization/validation necessary.
|
||||||
hb_blob_t* GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
|
hb_blob_t* GetTableFromFontData(const void* aFontData, uint32_t aTableTag);
|
||||||
|
|
||||||
|
// Font's unitsPerEm from the 'head' table, if available (will be set to
|
||||||
|
// kInvalidUPEM for non-sfnt font formats)
|
||||||
|
uint16_t mUnitsPerEm;
|
||||||
|
|
||||||
// Shaper-specific face objects, shared by all instantiations of the same
|
// Shaper-specific face objects, shared by all instantiations of the same
|
||||||
// physical font, regardless of size.
|
// physical font, regardless of size.
|
||||||
// Usually, only one of these will actually be created for any given font
|
// Usually, only one of these will actually be created for any given font
|
||||||
|
@ -44,8 +44,6 @@ typedef mozilla::dom::Element Element;
|
|||||||
|
|
||||||
mozilla::gfx::UserDataKey gfxTextContextPaint::sUserDataKey;
|
mozilla::gfx::UserDataKey gfxTextContextPaint::sUserDataKey;
|
||||||
|
|
||||||
const float gfxSVGGlyphs::SVG_UNITS_PER_EM = 1000.0f;
|
|
||||||
|
|
||||||
const gfxRGBA SimpleTextContextPaint::sZero = gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f);
|
const gfxRGBA SimpleTextContextPaint::sZero = gfxRGBA(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry)
|
gfxSVGGlyphs::gfxSVGGlyphs(hb_blob_t *aSVGTable, gfxFontEntry *aFontEntry)
|
||||||
|
@ -78,8 +78,6 @@ private:
|
|||||||
typedef gfxFont::DrawMode DrawMode;
|
typedef gfxFont::DrawMode DrawMode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const float SVG_UNITS_PER_EM;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param aSVGTable The SVG table from the OpenType font
|
* @param aSVGTable The SVG table from the OpenType font
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user