Backed out 5 changesets (bug 407059) for reftest asserts.

Backed out changeset 21fee1261f2e (bug 407059)
Backed out changeset c940a2d399c4 (bug 407059)
Backed out changeset 77593dd1b044 (bug 407059)
Backed out changeset cfcbc731d4db (bug 407059)
Backed out changeset d8244f3ecdcb (bug 407059)
This commit is contained in:
Ryan VanderMeulen 2014-04-22 11:00:13 -04:00
Родитель 36d9b20377
Коммит 0691160cfe
24 изменённых файлов: 453 добавлений и 1855 удалений

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

@ -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

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

@ -117,9 +117,7 @@ gfxFT2FontBase::GetMetrics()
new(&mMetrics) gfxFont::Metrics(); // zero initialize
mSpaceGlyph = 0;
} else {
gfxFT2LockedFace face(this);
mFUnitsConvFactor = face.XScale();
face.GetMetrics(&mMetrics, &mSpaceGlyph);
gfxFT2LockedFace(this).GetMetrics(&mMetrics, &mSpaceGlyph);
}
SanitizeMetrics(&mMetrics, false);

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

@ -426,6 +426,9 @@ gfxFT2Font::ShapeText(gfxContext *aContext,
if (!ok && gfxPlatform::GetPlatform()->UseHarfBuzzForScript(aScript)) {
if (!mHarfBuzzShaper) {
gfxFT2LockedFace face(this);
mFUnitsConvFactor = face.XScale();
mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
}
ok = mHarfBuzzShaper->ShapeText(aContext, aText,

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

@ -23,7 +23,6 @@
#include "gfxTypes.h"
#include "gfxContext.h"
#include "gfxFontMissingGlyphs.h"
#include "gfxHarfBuzzShaper.h"
#include "gfxUserFontSet.h"
#include "gfxPlatformFontList.h"
#include "gfxScriptItemizer.h"
@ -39,7 +38,6 @@
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "gfxSVGGlyphs.h"
#include "gfxMathTable.h"
#include "gfx2DGlue.h"
#if defined(XP_MACOSX)
@ -114,7 +112,6 @@ gfxFontEntry::gfxFontEntry() :
mIgnoreGDEF(false),
mIgnoreGSUB(false),
mSVGInitialized(false),
mMathInitialized(false),
mHasSpaceFeaturesInitialized(false),
mHasSpaceFeatures(false),
mHasSpaceFeaturesKerning(false),
@ -144,7 +141,6 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
mIgnoreGDEF(false),
mIgnoreGSUB(false),
mSVGInitialized(false),
mMathInitialized(false),
mHasSpaceFeaturesInitialized(false),
mHasSpaceFeatures(false),
mHasSpaceFeaturesKerning(false),
@ -393,78 +389,6 @@ gfxFontEntry::NotifyGlyphsChanged()
}
}
bool
gfxFontEntry::TryGetMathTable(gfxFont* aFont)
{
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 = new gfxMathTable(mathTable);
if (!mMathTable->HasValidHeaders()) {
mMathTable = 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);
}
/**
* FontTableBlobData
*
@ -2028,28 +1952,6 @@ gfxFont::~gfxFont()
}
}
gfxFloat
gfxFont::GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID)
{
if (ProvidesGlyphWidths()) {
return GetGlyphWidth(aCtx, aGID) / 65536.0;
}
if (mFUnitsConvFactor == 0.0f) {
GetMetrics();
}
NS_ASSERTION(mFUnitsConvFactor > 0.0f,
"missing font unit conversion factor");
if (!mHarfBuzzShaper) {
mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
}
gfxHarfBuzzShaper* shaper =
static_cast<gfxHarfBuzzShaper*>(mHarfBuzzShaper.get());
if (!shaper->Initialize() || !SetupCairoFont(aCtx)) {
return 0;
}
return shaper->GetGlyphHAdvance(aCtx, aGID) / 65536.0;
}
/*static*/
PLDHashOperator
gfxFont::AgeCacheEntry(CacheHashEntry *aEntry, void *aUserData)

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

@ -43,14 +43,11 @@ class gfxTextRun;
class gfxFont;
class gfxFontFamily;
class gfxFontGroup;
class gfxGraphiteShaper;
class gfxHarfBuzzShaper;
class gfxUserFontSet;
class gfxUserFontData;
class gfxShapedText;
class gfxShapedWord;
class gfxSVGGlyphs;
class gfxMathTable;
class gfxTextContextPaint;
class FontInfoData;
@ -314,79 +311,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(gfxFont* aFont);
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]);
virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
return true;
}
@ -509,7 +433,6 @@ public:
bool mIgnoreGDEF : 1;
bool mIgnoreGSUB : 1;
bool mSVGInitialized : 1;
bool mMathInitialized : 1;
bool mHasSpaceFeaturesInitialized : 1;
bool mHasSpaceFeatures : 1;
bool mHasSpaceFeaturesKerning : 1;
@ -535,7 +458,6 @@ public:
nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
// list of gfxFonts that are using SVG glyphs
nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
nsAutoPtr<gfxMathTable> mMathTable;
nsTArray<gfxFontFeature> mFeatureSettings;
uint32_t mLanguageOverride;
@ -1459,10 +1381,6 @@ protected:
/* a SPECIFIC single font family */
class gfxFont {
friend class gfxHarfBuzzShaper;
friend class gfxGraphiteShaper;
public:
nsrefcnt AddRef(void) {
NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
@ -1590,8 +1508,19 @@ public:
virtual uint32_t GetGlyph(uint32_t unicode, uint32_t variation_selector) {
return 0;
}
// Return the horizontal advance of a glyph.
gfxFloat GetGlyphHAdvance(gfxContext *aCtx, uint16_t aGID);
// subclasses may provide (possibly hinted) glyph widths (in font units);
// if they do not override this, harfbuzz will use unhinted widths
// derived from the font tables
virtual bool ProvidesGlyphWidths() {
return false;
}
// The return value is interpreted as a horizontal advance in 16.16 fixed
// point format.
virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) {
return -1;
}
// Return Azure GlyphRenderingOptions for drawing this font.
virtual mozilla::TemporaryRef<mozilla::gfx::GlyphRenderingOptions>
@ -1887,19 +1816,6 @@ public:
}
protected:
// subclasses may provide (possibly hinted) glyph widths (in font units);
// if they do not override this, harfbuzz will use unhinted widths
// derived from the font tables
virtual bool ProvidesGlyphWidths() {
return false;
}
// The return value is interpreted as a horizontal advance in 16.16 fixed
// point format.
virtual int32_t GetGlyphWidth(gfxContext *aCtx, uint16_t aGID) {
return -1;
}
void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);

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

@ -188,6 +188,10 @@ hb_position_t
gfxHarfBuzzShaper::GetGlyphHAdvance(gfxContext *aContext,
hb_codepoint_t glyph) const
{
if (mUseFontGlyphWidths) {
return mFont->GetGlyphWidth(aContext, glyph);
}
// font did not implement GetHintedGlyphWidth, so get an unhinted value
// directly from the font tables
@ -207,19 +211,13 @@ gfxHarfBuzzShaper::GetGlyphHAdvance(gfxContext *aContext,
uint16_t(hmtx->metrics[glyph].advanceWidth));
}
/* static */
hb_position_t
gfxHarfBuzzShaper::HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
hb_codepoint_t glyph, void *user_data)
static hb_position_t
HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
hb_codepoint_t glyph, void *user_data)
{
const gfxHarfBuzzShaper::FontCallbackData *fcd =
static_cast<const gfxHarfBuzzShaper::FontCallbackData*>(font_data);
gfxFont *gfxfont = fcd->mShaper->GetFont();
if (gfxfont->ProvidesGlyphWidths()) {
return gfxfont->GetGlyphWidth(fcd->mContext, glyph);
} else {
return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
}
return fcd->mShaper->GetGlyphHAdvance(fcd->mContext, glyph);
}
static hb_bool_t
@ -819,121 +817,6 @@ static hb_unicode_funcs_t * sHBUnicodeFuncs = nullptr;
static const hb_script_t sMathScript =
hb_ot_tag_to_script(HB_TAG('m','a','t','h'));
bool
gfxHarfBuzzShaper::Initialize()
{
if (mInitialized) {
return mHBFont != nullptr;
}
mInitialized = true;
mCallbackData.mShaper = this;
mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
if (!sHBFontFuncs) {
// static function callback pointers, initialized by the first
// harfbuzz shaper used
sHBFontFuncs = hb_font_funcs_create();
hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph,
nullptr, nullptr);
hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs,
HBGetGlyphHAdvance,
nullptr, nullptr);
hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
HBGetContourPoint,
nullptr, nullptr);
hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs,
HBGetHKerning,
nullptr, nullptr);
sHBUnicodeFuncs =
hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs,
HBGetMirroring,
nullptr, nullptr);
hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript,
nullptr, nullptr);
hb_unicode_funcs_set_general_category_func(sHBUnicodeFuncs,
HBGetGeneralCategory,
nullptr, nullptr);
hb_unicode_funcs_set_combining_class_func(sHBUnicodeFuncs,
HBGetCombiningClass,
nullptr, nullptr);
hb_unicode_funcs_set_eastasian_width_func(sHBUnicodeFuncs,
HBGetEastAsianWidth,
nullptr, nullptr);
hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs,
HBUnicodeCompose,
nullptr, nullptr);
hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs,
HBUnicodeDecompose,
nullptr, nullptr);
}
gfxFontEntry *entry = mFont->GetFontEntry();
if (!mUseFontGetGlyph) {
// get the cmap table and find offset to our subtable
mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
if (!mCmapTable) {
NS_WARNING("failed to load cmap, glyphs will be missing");
return false;
}
uint32_t len;
const uint8_t* data = (const uint8_t*)hb_blob_get_data(mCmapTable, &len);
bool symbol;
mCmapFormat = gfxFontUtils::
FindPreferredSubtable(data, len,
&mSubtableOffset, &mUVSTableOffset,
&symbol);
if (mCmapFormat <= 0) {
return false;
}
}
if (!mUseFontGlyphWidths) {
// if font doesn't implement GetGlyphWidth, we will be reading
// the hmtx table directly;
// read mNumLongMetrics from hhea table without caching its blob,
// and preload/cache the hmtx table
gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
if (hheaTable) {
uint32_t len;
const HMetricsHeader* hhea =
reinterpret_cast<const HMetricsHeader*>
(hb_blob_get_data(hheaTable, &len));
if (len >= sizeof(HMetricsHeader)) {
mNumLongMetrics = hhea->numberOfHMetrics;
if (mNumLongMetrics > 0 &&
int16_t(hhea->metricDataFormat) == 0) {
// no point reading hmtx if number of entries is zero!
// in that case, we won't be able to use this font
// (this method will return FALSE below if mHmtx is null)
mHmtxTable =
entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
if (hb_blob_get_length(mHmtxTable) <
mNumLongMetrics * sizeof(HLongMetric)) {
// hmtx table is not large enough for the claimed
// number of entries: invalid, do not use.
hb_blob_destroy(mHmtxTable);
mHmtxTable = nullptr;
}
}
}
}
if (!mHmtxTable) {
return false;
}
}
mHBFont = hb_font_create(mHBFace);
hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
hb_font_set_scale(mHBFont, scale, scale);
return true;
}
bool
gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
const char16_t *aText,
@ -948,8 +831,112 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
}
mCallbackData.mContext = aContext;
gfxFontEntry *entry = mFont->GetFontEntry();
if (!Initialize()) {
if (!mInitialized) {
mInitialized = true;
mCallbackData.mShaper = this;
mUseFontGlyphWidths = mFont->ProvidesGlyphWidths();
if (!sHBFontFuncs) {
// static function callback pointers, initialized by the first
// harfbuzz shaper used
sHBFontFuncs = hb_font_funcs_create();
hb_font_funcs_set_glyph_func(sHBFontFuncs, HBGetGlyph,
nullptr, nullptr);
hb_font_funcs_set_glyph_h_advance_func(sHBFontFuncs,
HBGetGlyphHAdvance,
nullptr, nullptr);
hb_font_funcs_set_glyph_contour_point_func(sHBFontFuncs,
HBGetContourPoint,
nullptr, nullptr);
hb_font_funcs_set_glyph_h_kerning_func(sHBFontFuncs,
HBGetHKerning,
nullptr, nullptr);
sHBUnicodeFuncs =
hb_unicode_funcs_create(hb_unicode_funcs_get_empty());
hb_unicode_funcs_set_mirroring_func(sHBUnicodeFuncs,
HBGetMirroring,
nullptr, nullptr);
hb_unicode_funcs_set_script_func(sHBUnicodeFuncs, HBGetScript,
nullptr, nullptr);
hb_unicode_funcs_set_general_category_func(sHBUnicodeFuncs,
HBGetGeneralCategory,
nullptr, nullptr);
hb_unicode_funcs_set_combining_class_func(sHBUnicodeFuncs,
HBGetCombiningClass,
nullptr, nullptr);
hb_unicode_funcs_set_eastasian_width_func(sHBUnicodeFuncs,
HBGetEastAsianWidth,
nullptr, nullptr);
hb_unicode_funcs_set_compose_func(sHBUnicodeFuncs,
HBUnicodeCompose,
nullptr, nullptr);
hb_unicode_funcs_set_decompose_func(sHBUnicodeFuncs,
HBUnicodeDecompose,
nullptr, nullptr);
}
if (!mUseFontGetGlyph) {
// get the cmap table and find offset to our subtable
mCmapTable = entry->GetFontTable(TRUETYPE_TAG('c','m','a','p'));
if (!mCmapTable) {
NS_WARNING("failed to load cmap, glyphs will be missing");
return false;
}
uint32_t len;
const uint8_t* data = (const uint8_t*)hb_blob_get_data(mCmapTable, &len);
bool symbol;
mCmapFormat = gfxFontUtils::
FindPreferredSubtable(data, len,
&mSubtableOffset, &mUVSTableOffset,
&symbol);
}
if (!mUseFontGlyphWidths) {
// if font doesn't implement GetGlyphWidth, we will be reading
// the hmtx table directly;
// read mNumLongMetrics from hhea table without caching its blob,
// and preload/cache the hmtx table
gfxFontEntry::AutoTable hheaTable(entry, TRUETYPE_TAG('h','h','e','a'));
if (hheaTable) {
uint32_t len;
const HMetricsHeader* hhea =
reinterpret_cast<const HMetricsHeader*>
(hb_blob_get_data(hheaTable, &len));
if (len >= sizeof(HMetricsHeader)) {
mNumLongMetrics = hhea->numberOfHMetrics;
if (mNumLongMetrics > 0 &&
int16_t(hhea->metricDataFormat) == 0) {
// no point reading hmtx if number of entries is zero!
// in that case, we won't be able to use this font
// (this method will return FALSE below if mHmtx is null)
mHmtxTable =
entry->GetFontTable(TRUETYPE_TAG('h','m','t','x'));
if (hb_blob_get_length(mHmtxTable) <
mNumLongMetrics * sizeof(HLongMetric)) {
// hmtx table is not large enough for the claimed
// number of entries: invalid, do not use.
hb_blob_destroy(mHmtxTable);
mHmtxTable = nullptr;
}
}
}
}
}
mHBFont = hb_font_create(mHBFace);
hb_font_set_funcs(mHBFont, sHBFontFuncs, &mCallbackData, nullptr);
hb_font_set_ppem(mHBFont, mFont->GetAdjustedSize(), mFont->GetAdjustedSize());
uint32_t scale = FloatToFixed(mFont->GetAdjustedSize()); // 16.16 fixed-point
hb_font_set_scale(mHBFont, scale, scale);
}
if ((!mUseFontGetGlyph && mCmapFormat <= 0) ||
(!mUseFontGlyphWidths && !mHmtxTable)) {
// unable to shape with this font
return false;
}
@ -958,7 +945,6 @@ gfxHarfBuzzShaper::ShapeText(gfxContext *aContext,
nsAutoTArray<hb_feature_t,20> features;
nsDataHashtable<nsUint32HashKey,uint32_t> mergedFeatures;
gfxFontEntry *entry = mFont->GetFontEntry();
if (MergeFontFeatures(style,
entry->mFeatureSettings,
aShapedText->DisableLigatures(),

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

@ -24,7 +24,6 @@ public:
gfxContext *mContext;
};
bool Initialize();
virtual bool ShapeText(gfxContext *aContext,
const char16_t *aText,
uint32_t aOffset,
@ -43,11 +42,6 @@ public:
hb_position_t GetGlyphHAdvance(gfxContext *aContext,
hb_codepoint_t glyph) const;
// get harfbuzz horizontal advance in 16.16 fixed point format.
static hb_position_t
HBGetGlyphHAdvance(hb_font_t *font, void *font_data,
hb_codepoint_t glyph, void *user_data);
hb_position_t GetHKerning(uint16_t aFirstGlyph,
uint16_t aSecondGlyph) const;

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

@ -1,459 +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/. */
#include "gfxMathTable.h"
#include "MathTableStructures.h"
#include "harfbuzz/hb.h"
#include <algorithm>
using namespace mozilla;
gfxMathTable::gfxMathTable(hb_blob_t* aMathTable)
: mMathTable(aMathTable)
, mGlyphConstruction(nullptr)
, mGlyphID(-1)
, mVertical(false)
{
}
gfxMathTable::~gfxMathTable()
{
hb_blob_destroy(mMathTable);
}
bool
gfxMathTable::HasValidHeaders()
{
const char* mathData = hb_blob_get_data(mMathTable, nullptr);
// Verify the MATH table header.
if (!ValidStructure(mathData, sizeof(MATHTableHeader))) {
return false;
}
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;
}
int32_t
gfxMathTable::GetMathConstant(gfxFontEntry::MathConstant aConstant)
{
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;
}
uint32_t
gfxMathTable::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
uint16_t aSize)
{
// Select the glyph construction.
SelectGlyphConstruction(aGlyphID, aVertical);
if (!mGlyphConstruction) {
return 0;
}
// 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);
}
bool
gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4])
{
// Get the glyph assembly corresponding to that (aGlyphID, aVertical) pair.
const GlyphAssembly* glyphAssembly = GetGlyphAssembly(aGlyphID, aVertical);
if (!glyphAssembly) {
return false;
}
// 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);
// 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
// github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
//
// The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
// aGlyphs[1] and aGlyphs[2]) and the extenders between these pieces should
// all be the same (aGlyphs[4]). Also, the parts of vertical assembly are
// stored from bottom to top in the Open Type MATH table while they are
// stored from top to bottom in nsMathMLChar.
// 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)) {
nonExtenderCount++;
}
}
if (nonExtenderCount > 3) {
// Not supported: too many pieces
return false;
}
// Now browse the list of pieces
// 0 = look for a left/bottom glyph
// 1 = look for an extender between left/bottom and mid
// 2 = look for a middle glyph
// 3 = look for an extender between middle and right/top
// 4 = look for a right/top glyph
// 5 = no more piece expected
uint8_t state = 0;
// 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;
if ((state == 1 || state == 2) && nonExtenderCount < 3) {
// do not try to find a middle glyph
state += 2;
}
if (isExtender) {
if (!extenderChar) {
extenderChar = glyph;
aGlyphs[3] = extenderChar;
} else if (extenderChar != glyph) {
// Not supported: different extenders
return false;
}
if (state == 0) { // or state == 1
// ignore left/bottom piece and multiple successive extenders
state = 1;
} else if (state == 2) { // or state == 3
// ignore middle piece and multiple successive extenders
state = 3;
} else if (state >= 4) {
// Not supported: unexpected extender
return false;
}
continue;
}
if (state == 0) {
// copy left/bottom part
aGlyphs[mVertical ? 2 : 0] = glyph;
state = 1;
continue;
}
if (state == 1 || state == 2) {
// copy middle part
aGlyphs[1] = glyph;
state = 3;
continue;
}
if (state == 3 || state == 4) {
// copy right/top part
aGlyphs[mVertical ? 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);
}
int32_t
gfxMathTable::GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph)
{
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);
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);
uint32_t imin = 0, imax = count;
while (imin < imax) {
uint32_t imid = (imin + imax) >> 1;
uint16_t glyphMid = glyphArray[imid];
if (glyphMid == aGlyph) {
return imid;
}
if (glyphMid < aGlyph) {
imin = imid + 1;
} else {
imax = imid;
}
}
}
} else if (uint16_t(aCoverage->mFormat) == 2) {
// Coverage Format 2: ranges of consecutive indices.
const CoverageFormat2* table =
reinterpret_cast<const CoverageFormat2*>(aCoverage);
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);
uint32_t imin = 0, imax = count;
while (imin < imax) {
uint32_t imid = (imin + imax) >> 1;
uint16_t rStart = rangeArray[imid].mStart;
uint16_t rEnd = rangeArray[imid].mEnd;
if (rEnd < aGlyph) {
imin = imid + 1;
} else if (aGlyph < rStart) {
imax = imid;
} else {
return (uint16_t(rangeArray[imid].mStartCoverageIndex) +
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);
}

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

@ -1,122 +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/. */
#ifndef GFX_MATH_TABLE_H
#define GFX_MATH_TABLE_H
#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.
*/
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.
*/
gfxMathTable(hb_blob_t* aMathTable);
/**
* Releases our reference to the MATH table and cleans up everything else.
*/
~gfxMathTable();
/**
* Returns the value of the specified constant from the MATH table.
*/
int32_t GetMathConstant(gfxFontEntry::MathConstant aConstant);
/**
* If the MATH table contains an italic correction for that glyph, this
* function gets the value and returns true. Otherwise it returns false.
*/
bool
GetMathItalicsCorrection(uint32_t aGlyphID, int16_t* aItalicCorrection);
/**
* @param aGlyphID glyph index of the character we want to stretch
* @param aVertical direction of the stretching (vertical/horizontal)
* @param aSize the desired size variant
*
* 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);
/**
* @param aGlyphID glyph index of the character we want to stretch
* @param aVertical direction of the stretching (vertical/horizontal)
* @param aGlyphs pre-allocated buffer of 4 elements where the glyph
* indexes (or 0 for absent parts) will be stored. The parts are stored in
* the order expected by the nsMathMLChar: Top (or Left), Middle, Bottom
* (or Right), Glue.
*
* Tries to fill-in aGlyphs with the relevant glyph indexes and returns
* whether the operation was successful. The function returns false if
* there is not any assembly for the character we want to stretch or if
* the format is not supported by the nsMathMLChar code.
*
*/
bool GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
uint32_t aGlyphs[4]);
protected:
friend class gfxFontEntry;
// This allows gfxFontEntry to verify the validity of the main headers
// before starting to use the MATH table.
bool HasValidHeaders();
private:
// HarfBuzz blob where the MATH table is stored.
hb_blob_t* mMathTable;
// 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);
};
#endif

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

@ -1624,7 +1624,10 @@ gfxFcFont::ShapeText(gfxContext *aContext,
if (!ok) {
if (!mHarfBuzzShaper) {
gfxFT2LockedFace face(this);
mHarfBuzzShaper = new gfxHarfBuzzShaper(this);
// Used by gfxHarfBuzzShaper, currently only for kerning
mFUnitsConvFactor = face.XScale();
}
ok = mHarfBuzzShaper->ShapeText(aContext, aText, aOffset, aLength,
aScript, aShapedText);

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

@ -26,7 +26,6 @@ EXPORTS += [
'gfxGradientCache.h',
'gfxImageSurface.h',
'gfxLineSegment.h',
'gfxMathTable.h',
'gfxMatrix.h',
'gfxPath.h',
'gfxPattern.h',
@ -236,7 +235,6 @@ UNIFIED_SOURCES += [
'gfxGraphiteShaper.cpp',
'gfxHarfBuzzShaper.cpp',
'gfxImageSurface.cpp',
'gfxMathTable.cpp',
'gfxMatrix.cpp',
'gfxPath.cpp',
'gfxPattern.cpp',

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

@ -11,9 +11,9 @@
# each font. Do not include the Unicode table in this list.
%ifdef XP_WIN
font.mathfont-glyph-tables = MathJax_Main, STIXNonUnicode, STIXSizeOneSym, Standard Symbols L, Symbol
font.mathfont-glyph-tables = MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXSize1, Asana Math, Standard Symbols L, Symbol
%else
font.mathfont-glyph-tables = MathJax_Main, STIXNonUnicode, STIXSizeOneSym, Standard Symbols L
font.mathfont-glyph-tables = MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXSize1, Asana Math, Standard Symbols L
%endif
# The ordered list of fonts with which to attempt to stretch MathML

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

@ -0,0 +1,145 @@
# 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/.
# LOCALIZATION NOTE: FILE
# Do not translate anything in this file
# This file contains the list of some stretchy MathML chars that
# can be rendered with Asana Math font.
# [ T/L | M | B/R | G | size0 ... size{N-1} ]
# (*) not in the MathML operator dictionary
\u0028 = \u239B\uFFFD\u239D\u239C\u0028\uDBFF\uDFF4\uDBFF\uDFF5\uDBFF\uDFF6 # (
\u0029 = \u239E\uFFFD\u23A0\u239F\u0029\uDBFF\uDFF7\uDBFF\uDFF8\uDBFF\uDFF9 # )
\u005B = \u23A1\uFFFD\u23A3\u23A2\u005B\uDBFF\uDFEE\uDBFF\uDFEF\uDBFF\uDFF0 # [
\u005D = \u23A4\uFFFD\u23A6\u23A5\u005D\uDBFF\uDFF1\uDBFF\uDFF2\uDBFF\uDFF3 # ]
\u007B = \u23A7\u23A8\u23A9\u23AA\u007B\uDBFF\uDFFA\uDBFF\uDFFB\uDBFF\uDFFC # {
\u007C = \uFFFD\uFFFD\uFFFD\u007C\u007C\uDBFF\uDFD6\uDBFF\uDFD7\uDBFF\uDFD8\uDBFF\uDFD9 # |
\u007D = \u23AB\u23AC\u23AD\u23AA\u007D\uDBFF\uDFFD\uDBFF\uDFFE\uDBFF\uDFFF # }
\u2016 = \uFFFD\uFFFD\uFFFD\uDBFF\uDFD1\u2016\uDBFF\uDFCE\uDBFF\uDFCF\uDBFF\uDFD0\uDBFF\uDFD1 # DOUBLE VERTICAL LINE
\u2044 = \uFFFD\uFFFD\uFFFD\uFFFD\u2044\uDBFF\uDFD2\uDBFF\uDFD3\uDBFF\uDFD4\uDBFF\uDFD5 # FRACTION SLASH
# \u2045 = \uDBFF\uDFB6\uDBFF\uDF53\uDBFF\uDFB7\uDBFF\uDFBA\u2045\uDBFF\uDFBB\uDBFF\uDFBC\uDBFF\uDFBD # LEFT SQUARE BRACKET WITH QUILL (*)
# \u2046 = \uDBFF\uDFB8\uDBFF\uDF54\uDBFF\uDFB9\uDBFF\uDF52\u2046\uDBFF\uDFBE\uDBFF\uDFBF\uDBFF\uDFC0 # RIGHT SQUARE BRACKET WITH QUILL (*)
\u2191 = \u2191\uFFFD\uFFFD\uDBFF\uDEC6\u2191 # UPWARDS ARROW
\u2193 = \uFFFD\uFFFD\u2193\uDBFF\uDEC6\u2193 # DOWNWARDS ARROW
\u21D1 = \u21D1\uFFFD\uFFFD\uDBFF\uDEC7\u21D1 # UPWARDS DOUBLE ARROW
\u21D3 = \uFFFD\uFFFD\u21D3\uDBFF\uDEC7\u21D3 # DOWNWARDS DOUBLE ARROW
\u220F = \uFFFD\uFFFD\uFFFD\uFFFD\u220F\uDBFF\uDF9F\uDBFF\uDFA0\uDBFF\uDFA1 # N-ARY PRODUCT
\u2210 = \uFFFD\uFFFD\uFFFD\uFFFD\u2210\uDBFF\uDFA2\uDBFF\uDFA3\uDBFF\uDFA4 # N-ARY COPRODUCT
\u2211 = \uFFFD\uFFFD\uFFFD\uFFFD\u2211\uDBFF\uDF9C\uDBFF\uDF9D\uDBFF\uDF9E # summation N-ARY SUMMATION
\u221A = \uDBFF\uDF6D\uFFFD\u23B7\u20D3\u221A\uDBFF\uDF6E\uDBFF\uDF6F\uDBFF\uDF70\uDBFF\uDF71 # SQUARE ROOT
\u2223 = \uFFFD\uFFFD\uFFFD\u2223\u2223 # DIVIDES
\u2225 = \uFFFD\uFFFD\uFFFD\u2225\u2225 # PARALLEL TO
\u222B = \u2320\uFFFD\u2321\u23AE\u222B\uDBFF\uDF99\uDBFF\uDF9A\uDBFF\uDF9B # INTEGRAL
\u222C = \uFFFD\uFFFD\uFFFD\uFFFD\u222C\uDBFF\uDF6A\uDBFF\uDF6B\uDBFF\uDF6C # DOUBLE INTEGRAL
\u222D = \uFFFD\uFFFD\uFFFD\uFFFD\u222D\uDBFF\uDF67\uDBFF\uDF68\uDBFF\uDF69 # TRIPLE INTEGRAL
\u222E = \uFFFD\uFFFD\uFFFD\uFFFD\u222E\uDBFF\uDF64\uDBFF\uDF65\uDBFF\uDF66 # CONTOUR INTEGRAL
\u222F = \uFFFD\uFFFD\uFFFD\uFFFD\u222F\uDBFF\uDF61\uDBFF\uDF62\uDBFF\uDF63 # SURFACE INTEGRAL
\u2230 = \uFFFD\uFFFD\uFFFD\uFFFD\u2230\uDBFF\uDF5E\uDBFF\uDF5F\uDBFF\uDF60 # VOLUME INTEGRAL
\u2231 = \uFFFD\uFFFD\uFFFD\uFFFD\u2231\uDBFF\uDF5B\uDBFF\uDF5C\uDBFF\uDF5D # CLOCKWISE INTEGRAL
\u2232 = \uFFFD\uFFFD\uFFFD\uFFFD\u2232\uDBFF\uDF58\uDBFF\uDF59\uDBFF\uDF5A # CLOCKWISE CONTOUR INTEGRAL
\u2233 = \uFFFD\uFFFD\uFFFD\uFFFD\u2233\uDBFF\uDF55\uDBFF\uDF56\uDBFF\uDF57 # ANTICLOCKWISE CONTOUR INTEGRAL
\u22C0 = \uFFFD\uFFFD\uFFFD\uFFFD\u22C0\uDBFF\uDF92\uDBFF\uDF93 # N-ARY LOGICAL AND
\u22C1 = \uFFFD\uFFFD\uFFFD\uFFFD\u22C1\uDBFF\uDF94\uDBFF\uDF95 # N-ARY LOGICAL OR
\u22C2 = \uFFFD\uFFFD\uFFFD\uFFFD\u22C2\uDBFF\uDF8E\uDBFF\uDF8F # N-ARY INTERSECTION
\u22C3 = \uFFFD\uFFFD\uFFFD\uFFFD\u22C3\uDBFF\uDF8C\uDBFF\uDF8D # N-ARY UNION
\u2308 = \u23A1\uFFFD\uFFFD\u23A2\u2308\uDBFF\uDFE2\uDBFF\uDFE3\uDBFF\uDFE4 # LEFT CEILING
\u2309 = \u23A4\uFFFD\uFFFD\u23A5\u2309\uDBFF\uDFE5\uDBF\uDFE6\uDBFF\uDFE7 # RIGHT CEILING
\u230A = \uFFFD\uFFFD\u23A3\u23A2\u230A\uDBFF\uDFE8\uDBFF\uDFE9\uDBFF\uDFEA # LEFT FLOOR
\u230B = \uFFFD\uFFFD\u23A6\u23A5\u230B\u230B\uDBFF\uDFEB\uDBFF\uDFEC\uDBFF\uDFED # RIGHT FLOOR
# \u27C5 = \uFFFD\uFFFD\uFFFD\uFFFD\u27C5\uDBFF\uDDF3\uDBFF\uDDF5\uDBFF\uDDF7\uDBFF\uDDF9\uDBFF\uDDFB # LEFT S-SHAPED BAG DELIMITER (*)
# \u27C6 = \uFFFD\uFFFD\uFFFD\uFFFD\uDBFF\uDDF4\uDBFF\uDDF6\uDBFF\uDDF8\uDBFF\uDDFA\uDBFF\uDDFC # RIGHT S-SHAPED BAG DELIMITER (*)
\u27E6 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E6\uDBFF\uDFDA\uDBFF\uDFDB\uDBFF\uDFDC\uDBFF\uDFDD # MATHEMATICAL LEFT WHITE SQUARE BRACKET
\u27E7 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E7\uDBFF\uDFDE\uDBFF\uDFDF\uDBFF\uDFE0\uDBFF\uDFE1 # MATHEMATICAL RIGHT WHITE SQUARE BRACKET
\u27E8 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E8\uDBFF\uDF89\uDBFF\uDF8A\uDBFF\uD8B # MATHEMATICAL LEFT ANGLE BRACKET
\u27E9 = \uFFFD\uFFFD\uFFFD\uFFFD\u27E9\uDBFF\uDF7C\uDBFF\uDF7D\uDBFF\uDF7E # MATHEMATICAL RIGHT ANGLE BRACKET
\u27EA = \uFFFD\uFFFD\uFFFD\uFFFD\u27EA\uDBFF\uDF76\uDBFF\uDF77\uDBFF\uDF78 # MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
\u27EB = \uFFFD\uFFFD\uFFFD\uFFFD\u27EB\uDBFF\uDF79\uDBFF\uDF7A\uDBFF\uDF7B # MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
\u29FC = \uFFFD\uFFFD\uFFFD\uFFFD\u29FC\uDBFF\uDEC8\uDBFF\uDEC9\uDBFF\uDECA # LEFT-POINTING CURVED ANGLE BRACKET
\u29FD = \uFFFD\uFFFD\uFFFD\uFFFD\u29FD\uDBFF\uDECB\uDBFF\uDECC\uDBFF\uDECD # RIGHT-POINTING CURVED ANGLE BRACKET
\u2A00 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A00\uDBFF\uDF96\uDBFF\uDF97 # N-ARY CIRCLED DOT OPERATOR
\u2A01 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A01\uDBFF\uDF98\uDBFF\uDFA5 # N-ARY CIRCLED PLUS OPERATOR
\u2A02 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A02\uDBFF\uDF7F\uDBFF\uDF80 # N-ARY CIRCLED TIMES OPERATOR
\u2A03 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A03\uDBFF\uDF81\uDBFF\uDF82 # N-ARY UNION OPERATOR WITH DOT
\u2A04 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A04\uDBFF\uDF90\uDBFF\uDF91 # N-ARY UNION OPERATOR WITH PLUS
\u2A05 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A05\uDBFF\uDF83\uDBFF\uDF84 # N-ARY SQUARE INTERSECTION OPERATOR
\u2A06 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A06\uDBFF\uDF85\uDBFF\uDF86 # N-ARY SQUARE UNION OPERATOR
\u2A07 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A07\uDBFF\uDF72\uDBFF\uDF73 # TWO LOGICAL AND OPERATOR
\u2A08 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A08\uDBFF\uDF74\uDBFF\uDF75 # TWO LOGICAL OR OPERATOR
\u2A09 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A09\uDBFF\uDF87\uDBFF\uDF88 # N-ARY TIMES OPERATOR
\u2A0C = \uFFFD\uFFFD\uFFFD\uFFFD\u2A0C\uDBFF\uDF1F\uDBFF\uDF20\uDBFF\uDF21 # QUADRUPLE INTEGRAL OPERATOR
\u2A0D = \uFFFD\uFFFD\uFFFD\uFFFD\u2A0D\uDBFF\uDF22\uDBFF\uDF23\uDBFF\uDF24 # FINITE PART INTEGRAL
\u2A0E = \uFFFD\uFFFD\uFFFD\uFFFD\u2A0E\uDBFF\uDF25\uDBFF\uDF26\uDBFF\uDF27 # INTEGRAL WITH DOUBLE STROKE
\u2A0F = \uFFFD\uFFFD\uFFFD\uFFFD\u2A0F\uDBFF\uDF28\uDBFF\uDF29\uDBFF\uDF2A # INTEGRAL AVERAGE WITH SLASH
\u2A10 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A10\uDBFF\uDF2B\uDBFF\uDF2C\uDBFF\uDF2D # CIRCULATION FUNCTION
\u2A11 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A11\uDBFF\uDF2E\uDBFF\uDF2F\uDBFF\uDF30 # ANTICLOCKWISE INTEGRATION
\u2A12 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A12\uDBFF\uDF31\uDBFF\uDF32\uDBFF\uDF33 # LINE INTEGRATION WITH RECTANGULAR PATH AROUND POLE
\u2A13 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A13\uDBFF\uDF34\uDBFF\uDF35\uDBFF\uDF36 # LINE INTEGRATION WITH SEMICIRCULAR PATH AROUND POLE
\u2A14 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A14\uDBFF\uDF37\uDBFF\uDF38\uDBFF\uDF39 # LINE INTEGRATION NOT INCLUDING THE POLE
\u2A15 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A15\uDBFF\uDF3A\uDBFF\uDF3B\uDBFF\uDF3C # INTEGRAL AROUND A POINT OPERATOR
\u2A16 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A16\uDBFF\uDF3D\uDBFF\uDF3E\uDBFF\uDF3F # QUATERNION INTEGRAL OPERATOR
\u2A17 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A17\uDBFF\uDF40\uDBFF\uDF41\uDBFF\uDF42 # INTEGRAL WITH LEFTWARDS ARROW WITH HOOK
\u2A18 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A18\uDBFF\uDF43\uDBFF\uDF44\uDBFF\uDF45 # INTEGRAL WITH TIMES SIGN
\u2A19 = \uFFFD\uFFFD\uFFFD\uFFFD\u2A19\uDBFF\uDF46\uDBFF\uDF47\uDBFF\uDF48 # INTEGRAL WITH INTERSECTION
\u2A1A = \uFFFD\uFFFD\uFFFD\uFFFD\u2A1A\uDBFF\uDF49\uDBFF\uDF4A\uDBFF\uDF4B # INTEGRAL WITH UNION
\u2A1B = \uFFFD\uFFFD\uFFFD\uFFFD\u2A1B\uDBFF\uDF4C\uDBFF\uDF4D\uDBFF\uDF4E # INTEGRAL WITH OVERBAR
\u2A1C = \uFFFD\uFFFD\uFFFD\uFFFD\u2A1C\uDBFF\uDF4F\uDBFF\uDF50\uDBFF\uDF51 # INTEGRAL WITH UNDERBAR
\u005E = \uFFFD\uFFFD\uFFFD\uFFFD\u005E\uDBFF\uDFA6\uDBFF\uDFA7\uDBFF\uDFA8 # CIRCUMFLEX ACCENT
\u0302 = \uFFFD\uFFFD\uFFFD\uFFFD\u005E\uDBFF\uDFA6\uDBFF\uDFA7\uDBFF\uDFA8 # COMBINING CIRCUMFLEX ACCENT
\u007E = \uFFFD\uFFFD\uFFFD\uFFFD\u007E\uDBFF\uDFAA\uDBFF\uDFAB\uDBFF\uDFAC\uDBFF\uDFAD # TILDE
\u02DC = \uFFFD\uFFFD\uFFFD\uFFFD\u007E\uDBFF\uDFAA\uDBFF\uDFAB\uDBFF\uDFAC\uDBFF\uDFAD # SMALL TILDE
# \u0303 = \uFFFD\uFFFD\uFFFD\uFFFD\u007E\uDBFF\uDFAA\uDBFF\uDFAB\uDBFF\uDFAC\uDBFF\uDFAD # COMBINING TILDE (*)
# \u0305 = \uFFFD\uFFFD\uFFFD\uDBFF\uDF1E\u0305 COMBINING OVERLINE (*)
# \u0306 = \uFFFD\uFFFD\uFFFD\uFFFD\u02D8\uDBFF\uDFB2\uDBFF\uDFB3\uDBFF\uDFB4\uDBFF\uDFB5 # COMBINING BREVE (*)
# \u02D8 = \uFFFD\uFFFD\uFFFD\uFFFD\u02D8\uDBFF\uDFB2\uDBFF\uDFB3\uDBFF\uDFB4\uDBFF\uDFB5 # BREVE (not stretchy)
\u02C7 = \uFFFD\uFFFD\uFFFD\uFFFD\u02C7\uDBFF\uDFAE\uDBFF\uDFAF\uDBFF\uDFB0\uDBFF\uDFB1 # CARON
# \u030C = \uFFFD\uFFFD\uFFFD\uFFFD\u02C7\uDBFF\uDFAE\uDBFF\uDFAF\uDBFF\uDFB0\uDBFF\uDFB1 # COMBINING CARON (*)
# \u0332 = \uFFFD\uFFFD\uFFFD\uDBFF\uDF1D\u0332\uDBFF\uDF1D\uDBFF\uDF18\uDBFF\uDF14 # COMBINING LOW LINE (*)
# \u0333 = \uFFFD\uFFFD\uFFFD\uDBFF\uDF1C\u0333\uDBFF\uDF1C\uDBFF\uDF17\uDBFF\uDF13 # COMBINING DOUBLE LOW LINE (*)
# \u033F = \uFFFD\uFFFD\uFFFD\uDBFF\uDF1B\u033F\uDBFF\uDF1B\uDBFF\uDF16\uDBFF\uDF12 # COMBINING DOUBLE OVERLINE (*)
# \u20D0 = \u20D0\uFFFD\uFFFD\uDBFF\uDF1A\u20D0 # COMBINING LEFT HARPOON ABOVE (*)
# \u20D1 = \uFFFD\uFFFD\u20D1\uDBFF\uDF1A\u20D1 # COMBINING RIGHT HARPOON ABOVE (*)
# \u20D6 = \u20D6\uFFFD\uFFFD\uDBFF\uDF1A\u20D6\uDBFF\uDE4A\uDBFF\uDE4B\uDBFF\uDE4C\uDBFF\uDE4D # COMBINING LEFT ARROW ABOVE (*)
# \u20D7 = \uFFFD\uFFFD\u20D7\uDBFF\uDF1A\u20D7\uDBFF\uDE4E\uDBFF\uDE4F\uDBFF\uDE50\uDBFF\uDE51 # COMBINING RIGHT ARROW ABOVE (*)
# \u20E1 = \u20D6\uFFFD\u20D7\uDBFF\uDF1A\u20E1 # COMBINING LEFT RIGHT ARROW ABOVE (*)
# \u20E9 = \uDBFF\uDEEC\uFFFD\uDBFF\uDEED\uDBFF\uDEEB\u20E9 # COMBINING WIDE BRIDGE ABOVE (*)
\u2190 = \uDBFF\uDF11\uFFFD\uDBFF\uDF10\u23AF\u2190 # LEFTWARDS ARROW
\u2192 = \uDBFF\uDF0E\uFFFD\uDBFF\uDF0F\u23AF\u2192 # RIGHTWARDS ARROW
\u2194 = \uDBFF\uDF11\uFFFD\uDBFF\uDF0F\u23AF\u2194 # LEFT RIGHT ARROW
\u21A4 = \uDBFF\uDF11\uFFFD\uDBFF\uDF08\u23AF\u21A4 # LEFTWARDS ARROW FROM BAR
\u21A6 = \uDBFF\uDF07\uFFFD\uDBFF\uDF0F\u23AF\u21A6 # RIGHTWARDS ARROW FROM BAR
\u21A9 = \uDBFF\uDF11\uFFFD\uDBFF\uDF06\u23AF\u21A9 # LEFTWARDS ARROW WITH HOOK
\u21AA = \uDBFF\uDF05\uFFFD\uDBFF\uDF0F\u23AF\u21AA # RIGHTWARDS ARROW WITH HOOK
\u21D0 = \uDBFF\uDF0D\uFFFD\uDBFF\uDF0C\uDBFF\uDF09\u21D0 # LEFTWARDS DOUBLE ARROW
\u21D2 = \uDBFF\uDF0A\uFFFD\uDBFF\uDF0B\uDBFF\uDF09\u21D2 # RIGHTWARDS DOUBLE ARROW
\u21D4 = \uDBFF\uDF0D\uFFFD\uDBFF\uDF0B\uDBFF\uDF09\u21D4 # LEFT RIGHT DOUBLE ARROW
\u23B4 = \uDBFF\uDEEC\uFFFD\uDBFF\uDEED\uDBFF\uDEEB\u23B4\uDBFF\uDEFD\uDBFF\uDEFE\uDBFF\uDEFF # TOP SQUARE BRACKET
\u23B5 = \uDBFF\uDEEE\uFFFD\uDBFF\uDEEF\uDBFF\uDEEA\u23B5\uDBFF\uDF00\uDBFF\uDF01\uDBFF\uDF02 # BOTTOM SQUARE BRACKET
\u23DC = \uDBFF\uDFC7\uFFFD\uDBFF\uDFC9\uDBFF\uDFCA\u23DC\uDBFF\uDEF7\uDBFF\uDEF8\uDBFF\uDEF9 # TOP PARENTHESIS
\uFE35 = \uDBFF\uDFC7\uFFFD\uDBFF\uDFC9\uDBFF\uDFCA\u23DC\uDBFF\uDEF7\uDBFF\uDEF8\uDBFF\uDEF9 # &OverParenthesis; (MathML 2.0)
\u23DD = \uDBFF\uDFCB\uFFFD\uDBFF\uDFCD\uDBFF\uDEF0\u23DD\uDBFF\uDEFA\uDBFF\uDEFB\uDBFF\uDEFC # BOTTOM PARENTHESIS
\uFE36 = \uDBFF\uDFCB\uFFFD\uDBFF\uDFCD\uDBFF\uDEF0\u23DD\uDBFF\uDEFA\uDBFF\uDEFB\uDBFF\uDEFC # &UnderParenthesis; (MathML 2.0)
\u23DE = \uDBFF\uDFC7\uDBFF\uDFC8\uDBFF\uDFC9\uDBFF\uDFCA\u23DE\uDBFF\uDFC1\uDBFF\uDFC2\uDBFF\uDFC3 # TOP CURLY BRACKET
\uFE37 = \uDBFF\uDFC7\uDBFF\uDFC8\uDBFF\uDFC9\uDBFF\uDFCA\u23DE\uDBFF\uDFC1\uDBFF\uDFC2\uDBFF\uDFC3 # &OverBrace; (MathML 2.0)
\u23DF = \uDBFF\uDFCB\uDBFF\uDFCC\uDBFF\uDFCD\uDBFF\uDEF0\u23DF\uDBFF\uDFC4\uDBFF\uDFC5\uDBFF\uDFC6 # BOTTOM CURLY BRACKET
\uFE38 = \uDBFF\uDFCB\uDBFF\uDFCC\uDBFF\uDFCD\uDBFF\uDEF0\u23DF\uDBFF\uDFC4\uDBFF\uDFC5\uDBFF\uDFC6 # &UnderBrace; (MathML 2.0)
\u23E0 = \uFFFD\uFFFD\uFFFD\uFFFD\u23E0\uDBFF\uDEF1\uDBFF\uDEF2\uDBFF\uDEF3 # TOP TORTOISE SHELL BRACKET
\u23E1 = \uFFFD\uFFFD\uFFFD\uFFFD\u23E1\uDBFF\uDEF4\uDBFF\uDEF5\uDBFF\uDEF6 # BOTTOM TORTOISE SHELL BRACKET
\u2906 = \uDBFF\uDF0D\uFFFD\uDBFF\uDF04\uDBFF\uDF09\u2906 # LEFTWARDS DOUBLE ARROW FROM BAR
\u2907 = \uDBFF\uDF03\uFFFD\uDBFF\uDF0B\uDBFF\uDF09\u2907 # RIGHTWARDS DOUBLE ARROW FROM BAR

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

@ -0,0 +1,70 @@
# 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/.
# LOCALIZATION NOTE: FILE
# Do not translate anything in this file
# This file contains the list of some stretchy MathML chars that
# can be rendered with STIXSize* set of fonts,
# with some help from STIXNonUnicode and STIXGeneral.
external.1 = STIXNonUnicode
external.2 = STIXSize2
external.3 = STIXSize3
external.4 = STIXSize4
external.5 = STIXSize5
external.6 = STIXGeneral
# [ T/L | M | B/R | G | size0 ... size{N-1} ]
\u0028 = \u239B\uFFFD\u239D\u239C\uFFFD((@2(@3(@4 # (
\u0029 = \u239E\uFFFD\u23A0\u239F\uFFFD))@2)@3)@4 # )
\u005B = \u23A1\uFFFD\u23A3\u23A2\u005B[[@2[@3[@4 # [
\u005D = \u23A4\uFFFD\u23A6\u23A5\u005D]]@2]@3]@4 # ]
\u007B = \u23A7\u23A8\u23A9\u23AA\u007B{{@2{@3{@4 # {
\u007D = \u23AB\u23AC\u23AD\u23AA\u007D}}@2}@3}@4 # }
# N-ARY operators
\u2140 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2140 # DOUBLE-STRUCK N-ARY SUMMATION
\u220F = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u220F # N-ARY PRODUCT
\u2210 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2210 # N-ARY COPRODUCT
\u2211 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2211 # N-ARY SUMMATION
\u22C0 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u22C0 # N-ARY LOGICAL AND
\u22C1 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u22C1 # N-ARY LOGICAL OR
\u22C2 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u22C2 # N-ARY INTERSECTION
\u22C3 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u22C3 # N-ARY UNION
\u2A00 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A00 # N-ARY CIRCLED DOT OPERATOR
\u2A01 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A01 # N-ARY CIRCLED PLUS OPERATOR
\u2A02 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A02 # N-ARY CIRCLED TIMES OPERATOR
\u2A03 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A03 # N-ARY UNION OPERATOR WITH DOT
\u2A04 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A04 # N-ARY UNION OPERATOR WITH PLUS
\u2A05 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A05 # N-ARY SQUARE INTERSECTION OPERATOR
\u2A06 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A06 # N-ARY SQUARE UNION OPERATOR
\u2A09 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2A09 # N-ARY TIMES OPERATOR
\u2AFF = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u2AFF # N-ARY WHITE VERTICAL BAR
# E000 stix-radical symbol vertical extender
# E001 stix-radical symbol top corner
\u221A = \uE001@1\uFFFD\u221A@4\uE000@1\uFFFD\u221A\u221A@2\u221A@3 # Sqrt, radic
\u222B = \u2320\uFFFD\u2321\u23AE\uFFFD\u222B@6 # Integral, int
\u27E8 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u27E8\u27E8@2\u27E8@3\u27E8@4 # LeftAngleBracket
\u27E9 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u27E9\u27E9@2\u27E9@3\u27E9@4 # RightAngleBracket
\u23DE = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DE\u23DE@2\u23DE@3\u23DE@4\u23DE@5 # &OverBrace; (Unicode)
\uFE37 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DE\u23DE@2\u23DE@3\u23DE@4\u23DE@5 # &OverBrace; (MathML 2.0)
\u23B4 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23B4\u23B4@2\u23B4@3\u23B4@4\u23B4@5 # &OverBracket;
\u23DC = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DC\u23DC@2\u23DC@3\u23DC@4\u23DC@5 # &OverParenthesis; (Unicode)
\uFE35 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DC\u23DC@2\u23DC@3\u23DC@4\u23DC@5 # &OverParenthesis; (MathML 2.0)
\u23DF = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DF\u23DF@2\u23DF@3\u23DF@4\u23DF@5 # &UnderBrace; (Unicode)
\uFE38 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DF\u23DF@2\u23DF@3\u23DF@4\u23DF@5 # &UnderBrace; (MathML 2.0)
\u23B5 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23B5\u23B5@2\u23B5@3\u23B5@4\u23B5@5 # &UnderBracket;
\u23DD = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DD\u23DD@2\u23DD@3\u23DD@4\u23DD@5 # &UnderParenthesis; (Unicode)
\uFE36 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u23DD\u23DD@2\u23DD@3\u23DD@4\u23DD@5 # &UnderParenthesis; (MathML 2.0)
\u005E = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0302\u0302@2\u0302@3\u0302@4\u0302@5 # circumflex accent, COMBINING CIRCUMFLEX ACCENT
\u02C6 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0302\u0302@2\u0302@3\u0302@4\u0302@5 # modifier letter circumflex accent, COMBINING CIRCUMFLEX ACCENT
\u007E = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0303\u0303@2\u0303@3\u0303@4\u0303@5 # ~ tilde, COMBINING TILDE
\u02DC = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u0303\u0303@2\u0303@3\u0303@4\u0303@5 # small tilde, COMBINING TILDE
\u02C7 = \uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\u030C\u030C@2\u030C@3\u030C@4\u030C@5 # caron, COMBINING CARON

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

@ -55,9 +55,11 @@ JAR_MANIFESTS += ['jar.mn']
RESOURCE_FILES.fonts += [
'mathfont.properties',
'mathfontAsanaMath.properties',
'mathfontMathJax_Main.properties',
'mathfontStandardSymbolsL.properties',
'mathfontSTIXNonUnicode.properties',
'mathfontSTIXSize1.properties',
'mathfontSTIXSizeOneSym.properties',
'mathfontUnicode.properties',
]

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

@ -28,15 +28,10 @@
#include "nsMathMLOperators.h"
#include <algorithm>
#include "gfxMathTable.h"
using namespace mozilla;
//#define NOISY_SEARCH 1
static const float kLargeOpFactor = float(M_SQRT2);
static const float kIntegralFactor = 2.0;
// -----------------------------------------------------------------------------
static const nsGlyphCode kNullGlyph = {{{0, 0}}, 0};
typedef enum {eExtension_base, eExtension_variants, eExtension_parts}
@ -46,59 +41,16 @@ typedef enum {eExtension_base, eExtension_variants, eExtension_parts}
// nsGlyphTable is a class that provides an interface for accessing glyphs
// of stretchy chars. It acts like a table that stores the variants of bigger
// sizes (if any) and the partial glyphs needed to build extensible symbols.
// An instance of nsGlyphTable is associated to one primary font. Extra glyphs
// can be taken in other additional fonts when stretching certain characters.
// These supplementary fonts are referred to as "external" fonts to the table.
//
// Bigger sizes (if any) of the char can then be retrieved with BigOf(...).
// Partial glyphs can be retrieved with ElementAt(...).
// Bigger sizes (if any) of the char can then be retrieved with
// BigOf(aSize). Partial glyphs can be retrieved with ElementAt()
//
// A table consists of "nsGlyphCode"s which are viewed either as Unicode
// points (for nsPropertiesTable) or as direct glyph indices (for
// nsOpenTypeTable)
// -----------------------------------------------------------------------------
class nsGlyphTable {
public:
virtual ~nsGlyphTable() {}
virtual const nsAString&
FontNameFor(const nsGlyphCode& aGlyphCode) const = 0;
// Getters for the parts
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aPosition) = 0;
virtual nsGlyphCode BigOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aSize) = 0;
// True if this table contains parts to render this char
virtual bool HasPartsOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical) = 0;
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph) = 0;
protected:
nsGlyphTable() : mCharCache(0) {}
// For speedy re-use, we always cache the last data used in the table.
// mCharCache is the Unicode point of the last char that was queried in this
// table.
char16_t mCharCache;
};
// An instance of nsPropertiesTable is associated with one primary font. Extra
// glyphs can be taken in other additional fonts when stretching certain
// characters.
// These supplementary fonts are referred to as "external" fonts to the table.
// points or as direct glyph indices, depending on the type of the table.
// XXX The latter is not yet supported.
// General format of MathFont Property Files from which glyph data are
// retrieved:
@ -115,6 +67,9 @@ protected:
// with the UNICODE REPLACEMENT CHARACTER 0xFFFD.
// -----------------------------------------------------------------------------
#define NS_TABLE_TYPE_UNICODE 0
#define NS_TABLE_TYPE_GLYPH_INDEX 1
#define NS_TABLE_STATE_ERROR -1
#define NS_TABLE_STATE_EMPTY 0
#define NS_TABLE_STATE_READY 1
@ -143,19 +98,23 @@ LoadProperties(const nsString& aName,
NS_ConvertUTF16toUTF8(uriStr));
}
class nsPropertiesTable MOZ_FINAL : public nsGlyphTable {
// -----------------------------------------------------------------------------
class nsGlyphTable {
public:
explicit nsPropertiesTable(const nsString& aPrimaryFontName)
: mFontName(1) // ensure space for primary font name.
, mState(NS_TABLE_STATE_EMPTY)
explicit nsGlyphTable(const nsString& aPrimaryFontName)
: mFontName(1), // ensure space for primary font name.
mState(NS_TABLE_STATE_EMPTY),
mCharCache(0)
{
MOZ_COUNT_CTOR(nsPropertiesTable);
MOZ_COUNT_CTOR(nsGlyphTable);
mFontName.AppendElement(aPrimaryFontName);
}
~nsPropertiesTable()
// not a virtual destructor: this class is not intended to be subclassed
~nsGlyphTable()
{
MOZ_COUNT_DTOR(nsPropertiesTable);
MOZ_COUNT_DTOR(nsGlyphTable);
}
const nsAString& PrimaryFontName() const
@ -163,52 +122,29 @@ public:
return mFontName[0];
}
const nsAString&
FontNameFor(const nsGlyphCode& aGlyphCode) const MOZ_OVERRIDE
const nsAString& FontNameFor(const nsGlyphCode& aGlyphCode) const
{
NS_ASSERTION(!aGlyphCode.IsGlyphID(),
"nsPropertiesTable can only access glyphs by code point");
"nsGlyphTable can only access glyphs by Unicode code point");
return mFontName[aGlyphCode.font];
}
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aPosition) MOZ_OVERRIDE;
virtual nsGlyphCode BigOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aSize) MOZ_OVERRIDE
{
return ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup,
aChar, aVertical, 4 + aSize);
// Getters for the parts
nsGlyphCode ElementAt(char16_t aChar, uint32_t aPosition);
nsGlyphCode BigOf(char16_t aChar, int32_t aSize) {
return ElementAt(aChar, 4 + aSize);
}
virtual bool HasPartsOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical) MOZ_OVERRIDE
{
return (ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup,
aChar, aVertical, 0).Exists() ||
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup,
aChar, aVertical, 1).Exists() ||
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup,
aChar, aVertical, 2).Exists() ||
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup,
aChar, aVertical, 3).Exists());
// True if this table contains parts to render this char
bool HasPartsOf(char16_t aChar) {
return (ElementAt(aChar, 0).Exists() || ElementAt(aChar, 1).Exists() ||
ElementAt(aChar, 2).Exists() || ElementAt(aChar, 3).Exists());
}
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph) MOZ_OVERRIDE;
gfxTextRun* MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph);
private:
// mFontName[0] is the primary font associated to this table. The others
@ -223,9 +159,10 @@ private:
// File
nsCOMPtr<nsIPersistentProperties> mGlyphProperties;
// mGlyphCache is a buffer containing the glyph data associated with
// mCharCache.
// For a property line 'key = value' in the MathFont Property File,
// For speedy re-use, we always cache the last data used in the table.
// mCharCache is the Unicode point of the last char that was queried in this
// table. mGlyphCache is a buffer containing the glyph data associated to
// that char. For a property line 'key = value' in the MathFont Property File,
// mCharCache will retain the 'key' -- which is a Unicode point, while
// mGlyphCache will retain the 'value', which is a consecutive list of
// nsGlyphCodes, i.e., the pairs of 'code@font' needed by the char -- in
@ -241,16 +178,11 @@ private:
// table. Other digits map to the "external" fonts that may have been
// specified in the MathFont Property File.
nsString mGlyphCache;
char16_t mCharCache;
};
/* virtual */
nsGlyphCode
nsPropertiesTable::ElementAt(gfxContext* /* aThebesContext */,
int32_t /* aAppUnitsPerDevPixel */,
gfxFontGroup* /* aFontGroup */,
char16_t aChar,
bool /* aVertical */,
uint32_t aPosition)
nsGlyphTable::ElementAt(char16_t aChar, uint32_t aPosition)
{
if (mState == NS_TABLE_STATE_ERROR) return kNullGlyph;
// Load glyph properties if this is the first time we have been here
@ -354,206 +286,18 @@ nsPropertiesTable::ElementAt(gfxContext* /* aThebesContext */,
return ch.code[0] == char16_t(0xFFFD) ? kNullGlyph : ch;
}
/* virtual */
gfxTextRun*
nsPropertiesTable::MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph)
nsGlyphTable::MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph)
{
NS_ASSERTION(!aGlyph.IsGlyphID(),
"nsPropertiesTable can only access glyphs by code point");
NS_ASSERTION(!aGlyph.IsGlyphID(), "not yet implemented");
return aFontGroup->
MakeTextRun(aGlyph.code, aGlyph.Length(), aThebesContext,
aAppUnitsPerDevPixel, 0);
}
// An instance of nsOpenTypeTable is associated with one gfxFontEntry that
// corresponds to an Open Type font with a MATH table. All the glyphs come from
// the same font and the calls to access size variants and parts are directly
// forwarded to the gfx code.
class nsOpenTypeTable MOZ_FINAL : public nsGlyphTable {
public:
~nsOpenTypeTable()
{
MOZ_COUNT_DTOR(nsOpenTypeTable);
}
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aPosition) MOZ_OVERRIDE;
virtual nsGlyphCode BigOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aSize) MOZ_OVERRIDE;
virtual bool HasPartsOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical) MOZ_OVERRIDE;
const nsAString&
FontNameFor(const nsGlyphCode& aGlyphCode) const MOZ_OVERRIDE {
NS_ASSERTION(aGlyphCode.IsGlyphID(),
"nsOpenTypeTable can only access glyphs by id");
return mFontEntry->FamilyName();
}
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph) MOZ_OVERRIDE;
// This returns a new OpenTypeTable instance to give access to OpenType MATH
// table or nullptr if the font does not have such table. Ownership is passed
// to the caller.
static nsOpenTypeTable* Create(gfxFont* aFont)
{
if (!aFont->GetFontEntry()->TryGetMathTable(aFont)) {
return nullptr;
}
return new nsOpenTypeTable(aFont->GetFontEntry());
}
private:
nsRefPtr<gfxFontEntry> mFontEntry;
uint32_t mGlyphID;
explicit nsOpenTypeTable(gfxFontEntry* aFontEntry)
: mFontEntry(aFontEntry) {
MOZ_COUNT_CTOR(nsOpenTypeTable);
}
void UpdateCache(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar);
};
void
nsOpenTypeTable::UpdateCache(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar)
{
if (mCharCache != aChar) {
nsAutoPtr<gfxTextRun> textRun;
textRun = aFontGroup->
MakeTextRun(&aChar, 1, aThebesContext, aAppUnitsPerDevPixel, 0);
const gfxTextRun::CompressedGlyph& data = textRun->GetCharacterGlyphs()[0];
if (data.IsSimpleGlyph()) {
mGlyphID = data.GetSimpleGlyph();
} else if (data.GetGlyphCount() == 1) {
mGlyphID = textRun->GetDetailedGlyphs(0)->mGlyphID;
} else {
mGlyphID = 0;
}
mCharCache = aChar;
}
}
/* virtual */
nsGlyphCode
nsOpenTypeTable::ElementAt(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aPosition)
{
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t parts[4];
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) {
return kNullGlyph;
}
uint32_t glyphID = parts[aPosition];
if (!glyphID) {
return kNullGlyph;
}
nsGlyphCode glyph;
glyph.glyphID = glyphID;
glyph.font = -1;
return glyph;
}
/* virtual */
nsGlyphCode
nsOpenTypeTable::BigOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical,
uint32_t aSize)
{
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t glyphID =
mFontEntry->GetMathVariantsSize(mGlyphID, aVertical, aSize);
if (!glyphID) {
return kNullGlyph;
}
nsGlyphCode glyph;
glyph.glyphID = glyphID;
glyph.font = -1;
return glyph;
}
/* virtual */
bool
nsOpenTypeTable::HasPartsOf(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
char16_t aChar,
bool aVertical)
{
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar);
uint32_t parts[4];
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) {
return false;
}
return parts[0] || parts[1] || parts[2] || parts[3];
}
/* virtual */
gfxTextRun*
nsOpenTypeTable::MakeTextRun(gfxContext* aThebesContext,
int32_t aAppUnitsPerDevPixel,
gfxFontGroup* aFontGroup,
const nsGlyphCode& aGlyph)
{
NS_ASSERTION(aGlyph.IsGlyphID(),
"nsOpenTypeTable can only access glyphs by id");
gfxTextRunFactory::Parameters params = {
aThebesContext, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
};
gfxTextRun* textRun = gfxTextRun::Create(&params, 1, aFontGroup, 0);
textRun->AddGlyphRun(aFontGroup->GetFontAt(0), gfxTextRange::kFontGroup, 0,
false);
gfxTextRun::DetailedGlyph detailedGlyph;
detailedGlyph.mGlyphID = aGlyph.glyphID;
detailedGlyph.mAdvance =
NSToCoordRound(aAppUnitsPerDevPixel *
aFontGroup->GetFontAt(0)->
GetGlyphHAdvance(aThebesContext, aGlyph.glyphID));
detailedGlyph.mXOffset = detailedGlyph.mYOffset = 0;
gfxShapedText::CompressedGlyph g;
g.SetComplex(true, true, 1);
textRun->SetGlyphs(0, g, &detailedGlyph);
return textRun;
}
// -----------------------------------------------------------------------------
// This is the list of all the applicable glyph tables.
// We will maintain a single global instance that will only reveal those
@ -567,7 +311,7 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
nsPropertiesTable mUnicodeTable;
nsGlyphTable mUnicodeTable;
nsGlyphTableList()
: mUnicodeTable(NS_LITERAL_STRING("Unicode"))
@ -592,14 +336,15 @@ public:
GetGlyphTableFor(const nsAString& aFamily);
private:
nsPropertiesTable* PropertiesTableAt(int32_t aIndex) {
return &mPropertiesTableList.ElementAt(aIndex);
nsGlyphTable* TableAt(int32_t aIndex) {
return &mTableList.ElementAt(aIndex);
}
int32_t PropertiesTableCount() {
return mPropertiesTableList.Length();
int32_t Count() {
return mTableList.Length();
}
// List of glyph tables;
nsTArray<nsPropertiesTable> mPropertiesTableList;
nsTArray<nsGlyphTable> mTableList;
};
NS_IMPL_ISUPPORTS1(nsGlyphTableList, nsIObserver)
@ -660,15 +405,15 @@ nsGlyphTableList::AddGlyphTable(const nsString& aPrimaryFontName)
return glyphTable;
// allocate a table
glyphTable = mPropertiesTableList.AppendElement(aPrimaryFontName);
glyphTable = mTableList.AppendElement(aPrimaryFontName);
return glyphTable;
}
nsGlyphTable*
nsGlyphTableList::GetGlyphTableFor(const nsAString& aFamily)
{
for (int32_t i = 0; i < PropertiesTableCount(); i++) {
nsPropertiesTable* glyphTable = PropertiesTableAt(i);
for (int32_t i = 0; i < Count(); i++) {
nsGlyphTable* glyphTable = TableAt(i);
const nsAString& fontName = glyphTable->PrimaryFontName();
// TODO: would be nice to consider StripWhitespace and other aliasing
if (fontName.Equals(aFamily, nsCaseInsensitiveStringComparator())) {
@ -1185,12 +930,8 @@ public:
EnumCallback(const nsString& aFamily, bool aGeneric, void *aData);
private:
bool TryVariants(nsGlyphTable* aGlyphTable,
nsRefPtr<gfxFontGroup>* aFontGroup,
const nsAString& aFamily);
bool TryParts(nsGlyphTable* aGlyphTable,
nsRefPtr<gfxFontGroup>* aFontGroup,
const nsAString& aFamily);
bool TryVariants(nsGlyphTable* aGlyphTable, const nsAString& aFamily);
bool TryParts(nsGlyphTable* aGlyphTable, const nsAString& aFamily);
nsMathMLChar* mChar;
nsPresContext* mPresContext;
@ -1216,10 +957,8 @@ private:
// Returns true if the size is OK, false to keep searching.
// Always updates the char if a better match is found.
bool
nsMathMLChar::
StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
nsRefPtr<gfxFontGroup>* aFontGroup,
const nsAString& aFamily)
nsMathMLChar::StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
const nsAString& aFamily)
{
// Use our stretchy style context now that stretching is in progress
nsStyleContext *sc = mChar->mStyleContext;
@ -1228,8 +967,6 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
font.name.Truncate();
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL);
nscoord oneDevPixel = mPresContext->AppUnitsPerDevPixel();
char16_t uchar = mChar->mData[0];
bool largeop = (NS_STRETCH_LARGEOP & mStretchHint) != 0;
bool largeopOnly =
largeop && (NS_STRETCH_VARIABLE_MASK & mStretchHint) == 0;
@ -1242,49 +979,17 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
// start at size = 1 (size = 0 is the char at its normal size)
int32_t size = 1;
nsGlyphCode ch;
nscoord displayOperatorMinHeight = 0;
if (largeopOnly) {
NS_ASSERTION(isVertical, "Stretching should be in the vertical direction");
ch = aGlyphTable->BigOf(mThebesContext, oneDevPixel, *aFontGroup, uchar,
isVertical, 0);
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font,
aFontGroup)) {
return false;
}
gfxFont* mathFont = aFontGroup->get()->GetFontAt(0);
if (mathFont->GetFontEntry()->TryGetMathTable(mathFont)) {
// For OpenType MATH fonts, we will rely on the DisplayOperatorMinHeight
// to select the right size variant. Note that the value is sometimes too
// small so we use kLargeOpFactor/kIntegralFactor as a minimum value.
displayOperatorMinHeight =
NSToCoordRound(mathFont->GetFontEntry()->
GetMathConstant(gfxFontEntry::DisplayOperatorMinHeight) *
mathFont->GetAdjustedSize() * oneDevPixel);
nsAutoPtr<gfxTextRun> textRun;
textRun = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel,
*aFontGroup, ch);
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun);
float largeopFactor = kLargeOpFactor;
if (NS_STRETCH_INTEGRAL & mStretchHint) {
// integrals are drawn taller
largeopFactor = kIntegralFactor;
}
nscoord minHeight = largeopFactor * (bm.ascent + bm.descent);
if (displayOperatorMinHeight < minHeight) {
displayOperatorMinHeight = minHeight;
}
}
}
#ifdef NOISY_SEARCH
printf(" searching in %s ...\n",
NS_LossyConvertUTF16toASCII(aFamily).get());
#endif
while ((ch = aGlyphTable->BigOf(mThebesContext, oneDevPixel, *aFontGroup,
uchar, isVertical, size)).Exists()) {
nsGlyphCode ch;
nsRefPtr<gfxFontGroup> fontGroup;
while ((ch = aGlyphTable->BigOf(mChar->mData[0], size)).Exists()) {
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font,
aFontGroup)) {
&fontGroup)) {
// if largeopOnly is set, break now
if (largeopOnly) break;
++size;
@ -1292,31 +997,10 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
}
nsAutoPtr<gfxTextRun> textRun;
textRun = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel,
*aFontGroup, ch);
textRun = aGlyphTable->MakeTextRun(mThebesContext,
mPresContext->AppUnitsPerDevPixel(),
fontGroup, ch);
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun);
if (ch.IsGlyphID()) {
gfxFont* mathFont = aFontGroup->get()->GetFontAt(0);
if (mathFont->GetFontEntry()->TryGetMathTable(mathFont)) {
// MeasureTextRun should have set the advance width to the right
// bearing for OpenType MATH fonts. We now subtract the italic
// correction, so that nsMathMLmmultiscripts will place the scripts
// correctly.
// 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)) {
bm.width -=
NSToCoordRound(italicCorrection *
mathFont->GetAdjustedSize() * oneDevPixel);
if (bm.width < 0) {
bm.width = 0;
}
}
}
}
nscoord charSize =
isVertical ? bm.ascent + bm.descent
@ -1356,10 +1040,8 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
break; // Not making an futher progress, stop searching
}
// If this a largeop only operator, we stop if the glyph is large enough.
if (largeopOnly && (bm.ascent + bm.descent) >= displayOperatorMinHeight) {
break;
}
// if largeopOnly is set, break now
if (largeopOnly) break;
++size;
}
@ -1372,10 +1054,14 @@ StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable,
// Returns true if the size is OK, false to keep searching.
// Always updates the char if a better match is found.
bool
nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable,
nsRefPtr<gfxFontGroup>* aFontGroup,
nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable,
const nsAString& aFamily)
{
if (!aGlyphTable->HasPartsOf(mChar->mData[0]))
return false; // to next table
// See if the parts of this table fit in the desired space //////////////////
// Use our stretchy style context now that stretching is in progress
nsFont font = mChar->mStyleContext->StyleFont()->mFont;
// Ensure SetFontFamily will set the font
@ -1388,24 +1074,20 @@ nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable,
nscoord sizedata[4];
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL);
nscoord oneDevPixel = mPresContext->AppUnitsPerDevPixel();
char16_t uchar = mChar->mData[0];
bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0;
if (!aGlyphTable->HasPartsOf(mThebesContext, oneDevPixel, *aFontGroup,
uchar, isVertical))
return false; // to next table
nsRefPtr<gfxFontGroup> fontGroup;
for (int32_t i = 0; i < 4; i++) {
nsGlyphCode ch = aGlyphTable->ElementAt(mThebesContext, oneDevPixel,
*aFontGroup, uchar, isVertical, i);
nsGlyphCode ch = aGlyphTable->ElementAt(mChar->mData[0], i);
chdata[i] = ch;
if (ch.Exists()) {
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font,
aFontGroup))
&fontGroup))
return false;
textRun[i] = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel,
*aFontGroup, ch);
textRun[i] = aGlyphTable->MakeTextRun(mThebesContext,
mPresContext->AppUnitsPerDevPixel(),
fontGroup, ch);
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun[i]);
// TODO: For the generic Unicode table, ideally we should check that the
@ -1525,6 +1207,15 @@ nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily,
{
StretchEnumContext* context = static_cast<StretchEnumContext*>(aData);
// See if there is a special table for the family, but always use the
// Unicode table for generic fonts.
nsGlyphTable* glyphTable = aGeneric ?
&gGlyphTableList->mUnicodeTable :
gGlyphTableList->GetGlyphTableFor(aFamily);
if (context->mTablesTried.Contains(glyphTable))
return true; // already tried this one
// Check font family if it is not a generic one
// We test with the kNullGlyph
nsStyleContext *sc = context->mChar->mStyleContext;
@ -1535,31 +1226,10 @@ nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily,
font, &fontGroup))
return true; // Could not set the family
// Determine the glyph table to use for this font.
nsAutoPtr<nsOpenTypeTable> openTypeTable;
nsGlyphTable* glyphTable;
if (aGeneric) {
// This is a generic font, use the Unicode table.
glyphTable = &gGlyphTableList->mUnicodeTable;
} else {
// If the font contains an Open Type MATH table, use it.
openTypeTable = nsOpenTypeTable::Create(fontGroup->GetFontAt(0));
if (openTypeTable) {
glyphTable = openTypeTable;
} else {
// Otherwise try to find a .properties file corresponding to that font
// family or fallback to the Unicode table.
glyphTable = gGlyphTableList->GetGlyphTableFor(aFamily);
}
}
// Now see if the table has a glyph that matches the container
if (!openTypeTable) {
if (context->mTablesTried.Contains(glyphTable))
return true; // already tried this one
// Only try this table once.
context->mTablesTried.AppendElement(glyphTable);
}
// Only try this table once.
context->mTablesTried.AppendElement(glyphTable);
// If the unicode table is being used, then search all font families. If a
// special table is being used then the font in this family should have the
@ -1567,9 +1237,8 @@ nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily,
const nsAString& family = glyphTable == &gGlyphTableList->mUnicodeTable ?
context->mFamilies : aFamily;
if((context->mTryVariants &&
context->TryVariants(glyphTable, &fontGroup, family)) ||
(context->mTryParts && context->TryParts(glyphTable, &fontGroup, family)))
if((context->mTryVariants && context->TryVariants(glyphTable, family)) ||
(context->mTryParts && context->TryParts(glyphTable, family)))
return false; // no need to continue
return true; // true means continue
@ -1805,7 +1474,7 @@ nsMathMLChar::StretchInternal(nsPresContext* aPresContext,
// apply a scale transform to the base char.
if (!glyphFound && largeop) {
float scale;
float largeopFactor = kLargeOpFactor;
float largeopFactor = float(M_SQRT2);
// increase the width if it is not largeopFactor times larger
// than the initial one.
@ -1826,7 +1495,7 @@ nsMathMLChar::StretchInternal(nsPresContext* aPresContext,
// than the initial one.
if (NS_STRETCH_INTEGRAL & aStretchHint) {
// integrals are drawn taller
largeopFactor = kIntegralFactor;
largeopFactor = 2.0;
}
if ((aDesiredStretchSize.ascent + aDesiredStretchSize.descent) <
largeopFactor * (initialSize.ascent + initialSize.descent)) {

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

@ -199,8 +199,6 @@ public:
protected:
friend class nsGlyphTable;
friend class nsPropertiesTable;
friend class nsOpenTypeTable;
nsString mData;
private:

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

@ -1,6 +0,0 @@
The fonts in this directory are autogenerated with FontForge using the Python
script generate.py. See the comments in that file for more information on how
to run the script.
These fonts are intended to test the The MATH table and OpenType Features used
in MathML. See layout/reftests/mathml/

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

@ -1,231 +0,0 @@
#!/usr/bin/python
# vim: set shiftwidth=4 tabstop=8 autoindent expandtab:
# 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/.
# For general fontforge documentation, see:
# http://fontforge.sourceforge.net/
# For fontforge scripting documentation, see:
# http://fontforge.sourceforge.net/scripting-tutorial.html
# http://fontforge.sourceforge.net/scripting.html
# and most importantly:
# http://fontforge.sourceforge.net/python.html
# To install what you need, on Ubuntu,
# sudo apt-get install python-fontforge
from __future__ import print_function
import fontforge
em = 1000
def newMathFont(aName):
print("Generating %s.otf..." % aName, end="")
mathFont = fontforge.font()
mathFont.fontname = aName
mathFont.familyname = aName
mathFont.fullname = aName
mathFont.copyright = "Copyright (c) 2014 Mozilla Corporation"
mathFont.encoding = "UnicodeFull"
# Create a space character. Also force the creation of some MATH subtables
# so that OTS will not reject the MATH table.
g = mathFont.createChar(ord(" "), "space")
g.width = em
g.italicCorrection = 0
g.topaccent = 0
g.mathKern.bottomLeft = tuple([(0,0)])
g.mathKern.bottomRight = tuple([(0,0)])
g.mathKern.topLeft = tuple([(0,0)])
g.mathKern.topRight = tuple([(0,0)])
mathFont[ord(" ")].horizontalVariants = "space"
mathFont[ord(" ")].verticalVariants = "space"
return mathFont
def saveMathFont(aFont):
aFont.em = em
aFont.ascent = aFont.descent = em/2
aFont.hhea_ascent = aFont.os2_typoascent = aFont.os2_winascent = em/2
aFont.descent = aFont.hhea_descent = em/2
aFont.os2_typodescent = aFont.os2_windescent = em/2
aFont.hhea_ascent_add = aFont.hhea_descent_add = 0
aFont.os2_typoascent_add = aFont.os2_typodescent_add = 0
aFont.os2_winascent_add = aFont.os2_windescent_add = 0
aFont.os2_use_typo_metrics = True
aFont.generate(aFont.fontname + ".otf")
print(" done.")
################################################################################
# Glyph variants and constructions
f = newMathFont("stretchy")
nvariants = 3
# Draw boxes for the size variants and glues
for i in range(0, nvariants):
s = em * (i + 1)
g = f.createChar(-1, "h%d" % i)
p = g.glyphPen()
p.moveTo(0, -em)
p.lineTo(0, em)
p.lineTo(s, em)
p.lineTo(s, -em)
p.closePath()
g.width = s
g = f.createChar(-1, "v%d" % i)
p = g.glyphPen()
p.moveTo(0, 0)
p.lineTo(0, s)
p.lineTo(2 * em, s)
p.lineTo(2 * em, 0)
p.closePath();
g.width = 2 * em
# Draw some pieces for stretchy operators
s = em * nvariants
g = f.createChar(-1, "left")
p = g.glyphPen()
p.moveTo(0, -2 * em)
p.lineTo(0, 2 * em)
p.lineTo(s, em)
p.lineTo(s, -em)
p.closePath();
g.width = s
g = f.createChar(-1, "right")
p = g.glyphPen()
p.moveTo(0, -em)
p.lineTo(0, em)
p.lineTo(s, 2 * em)
p.lineTo(s, -2 * em)
p.closePath();
g.width = s
g = f.createChar(-1, "hmid")
p = g.glyphPen()
p.moveTo(0, -em)
p.lineTo(0, em)
p.lineTo(s, 2 * em)
p.lineTo(2 * s, em)
p.lineTo(2 * s, -em)
p.lineTo(s, -2 * em)
p.closePath();
g.width = 2 * s
g = f.createChar(-1, "bottom")
p = g.glyphPen()
p.moveTo(0, 0)
p.lineTo(0, s)
p.lineTo(2 * em, s)
p.lineTo(4 * em, 0)
p.closePath();
g.width = 4 * em
g = f.createChar(-1, "top")
p = g.glyphPen()
p.moveTo(0, 0)
p.lineTo(4 * em, 0)
p.lineTo(2 * em, -s)
p.lineTo(0, -s)
p.closePath();
g.width = 4 * em
g = f.createChar(-1, "vmid")
p = g.glyphPen()
p.moveTo(0, s)
p.lineTo(2 * em, s)
p.lineTo(4 * em, 0)
p.lineTo(2 * em, -s)
p.lineTo(0, -s)
p.closePath();
g.width = 3 * em
# Create small rectangle of various size for some exotic arrows that are
# unlikely to be stretchable with standard fonts.
hstretchy = [
0x219C, # leftwards wave arrow
0x219D, # rightwards wave arrow
0x219E, # leftwards two headed arrow
0x21A0, # rightwards two headed arrow
0x21A2 # leftwards arrow with tail
]
vstretchy = [
0x219F, # upwards two headed arrow
0x21A1, # downwards two headed arrow
0x21A5, # upwards arrow from bar
0x21A7, # downwards arrow from bar
0x21A8 # up down arrow with base
]
for i in range(0, 1 + nvariants + 1):
s = (i + 1) * em/10
g = f.createChar(hstretchy[i])
p = g.glyphPen()
p.moveTo(0, -em/10)
p.lineTo(0, em/10)
p.lineTo(s, em/10)
p.lineTo(s, -em/10)
p.closePath()
g.width = s
g = f.createChar(vstretchy[i])
p = g.glyphPen()
p.moveTo(0, 0)
p.lineTo(0, s)
p.lineTo(2 * em/10, s)
p.lineTo(2 * em/10, 0)
p.closePath();
g.width = 2 * em/10
# hstretchy[0] and vstretchy[0] have all the variants and the components. The others only have one of them.
s = em * nvariants
f[hstretchy[0]].horizontalVariants = "uni219C h0 h1 h2"
f[hstretchy[0]].horizontalComponents = (("left", False, 0, 0, s), \
("h2", True, 0, 0, s), ("hmid", False, 0, 0, 2 * s), ("h2", True, 0, 0, s), \
("right", False, 0, 0, s))
f[hstretchy[1]].horizontalVariants = "uni219D h0"
f[hstretchy[2]].horizontalVariants = "uni219E h1"
f[hstretchy[3]].horizontalVariants = "uni21A0 h2"
f[hstretchy[4]].horizontalVariants = "uni21A2 h2"
f[hstretchy[4]].horizontalComponents = f[hstretchy[0]].horizontalComponents
f[vstretchy[0]].verticalVariants = "uni219F v0 v1 v2"
f[vstretchy[0]].verticalComponents = (("bottom", False, 0, 0, s), \
("v2", True, 0, 0, s), ("vmid", False, 0, 0, 2 * s), ("v2", True, 0, 0, s), \
("top", False, 0, 0, s))
f[vstretchy[1]].verticalVariants = "uni21A1 v0"
f[vstretchy[2]].verticalVariants = "uni21A5 v1"
f[vstretchy[3]].verticalVariants = "uni21A7 v2"
f[vstretchy[4]].verticalVariants = "uni21A8"
f[vstretchy[4]].verticalComponents = f[vstretchy[0]].verticalComponents
################################################################################
# Testing DisplayOperatorMinHeight
f.math.DisplayOperatorMinHeight = 8 * em
largeop = [0x2A1B, 0x2A1C] # integral with overbar/underbar
# Draw boxes of size 1, 2, 7, 8, 9em.
for i in [1, 2, 7, 8, 9]:
s = em * i
if i == 1 or i == 2:
g = f.createChar(largeop[i-1])
else:
g = f.createChar(-1, "L%d" % i)
p = g.glyphPen()
p.moveTo(0, 0)
p.lineTo(0, s)
p.lineTo(s, s)
p.lineTo(s, 0)
p.closePath();
g.width = s
f[largeop[0]].verticalVariants = "uni2A1B L7 L8 L9"
f[largeop[1]].verticalVariants = "uni2A1C L8"
saveMathFont(f)

Двоичные данные
layout/reftests/fonts/math/stretchy.otf

Двоичный файл не отображается.

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

@ -1,73 +0,0 @@
<!doctype html>
<html>
<head>
<title>Open Type MATH - stretchy operator</title>
<meta charset="utf-8"/>
<style type="text/css">
@font-face {
font-family: stretchy;
src: url(../fonts/math/stretchy.otf);
}
math {
font-family: stretchy;
font-size: 10px;
}
::-moz-math-stretchy {
font-family: stretchy;
font-size: 10px;
}
</style>
</head>
<body>
<!--
hstretchy = [
0x219C, # leftwards wave arrow
0x219D, # rightwards wave arrow
0x219E, # leftwards two headed arrow
0x21A0, # rightwards two headed arrow
0x21A2 # leftwards arrow with tail
]
vstretchy = [
0x219F, # upwards two headed arrow
0x21A1, # downwards two headed arrow
0x21A5, # upwards arrow from bar
0x21A7, # downwards arrow from bar
0x21A8 # up down arrow with base
]
hstretchy[0] and vstretchy[0] have all the variants and the components. The others only have one of them.
-->
<p>
<math>
<mstyle scriptsizemultiplier="1">
<mover><mo stretchy="true">&#x219D;</mo><mspace width="1em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x219E;</mo><mspace width="2em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x21A0;</mo><mspace width="3em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x21A2;</mo><mspace width="15em" height="1px" mathbackground="red"/></mover>
</mstyle>
</math>
</p>
<p>
<math><mrow><mo symmetric="false" stretchy="true" minsize="1em">&#x21A1;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="2em">&#x21A5;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="3em">&#x21A7;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="15em">&#x21A8;</mo></mrow></math>
</p>
<!--
DisplayOperatorMinHeight = 8em
largeop = [0x2A1B, 0x2A1C] # integral with overbar/underbar
largeop[0] has variants of size 7, 8, 9em
largeop[1] has one variant of size 8em.
-->
<p>
<math displaystyle="true">
<mrow><mo>&#x2A1C;</mo></mrow>
</math>
</p>
</body>
</html>

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

@ -1,73 +0,0 @@
<!doctype html>
<html>
<head>
<title>Open Type MATH - stretchy operator</title>
<meta charset="utf-8"/>
<style type="text/css">
@font-face {
font-family: stretchy;
src: url(../fonts/math/stretchy.otf);
}
math {
font-family: stretchy;
font-size: 10px;
}
::-moz-math-stretchy {
font-family: stretchy;
font-size: 10px;
}
</style>
</head>
<body>
<!--
hstretchy = [
0x219C, # leftwards wave arrow
0x219D, # rightwards wave arrow
0x219E, # leftwards two headed arrow
0x21A0, # rightwards two headed arrow
0x21A2 # leftwards arrow with tail
]
vstretchy = [
0x219F, # upwards two headed arrow
0x21A1, # downwards two headed arrow
0x21A5, # upwards arrow from bar
0x21A7, # downwards arrow from bar
0x21A8 # up down arrow with base
]
hstretchy[0] and vstretchy[0] have all the variants and the components. The others only have one of them.
-->
<p>
<math>
<mstyle scriptsizemultiplier="1">
<mover><mo stretchy="true">&#x219C;</mo><mspace width="1em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x219C;</mo><mspace width="2em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x219C;</mo><mspace width="3em" height="1px" mathbackground="red"/></mover>
<mover><mo stretchy="true">&#x219C;</mo><mspace width="15em" height="1px" mathbackground="red"/></mover>
</mstyle>
</math>
</p>
<p>
<math><mrow><mo symmetric="false" stretchy="true" minsize="1em">&#x219F;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="2em">&#x219F;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="3em">&#x219F;</mo></mrow></math>
<math><mrow><mo symmetric="false" stretchy="true" minsize="15em">&#x219F;</mo></mrow></math>
</p>
<!--
DisplayOperatorMinHeight = 8em
largeop = [0x2A1B, 0x2A1C] # integral with overbar/underbar
largeop[0] has variants of size 7, 8, 9em
largeop[1] has one variant of size 8em.
-->
<p>
<math displaystyle="true">
<mrow><mo>&#x2A1B;</mo></mrow>
</math>
</p>
</body>
</html>

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

@ -152,7 +152,6 @@ skip-if(B2G) == maction-dynamic-3.html maction-dynamic-3-ref.html # bug 773482
== whitespace-trim-3.html whitespace-trim-3-ref.html
fails == whitespace-trim-4.html whitespace-trim-4-ref.html # Bug 787215
== whitespace-trim-5.html whitespace-trim-5-ref.html
fails-if(winWidget&&!d2d) == opentype-stretchy.html opentype-stretchy-ref.html
== operator-1.xhtml operator-1-ref.xhtml
== scriptshift-1.xhtml scriptshift-1-ref.xhtml
== number-size-1.xhtml number-size-1-ref.xhtml

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

@ -1521,7 +1521,7 @@ pref("intl.hyphenation-alias.no-*", "nb");
pref("intl.hyphenation-alias.nb-*", "nb");
pref("intl.hyphenation-alias.nn-*", "nn");
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Asana Math, Standard Symbols L, DejaVu Sans, Cambria Math");
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXSize1, STIXGeneral, Asana Math, Standard Symbols L, DejaVu Sans, Cambria Math");
// Some CJK fonts have bad underline offset, their CJK character glyphs are overlapped (or adjoined) to its underline.
// These fonts are ignored the underline offset, instead of it, the underline is lowered to bottom of its em descent.
@ -2550,7 +2550,7 @@ pref("font.size.variable.zh-HK", 16);
pref("font.size.fixed.zh-HK", 16);
// We have special support for Monotype Symbol on Windows.
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Asana Math, Symbol, DejaVu Sans, Cambria Math");
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXSize1, STIXGeneral, Asana Math, Symbol, DejaVu Sans, Cambria Math");
// cleartype settings - false implies default system settings
@ -3082,7 +3082,7 @@ pref("font.size.variable.zh-HK", 15);
pref("font.size.fixed.zh-HK", 16);
// Apple's Symbol is Unicode so use it
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXGeneral, Asana Math, Symbol, DejaVu Sans, Cambria Math");
pref("font.mathfont-family", "MathJax_Main, STIXNonUnicode, STIXSizeOneSym, STIXSize1, STIXGeneral, Asana Math, Symbol, DejaVu Sans, Cambria Math");
// individual font faces to be treated as independent families
// names are Postscript names of each face