Bug 1305977 - Use HarfBuzz ot-math API to parse the OpenType MATH table. r=jfkthame

--HG--
extra : rebase_source : 743927b509e8e4b37334c46f32e4e69b3ba35091
This commit is contained in:
Frédéric Wang 2016-10-31 04:18:00 +01:00
Родитель fa5f21c539
Коммит 1c9167ba68
14 изменённых файлов: 325 добавлений и 831 удалений

Просмотреть файл

@ -1,121 +0,0 @@
/* 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/. */
// This file contains the structures described in Microsoft's document
// "The MATH table and OpenType Features for Math Processing" (not yet public).
//
// Arrays of varying size are indicated in comments. Typically, gfxMathTable
// will read the header of the structure first, verify that there is enough
// space for the specified arrays and then use a pointer to browse these arrays.
#ifndef MATH_TABLE_STRUCTURE_H
#define MATH_TABLE_STRUCTURE_H
#include "gfxFontUtils.h"
typedef mozilla::AutoSwap_PRUint16 Count16;
typedef mozilla::AutoSwap_PRUint16 GlyphID;
typedef mozilla::AutoSwap_PRUint16 Offset;
struct MathValueRecord {
mozilla::AutoSwap_PRInt16 mValue;
Offset mDeviceTable;
};
struct RangeRecord {
GlyphID mStart;
GlyphID mEnd;
mozilla::AutoSwap_PRUint16 mStartCoverageIndex;
};
struct Coverage {
mozilla::AutoSwap_PRUint16 mFormat;
};
struct CoverageFormat1 {
mozilla::AutoSwap_PRUint16 mFormat;
Count16 mGlyphCount;
// GlyphID mGlyphArray[mGlyphCount]
};
struct CoverageFormat2 {
mozilla::AutoSwap_PRUint16 mFormat;
Count16 mRangeCount;
// RangeRecord mRangeArray[mRangeCount];
};
struct MATHTableHeader {
mozilla::AutoSwap_PRUint32 mVersion;
Offset mMathConstants;
Offset mMathGlyphInfo;
Offset mMathVariants;
};
struct MathConstants {
mozilla::AutoSwap_PRInt16 mInt16[gfxFontEntry::ScriptScriptPercentScaleDown -
gfxFontEntry::ScriptPercentScaleDown + 1];
mozilla::AutoSwap_PRUint16 mUint16[gfxFontEntry::DisplayOperatorMinHeight -
gfxFontEntry::
DelimitedSubFormulaMinHeight + 1];
MathValueRecord mMathValues[gfxFontEntry::RadicalKernAfterDegree -
gfxFontEntry::MathLeading + 1];
mozilla::AutoSwap_PRUint16 mRadicalDegreeBottomRaisePercent;
};
struct MathGlyphInfo {
Offset mMathItalicsCorrectionInfo;
Offset mMathTopAccentAttachment;
Offset mExtendedShapeCoverage;
Offset mMathKernInfo;
};
struct MathItalicsCorrectionInfo {
Offset mCoverage;
Count16 mItalicsCorrectionCount;
// MathValueRecord mItalicsCorrection[mItalicsCorrectionCount]
};
struct MathVariants {
mozilla::AutoSwap_PRUint16 mMinConnectorOverlap;
Offset mVertGlyphCoverage;
Offset mHorizGlyphCoverage;
Count16 mVertGlyphCount;
Count16 mHorizGlyphCount;
// Offset mVertGlyphConstruction[mVertGlyphCount];
// Offset mHorizGlyphConstruction[mHorizGlyphCount];
};
struct MathGlyphVariantRecord {
GlyphID mVariantGlyph;
mozilla::AutoSwap_PRUint16 mAdvanceMeasurement;
};
struct MathGlyphConstruction {
Offset mGlyphAssembly;
Count16 mVariantCount;
// MathGlyphVariantRecord mMathGlyphVariantRecord[mVariantCount]
};
struct GlyphPartRecord {
GlyphID mGlyph;
mozilla::AutoSwap_PRUint16 mStartConnectorLength;
mozilla::AutoSwap_PRUint16 mEndConnectorLength;
mozilla::AutoSwap_PRUint16 mFullAdvance;
mozilla::AutoSwap_PRUint16 mPartFlags;
};
// PartFlags enumeration currently uses only one bit:
// 0x0001 If set, the part can be skipped or repeated.
// 0xFFFE Reserved.
enum {
PART_FLAG_EXTENDER = 0x01
};
struct GlyphAssembly {
MathValueRecord mItalicsCorrection;
Count16 mPartCount;
// GlyphPartRecord mPartRecords[mPartCount]
};
#endif

Просмотреть файл

@ -37,6 +37,7 @@
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "gfxMathTable.h"
#include "gfxSVGGlyphs.h"
#include "gfx2DGlue.h"
@ -841,6 +842,7 @@ gfxFont::gfxFont(gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
mScaledFont(aScaledFont),
mFontEntry(aFontEntry), mIsValid(true),
mApplySyntheticBold(false),
mMathInitialized(false),
mStyle(*aFontStyle),
mAdjustedSize(0.0),
mFUnitsConvFactor(-1.0f), // negative to indicate "not yet initialized"
@ -4007,3 +4009,21 @@ gfxFontStyle::AdjustForSubSuperscript(int32_t aAppUnitsPerDevPixel)
// clear the variant field
variantSubSuper = NS_FONT_VARIANT_POSITION_NORMAL;
}
bool
gfxFont::TryGetMathTable()
{
if (!mMathInitialized) {
mMathInitialized = true;
hb_face_t *face = GetFontEntry()->GetHBFace();
if (face) {
if (hb_ot_math_has_data(face)) {
mMathTable = MakeUnique<gfxMathTable>(face, GetAdjustedSize());
}
hb_face_destroy(face);
}
}
return !!mMathTable;
}

Просмотреть файл

