зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
fa5f21c539
Коммит
1c9167ba68
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче