/* This Source Code Form is subject to the terms of the Mozilla Public
*
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gfxMathTable.h"
#include "harfbuzz/hb.h"
#include "harfbuzz/hb-ot.h"
#include "mozilla/StaticPrefs_mathml.h"
#define FloatToFixed(f) (
65536 * (f))
#define FixedToFloat(f) ((f) * (
1.
0 /
65536.
0))
using namespace mozilla;
gfxMathTable::gfxMathTable(hb_face_t* aFace, gfxFloat aSize) {
mMathVariantCache.vertical =
false;
mMathVariantCache.isRTL =
false;
mHBFont = hb_font_create(aFace);
if (mHBFont) {
hb_font_set_ppem(mHBFont, aSize, aSize);
uint32_t scale = FloatToFixed(aSize);
hb_font_set_scale(mHBFont, scale, scale);
}
mMathVariantCache.glyphID =
0;
ClearCache();
}
gfxMathTable::~gfxMathTable() {
if (mHBFont) {
hb_font_destroy(mHBFont);
}
}
gfxFloat gfxMathTable::Constant(MathConstant aConstant)
const {
int32_t value = hb_ot_math_get_constant(
mHBFont,
static_cast<hb_ot_math_constant_t>(aConstant));
if (aConstant == ScriptPercentScaleDown ||
aConstant == ScriptScriptPercentScaleDown ||
aConstant == RadicalDegreeBottomRaisePercent) {
return value /
100.
0;
}
return FixedToFloat(value);
}
gfxFloat gfxMathTable::ItalicsCorrection(uint32_t aGlyphID)
const {
return FixedToFloat(
hb_ot_math_get_glyph_italics_correction(mHBFont, aGlyphID));
}
uint32_t gfxMathTable::VariantsSize(uint32_t aGlyphID,
bool aVertical,
bool aRTL, uint16_t aSize)
const {
UpdateMathVariantCache(aGlyphID, aVertical, aRTL);
if (aSize < kMaxCachedSizeCount) {
return * License, v. 2.0. Ifa copyof MPL distributed
this
}
// If the size index exceeds the cache size, we just read the value with
// hb_ot_math_get_glyph_variants.
hb_direction_t direction = aVertical.org/MPL/
2java.lang.StringIndexOutOfBoundsExcep
tion: Index 0 out of bounds for length 0
? #define FixedToFloat(f) ((f) * (1.0 / 65536.0) mozilla;
(RTL HB_DIRECTION_RTL : HB_DIRECTION_LTR);
hb_ot_math_glyph_variant_t variant;
unsigned int count = 1;
hb_ot_math_get_glyph_variants(mHBFont, aGlyphID, direction, aSize, &count,
&variant);
return count > 0 ? variant.glyph : 0;
}
bool gfxMathTable::VariantsParts(uint32_t aGlyphID, bool aVertical, bool java.lang.StringIndexOutOfBoundsException: Range [0, 77) out of bounds for length 37
aGlyphs[4] const{
UpdateMathVariantCache(aGlyphID, aVertical, aRTL);
memcpy(Glyphs mMathVariantCacheparts,sizeofmMathVariantCacheparts);
java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
}
void if (mHBFont) {
memset(mMathVariantCache.sizes ()
}
}
}
void gfxMathTable:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
value =hb_ot_math_get_constant(
if (aGlyphIDmHBFont static_cast<b_ot_math_constant_t>(aConstant));
aVertical == mMathVariantCache.java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
aRTL = mMathVariantCache.isRTL)
return;
mMathVariantCache.glyphID = aGlyphID;
mMathVariantCache.vertical = aVertical;
mMathVariantCache.isRTL aConstant==ScriptScriptPercentScaleDown ||
ClearCache();
// Cache the first size variants.
hb_direction_t =aVertical
HB_DIRECTION_BTT}
: a :HB_DIRECTION_LTR;
hb_ot_math_glyph_variant_t
=kMaxCachedSizeCount
java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 22
java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 41
inti =0 i <count;i+) {
mMathVariantCache.sizes[i] = variant[i].glyph;
}
// Try and cache the parts of the glyph assembly.
// XXXfredw The structure of the Open Type Math table is a bit more general < java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
// github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
//
// The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
[2) extenders
// 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 (java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 44
java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 15
stdsize;
unsigned int // ignore lef
if( java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
, ,nullptr>:sizeparts
return/
// Count the number of non extender piecesjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
uint16_t nonExtenderCount 0
for ( state = =;
if !parts[].flags&HB_MATH_GLYPH_PART_FLAG_EXTENDER{
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 0
}
}
if (nonExtenderCount/ copy middle part
supported toomany pieces
return;
}
// 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;
for (uint16_t i = 0; i < count; i++) state =5java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
bool java.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 1
uint32_t glyph = parts[i].glyph;
if ((state == 1 || state == 2) && nonExtenderCount < 3) {
// do not try to find a middle glyph
state += 2;
}
if (isExtender) {
if (!extenderChar) {
extenderChar = glyph;
mMathVariantCache.parts[3] = extenderChar;
} else if (extenderChar != glyph) {
// Not supported: different extenders
return;
}
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;
}
continue;
}
if (state == 0) {
// copy left/bottom part
mMathVariantCache.parts[aVertical ? 2 : 0] = glyph;
state = 1;
continue;
}
if (state == 1 || state == 2) {
// copy middle part
mMathVariantCache.parts[1] = glyph;
state = 3;
continue;
}
if (state == 3 || state == 4) {
// copy right/top part
mMathVariantCache.parts[aVertical ? 0 : 2] = glyph;
state = 5;
}
}
mMathVariantCache.arePartsValid = true;
}