@ -46,6 +46,7 @@ class gfxGlyphExtents;
class gfxShapedText;
class gfxShapedWord;
class gfxSkipChars;
class gfxMathTable;
#define FONT_MAX_SIZE 2000.0
@ -1844,22 +1845,13 @@ public:
delete sDefaultFeatures;
}
// Get a font dimension from the MATH table, scaled to appUnits;
// may only be called if mFontEntry->TryGetMathTable has succeeded
// (i.e. the font is known to be a valid OpenType math font).
nscoord GetMathConstant(gfxFontEntry::MathConstant aConstant,
uint32_t aAppUnitsPerDevPixel)
{
return NSToCoordRound(mFontEntry->GetMathConstant(aConstant) *
GetAdjustedSize() * aAppUnitsPerDevPixel);
}
// Get a dimensionless math constant (e.g. a percentage);
// may only be called if mFontEntry->TryGetMathTable has succeeded
// (i.e. the font is known to be a valid OpenType math font).
float GetMathConstant(gfxFontEntry::MathConstant aConstant)
{
return mFontEntry->GetMathConstant(aConstant);
// Call TryGetMathTable() to try and load the Open Type MATH table.
// If (and ONLY if) TryGetMathTable() has returned true, the MathTable()
// method may be called to access the gfxMathTable data.
bool TryGetMathTable();
gfxMathTable* MathTable() {
MOZ_RELEASE_ASSERT(mMathTable, "A successful call to TryGetMathTable() must be performed before calling this function");
return mMathTable.get();
}
// return a cloned font resized and offset to simulate sub/superscript glyphs
@ -2096,6 +2088,8 @@ protected:
bool mKerningSet; // kerning explicitly set?
bool mKerningEnabled; // if set, on or off?
bool mMathInitialized; // TryGetMathTable() called?
nsExpirationState mExpirationState;
gfxFontStyle mStyle;
nsTArray<mozilla::UniquePtr<gfxGlyphExtents>> mGlyphExtentsArray;
@ -2131,6 +2125,9 @@ protected:
// For vertical metrics, created on demand.
mozilla::UniquePtr<const Metrics> mVerticalMetrics;
// Table used for MathML layout.
mozilla::UniquePtr<gfxMathTable> mMathTable;
// Helper for subclasses that want to initialize standard metrics from the
// tables of sfnt (TrueType/OpenType) fonts.
// This will use mFUnitsConvFactor if it is already set, else compute it

Просмотреть файл

@ -35,7 +35,6 @@
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "gfxSVGGlyphs.h"
#include "gfxMathTable.h"
#include "gfx2DGlue.h"
#include "cairo.h"
@ -73,7 +72,6 @@ gfxFontEntry::gfxFontEntry() :
mIgnoreGDEF(false),
mIgnoreGSUB(false),
mSVGInitialized(false),
mMathInitialized(false),
mHasSpaceFeaturesInitialized(false),
mHasSpaceFeatures(false),
mHasSpaceFeaturesKerning(false),
@ -113,7 +111,6 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
mIgnoreGDEF(false),
mIgnoreGSUB(false),
mSVGInitialized(false),
mMathInitialized(false),
mHasSpaceFeaturesInitialized(false),
mHasSpaceFeatures(false),
mHasSpaceFeaturesKerning(false),
@ -406,78 +403,6 @@ gfxFontEntry::NotifyGlyphsChanged()
}
}
bool
gfxFontEntry::TryGetMathTable()
{
if (!mMathInitialized) {
mMathInitialized = true;
// If UnitsPerEm is not known/valid, we can't use MATH table
if (UnitsPerEm() == kInvalidUPEM) {
return false;
}
// We don't use AutoTable here because we'll pass ownership of this
// blob to the gfxMathTable, once we've confirmed the table exists
hb_blob_t *mathTable = GetFontTable(TRUETYPE_TAG('M','A','T','H'));
if (!mathTable) {
return false;
}
// gfxMathTable will hb_blob_destroy() the table when it is finished
// with it.
mMathTable = MakeUnique<gfxMathTable>(mathTable);
if (!mMathTable->HasValidHeaders()) {
mMathTable.reset(nullptr);
return false;
}
}
return !!mMathTable;
}
gfxFloat
gfxFontEntry::GetMathConstant(gfxFontEntry::MathConstant aConstant)
{
NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
gfxFloat value = mMathTable->GetMathConstant(aConstant);
if (aConstant == gfxFontEntry::ScriptPercentScaleDown ||
aConstant == gfxFontEntry::ScriptScriptPercentScaleDown ||
aConstant == gfxFontEntry::RadicalDegreeBottomRaisePercent) {
return value / 100.0;
}
return value / mUnitsPerEm;
}
bool
gfxFontEntry::GetMathItalicsCorrection(uint32_t aGlyphID,
gfxFloat* aItalicCorrection)
{
NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
int16_t italicCorrection;
if (!mMathTable->GetMathItalicsCorrection(aGlyphID, &italicCorrection)) {
return false;
}
*aItalicCorrection = gfxFloat(italicCorrection) / mUnitsPerEm;
return true;
}
uint32_t
gfxFontEntry::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize)
{
NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
return mMathTable->GetMathVariantsSize(aGlyphID, aVertical, aSize);
}
bool
gfxFontEntry::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4])
{
NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
return mMathTable->GetMathVariantsParts(aGlyphID, aVertical, aGlyphs);
}
bool
gfxFontEntry::TryGetColorGlyphs()
{
@ -1087,10 +1012,6 @@ gfxFontEntry::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
aSizes->mFontTableCacheSize +=
mSVGGlyphs->SizeOfIncludingThis(aMallocSizeOf);
}
if (mMathTable) {
aSizes->mFontTableCacheSize +=
mMathTable->SizeOfIncludingThis(aMallocSizeOf);
}
if (mSupportedFeatures) {
aSizes->mFontTableCacheSize +=
mSupportedFeatures->ShallowSizeOfIncludingThis(aMallocSizeOf);

Просмотреть файл

@ -33,7 +33,6 @@ class gfxFont;
class gfxFontFamily;
class gfxUserFontData;
class gfxSVGGlyphs;
class gfxMathTable;
class FontInfoData;
struct FontListSizes;
class nsIAtom;
@ -193,79 +192,6 @@ public:
// (e.g. animated SVG glyphs)
void NotifyGlyphsChanged();
enum MathConstant {
// The order of the constants must match the order of the fields
// defined in the MATH table.
ScriptPercentScaleDown,
ScriptScriptPercentScaleDown,
DelimitedSubFormulaMinHeight,
DisplayOperatorMinHeight,
MathLeading,
AxisHeight,
AccentBaseHeight,
FlattenedAccentBaseHeight,
SubscriptShiftDown,
SubscriptTopMax,
SubscriptBaselineDropMin,
SuperscriptShiftUp,
SuperscriptShiftUpCramped,
SuperscriptBottomMin,
SuperscriptBaselineDropMax,
SubSuperscriptGapMin,
SuperscriptBottomMaxWithSubscript,
SpaceAfterScript,
UpperLimitGapMin,
UpperLimitBaselineRiseMin,
LowerLimitGapMin,
LowerLimitBaselineDropMin,
StackTopShiftUp,
StackTopDisplayStyleShiftUp,
StackBottomShiftDown,
StackBottomDisplayStyleShiftDown,
StackGapMin,
StackDisplayStyleGapMin,
StretchStackTopShiftUp,
StretchStackBottomShiftDown,
StretchStackGapAboveMin,
StretchStackGapBelowMin,
FractionNumeratorShiftUp,
FractionNumeratorDisplayStyleShiftUp,
FractionDenominatorShiftDown,
FractionDenominatorDisplayStyleShiftDown,
FractionNumeratorGapMin,
FractionNumDisplayStyleGapMin,
FractionRuleThickness,
FractionDenominatorGapMin,
FractionDenomDisplayStyleGapMin,
SkewedFractionHorizontalGap,
SkewedFractionVerticalGap,
OverbarVerticalGap,
OverbarRuleThickness,
OverbarExtraAscender,
UnderbarVerticalGap,
UnderbarRuleThickness,
UnderbarExtraDescender,
RadicalVerticalGap,
RadicalDisplayStyleVerticalGap,
RadicalRuleThickness,
RadicalExtraAscender,
RadicalKernBeforeDegree,
RadicalKernAfterDegree,
RadicalDegreeBottomRaisePercent
};
// Call TryGetMathTable to try to load the Open Type MATH table. The other
// functions forward the call to the gfxMathTable class. The GetMath...()
// functions MUST NOT be called unless TryGetMathTable() has returned true.
bool TryGetMathTable();
gfxFloat GetMathConstant(MathConstant aConstant);
bool GetMathItalicsCorrection(uint32_t aGlyphID,
gfxFloat* aItalicCorrection);
uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize);
bool GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4]);
bool TryGetColorGlyphs();
bool GetColorLayersInfo(uint32_t aGlyphId,
const mozilla::gfx::Color& aDefaultColor,
@ -415,7 +341,6 @@ public:
bool mIgnoreGDEF : 1;
bool mIgnoreGSUB : 1;
bool mSVGInitialized : 1;
bool mMathInitialized : 1;
bool mHasSpaceFeaturesInitialized : 1;
bool mHasSpaceFeatures : 1;
bool mHasSpaceFeaturesKerning : 1;
@ -446,7 +371,6 @@ public:
mozilla::UniquePtr<gfxSVGGlyphs> mSVGGlyphs;
// list of gfxFonts that are using SVG glyphs
nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
mozilla::UniquePtr<gfxMathTable> mMathTable;
nsTArray<gfxFontFeature> mFeatureSettings;
mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,bool>> mSupportedFeatures;
mozilla::UniquePtr<nsDataHashtable<nsUint32HashKey,hb_set_t*>> mFeatureInputs;

Просмотреть файл

@ -4,182 +4,109 @@
#include "gfxMathTable.h"
#include "MathTableStructures.h"
#include "harfbuzz/hb.h"
#include "mozilla/BinarySearch.h"
#include <algorithm>
#include "harfbuzz/hb-ot.h"
#define FixedToFloat(f) ((f) * (1.0 / 65536.0))
using namespace mozilla;
gfxMathTable::gfxMathTable(hb_blob_t* aMathTable)
: mMathTable(aMathTable)
, mGlyphConstruction(nullptr)
, mGlyphID(-1)
, mVertical(false)
gfxMathTable::gfxMathTable(hb_face_t *aFace, gfxFloat aSize)
{
mHBFont = hb_font_create(aFace);
if (mHBFont) {
hb_font_set_ppem(mHBFont, aSize, aSize);
uint32_t scale = FloatToFixed(aSize);
hb_font_set_scale(mHBFont, scale, scale);
}
mMathVariantCache.glyphID = 0;
ClearCache();
}
gfxMathTable::~gfxMathTable()
{
hb_blob_destroy(mMathTable);
if (mHBFont) {
hb_font_destroy(mHBFont);
}
}
bool
gfxMathTable::HasValidHeaders()
gfxFloat
gfxMathTable::Constant(MathConstant aConstant) const
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
// Verify the MATH table header.
if (!ValidStructure(mathData, sizeof(MATHTableHeader))) {
return false;
int32_t value = hb_ot_math_get_constant(mHBFont, static_cast<hb_ot_math_constant_t>(aConstant));
if (aConstant == ScriptPercentScaleDown ||
aConstant == ScriptScriptPercentScaleDown ||
aConstant == RadicalDegreeBottomRaisePercent) {
return value / 100.0;
}
const MATHTableHeader* header = GetMATHTableHeader();
if (uint32_t(header->mVersion) != 0x00010000 ||
!ValidOffset(mathData, uint16_t(header->mMathConstants)) ||
!ValidOffset(mathData, uint16_t(header->mMathGlyphInfo)) ||
!ValidOffset(mathData, uint16_t(header->mMathVariants))) {
return false;
}
// Verify the MathConstants header.
const MathConstants* mathconstants = GetMathConstants();
const char* start = reinterpret_cast<const char*>(mathconstants);
if (!ValidStructure(start, sizeof(MathConstants))) {
return false;
}
// Verify the MathGlyphInfo header.
const MathGlyphInfo* mathglyphinfo = GetMathGlyphInfo();
start = reinterpret_cast<const char*>(mathglyphinfo);
if (!ValidStructure(start, sizeof(MathGlyphInfo))) {
return false;
}
// Verify the MathVariants header.
const MathVariants* mathvariants = GetMathVariants();
start = reinterpret_cast<const char*>(mathvariants);
if (!ValidStructure(start, sizeof(MathVariants)) ||
!ValidStructure(start,
sizeof(MathVariants) + sizeof(Offset) *
(uint16_t(mathvariants->mVertGlyphCount) +
uint16_t(mathvariants->mHorizGlyphCount))) ||
!ValidOffset(start, uint16_t(mathvariants->mVertGlyphCoverage)) ||
!ValidOffset(start, uint16_t(mathvariants->mHorizGlyphCoverage))) {
return false;
}
return true;
return FixedToFloat(value);
}
int32_t
gfxMathTable::GetMathConstant(gfxFontEntry::MathConstant aConstant)
gfxFloat
gfxMathTable::ItalicsCorrection(uint32_t aGlyphID) const
{
const MathConstants* mathconstants = GetMathConstants();
if (aConstant <= gfxFontEntry::ScriptScriptPercentScaleDown) {
return int16_t(mathconstants->mInt16[aConstant]);
}
if (aConstant <= gfxFontEntry::DisplayOperatorMinHeight) {
return
uint16_t(mathconstants->
mUint16[aConstant - gfxFontEntry::DelimitedSubFormulaMinHeight]);
}
if (aConstant <= gfxFontEntry::RadicalKernAfterDegree) {
return int16_t(mathconstants->
mMathValues[aConstant - gfxFontEntry::MathLeading].mValue);
}
return uint16_t(mathconstants->mRadicalDegreeBottomRaisePercent);
}
bool
gfxMathTable::GetMathItalicsCorrection(uint32_t aGlyphID,
int16_t* aItalicCorrection)
{
const MathGlyphInfo* mathglyphinfo = GetMathGlyphInfo();
// Get the offset of the italic correction and verify whether it is valid.
const char* start = reinterpret_cast<const char*>(mathglyphinfo);
uint16_t offset = mathglyphinfo->mMathItalicsCorrectionInfo;
if (offset == 0 || !ValidOffset(start, offset)) {
return false;
}
start += offset;
// Verify the validity of the MathItalicsCorrectionInfo and retrieve it.
if (!ValidStructure(start, sizeof(MathItalicsCorrectionInfo))) {
return false;
}
const MathItalicsCorrectionInfo* italicsCorrectionInfo =
reinterpret_cast<const MathItalicsCorrectionInfo*>(start);
// Get the coverage index for the glyph.
offset = italicsCorrectionInfo->mCoverage;
const Coverage* coverage =
reinterpret_cast<const Coverage*>(start + offset);
int32_t i = GetCoverageIndex(coverage, aGlyphID);
// Get the ItalicsCorrection.
uint16_t count = italicsCorrectionInfo->mItalicsCorrectionCount;
if (i < 0 || i >= count) {
return false;
}
start = reinterpret_cast<const char*>(italicsCorrectionInfo + 1);
if (!ValidStructure(start, count * sizeof(MathValueRecord))) {
return false;
}
const MathValueRecord* mathValueRecordArray =
reinterpret_cast<const MathValueRecord*>(start);
*aItalicCorrection = int16_t(mathValueRecordArray[i].mValue);
return true;
return FixedToFloat(hb_ot_math_get_glyph_italics_correction(mHBFont, aGlyphID));
}
uint32_t
gfxMathTable::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize)
gfxMathTable::VariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize) const
{
// Select the glyph construction.
SelectGlyphConstruction(aGlyphID, aVertical);
if (!mGlyphConstruction) {
return 0;
UpdateMathVariantCache(aGlyphID, aVertical);
if (aSize < kMaxCachedSizeCount) {
return mMathVariantCache.sizes[aSize];
}
// Verify the validity of the array of the MathGlyphVariantRecord's and
// whether there is a variant of the requested size.
uint16_t count = mGlyphConstruction->mVariantCount;
const char* start = reinterpret_cast<const char*>(mGlyphConstruction + 1);
if (aSize >= count ||
!ValidStructure(start, count * sizeof(MathGlyphVariantRecord))) {
return 0;
}
// Return the glyph index of the requested size variant.
const MathGlyphVariantRecord* recordArray =
reinterpret_cast<const MathGlyphVariantRecord*>(start);
return uint32_t(recordArray[aSize].mVariantGlyph);
// If the size index exceeds the cache size, we just read the value with
// hb_ot_math_get_glyph_variants.
hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
hb_ot_math_glyph_variant_t variant;
unsigned int count = 1;
hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, aSize, &count,
&variant);
return count > 0 ? variant.glyph : 0;
}
bool
gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4])
gfxMathTable::VariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4]) const
{
// Get the glyph assembly corresponding to that (aGlyphID, aVertical) pair.
const GlyphAssembly* glyphAssembly = GetGlyphAssembly(aGlyphID, aVertical);
if (!glyphAssembly) {
return false;
UpdateMathVariantCache(aGlyphID, aVertical);
memcpy(aGlyphs, mMathVariantCache.parts, sizeof(mMathVariantCache.parts));
return mMathVariantCache.arePartsValid;
}
void
gfxMathTable::ClearCache() const
{
memset(mMathVariantCache.sizes, 0, sizeof(mMathVariantCache.sizes));
memset(mMathVariantCache.parts, 0, sizeof(mMathVariantCache.parts));
mMathVariantCache.arePartsValid = false;
}
void
gfxMathTable::UpdateMathVariantCache(uint32_t aGlyphID, bool aVertical) const
{
if (aGlyphID == mMathVariantCache.glyphID &&
aVertical == mMathVariantCache.vertical)
return;
mMathVariantCache.glyphID = aGlyphID;
mMathVariantCache.vertical = aVertical;
ClearCache();
// Cache the first size variants.
hb_direction_t direction = aVertical ? HB_DIRECTION_BTT : HB_DIRECTION_LTR;
hb_ot_math_glyph_variant_t variant[kMaxCachedSizeCount];
unsigned int count = kMaxCachedSizeCount;
hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, 0, &count,
variant);
for (unsigned int i = 0; i < count; i++) {
mMathVariantCache.sizes[i] = variant[i].glyph;
}
// Verify the validity of the array of GlyphPartRecord's and retrieve it.
uint16_t count = glyphAssembly->mPartCount;
const char* start = reinterpret_cast<const char*>(glyphAssembly + 1);
if (!ValidStructure(start, count * sizeof(GlyphPartRecord))) {
return false;
}
const GlyphPartRecord* recordArray =
reinterpret_cast<const GlyphPartRecord*>(start);
// Try and cache the parts of the glyph assembly.
// XXXfredw The structure of the Open Type Math table is a bit more general
// than the one currently used by the nsMathMLChar code, so we try to fallback
// in reasonable way. We use the approach of the copyComponents function in
@ -191,16 +118,24 @@ gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
// stored from bottom to top in the Open Type MATH table while they are
// stored from top to bottom in nsMathMLChar.
hb_ot_math_glyph_part_t parts[5];
count = MOZ_ARRAY_LENGTH(parts);
unsigned int offset = 0;
if (hb_ot_math_get_glyph_assembly(mHBFont, aGlyphID, direction, offset, &count, parts, NULL) > MOZ_ARRAY_LENGTH(parts))
return; // Not supported: Too many pieces.
if (count <= 0)
return; // Not supported: No pieces.
// Count the number of non extender pieces
uint16_t nonExtenderCount = 0;
for (uint16_t i = 0; i < count; i++) {
if (!(uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER)) {
if (!(parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER)) {
nonExtenderCount++;
}
}
if (nonExtenderCount > 3) {
// Not supported: too many pieces
return false;
return;
}
// Now browse the list of pieces
@ -216,13 +151,10 @@ gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
// First extender char found.
uint32_t extenderChar = 0;
// Clear the aGlyphs table.
memset(aGlyphs, 0, sizeof(uint32_t) * 4);
for (uint16_t i = 0; i < count; i++) {
bool isExtender = uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER;
uint32_t glyph = recordArray[i].mGlyph;
bool isExtender = parts[i].flags & HB_MATH_GLYPH_PART_FLAG_EXTENDER;
uint32_t glyph = parts[i].glyph;
if ((state == 1 || state == 2) && nonExtenderCount < 3) {
// do not try to find a middle glyph
@ -232,10 +164,10 @@ gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
if (isExtender) {
if (!extenderChar) {
extenderChar = glyph;
aGlyphs[3] = extenderChar;
mMathVariantCache.parts[3] = extenderChar;
} else if (extenderChar != glyph) {
// Not supported: different extenders
return false;
return;
}
if (state == 0) { // or state == 1
@ -246,7 +178,7 @@ gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
state = 3;
} else if (state >= 4) {
// Not supported: unexpected extender
return false;
return;
}
continue;
@ -254,233 +186,25 @@ gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
if (state == 0) {
// copy left/bottom part
aGlyphs[mVertical ? 2 : 0] = glyph;
mMathVariantCache.parts[aVertical ? 2 : 0] = glyph;
state = 1;
continue;
}
if (state == 1 || state == 2) {
// copy middle part
aGlyphs[1] = glyph;
mMathVariantCache.parts[1] = glyph;
state = 3;
continue;
}
if (state == 3 || state == 4) {
// copy right/top part
aGlyphs[mVertical ? 0 : 2] = glyph;
mMathVariantCache.parts[aVertical ? 0 : 2] = glyph;
state = 5;
}
}
return true;
}
bool
gfxMathTable::ValidStructure(const char* aStart, uint16_t aSize)
{
unsigned int mathDataLength;
const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
return (mathData <= aStart &&
aStart + aSize <= mathData + mathDataLength);
}
bool
gfxMathTable::ValidOffset(const char* aStart, uint16_t aOffset)
{
unsigned int mathDataLength;
const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
return (mathData <= aStart + aOffset &&
aStart + aOffset < mathData + mathDataLength);
}
const MATHTableHeader*
gfxMathTable::GetMATHTableHeader()
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
return reinterpret_cast<const MATHTableHeader*>(mathData);
}
const MathConstants*
gfxMathTable::GetMathConstants()
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
return
reinterpret_cast<const MathConstants*>(mathData +
uint16_t(GetMATHTableHeader()->
mMathConstants));
}
const MathGlyphInfo*
gfxMathTable::GetMathGlyphInfo()
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
return
reinterpret_cast<const MathGlyphInfo*>(mathData +
uint16_t(GetMATHTableHeader()->
mMathGlyphInfo));
}
const MathVariants*
gfxMathTable::GetMathVariants()
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
return
reinterpret_cast<const MathVariants*>(mathData +
uint16_t(GetMATHTableHeader()->
mMathVariants));
}
const GlyphAssembly*
gfxMathTable::GetGlyphAssembly(uint32_t aGlyphID, bool aVertical)
{
// Select the glyph construction.
SelectGlyphConstruction(aGlyphID, aVertical);
if (!mGlyphConstruction) {
return nullptr;
}
// Get the offset of the glyph assembly and verify whether it is valid.
const char* start = reinterpret_cast<const char*>(mGlyphConstruction);
uint16_t offset = mGlyphConstruction->mGlyphAssembly;
if (offset == 0 || !ValidOffset(start, offset)) {
return nullptr;
}
start += offset;
// Verify the validity of the GlyphAssembly and return it.
if (!ValidStructure(start, sizeof(GlyphAssembly))) {
return nullptr;
}
return reinterpret_cast<const GlyphAssembly*>(start);
}
namespace {
struct GlyphArrayWrapper
{
const GlyphID* const mGlyphArray;
explicit GlyphArrayWrapper(const GlyphID* const aGlyphArray) : mGlyphArray(aGlyphArray)
{}
uint16_t operator[](size_t index) const {
return mGlyphArray[index];
}
};
struct RangeRecordComparator
{
const uint32_t mGlyph;
explicit RangeRecordComparator(uint32_t aGlyph) : mGlyph(aGlyph) {}
int operator()(const RangeRecord& aRecord) const {
if (mGlyph < static_cast<uint16_t>(aRecord.mStart)) {
return -1;
}
if (mGlyph > static_cast<uint16_t>(aRecord.mEnd)) {
return 1;
}
return 0;
}
};
} // namespace
int32_t
gfxMathTable::GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph)
{
using mozilla::BinarySearch;
using mozilla::BinarySearchIf;
if (uint16_t(aCoverage->mFormat) == 1) {
// Coverage Format 1: list of individual glyph indices in the glyph set.
const CoverageFormat1* table =
reinterpret_cast<const CoverageFormat1*>(aCoverage);
const uint16_t count = table->mGlyphCount;
const char* start = reinterpret_cast<const char*>(table + 1);
if (ValidStructure(start, count * sizeof(GlyphID))) {
const GlyphID* glyphArray = reinterpret_cast<const GlyphID*>(start);
size_t index;
if (BinarySearch(GlyphArrayWrapper(glyphArray), 0, count, aGlyph, &index)) {
return index;
}
}
} else if (uint16_t(aCoverage->mFormat) == 2) {
// Coverage Format 2: ranges of consecutive indices.
const CoverageFormat2* table =
reinterpret_cast<const CoverageFormat2*>(aCoverage);
const uint16_t count = table->mRangeCount;
const char* start = reinterpret_cast<const char*>(table + 1);
if (ValidStructure(start, count * sizeof(RangeRecord))) {
const RangeRecord* rangeArray = reinterpret_cast<const RangeRecord*>(start);
size_t index;
if (BinarySearchIf(rangeArray, 0, count, RangeRecordComparator(aGlyph),
&index)) {
uint16_t rStart = rangeArray[index].mStart;
uint16_t startCoverageIndex = rangeArray[index].mStartCoverageIndex;
return (startCoverageIndex + aGlyph - rStart);
}
}
}
return -1;
}
void
gfxMathTable::SelectGlyphConstruction(uint32_t aGlyphID, bool aVertical)
{
if (mGlyphID == aGlyphID && mVertical == aVertical) {
// The (glyph, direction) pair is already selected: nothing to do.
return;
}
// Update our cached values.
mVertical = aVertical;
mGlyphID = aGlyphID;
mGlyphConstruction = nullptr;
// Get the coverage index for the new values.
const MathVariants* mathvariants = GetMathVariants();
const char* start = reinterpret_cast<const char*>(mathvariants);
uint16_t offset = (aVertical ?
mathvariants->mVertGlyphCoverage :
mathvariants->mHorizGlyphCoverage);
const Coverage* coverage =
reinterpret_cast<const Coverage*>(start + offset);
int32_t i = GetCoverageIndex(coverage, aGlyphID);
// Get the offset to the glyph construction.
uint16_t count = (aVertical ?
mathvariants->mVertGlyphCount :
mathvariants->mHorizGlyphCount);
start = reinterpret_cast<const char*>(mathvariants + 1);
if (i < 0 || i >= count) {
return;
}
if (!aVertical) {
start += uint16_t(mathvariants->mVertGlyphCount) * sizeof(Offset);
}
if (!ValidStructure(start, count * sizeof(Offset))) {
return;
}
const Offset* offsetArray = reinterpret_cast<const Offset*>(start);
offset = uint16_t(offsetArray[i]);
// Make mGlyphConstruction point to the desired glyph construction.
start = reinterpret_cast<const char*>(mathvariants);
if (!ValidStructure(start + offset, sizeof(MathGlyphConstruction))) {
return;
}
mGlyphConstruction =
reinterpret_cast<const MathGlyphConstruction*>(start + offset);
}
size_t
gfxMathTable::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
// We don't include the size of mMathTable here, because (depending on the
// font backend implementation) it will either wrap a block of data owned
// by the system (and potentially shared), or a table that's in our font
// table cache and therefore already counted.
return aMallocSizeOf(this);
mMathVariantCache.arePartsValid = true;
}

Просмотреть файл

@ -7,46 +7,105 @@
#include "gfxFont.h"
struct Coverage;
struct GlyphAssembly;
struct MATHTableHeader;
struct MathConstants;
struct MathGlyphConstruction;
struct MathGlyphInfo;
struct MathVariants;
/**
* Used by |gfxFontEntry| to represent the MATH table of an OpenType font.
* Each |gfxFontEntry| owns at most one |gfxMathTable| instance.
* Used by |gfxFont| to represent the MATH table of an OpenType font.
* Each |gfxFont| owns at most one |gfxMathTable| instance.
*/
class gfxMathTable
{
public:
/**
* @param aMathTable The MATH table from the OpenType font
*
* The gfxMathTable object takes over ownership of the blob references
* that are passed in, and will hb_blob_destroy() them when finished;
* the caller should -not- destroy this reference.
* @param aFace The HarfBuzz face containing the math table.
* @param aSize The font size to pass to HarfBuzz.
*/
explicit gfxMathTable(hb_blob_t* aMathTable);
gfxMathTable(hb_face_t *aFace, gfxFloat aSize);
/**
* Releases our reference to the MATH table and cleans up everything else.
*/
~gfxMathTable();
enum MathConstant {
// The order of the constants must match the order of the fields
// defined in the MATH table.
ScriptPercentScaleDown,
ScriptScriptPercentScaleDown,
DelimitedSubFormulaMinHeight,
DisplayOperatorMinHeight,
MathLeading,
AxisHeight,
AccentBaseHeight,
FlattenedAccentBaseHeight,
SubscriptShiftDown,
SubscriptTopMax,
SubscriptBaselineDropMin,
SuperscriptShiftUp,
SuperscriptShiftUpCramped,
SuperscriptBottomMin,
SuperscriptBaselineDropMax,
SubSuperscriptGapMin,
SuperscriptBottomMaxWithSubscript,
SpaceAfterScript,
UpperLimitGapMin,
UpperLimitBaselineRiseMin,
LowerLimitGapMin,
LowerLimitBaselineDropMin,
StackTopShiftUp,
StackTopDisplayStyleShiftUp,
StackBottomShiftDown,
StackBottomDisplayStyleShiftDown,
StackGapMin,
StackDisplayStyleGapMin,
StretchStackTopShiftUp,
StretchStackBottomShiftDown,
StretchStackGapAboveMin,
StretchStackGapBelowMin,
FractionNumeratorShiftUp,
FractionNumeratorDisplayStyleShiftUp,
FractionDenominatorShiftDown,
FractionDenominatorDisplayStyleShiftDown,
FractionNumeratorGapMin,
FractionNumDisplayStyleGapMin,
FractionRuleThickness,
FractionDenominatorGapMin,
FractionDenomDisplayStyleGapMin,
SkewedFractionHorizontalGap,
SkewedFractionVerticalGap,
OverbarVerticalGap,
OverbarRuleThickness,
OverbarExtraAscender,
UnderbarVerticalGap,
UnderbarRuleThickness,
UnderbarExtraDescender,
RadicalVerticalGap,
RadicalDisplayStyleVerticalGap,
RadicalRuleThickness,
RadicalExtraAscender,
RadicalKernBeforeDegree,
RadicalKernAfterDegree,
RadicalDegreeBottomRaisePercent
};
/**
* Returns the value of the specified constant from the MATH table.
*/
int32_t GetMathConstant(gfxFontEntry::MathConstant aConstant);
gfxFloat Constant(MathConstant aConstant) const;
/**
* Returns the value of the specified constant in app units.
*/
nscoord Constant(MathConstant aConstant,
uint32_t aAppUnitsPerDevPixel) const
{
return NSToCoordRound(Constant(aConstant) * aAppUnitsPerDevPixel);
}
/**
* If the MATH table contains an italic correction for that glyph, this
* function gets the value and returns true. Otherwise it returns false.
* function returns the corresponding value. Otherwise it returns 0.
*/
bool
GetMathItalicsCorrection(uint32_t aGlyphID, int16_t* aItalicCorrection);
gfxFloat
ItalicsCorrection(uint32_t aGlyphID) const;
/**
* @param aGlyphID glyph index of the character we want to stretch
@ -56,8 +115,8 @@ public:
* Returns the glyph index of the desired size variant or 0 if there is not
* any such size variant.
*/
uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize);
uint32_t VariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize) const;
/**
* @param aGlyphID glyph index of the character we want to stretch
@ -73,52 +132,24 @@ public:
* the format is not supported by the nsMathMLChar code.
*
*/
bool GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4]);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
protected:
friend class gfxFontEntry;
// This allows gfxFontEntry to verify the validity of the main headers
// before starting to use the MATH table.
bool HasValidHeaders();
bool VariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4]) const;
private:
// HarfBuzz blob where the MATH table is stored.
hb_blob_t* mMathTable;
// size-specific font object, owned by the gfxMathTable
hb_font_t *mHBFont;
// Cached values for the latest (mGlyphID, mVertical) pair that has been
// accessed and the corresponding glyph construction. These are verified
// by SelectGlyphConstruction and updated if necessary.
// mGlyphConstruction will be set to nullptr if no construction is defined
// for the glyph. If non-null, its mGlyphAssembly and mVariantCount fields
// may be safely read, but no further validation will have been done.
const MathGlyphConstruction* mGlyphConstruction;
uint32_t mGlyphID;
bool mVertical;
void SelectGlyphConstruction(uint32_t aGlyphID, bool aVertical);
// Access to some structures of the MATH table.
// These accessors just return a pointer, but do NOT themselves check the
// validity of anything. Until we've checked that HasValidHeaders (which
// does validate them) returns true, they might return pointers that cannot
// even safely be dereferenced. GetGlyphAssembly may return nullptr if the
// given glyph has no assembly defined.
const MATHTableHeader* GetMATHTableHeader();
const MathConstants* GetMathConstants();
const MathGlyphInfo* GetMathGlyphInfo();
const MathVariants* GetMathVariants();
const GlyphAssembly* GetGlyphAssembly(uint32_t aGlyphID, bool aVertical);
// Verify whether a structure or an offset belongs to the math data and can
// be read safely.
bool ValidStructure(const char* aStructStart, uint16_t aStructSize);
bool ValidOffset(const char* aOffsetStart, uint16_t aOffset);
// Get the coverage index of a glyph index from an Open Type coverage table
// or -1 if the glyph index is not found.
int32_t GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph);
static const unsigned int kMaxCachedSizeCount = 10;
struct MathVariantCacheEntry {
uint32_t glyphID;
bool vertical;
uint32_t sizes[kMaxCachedSizeCount];
uint32_t parts[4];
bool arePartsValid;
};
mutable MathVariantCacheEntry mMathVariantCache;
void ClearCache() const;
void UpdateMathVariantCache(uint32_t aGlyphID, bool aVertical) const;
};
#endif

Просмотреть файл

@ -1898,7 +1898,7 @@ gfxFontGroup::GetFirstMathFont()
uint32_t count = mFonts.Length();
for (uint32_t i = 0; i < count; ++i) {
gfxFont* font = GetFontAt(i);
if (font && font->GetFontEntry()->TryGetMathTable()) {
if (font && font->TryGetMathTable()) {
return font;
}
}

Просмотреть файл

@ -443,20 +443,20 @@ public:
// to the caller.
static nsOpenTypeTable* Create(gfxFont* aFont)
{
if (!aFont->GetFontEntry()->TryGetMathTable()) {
if (!aFont->TryGetMathTable()) {
return nullptr;
}
return new nsOpenTypeTable(aFont->GetFontEntry());
return new nsOpenTypeTable(aFont);
}
private:
RefPtr<gfxFontEntry> mFontEntry;
RefPtr<gfxFont> mFont;
FontFamilyName mFontFamilyName;
uint32_t mGlyphID;
explicit nsOpenTypeTable(gfxFontEntry* aFontEntry)
: mFontEntry(aFontEntry),
mFontFamilyName(aFontEntry->FamilyName(), eUnquotedName) {
explicit nsOpenTypeTable(gfxFont* aFont)
: mFont(aFont),
mFontFamilyName(aFont->GetFontEntry()->FamilyName(), eUnquotedName) {
MOZ_COUNT_CTOR(nsOpenTypeTable);
}
@ -499,7 +499,7 @@ nsOpenTypeTable::ElementAt(DrawTarget* aDrawTarget,
UpdateCache(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t parts[4];
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) {
if (!mFont->MathTable()->VariantsParts(mGlyphID, aVertical, parts)) {
return kNullGlyph;
}
@ -525,7 +525,7 @@ nsOpenTypeTable::BigOf(DrawTarget* aDrawTarget,
UpdateCache(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t glyphID =
mFontEntry->GetMathVariantsSize(mGlyphID, aVertical, aSize);
mFont->MathTable()->VariantsSize(mGlyphID, aVertical, aSize);
if (!glyphID) {
return kNullGlyph;
}
@ -547,7 +547,7 @@ nsOpenTypeTable::HasPartsOf(DrawTarget* aDrawTarget,
UpdateCache(aDrawTarget, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t parts[4];
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) {
if (!mFont->MathTable()->VariantsParts(mGlyphID, aVertical, parts)) {
return false;
}
@ -1133,9 +1133,8 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
// to select the right size variant. Note that the value is sometimes too
// small so we use kLargeOpFactor/kIntegralFactor as a minimum value.
if (mathFont) {
displayOperatorMinHeight =
mathFont->GetMathConstant(gfxFontEntry::DisplayOperatorMinHeight,
oneDevPixel);
displayOperatorMinHeight = mathFont->MathTable()->
Constant(gfxMathTable::DisplayOperatorMinHeight, oneDevPixel);
RefPtr<gfxTextRun> textRun =
aGlyphTable->MakeTextRun(mDrawTarget, oneDevPixel, *aFontGroup, ch);
nsBoundingMetrics bm = MeasureTextRun(mDrawTarget, textRun.get());
@ -1179,12 +1178,11 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
// Note that STIX-Word does not provide italic corrections but its
// advance widths do not match right bearings.
// (http://sourceforge.net/p/stixfonts/tracking/50/)
gfxFloat italicCorrection;
if (mathFont->GetFontEntry()->
GetMathItalicsCorrection(ch.glyphID, &italicCorrection)) {
gfxFloat italicCorrection =
mathFont->MathTable()->ItalicsCorrection(ch.glyphID);
if (italicCorrection) {
bm.width -=
NSToCoordRound(italicCorrection *
mathFont->GetAdjustedSize() * oneDevPixel);
NSToCoordRound(italicCorrection * oneDevPixel);
if (bm.width < 0) {
bm.width = 0;
}

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsMathMLChar.h"
#include "nsCSSPseudoElements.h"
#include "nsMathMLElement.h"
#include "gfxMathTable.h"
// used to map attributes into CSS rules
#include "mozilla/StyleSetHandle.h"
@ -193,8 +194,8 @@ nsMathMLFrame::GetAxisHeight(DrawTarget* aDrawTarget,
gfxFont* mathFont = aFontMetrics->GetThebesFontGroup()->GetFirstMathFont();
if (mathFont) {
aAxisHeight =
mathFont->GetMathConstant(gfxFontEntry::AxisHeight,
aFontMetrics->AppUnitsPerDevPixel());
mathFont->MathTable()->Constant(gfxMathTable::AxisHeight,
aFontMetrics->AppUnitsPerDevPixel());
return;
}
@ -393,18 +394,16 @@ nsMathMLFrame::GetRadicalParameters(nsFontMetrics* aFontMetrics,
// get the radical rulethickness
if (mathFont) {
aRadicalRuleThickness =
mathFont->GetMathConstant(gfxFontEntry::RadicalRuleThickness,
oneDevPixel);
aRadicalRuleThickness = mathFont->MathTable()->
Constant(gfxMathTable::RadicalRuleThickness, oneDevPixel);
} else {
GetRuleThickness(aFontMetrics, aRadicalRuleThickness);
}
// get the leading to be left at the top of the resulting frame
if (mathFont) {
aRadicalExtraAscender =
mathFont->GetMathConstant(gfxFontEntry::RadicalExtraAscender,
oneDevPixel);
aRadicalExtraAscender = mathFont->MathTable()->
Constant(gfxMathTable::RadicalExtraAscender, oneDevPixel);
} else {
// This seems more reliable than using aFontMetrics->GetLeading() on
// suspicious fonts.
@ -415,11 +414,11 @@ nsMathMLFrame::GetRadicalParameters(nsFontMetrics* aFontMetrics,
// get the clearance between rule and content
if (mathFont) {
aRadicalVerticalGap =
mathFont->GetMathConstant(aDisplayStyle ?
gfxFontEntry::RadicalDisplayStyleVerticalGap :
gfxFontEntry::RadicalVerticalGap,
oneDevPixel);
aRadicalVerticalGap = mathFont->MathTable()->
Constant(aDisplayStyle ?
gfxMathTable::RadicalDisplayStyleVerticalGap :
gfxMathTable::RadicalVerticalGap,
oneDevPixel);
} else {
// Rule 11, App. G, TeXbook
aRadicalVerticalGap = aRadicalRuleThickness +

Просмотреть файл

@ -16,6 +16,7 @@
#include "gfxContext.h"
#include "nsMathMLElement.h"
#include <algorithm>
#include "gfxMathTable.h"
using namespace mozilla;
using namespace mozilla::gfx;
@ -239,9 +240,8 @@ nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
nscoord oneDevPixel = fm->AppUnitsPerDevPixel();
gfxFont* mathFont = fm->GetThebesFontGroup()->GetFirstMathFont();
if (mathFont) {
defaultRuleThickness =
mathFont->GetMathConstant(gfxFontEntry::FractionRuleThickness,
oneDevPixel);
defaultRuleThickness = mathFont->MathTable()->
Constant(gfxMathTable::FractionRuleThickness, oneDevPixel);
} else {
GetRuleThickness(aDrawTarget, fm, defaultRuleThickness);
}
@ -305,31 +305,30 @@ nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
denShift = displayStyle ? denShift1 : denShift2;
if (mathFont) {
numShift = mathFont->
GetMathConstant(displayStyle ?
gfxFontEntry::StackTopDisplayStyleShiftUp :
gfxFontEntry::StackTopShiftUp,
oneDevPixel);
MathTable()->Constant(displayStyle ?
gfxMathTable::StackTopDisplayStyleShiftUp :
gfxMathTable::StackTopShiftUp,
oneDevPixel);
denShift = mathFont->
GetMathConstant(displayStyle ?
gfxFontEntry::StackBottomDisplayStyleShiftDown :
gfxFontEntry::StackBottomShiftDown,
oneDevPixel);
MathTable()->Constant(displayStyle ?
gfxMathTable::StackBottomDisplayStyleShiftDown :
gfxMathTable::StackBottomShiftDown,
oneDevPixel);
}
} else {
numShift = displayStyle ? numShift1 : numShift2;
denShift = displayStyle ? denShift1 : denShift2;
if (mathFont) {
numShift = mathFont->
GetMathConstant(displayStyle ?
gfxFontEntry::FractionNumeratorDisplayStyleShiftUp :
gfxFontEntry::FractionNumeratorShiftUp,
oneDevPixel);
denShift = mathFont->
GetMathConstant(
displayStyle ?
gfxFontEntry::FractionDenominatorDisplayStyleShiftDown :
gfxFontEntry::FractionDenominatorShiftDown,
oneDevPixel);
numShift = mathFont->MathTable()->
Constant(displayStyle ?
gfxMathTable::FractionNumeratorDisplayStyleShiftUp :
gfxMathTable::FractionNumeratorShiftUp,
oneDevPixel);
denShift = mathFont->MathTable()->
Constant(displayStyle ?
gfxMathTable::FractionDenominatorDisplayStyleShiftDown :
gfxMathTable::FractionDenominatorShiftDown,
oneDevPixel);
}
}
@ -340,11 +339,11 @@ nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
nscoord minClearance = displayStyle ?
7 * defaultRuleThickness : 3 * defaultRuleThickness;
if (mathFont) {
minClearance =
mathFont->GetMathConstant(displayStyle ?
gfxFontEntry::StackDisplayStyleGapMin :
gfxFontEntry::StackGapMin,
oneDevPixel);
minClearance = mathFont->MathTable()->
Constant(displayStyle ?
gfxMathTable::StackDisplayStyleGapMin :
gfxMathTable::StackGapMin,
oneDevPixel);
}
// Factor in axis height
// http://www.mathml-association.org/MathMLinHTML5/S3.html#SS3.SSS2
@ -379,15 +378,15 @@ nsMathMLmfracFrame::PlaceInternal(DrawTarget* aDrawTarget,
nscoord minClearanceDen = minClearanceNum;
if (mathFont) {
minClearanceNum = mathFont->
GetMathConstant(displayStyle ?
gfxFontEntry::FractionNumDisplayStyleGapMin :
gfxFontEntry::FractionNumeratorGapMin,
oneDevPixel);
MathTable()->Constant(displayStyle ?
gfxMathTable::FractionNumDisplayStyleGapMin :
gfxMathTable::FractionNumeratorGapMin,
oneDevPixel);
minClearanceDen = mathFont->
GetMathConstant(displayStyle ?
gfxFontEntry::FractionDenomDisplayStyleGapMin :
gfxFontEntry::FractionDenominatorGapMin,
oneDevPixel);
MathTable()->Constant(displayStyle ?
gfxMathTable::FractionDenomDisplayStyleGapMin :
gfxMathTable::FractionDenominatorGapMin,
oneDevPixel);
}
// adjust numShift to maintain minClearanceNum if needed

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsPresContext.h"
#include "nsRenderingContext.h"
#include <algorithm>
#include "gfxMathTable.h"
using mozilla::WritingMode;
@ -195,8 +196,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
// scriptspace from TeX for extra spacing after sup/subscript
nscoord scriptSpace;
if (mathFont) {
scriptSpace =
mathFont->GetMathConstant(gfxFontEntry::SpaceAfterScript, oneDevPixel);
scriptSpace = mathFont->MathTable()->
Constant(gfxMathTable::SpaceAfterScript, oneDevPixel);
} else {
// (0.5pt in plain TeX)
scriptSpace = nsPresContext::CSSPointsToAppUnits(0.5f);
@ -204,10 +205,10 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
// Try and read sub and sup drops from the MATH table.
if (mathFont) {
subDrop = mathFont->
GetMathConstant(gfxFontEntry::SubscriptBaselineDropMin, oneDevPixel);
supDrop = mathFont->
GetMathConstant(gfxFontEntry::SuperscriptBaselineDropMax, oneDevPixel);
subDrop = mathFont->MathTable()->
Constant(gfxMathTable::SubscriptBaselineDropMin, oneDevPixel);
supDrop = mathFont->MathTable()->
Constant(gfxMathTable::SuperscriptBaselineDropMax, oneDevPixel);
}
// force the scriptSpace to be at least 1 pixel
@ -221,8 +222,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
if (mathFont) {
// Try and get the sub script shift from the MATH table. Note that contrary
// to TeX we only have one parameter.
subScriptShift =
mathFont->GetMathConstant(gfxFontEntry::SubscriptShiftDown, oneDevPixel);
subScriptShift = mathFont->MathTable()->
Constant(gfxMathTable::SubscriptShiftDown, oneDevPixel);
} else {
// subScriptShift{1,2}
// = minimum amount to shift the subscript down
@ -253,10 +254,10 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
// Try and get the super script shift from the MATH table. Note that
// contrary to TeX we only have two parameters.
supScriptShift = mathFont->
GetMathConstant(NS_MATHML_IS_COMPRESSED(presentationData.flags) ?
gfxFontEntry::SuperscriptShiftUpCramped :
gfxFontEntry::SuperscriptShiftUp,
oneDevPixel);
MathTable()->Constant(NS_MATHML_IS_COMPRESSED(presentationData.flags) ?
gfxMathTable::SuperscriptShiftUpCramped :
gfxMathTable::SuperscriptShiftUp,
oneDevPixel);
} else {
// supScriptShift{1,2,3}
// = minimum amount to shift the supscript up
@ -424,8 +425,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
nscoord subscriptTopMax;
if (mathFont) {
subscriptTopMax =
mathFont->GetMathConstant(gfxFontEntry::SubscriptTopMax,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::SubscriptTopMax,
oneDevPixel);
} else {
// get min subscript shift limit from x-height
// = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook
@ -450,8 +451,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
nscoord superscriptBottomMin;
if (mathFont) {
superscriptBottomMin =
mathFont->GetMathConstant(gfxFontEntry::SuperscriptBottomMin,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::SuperscriptBottomMin,
oneDevPixel);
} else {
// get min supscript shift limit from x-height
// = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook
@ -495,9 +496,8 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
tag == nsGkAtoms::msubsup_) {
nscoord subSuperscriptGapMin;
if (mathFont) {
subSuperscriptGapMin =
mathFont->GetMathConstant(gfxFontEntry::SubSuperscriptGapMin,
oneDevPixel);
subSuperscriptGapMin = mathFont->MathTable()->
Constant(gfxMathTable::SubSuperscriptGapMin, oneDevPixel);
} else {
nscoord ruleSize;
GetRuleThickness(aDrawTarget, fm, ruleSize);
@ -515,9 +515,9 @@ nsMathMLmmultiscriptsFrame::PlaceMultiScript(nsPresContext* aPresContext,
// will be > superscriptBottomMaxWithSubscript
nscoord superscriptBottomMaxWithSubscript;
if (mathFont) {
superscriptBottomMaxWithSubscript = mathFont->
GetMathConstant(gfxFontEntry::SuperscriptBottomMaxWithSubscript,
oneDevPixel);
superscriptBottomMaxWithSubscript = mathFont->MathTable()->
Constant(gfxMathTable::SuperscriptBottomMaxWithSubscript,
oneDevPixel);
} else {
superscriptBottomMaxWithSubscript =
NSToCoordRound((4.0f / 5.0f) * xHeight);

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsPresContext.h"
#include "nsRenderingContext.h"
#include <algorithm>
#include "gfxMathTable.h"
using namespace mozilla;
@ -116,8 +117,8 @@ nsMathMLmrootFrame::GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth,
gfxFont* mathFont = aFontMetrics->GetThebesFontGroup()->GetFirstMathFont();
if (mathFont) {
indexRadicalKern =
mathFont->GetMathConstant(gfxFontEntry::RadicalKernAfterDegree,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::RadicalKernAfterDegree,
oneDevPixel);
indexRadicalKern = -indexRadicalKern;
}
if (indexRadicalKern > aIndexWidth) {
@ -133,8 +134,8 @@ nsMathMLmrootFrame::GetRadicalXOffsets(nscoord aIndexWidth, nscoord aSqrWidth,
// add some kern before the radical index
nscoord indexRadicalKernBefore = 0;
indexRadicalKernBefore =
mathFont->GetMathConstant(gfxFontEntry::RadicalKernBeforeDegree,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::RadicalKernBeforeDegree,
oneDevPixel);
dxIndex += indexRadicalKernBefore;
dxSqr += indexRadicalKernBefore;
} else {
@ -295,8 +296,8 @@ nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext,
float raiseIndexPercent = 0.6f;
gfxFont* mathFont = fm->GetThebesFontGroup()->GetFirstMathFont();
if (mathFont) {
raiseIndexPercent =
mathFont->GetMathConstant(gfxFontEntry::RadicalDegreeBottomRaisePercent);
raiseIndexPercent = mathFont->MathTable()->
Constant(gfxMathTable::RadicalDegreeBottomRaisePercent);
}
nscoord raiseIndexDelta = NSToCoordRound(raiseIndexPercent *
(bmSqr.ascent + bmSqr.descent));

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsRenderingContext.h"
#include "nsMathMLmmultiscriptsFrame.h"
#include <algorithm>
#include "gfxMathTable.h"
//
// <munderover> -- attach an underscript-overscript pair to a base - implementation
@ -429,11 +430,11 @@ nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
// that we may use when the base is a stretchy horizontal operator. See
// bug 963131.
bigOpSpacing2 =
mathFont->GetMathConstant(gfxFontEntry::LowerLimitGapMin,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::LowerLimitGapMin,
oneDevPixel);
bigOpSpacing4 =
mathFont->GetMathConstant(gfxFontEntry::LowerLimitBaselineDropMin,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::LowerLimitBaselineDropMin,
oneDevPixel);
bigOpSpacing5 = 0;
}
underDelta1 = std::max(bigOpSpacing2, (bigOpSpacing4 - bmUnder.ascent));
@ -472,11 +473,11 @@ nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
// that we may use when the base is a stretchy horizontal operator. See
// bug 963131.
bigOpSpacing1 =
mathFont->GetMathConstant(gfxFontEntry::UpperLimitGapMin,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::UpperLimitGapMin,
oneDevPixel);
bigOpSpacing3 =
mathFont->GetMathConstant(gfxFontEntry::UpperLimitBaselineRiseMin,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::UpperLimitBaselineRiseMin,
oneDevPixel);
bigOpSpacing5 = 0;
}
overDelta1 = std::max(bigOpSpacing1, (bigOpSpacing3 - bmOver.descent));
@ -522,8 +523,8 @@ nsMathMLmunderoverFrame::Place(DrawTarget* aDrawTarget,
nscoord accentBaseHeight = xHeight;
if (mathFont) {
accentBaseHeight =
mathFont->GetMathConstant(gfxFontEntry::AccentBaseHeight,
oneDevPixel);
mathFont->MathTable()->Constant(gfxMathTable::AccentBaseHeight,
oneDevPixel);
}
if (bmBase.ascent < accentBaseHeight) {
// also ensure at least accentBaseHeight above the baseline of the base