|
|
|
|
| 23 |
#include "nsCSSRendering.h" |
23 |
#include "nsCSSRendering.h" |
| 24 |
#include "prprf.h" // For PR_snprintf() |
24 |
#include "prprf.h" // For PR_snprintf() |
| 25 |
|
25 |
|
| 26 |
#include "nsDisplayList.h" |
26 |
#include "nsDisplayList.h" |
| 27 |
|
27 |
|
| 28 |
#include "nsMathMLOperators.h" |
28 |
#include "nsMathMLOperators.h" |
| 29 |
#include <algorithm> |
29 |
#include <algorithm> |
| 30 |
|
30 |
|
|
|
31 |
#include "gfxMathTable.h" |
| 32 |
|
| 31 |
using namespace mozilla; |
33 |
using namespace mozilla; |
| 32 |
|
34 |
|
| 33 |
//#define NOISY_SEARCH 1 |
35 |
//#define NOISY_SEARCH 1 |
| 34 |
|
36 |
|
|
|
37 |
static const float kLargeOpFactor = float(M_SQRT2); |
| 38 |
static const float kIntegralFactor = 2.0; |
| 39 |
|
| 35 |
// ----------------------------------------------------------------------------- |
40 |
// ----------------------------------------------------------------------------- |
| 36 |
static const nsGlyphCode kNullGlyph = {{{0, 0}}, 0}; |
41 |
static const nsGlyphCode kNullGlyph = {{{0, 0}}, 0}; |
| 37 |
typedef enum {eExtension_base, eExtension_variants, eExtension_parts} |
42 |
typedef enum {eExtension_base, eExtension_variants, eExtension_parts} |
| 38 |
nsMathfontPrefExtension; |
43 |
nsMathfontPrefExtension; |
| 39 |
|
44 |
|
| 40 |
// ----------------------------------------------------------------------------- |
45 |
// ----------------------------------------------------------------------------- |
| 41 |
// nsGlyphTable is a class that provides an interface for accessing glyphs |
46 |
// nsGlyphTable is a class that provides an interface for accessing glyphs |
| 42 |
// of stretchy chars. It acts like a table that stores the variants of bigger |
47 |
// of stretchy chars. It acts like a table that stores the variants of bigger |
| 43 |
// sizes (if any) and the partial glyphs needed to build extensible symbols. |
48 |
// sizes (if any) and the partial glyphs needed to build extensible symbols. |
| 44 |
// An instance of nsGlyphTable is associated to one primary font. Extra glyphs |
|
|
| 45 |
// can be taken in other additional fonts when stretching certain characters. |
| 46 |
// These supplementary fonts are referred to as "external" fonts to the table. |
| 47 |
// |
49 |
// |
| 48 |
// Bigger sizes (if any) of the char can then be retrieved with |
50 |
// Bigger sizes (if any) of the char can then be retrieved with BigOf(...). |
| 49 |
// BigOf(aSize). Partial glyphs can be retrieved with ElementAt() |
51 |
// Partial glyphs can be retrieved with ElementAt(...). |
| 50 |
// |
52 |
// |
| 51 |
// A table consists of "nsGlyphCode"s which are viewed either as Unicode |
53 |
// A table consists of "nsGlyphCode"s which are viewed either as Unicode |
| 52 |
// points or as direct glyph indices, depending on the type of the table. |
54 |
// points (for nsPropertiesTable) or as direct glyph indices (for |
| 53 |
// XXX The latter is not yet supported. |
55 |
// nsOpenTypeTable) |
|
|
56 |
// ----------------------------------------------------------------------------- |
| 57 |
|
| 58 |
class nsGlyphTable { |
| 59 |
public: |
| 60 |
virtual ~nsGlyphTable() {} |
| 61 |
|
| 62 |
virtual const nsAString& |
| 63 |
FontNameFor(const nsGlyphCode& aGlyphCode) const = 0; |
| 64 |
|
| 65 |
// Getters for the parts |
| 66 |
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext, |
| 67 |
int32_t aAppUnitsPerDevPixel, |
| 68 |
gfxFontGroup* aFontGroup, |
| 69 |
char16_t aChar, |
| 70 |
bool aVertical, |
| 71 |
uint32_t aPosition) = 0; |
| 72 |
virtual nsGlyphCode BigOf(gfxContext* aThebesContext, |
| 73 |
int32_t aAppUnitsPerDevPixel, |
| 74 |
gfxFontGroup* aFontGroup, |
| 75 |
char16_t aChar, |
| 76 |
bool aVertical, |
| 77 |
uint32_t aSize) = 0; |
| 78 |
|
| 79 |
// True if this table contains parts to render this char |
| 80 |
virtual bool HasPartsOf(gfxContext* aThebesContext, |
| 81 |
int32_t aAppUnitsPerDevPixel, |
| 82 |
gfxFontGroup* aFontGroup, |
| 83 |
char16_t aChar, |
| 84 |
bool aVertical) = 0; |
| 85 |
|
| 86 |
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext, |
| 87 |
int32_t aAppUnitsPerDevPixel, |
| 88 |
gfxFontGroup* aFontGroup, |
| 89 |
const nsGlyphCode& aGlyph) = 0; |
| 90 |
protected: |
| 91 |
nsGlyphTable() : mCharCache(0) {} |
| 92 |
// For speedy re-use, we always cache the last data used in the table. |
| 93 |
// mCharCache is the Unicode point of the last char that was queried in this |
| 94 |
// table. |
| 95 |
char16_t mCharCache; |
| 96 |
}; |
| 97 |
|
| 98 |
// An instance of nsPropertiesTable is associated with one primary font. Extra |
| 99 |
// glyphs can be taken in other additional fonts when stretching certain |
| 100 |
// characters. |
| 101 |
// These supplementary fonts are referred to as "external" fonts to the table. |
| 54 |
|
102 |
|
| 55 |
// General format of MathFont Property Files from which glyph data are |
103 |
// General format of MathFont Property Files from which glyph data are |
| 56 |
// retrieved: |
104 |
// retrieved: |
| 57 |
// ----------------------------------------------------------------------------- |
105 |
// ----------------------------------------------------------------------------- |
| 58 |
// Each font should have its set of glyph data. For example, the glyph data for |
106 |
// Each font should have its set of glyph data. For example, the glyph data for |
| 59 |
// the "Symbol" font and the "MT Extra" font are in "mathfontSymbol.properties" |
107 |
// the "Symbol" font and the "MT Extra" font are in "mathfontSymbol.properties" |
| 60 |
// and "mathfontMTExtra.properties", respectively. The mathfont property file |
108 |
// and "mathfontMTExtra.properties", respectively. The mathfont property file |
| 61 |
// is a set of all the stretchy MathML characters that can be rendered with that |
109 |
// is a set of all the stretchy MathML characters that can be rendered with that |
| 62 |
// font using larger and/or partial glyphs. The entry of each stretchy character |
110 |
// font using larger and/or partial glyphs. The entry of each stretchy character |
| 63 |
// in the mathfont property file gives, in that order, the 4 partial glyphs: |
111 |
// in the mathfont property file gives, in that order, the 4 partial glyphs: |
| 64 |
// Top (or Left), Middle, Bottom (or Right), Glue; and the variants of bigger |
112 |
// Top (or Left), Middle, Bottom (or Right), Glue; and the variants of bigger |
| 65 |
// sizes (if any). |
113 |
// sizes (if any). |
| 66 |
// A position that is not relevant to a particular character is indicated there |
114 |
// A position that is not relevant to a particular character is indicated there |
| 67 |
// with the UNICODE REPLACEMENT CHARACTER 0xFFFD. |
115 |
// with the UNICODE REPLACEMENT CHARACTER 0xFFFD. |
| 68 |
// ----------------------------------------------------------------------------- |
116 |
// ----------------------------------------------------------------------------- |
| 69 |
|
117 |
|
| 70 |
#define NS_TABLE_TYPE_UNICODE 0 |
|
|
| 71 |
#define NS_TABLE_TYPE_GLYPH_INDEX 1 |
| 72 |
|
| 73 |
#define NS_TABLE_STATE_ERROR -1 |
118 |
#define NS_TABLE_STATE_ERROR -1 |
| 74 |
#define NS_TABLE_STATE_EMPTY 0 |
119 |
#define NS_TABLE_STATE_EMPTY 0 |
| 75 |
#define NS_TABLE_STATE_READY 1 |
120 |
#define NS_TABLE_STATE_READY 1 |
| 76 |
|
121 |
|
| 77 |
// helper to trim off comments from data in a MathFont Property File |
122 |
// helper to trim off comments from data in a MathFont Property File |
| 78 |
static void |
123 |
static void |
| 79 |
Clean(nsString& aValue) |
124 |
Clean(nsString& aValue) |
| 80 |
{ |
125 |
{ |
|
Lines 93-193
LoadProperties(const nsString& aName,
|
Link Here
|
|---|
|
| 93 |
uriStr.AssignLiteral("resource://gre/res/fonts/mathfont"); |
138 |
uriStr.AssignLiteral("resource://gre/res/fonts/mathfont"); |
| 94 |
uriStr.Append(aName); |
139 |
uriStr.Append(aName); |
| 95 |
uriStr.StripWhitespace(); // that may come from aName |
140 |
uriStr.StripWhitespace(); // that may come from aName |
| 96 |
uriStr.AppendLiteral(".properties"); |
141 |
uriStr.AppendLiteral(".properties"); |
| 97 |
return NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(aProperties), |
142 |
return NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(aProperties), |
| 98 |
NS_ConvertUTF16toUTF8(uriStr)); |
143 |
NS_ConvertUTF16toUTF8(uriStr)); |
| 99 |
} |
144 |
} |
| 100 |
|
145 |
|
| 101 |
// ----------------------------------------------------------------------------- |
146 |
class nsPropertiesTable MOZ_FINAL : public nsGlyphTable { |
| 102 |
|
|
|
| 103 |
class nsGlyphTable { |
| 104 |
public: |
147 |
public: |
| 105 |
explicit nsGlyphTable(const nsString& aPrimaryFontName) |
148 |
explicit nsPropertiesTable(const nsString& aPrimaryFontName) |
| 106 |
: mFontName(1), // ensure space for primary font name. |
149 |
: mFontName(1) // ensure space for primary font name. |
| 107 |
mState(NS_TABLE_STATE_EMPTY), |
150 |
, mState(NS_TABLE_STATE_EMPTY) |
| 108 |
mCharCache(0) |
|
|
| 109 |
{ |
151 |
{ |
| 110 |
MOZ_COUNT_CTOR(nsGlyphTable); |
152 |
MOZ_COUNT_CTOR(nsPropertiesTable); |
| 111 |
mFontName.AppendElement(aPrimaryFontName); |
153 |
mFontName.AppendElement(aPrimaryFontName); |
| 112 |
} |
154 |
} |
| 113 |
|
155 |
|
| 114 |
// not a virtual destructor: this class is not intended to be subclassed |
156 |
~nsPropertiesTable() |
| 115 |
~nsGlyphTable() |
|
|
| 116 |
{ |
157 |
{ |
| 117 |
MOZ_COUNT_DTOR(nsGlyphTable); |
158 |
MOZ_COUNT_DTOR(nsPropertiesTable); |
| 118 |
} |
159 |
} |
| 119 |
|
160 |
|
| 120 |
const nsAString& PrimaryFontName() const |
161 |
const nsAString& PrimaryFontName() const |
| 121 |
{ |
162 |
{ |
| 122 |
return mFontName[0]; |
163 |
return mFontName[0]; |
| 123 |
} |
164 |
} |
| 124 |
|
165 |
|
| 125 |
const nsAString& FontNameFor(const nsGlyphCode& aGlyphCode) const |
166 |
const nsAString& |
|
|
167 |
FontNameFor(const nsGlyphCode& aGlyphCode) const MOZ_OVERRIDE |
| 126 |
{ |
168 |
{ |
| 127 |
NS_ASSERTION(!aGlyphCode.IsGlyphID(), |
169 |
NS_ASSERTION(!aGlyphCode.IsGlyphID(), |
| 128 |
"nsGlyphTable can only access glyphs by Unicode code point"); |
170 |
"nsPropertiesTable can only access glyphs by code point"); |
| 129 |
return mFontName[aGlyphCode.font]; |
171 |
return mFontName[aGlyphCode.font]; |
| 130 |
} |
172 |
} |
| 131 |
|
173 |
|
| 132 |
// Getters for the parts |
174 |
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext, |
| 133 |
nsGlyphCode ElementAt(char16_t aChar, uint32_t aPosition); |
175 |
int32_t aAppUnitsPerDevPixel, |
| 134 |
nsGlyphCode BigOf(char16_t aChar, int32_t aSize) { |
176 |
gfxFontGroup* aFontGroup, |
| 135 |
return ElementAt(aChar, 4 + aSize); |
177 |
char16_t aChar, |
|
|
178 |
bool aVertical, |
| 179 |
uint32_t aPosition) MOZ_OVERRIDE; |
| 180 |
|
| 181 |
virtual nsGlyphCode BigOf(gfxContext* aThebesContext, |
| 182 |
int32_t aAppUnitsPerDevPixel, |
| 183 |
gfxFontGroup* aFontGroup, |
| 184 |
char16_t aChar, |
| 185 |
bool aVertical, |
| 186 |
uint32_t aSize) MOZ_OVERRIDE |
| 187 |
{ |
| 188 |
return ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, |
| 189 |
aChar, aVertical, 4 + aSize); |
| 136 |
} |
190 |
} |
| 137 |
|
191 |
|
| 138 |
// True if this table contains parts to render this char |
192 |
virtual bool HasPartsOf(gfxContext* aThebesContext, |
| 139 |
bool HasPartsOf(char16_t aChar) { |
193 |
int32_t aAppUnitsPerDevPixel, |
| 140 |
return (ElementAt(aChar, 0).Exists() || ElementAt(aChar, 1).Exists() || |
194 |
gfxFontGroup* aFontGroup, |
| 141 |
ElementAt(aChar, 2).Exists() || ElementAt(aChar, 3).Exists()); |
195 |
char16_t aChar, |
|
|
196 |
bool aVertical) MOZ_OVERRIDE |
| 197 |
{ |
| 198 |
return (ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, |
| 199 |
aChar, aVertical, 0).Exists() || |
| 200 |
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, |
| 201 |
aChar, aVertical, 1).Exists() || |
| 202 |
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, |
| 203 |
aChar, aVertical, 2).Exists() || |
| 204 |
ElementAt(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, |
| 205 |
aChar, aVertical, 3).Exists()); |
| 142 |
} |
206 |
} |
| 143 |
|
207 |
|
| 144 |
gfxTextRun* MakeTextRun(gfxContext* aThebesContext, |
208 |
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext, |
| 145 |
int32_t aAppUnitsPerDevPixel, |
209 |
int32_t aAppUnitsPerDevPixel, |
| 146 |
gfxFontGroup* aFontGroup, |
210 |
gfxFontGroup* aFontGroup, |
| 147 |
const nsGlyphCode& aGlyph); |
211 |
const nsGlyphCode& aGlyph) MOZ_OVERRIDE; |
| 148 |
private: |
212 |
private: |
| 149 |
|
213 |
|
| 150 |
// mFontName[0] is the primary font associated to this table. The others |
214 |
// mFontName[0] is the primary font associated to this table. The others |
| 151 |
// are possible "external" fonts for glyphs not in the primary font |
215 |
// are possible "external" fonts for glyphs not in the primary font |
| 152 |
// but which are needed to stretch certain characters in the table |
216 |
// but which are needed to stretch certain characters in the table |
| 153 |
nsTArray<nsString> mFontName; |
217 |
nsTArray<nsString> mFontName; |
| 154 |
|
218 |
|
| 155 |
// Tri-state variable for error/empty/ready |
219 |
// Tri-state variable for error/empty/ready |
| 156 |
int32_t mState; |
220 |
int32_t mState; |
| 157 |
|
221 |
|
| 158 |
// The set of glyph data in this table, as provided by the MathFont Property |
222 |
// The set of glyph data in this table, as provided by the MathFont Property |
| 159 |
// File |
223 |
// File |
| 160 |
nsCOMPtr<nsIPersistentProperties> mGlyphProperties; |
224 |
nsCOMPtr<nsIPersistentProperties> mGlyphProperties; |
| 161 |
|
225 |
|
| 162 |
// For speedy re-use, we always cache the last data used in the table. |
226 |
// mGlyphCache is a buffer containing the glyph data associated with |
| 163 |
// mCharCache is the Unicode point of the last char that was queried in this |
227 |
// mCharCache. |
| 164 |
// table. mGlyphCache is a buffer containing the glyph data associated to |
228 |
// For a property line 'key = value' in the MathFont Property File, |
| 165 |
// that char. For a property line 'key = value' in the MathFont Property File, |
|
|
| 166 |
// mCharCache will retain the 'key' -- which is a Unicode point, while |
229 |
// mCharCache will retain the 'key' -- which is a Unicode point, while |
| 167 |
// mGlyphCache will retain the 'value', which is a consecutive list of |
230 |
// mGlyphCache will retain the 'value', which is a consecutive list of |
| 168 |
// nsGlyphCodes, i.e., the pairs of 'code@font' needed by the char -- in |
231 |
// nsGlyphCodes, i.e., the pairs of 'code@font' needed by the char -- in |
| 169 |
// which 'code@0' can be specified |
232 |
// which 'code@0' can be specified |
| 170 |
// without the optional '@0'. However, to ease subsequent processing, |
233 |
// without the optional '@0'. However, to ease subsequent processing, |
| 171 |
// mGlyphCache excludes the '@' symbol and explicitly inserts all optional '0' |
234 |
// mGlyphCache excludes the '@' symbol and explicitly inserts all optional '0' |
| 172 |
// that indicates the primary font identifier. Specifically therefore, the |
235 |
// that indicates the primary font identifier. Specifically therefore, the |
| 173 |
// k-th glyph is characterized by : |
236 |
// k-th glyph is characterized by : |
| 174 |
// 1) mGlyphCache[3*k],mGlyphCache[3*k+1] : its Unicode point |
237 |
// 1) mGlyphCache[3*k],mGlyphCache[3*k+1] : its Unicode point |
| 175 |
// 2) mGlyphCache[3*k+2] : the numeric identifier of the font where it comes |
238 |
// 2) mGlyphCache[3*k+2] : the numeric identifier of the font where it comes |
| 176 |
// from. |
239 |
// from. |
| 177 |
// A font identifier of '0' means the default primary font associated to this |
240 |
// A font identifier of '0' means the default primary font associated to this |
| 178 |
// table. Other digits map to the "external" fonts that may have been |
241 |
// table. Other digits map to the "external" fonts that may have been |
| 179 |
// specified in the MathFont Property File. |
242 |
// specified in the MathFont Property File. |
| 180 |
nsString mGlyphCache; |
243 |
nsString mGlyphCache; |
| 181 |
char16_t mCharCache; |
|
|
| 182 |
}; |
244 |
}; |
| 183 |
|
245 |
|
|
|
246 |
/* virtual */ |
| 184 |
nsGlyphCode |
247 |
nsGlyphCode |
| 185 |
nsGlyphTable::ElementAt(char16_t aChar, uint32_t aPosition) |
248 |
nsPropertiesTable::ElementAt(gfxContext* /* aThebesContext */, |
|
|
249 |
int32_t /* aAppUnitsPerDevPixel */, |
| 250 |
gfxFontGroup* /* aFontGroup */, |
| 251 |
char16_t aChar, |
| 252 |
bool /* aVertical */, |
| 253 |
uint32_t aPosition) |
| 186 |
{ |
254 |
{ |
| 187 |
if (mState == NS_TABLE_STATE_ERROR) return kNullGlyph; |
255 |
if (mState == NS_TABLE_STATE_ERROR) return kNullGlyph; |
| 188 |
// Load glyph properties if this is the first time we have been here |
256 |
// Load glyph properties if this is the first time we have been here |
| 189 |
if (mState == NS_TABLE_STATE_EMPTY) { |
257 |
if (mState == NS_TABLE_STATE_EMPTY) { |
| 190 |
nsresult rv = LoadProperties(mFontName[0], mGlyphProperties); |
258 |
nsresult rv = LoadProperties(mFontName[0], mGlyphProperties); |
| 191 |
#ifdef DEBUG |
259 |
#ifdef DEBUG |
| 192 |
nsAutoCString uriStr; |
260 |
nsAutoCString uriStr; |
| 193 |
uriStr.AssignLiteral("resource://gre/res/fonts/mathfont"); |
261 |
uriStr.AssignLiteral("resource://gre/res/fonts/mathfont"); |
|
Lines 281-322
nsGlyphTable::ElementAt(char16_t aChar,
|
Link Here
|
|---|
|
| 281 |
if (index+2 >= mGlyphCache.Length()) return kNullGlyph; |
349 |
if (index+2 >= mGlyphCache.Length()) return kNullGlyph; |
| 282 |
nsGlyphCode ch; |
350 |
nsGlyphCode ch; |
| 283 |
ch.code[0] = mGlyphCache.CharAt(index); |
351 |
ch.code[0] = mGlyphCache.CharAt(index); |
| 284 |
ch.code[1] = mGlyphCache.CharAt(index + 1); |
352 |
ch.code[1] = mGlyphCache.CharAt(index + 1); |
| 285 |
ch.font = mGlyphCache.CharAt(index + 2); |
353 |
ch.font = mGlyphCache.CharAt(index + 2); |
| 286 |
return ch.code[0] == char16_t(0xFFFD) ? kNullGlyph : ch; |
354 |
return ch.code[0] == char16_t(0xFFFD) ? kNullGlyph : ch; |
| 287 |
} |
355 |
} |
| 288 |
|
356 |
|
|
|
357 |
/* virtual */ |
| 289 |
gfxTextRun* |
358 |
gfxTextRun* |
| 290 |
nsGlyphTable::MakeTextRun(gfxContext* aThebesContext, |
359 |
nsPropertiesTable::MakeTextRun(gfxContext* aThebesContext, |
| 291 |
int32_t aAppUnitsPerDevPixel, |
360 |
int32_t aAppUnitsPerDevPixel, |
| 292 |
gfxFontGroup* aFontGroup, |
361 |
gfxFontGroup* aFontGroup, |
| 293 |
const nsGlyphCode& aGlyph) |
362 |
const nsGlyphCode& aGlyph) |
| 294 |
{ |
363 |
{ |
| 295 |
NS_ASSERTION(!aGlyph.IsGlyphID(), "not yet implemented"); |
364 |
NS_ASSERTION(!aGlyph.IsGlyphID(), |
|
|
365 |
"nsPropertiesTable can only access glyphs by code point"); |
| 296 |
return aFontGroup-> |
366 |
return aFontGroup-> |
| 297 |
MakeTextRun(aGlyph.code, aGlyph.Length(), aThebesContext, |
367 |
MakeTextRun(aGlyph.code, aGlyph.Length(), aThebesContext, |
| 298 |
aAppUnitsPerDevPixel, 0); |
368 |
aAppUnitsPerDevPixel, 0); |
| 299 |
} |
369 |
} |
| 300 |
|
370 |
|
|
|
371 |
// An instance of nsOpenTypeTable is associated with one gfxFontEntry that |
| 372 |
// corresponds to an Open Type font with a MATH table. All the glyphs come from |
| 373 |
// the same font and the calls to access size variants and parts are directly |
| 374 |
// forwarded to the gfx code. |
| 375 |
class nsOpenTypeTable MOZ_FINAL : public nsGlyphTable { |
| 376 |
public: |
| 377 |
~nsOpenTypeTable() |
| 378 |
{ |
| 379 |
MOZ_COUNT_DTOR(nsOpenTypeTable); |
| 380 |
} |
| 381 |
|
| 382 |
virtual nsGlyphCode ElementAt(gfxContext* aThebesContext, |
| 383 |
int32_t aAppUnitsPerDevPixel, |
| 384 |
gfxFontGroup* aFontGroup, |
| 385 |
char16_t aChar, |
| 386 |
bool aVertical, |
| 387 |
uint32_t aPosition) MOZ_OVERRIDE; |
| 388 |
virtual nsGlyphCode BigOf(gfxContext* aThebesContext, |
| 389 |
int32_t aAppUnitsPerDevPixel, |
| 390 |
gfxFontGroup* aFontGroup, |
| 391 |
char16_t aChar, |
| 392 |
bool aVertical, |
| 393 |
uint32_t aSize) MOZ_OVERRIDE; |
| 394 |
virtual bool HasPartsOf(gfxContext* aThebesContext, |
| 395 |
int32_t aAppUnitsPerDevPixel, |
| 396 |
gfxFontGroup* aFontGroup, |
| 397 |
char16_t aChar, |
| 398 |
bool aVertical) MOZ_OVERRIDE; |
| 399 |
|
| 400 |
const nsAString& |
| 401 |
FontNameFor(const nsGlyphCode& aGlyphCode) const MOZ_OVERRIDE { |
| 402 |
NS_ASSERTION(aGlyphCode.IsGlyphID(), |
| 403 |
"nsOpenTypeTable can only access glyphs by id"); |
| 404 |
return mFontEntry->FamilyName(); |
| 405 |
} |
| 406 |
|
| 407 |
virtual gfxTextRun* MakeTextRun(gfxContext* aThebesContext, |
| 408 |
int32_t aAppUnitsPerDevPixel, |
| 409 |
gfxFontGroup* aFontGroup, |
| 410 |
const nsGlyphCode& aGlyph) MOZ_OVERRIDE; |
| 411 |
|
| 412 |
// This returns a new OpenTypeTable instance to give access to OpenType MATH |
| 413 |
// table or nullptr if the font does not have such table. Ownership is passed |
| 414 |
// to the caller. |
| 415 |
static nsOpenTypeTable* Create(gfxFont* aFont) |
| 416 |
{ |
| 417 |
if (!aFont->GetFontEntry()->TryGetMathTable(aFont)) { |
| 418 |
return nullptr; |
| 419 |
} |
| 420 |
return new nsOpenTypeTable(aFont->GetFontEntry()); |
| 421 |
} |
| 422 |
|
| 423 |
private: |
| 424 |
nsRefPtr<gfxFontEntry> mFontEntry; |
| 425 |
uint32_t mGlyphID; |
| 426 |
|
| 427 |
explicit nsOpenTypeTable(gfxFontEntry* aFontEntry) |
| 428 |
: mFontEntry(aFontEntry) { |
| 429 |
MOZ_COUNT_CTOR(nsOpenTypeTable); |
| 430 |
} |
| 431 |
|
| 432 |
void UpdateCache(gfxContext* aThebesContext, |
| 433 |
int32_t aAppUnitsPerDevPixel, |
| 434 |
gfxFontGroup* aFontGroup, |
| 435 |
char16_t aChar); |
| 436 |
}; |
| 437 |
|
| 438 |
void |
| 439 |
nsOpenTypeTable::UpdateCache(gfxContext* aThebesContext, |
| 440 |
int32_t aAppUnitsPerDevPixel, |
| 441 |
gfxFontGroup* aFontGroup, |
| 442 |
char16_t aChar) |
| 443 |
{ |
| 444 |
if (mCharCache != aChar) { |
| 445 |
nsAutoPtr<gfxTextRun> textRun; |
| 446 |
textRun = aFontGroup-> |
| 447 |
MakeTextRun(&aChar, 1, aThebesContext, aAppUnitsPerDevPixel, 0); |
| 448 |
const gfxTextRun::CompressedGlyph& data = textRun->GetCharacterGlyphs()[0]; |
| 449 |
if (data.IsSimpleGlyph()) { |
| 450 |
mGlyphID = data.GetSimpleGlyph(); |
| 451 |
} else if (data.GetGlyphCount() == 1) { |
| 452 |
mGlyphID = textRun->GetDetailedGlyphs(0)->mGlyphID; |
| 453 |
} else { |
| 454 |
mGlyphID = 0; |
| 455 |
} |
| 456 |
mCharCache = aChar; |
| 457 |
} |
| 458 |
} |
| 459 |
|
| 460 |
/* virtual */ |
| 461 |
nsGlyphCode |
| 462 |
nsOpenTypeTable::ElementAt(gfxContext* aThebesContext, |
| 463 |
int32_t aAppUnitsPerDevPixel, |
| 464 |
gfxFontGroup* aFontGroup, |
| 465 |
char16_t aChar, |
| 466 |
bool aVertical, |
| 467 |
uint32_t aPosition) |
| 468 |
{ |
| 469 |
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar); |
| 470 |
|
| 471 |
uint32_t parts[4]; |
| 472 |
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) { |
| 473 |
return kNullGlyph; |
| 474 |
} |
| 475 |
|
| 476 |
uint32_t glyphID = parts[aPosition]; |
| 477 |
if (!glyphID) { |
| 478 |
return kNullGlyph; |
| 479 |
} |
| 480 |
nsGlyphCode glyph; |
| 481 |
glyph.glyphID = glyphID; |
| 482 |
glyph.font = -1; |
| 483 |
return glyph; |
| 484 |
} |
| 485 |
|
| 486 |
/* virtual */ |
| 487 |
nsGlyphCode |
| 488 |
nsOpenTypeTable::BigOf(gfxContext* aThebesContext, |
| 489 |
int32_t aAppUnitsPerDevPixel, |
| 490 |
gfxFontGroup* aFontGroup, |
| 491 |
char16_t aChar, |
| 492 |
bool aVertical, |
| 493 |
uint32_t aSize) |
| 494 |
{ |
| 495 |
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar); |
| 496 |
|
| 497 |
uint32_t glyphID = |
| 498 |
mFontEntry->GetMathVariantsSize(mGlyphID, aVertical, aSize); |
| 499 |
if (!glyphID) { |
| 500 |
return kNullGlyph; |
| 501 |
} |
| 502 |
|
| 503 |
nsGlyphCode glyph; |
| 504 |
glyph.glyphID = glyphID; |
| 505 |
glyph.font = -1; |
| 506 |
return glyph; |
| 507 |
} |
| 508 |
|
| 509 |
/* virtual */ |
| 510 |
bool |
| 511 |
nsOpenTypeTable::HasPartsOf(gfxContext* aThebesContext, |
| 512 |
int32_t aAppUnitsPerDevPixel, |
| 513 |
gfxFontGroup* aFontGroup, |
| 514 |
char16_t aChar, |
| 515 |
bool aVertical) |
| 516 |
{ |
| 517 |
UpdateCache(aThebesContext, aAppUnitsPerDevPixel, aFontGroup, aChar); |
| 518 |
|
| 519 |
uint32_t parts[4]; |
| 520 |
if (!mFontEntry->GetMathVariantsParts(mGlyphID, aVertical, parts)) { |
| 521 |
return false; |
| 522 |
} |
| 523 |
|
| 524 |
return parts[0] || parts[1] || parts[2] || parts[3]; |
| 525 |
} |
| 526 |
|
| 527 |
/* virtual */ |
| 528 |
gfxTextRun* |
| 529 |
nsOpenTypeTable::MakeTextRun(gfxContext* aThebesContext, |
| 530 |
int32_t aAppUnitsPerDevPixel, |
| 531 |
gfxFontGroup* aFontGroup, |
| 532 |
const nsGlyphCode& aGlyph) |
| 533 |
{ |
| 534 |
NS_ASSERTION(aGlyph.IsGlyphID(), |
| 535 |
"nsOpenTypeTable can only access glyphs by id"); |
| 536 |
|
| 537 |
gfxTextRunFactory::Parameters params = { |
| 538 |
aThebesContext, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel |
| 539 |
}; |
| 540 |
gfxTextRun* textRun = gfxTextRun::Create(¶ms, 1, aFontGroup, 0); |
| 541 |
textRun->AddGlyphRun(aFontGroup->GetFontAt(0), gfxTextRange::kFontGroup, 0, |
| 542 |
false); |
| 543 |
gfxTextRun::DetailedGlyph detailedGlyph; |
| 544 |
detailedGlyph.mGlyphID = aGlyph.glyphID; |
| 545 |
// We set the advance width to zero and this will be fixed in MeasureTextRun. |
| 546 |
// XXXfredw: We should use gfxHarfbuzzShaper::GetGlyphHAdvance() |
| 547 |
detailedGlyph.mAdvance = 0; |
| 548 |
detailedGlyph.mXOffset = detailedGlyph.mYOffset = 0; |
| 549 |
gfxShapedText::CompressedGlyph g; |
| 550 |
g.SetComplex(true, true, 1); |
| 551 |
textRun->SetGlyphs(0, g, &detailedGlyph); |
| 552 |
|
| 553 |
return textRun; |
| 554 |
} |
| 555 |
|
| 301 |
// ----------------------------------------------------------------------------- |
556 |
// ----------------------------------------------------------------------------- |
| 302 |
// This is the list of all the applicable glyph tables. |
557 |
// This is the list of all the applicable glyph tables. |
| 303 |
// We will maintain a single global instance that will only reveal those |
558 |
// We will maintain a single global instance that will only reveal those |
| 304 |
// glyph tables that are associated to fonts currently installed on the |
559 |
// glyph tables that are associated to fonts currently installed on the |
| 305 |
// user' system. The class is an XPCOM shutdown observer to allow us to |
560 |
// user' system. The class is an XPCOM shutdown observer to allow us to |
| 306 |
// free its allocated data at shutdown |
561 |
// free its allocated data at shutdown |
| 307 |
|
562 |
|
| 308 |
class nsGlyphTableList : public nsIObserver |
563 |
class nsGlyphTableList : public nsIObserver |
| 309 |
{ |
564 |
{ |
| 310 |
public: |
565 |
public: |
| 311 |
NS_DECL_ISUPPORTS |
566 |
NS_DECL_ISUPPORTS |
| 312 |
NS_DECL_NSIOBSERVER |
567 |
NS_DECL_NSIOBSERVER |
| 313 |
|
568 |
|
| 314 |
nsGlyphTable mUnicodeTable; |
569 |
nsPropertiesTable mUnicodeTable; |
| 315 |
|
570 |
|
| 316 |
nsGlyphTableList() |
571 |
nsGlyphTableList() |
| 317 |
: mUnicodeTable(NS_LITERAL_STRING("Unicode")) |
572 |
: mUnicodeTable(NS_LITERAL_STRING("Unicode")) |
| 318 |
{ |
573 |
{ |
| 319 |
MOZ_COUNT_CTOR(nsGlyphTableList); |
574 |
MOZ_COUNT_CTOR(nsGlyphTableList); |
| 320 |
} |
575 |
} |
| 321 |
|
576 |
|
| 322 |
virtual ~nsGlyphTableList() |
577 |
virtual ~nsGlyphTableList() |
|
|
| 331 |
nsGlyphTable* |
586 |
nsGlyphTable* |
| 332 |
AddGlyphTable(const nsString& aPrimaryFontName); |
587 |
AddGlyphTable(const nsString& aPrimaryFontName); |
| 333 |
|
588 |
|
| 334 |
// Find the glyph table in the list corresponding to the given font family. |
589 |
// Find the glyph table in the list corresponding to the given font family. |
| 335 |
nsGlyphTable* |
590 |
nsGlyphTable* |
| 336 |
GetGlyphTableFor(const nsAString& aFamily); |
591 |
GetGlyphTableFor(const nsAString& aFamily); |
| 337 |
|
592 |
|
| 338 |
private: |
593 |
private: |
| 339 |
nsGlyphTable* TableAt(int32_t aIndex) { |
594 |
nsPropertiesTable* PropertiesTableAt(int32_t aIndex) { |
| 340 |
return &mTableList.ElementAt(aIndex); |
595 |
return &mPropertiesTableList.ElementAt(aIndex); |
| 341 |
} |
596 |
} |
| 342 |
int32_t Count() { |
597 |
int32_t PropertiesTableCount() { |
| 343 |
return mTableList.Length(); |
598 |
return mPropertiesTableList.Length(); |
| 344 |
} |
599 |
} |
| 345 |
|
|
|
| 346 |
// List of glyph tables; |
600 |
// List of glyph tables; |
| 347 |
nsTArray<nsGlyphTable> mTableList; |
601 |
nsTArray<nsPropertiesTable> mPropertiesTableList; |
| 348 |
}; |
602 |
}; |
| 349 |
|
603 |
|
| 350 |
NS_IMPL_ISUPPORTS1(nsGlyphTableList, nsIObserver) |
604 |
NS_IMPL_ISUPPORTS1(nsGlyphTableList, nsIObserver) |
| 351 |
|
605 |
|
| 352 |
// ----------------------------------------------------------------------------- |
606 |
// ----------------------------------------------------------------------------- |
| 353 |
// Here is the global list of applicable glyph tables that we will be using |
607 |
// Here is the global list of applicable glyph tables that we will be using |
| 354 |
static nsGlyphTableList* gGlyphTableList = nullptr; |
608 |
static nsGlyphTableList* gGlyphTableList = nullptr; |
| 355 |
|
609 |
|
|
|
| 400 |
nsGlyphTableList::AddGlyphTable(const nsString& aPrimaryFontName) |
654 |
nsGlyphTableList::AddGlyphTable(const nsString& aPrimaryFontName) |
| 401 |
{ |
655 |
{ |
| 402 |
// See if there is already a special table for this family. |
656 |
// See if there is already a special table for this family. |
| 403 |
nsGlyphTable* glyphTable = GetGlyphTableFor(aPrimaryFontName); |
657 |
nsGlyphTable* glyphTable = GetGlyphTableFor(aPrimaryFontName); |
| 404 |
if (glyphTable != &mUnicodeTable) |
658 |
if (glyphTable != &mUnicodeTable) |
| 405 |
return glyphTable; |
659 |
return glyphTable; |
| 406 |
|
660 |
|
| 407 |
// allocate a table |
661 |
// allocate a table |
| 408 |
glyphTable = mTableList.AppendElement(aPrimaryFontName); |
662 |
glyphTable = mPropertiesTableList.AppendElement(aPrimaryFontName); |
| 409 |
return glyphTable; |
663 |
return glyphTable; |
| 410 |
} |
664 |
} |
| 411 |
|
665 |
|
| 412 |
nsGlyphTable* |
666 |
nsGlyphTable* |
| 413 |
nsGlyphTableList::GetGlyphTableFor(const nsAString& aFamily) |
667 |
nsGlyphTableList::GetGlyphTableFor(const nsAString& aFamily) |
| 414 |
{ |
668 |
{ |
| 415 |
for (int32_t i = 0; i < Count(); i++) { |
669 |
for (int32_t i = 0; i < PropertiesTableCount(); i++) { |
| 416 |
nsGlyphTable* glyphTable = TableAt(i); |
670 |
nsPropertiesTable* glyphTable = PropertiesTableAt(i); |
| 417 |
const nsAString& fontName = glyphTable->PrimaryFontName(); |
671 |
const nsAString& fontName = glyphTable->PrimaryFontName(); |
| 418 |
// TODO: would be nice to consider StripWhitespace and other aliasing |
672 |
// TODO: would be nice to consider StripWhitespace and other aliasing |
| 419 |
if (fontName.Equals(aFamily, nsCaseInsensitiveStringComparator())) { |
673 |
if (fontName.Equals(aFamily, nsCaseInsensitiveStringComparator())) { |
| 420 |
return glyphTable; |
674 |
return glyphTable; |
| 421 |
} |
675 |
} |
| 422 |
} |
676 |
} |
| 423 |
// Fall back to default Unicode table |
677 |
// Fall back to default Unicode table |
| 424 |
return &mUnicodeTable; |
678 |
return &mUnicodeTable; |
|
Lines 894-909
MeasureTextRun(gfxContext* aThebesContex
|
Link Here
|
|---|
|
| 894 |
aThebesContext, nullptr); |
1148 |
aThebesContext, nullptr); |
| 895 |
|
1149 |
|
| 896 |
nsBoundingMetrics bm; |
1150 |
nsBoundingMetrics bm; |
| 897 |
bm.leftBearing = NSToCoordFloor(metrics.mBoundingBox.X()); |
1151 |
bm.leftBearing = NSToCoordFloor(metrics.mBoundingBox.X()); |
| 898 |
bm.rightBearing = NSToCoordCeil(metrics.mBoundingBox.XMost()); |
1152 |
bm.rightBearing = NSToCoordCeil(metrics.mBoundingBox.XMost()); |
| 899 |
bm.ascent = NSToCoordCeil(-metrics.mBoundingBox.Y()); |
1153 |
bm.ascent = NSToCoordCeil(-metrics.mBoundingBox.Y()); |
| 900 |
bm.descent = NSToCoordCeil(metrics.mBoundingBox.YMost()); |
1154 |
bm.descent = NSToCoordCeil(metrics.mBoundingBox.YMost()); |
| 901 |
bm.width = NSToCoordRound(metrics.mAdvanceWidth); |
1155 |
bm.width = NSToCoordRound(metrics.mAdvanceWidth); |
|
|
1156 |
if (bm.width == 0) { |
| 1157 |
// The advance width was not set in nsGlyphTable::MakeTextRun, so we use |
| 1158 |
// the right bearing instead. |
| 1159 |
bm.width = bm.rightBearing; |
| 1160 |
} |
| 902 |
|
1161 |
|
| 903 |
return bm; |
1162 |
return bm; |
| 904 |
} |
1163 |
} |
| 905 |
|
1164 |
|
| 906 |
class nsMathMLChar::StretchEnumContext { |
1165 |
class nsMathMLChar::StretchEnumContext { |
| 907 |
public: |
1166 |
public: |
| 908 |
StretchEnumContext(nsMathMLChar* aChar, |
1167 |
StretchEnumContext(nsMathMLChar* aChar, |
| 909 |
nsPresContext* aPresContext, |
1168 |
nsPresContext* aPresContext, |
|
|
| 925 |
mTryVariants(true), |
1184 |
mTryVariants(true), |
| 926 |
mTryParts(true), |
1185 |
mTryParts(true), |
| 927 |
mGlyphFound(aGlyphFound) {} |
1186 |
mGlyphFound(aGlyphFound) {} |
| 928 |
|
1187 |
|
| 929 |
static bool |
1188 |
static bool |
| 930 |
EnumCallback(const nsString& aFamily, bool aGeneric, void *aData); |
1189 |
EnumCallback(const nsString& aFamily, bool aGeneric, void *aData); |
| 931 |
|
1190 |
|
| 932 |
private: |
1191 |
private: |
| 933 |
bool TryVariants(nsGlyphTable* aGlyphTable, const nsAString& aFamily); |
1192 |
bool TryVariants(nsGlyphTable* aGlyphTable, |
| 934 |
bool TryParts(nsGlyphTable* aGlyphTable, const nsAString& aFamily); |
1193 |
nsRefPtr<gfxFontGroup>* aFontGroup, |
|
|
1194 |
const nsAString& aFamily); |
| 1195 |
bool TryParts(nsGlyphTable* aGlyphTable, |
| 1196 |
nsRefPtr<gfxFontGroup>* aFontGroup, |
| 1197 |
const nsAString& aFamily); |
| 935 |
|
1198 |
|
| 936 |
nsMathMLChar* mChar; |
1199 |
nsMathMLChar* mChar; |
| 937 |
nsPresContext* mPresContext; |
1200 |
nsPresContext* mPresContext; |
| 938 |
gfxContext* mThebesContext; |
1201 |
gfxContext* mThebesContext; |
| 939 |
const nsStretchDirection mDirection; |
1202 |
const nsStretchDirection mDirection; |
| 940 |
const nscoord mTargetSize; |
1203 |
const nscoord mTargetSize; |
| 941 |
const uint32_t mStretchHint; |
1204 |
const uint32_t mStretchHint; |
| 942 |
nsBoundingMetrics& mBoundingMetrics; |
1205 |
nsBoundingMetrics& mBoundingMetrics; |
|
|
| 952 |
bool& mGlyphFound; |
1215 |
bool& mGlyphFound; |
| 953 |
}; |
1216 |
}; |
| 954 |
|
1217 |
|
| 955 |
|
1218 |
|
| 956 |
// 2. See if there are any glyphs of the appropriate size. |
1219 |
// 2. See if there are any glyphs of the appropriate size. |
| 957 |
// Returns true if the size is OK, false to keep searching. |
1220 |
// Returns true if the size is OK, false to keep searching. |
| 958 |
// Always updates the char if a better match is found. |
1221 |
// Always updates the char if a better match is found. |
| 959 |
bool |
1222 |
bool |
| 960 |
nsMathMLChar::StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable, |
1223 |
nsMathMLChar:: |
| 961 |
const nsAString& aFamily) |
1224 |
StretchEnumContext::TryVariants(nsGlyphTable* aGlyphTable, |
|
|
1225 |
nsRefPtr<gfxFontGroup>* aFontGroup, |
| 1226 |
const nsAString& aFamily) |
| 962 |
{ |
1227 |
{ |
| 963 |
// Use our stretchy style context now that stretching is in progress |
1228 |
// Use our stretchy style context now that stretching is in progress |
| 964 |
nsStyleContext *sc = mChar->mStyleContext; |
1229 |
nsStyleContext *sc = mChar->mStyleContext; |
| 965 |
nsFont font = sc->StyleFont()->mFont; |
1230 |
nsFont font = sc->StyleFont()->mFont; |
| 966 |
// Ensure SetFontFamily will set the font |
1231 |
// Ensure SetFontFamily will set the font |
| 967 |
font.name.Truncate(); |
1232 |
font.name.Truncate(); |
| 968 |
|
1233 |
|
| 969 |
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL); |
1234 |
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL); |
|
|
1235 |
nscoord oneDevPixel = mPresContext->AppUnitsPerDevPixel(); |
| 1236 |
char16_t uchar = mChar->mData[0]; |
| 970 |
bool largeop = (NS_STRETCH_LARGEOP & mStretchHint) != 0; |
1237 |
bool largeop = (NS_STRETCH_LARGEOP & mStretchHint) != 0; |
| 971 |
bool largeopOnly = |
1238 |
bool largeopOnly = |
| 972 |
largeop && (NS_STRETCH_VARIABLE_MASK & mStretchHint) == 0; |
1239 |
largeop && (NS_STRETCH_VARIABLE_MASK & mStretchHint) == 0; |
| 973 |
bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0; |
1240 |
bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0; |
| 974 |
|
1241 |
|
| 975 |
nscoord bestSize = |
1242 |
nscoord bestSize = |
| 976 |
isVertical ? mBoundingMetrics.ascent + mBoundingMetrics.descent |
1243 |
isVertical ? mBoundingMetrics.ascent + mBoundingMetrics.descent |
| 977 |
: mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing; |
1244 |
: mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing; |
| 978 |
bool haveBetter = false; |
1245 |
bool haveBetter = false; |
| 979 |
|
1246 |
|
| 980 |
// start at size = 1 (size = 0 is the char at its normal size) |
1247 |
// start at size = 1 (size = 0 is the char at its normal size) |
| 981 |
int32_t size = 1; |
1248 |
int32_t size = 1; |
|
|
1249 |
nsGlyphCode ch; |
| 1250 |
nscoord displayOperatorMinHeight = 0; |
| 1251 |
if (largeopOnly) { |
| 1252 |
NS_ASSERTION(isVertical, "Stretching should be in the vertical direction"); |
| 1253 |
ch = aGlyphTable->BigOf(mThebesContext, oneDevPixel, *aFontGroup, uchar, |
| 1254 |
isVertical, 0); |
| 1255 |
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font, |
| 1256 |
aFontGroup)) { |
| 1257 |
return false; |
| 1258 |
} |
| 1259 |
gfxFont* mathFont = aFontGroup->get()->GetFontAt(0); |
| 1260 |
if (mathFont->GetFontEntry()->TryGetMathTable(mathFont)) { |
| 1261 |
// For OpenType MATH fonts, we will rely on the DisplayOperatorMinHeight |
| 1262 |
// to select the right size variant. Note that the value is sometimes too |
| 1263 |
// small so we use kLargeOpFactor/kIntegralFactor as a minimum value. |
| 1264 |
displayOperatorMinHeight = |
| 1265 |
NSToCoordRound(mathFont->GetFontEntry()-> |
| 1266 |
GetMathConstant(gfxFontEntry::DisplayOperatorMinHeight) * |
| 1267 |
mathFont->GetAdjustedSize() * oneDevPixel); |
| 1268 |
nsAutoPtr<gfxTextRun> textRun; |
| 1269 |
textRun = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel, |
| 1270 |
*aFontGroup, ch); |
| 1271 |
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun); |
| 1272 |
float largeopFactor = kLargeOpFactor; |
| 1273 |
if (NS_STRETCH_INTEGRAL & mStretchHint) { |
| 1274 |
// integrals are drawn taller |
| 1275 |
largeopFactor = kIntegralFactor; |
| 1276 |
} |
| 1277 |
nscoord minHeight = largeopFactor * (bm.ascent + bm.descent); |
| 1278 |
if (displayOperatorMinHeight < minHeight) { |
| 1279 |
displayOperatorMinHeight = minHeight; |
| 1280 |
} |
| 1281 |
} |
| 1282 |
} |
| 982 |
#ifdef NOISY_SEARCH |
1283 |
#ifdef NOISY_SEARCH |
| 983 |
printf(" searching in %s ...\n", |
1284 |
printf(" searching in %s ...\n", |
| 984 |
NS_LossyConvertUTF16toASCII(aFamily).get()); |
1285 |
NS_LossyConvertUTF16toASCII(aFamily).get()); |
| 985 |
#endif |
1286 |
#endif |
| 986 |
|
1287 |
while ((ch = aGlyphTable->BigOf(mThebesContext, oneDevPixel, *aFontGroup, |
| 987 |
nsGlyphCode ch; |
1288 |
uchar, isVertical, size)).Exists()) { |
| 988 |
nsRefPtr<gfxFontGroup> fontGroup; |
|
|
| 989 |
while ((ch = aGlyphTable->BigOf(mChar->mData[0], size)).Exists()) { |
| 990 |
|
1289 |
|
| 991 |
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font, |
1290 |
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font, |
| 992 |
&fontGroup)) { |
1291 |
aFontGroup)) { |
| 993 |
// if largeopOnly is set, break now |
1292 |
// if largeopOnly is set, break now |
| 994 |
if (largeopOnly) break; |
1293 |
if (largeopOnly) break; |
| 995 |
++size; |
1294 |
++size; |
| 996 |
continue; |
1295 |
continue; |
| 997 |
} |
1296 |
} |
| 998 |
|
1297 |
|
| 999 |
nsAutoPtr<gfxTextRun> textRun; |
1298 |
nsAutoPtr<gfxTextRun> textRun; |
| 1000 |
textRun = aGlyphTable->MakeTextRun(mThebesContext, |
1299 |
textRun = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel, |
| 1001 |
mPresContext->AppUnitsPerDevPixel(), |
1300 |
*aFontGroup, ch); |
| 1002 |
fontGroup, ch); |
|
|
| 1003 |
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun); |
1301 |
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun); |
|
|
1302 |
if (ch.IsGlyphID()) { |
| 1303 |
gfxFont* mathFont = aFontGroup->get()->GetFontAt(0); |
| 1304 |
if (mathFont->GetFontEntry()->TryGetMathTable(mathFont)) { |
| 1305 |
// MeasureTextRun has set the advance width to the right bearing. We now |
| 1306 |
// subtract the italic correction, so that nsMathMLmmultiscripts will |
| 1307 |
// place the scripts correctly. |
| 1308 |
// Note that STIX-Word does not provide italic corrections |
| 1309 |
// (http://sourceforge.net/p/stixfonts/tracking/50/) |
| 1310 |
gfxFloat italicCorrection; |
| 1311 |
if (mathFont->GetFontEntry()-> |
| 1312 |
GetMathItalicsCorrection(ch.glyphID, &italicCorrection)) { |
| 1313 |
bm.width -= |
| 1314 |
NSToCoordRound(italicCorrection * |
| 1315 |
mathFont->GetAdjustedSize() * oneDevPixel); |
| 1316 |
if (bm.width < 0) { |
| 1317 |
bm.width = 0; |
| 1318 |
} |
| 1319 |
} |
| 1320 |
} |
| 1321 |
} |
| 1004 |
|
1322 |
|
| 1005 |
nscoord charSize = |
1323 |
nscoord charSize = |
| 1006 |
isVertical ? bm.ascent + bm.descent |
1324 |
isVertical ? bm.ascent + bm.descent |
| 1007 |
: bm.rightBearing - bm.leftBearing; |
1325 |
: bm.rightBearing - bm.leftBearing; |
| 1008 |
|
1326 |
|
| 1009 |
if (largeopOnly || |
1327 |
if (largeopOnly || |
| 1010 |
IsSizeBetter(charSize, bestSize, mTargetSize, mStretchHint)) { |
1328 |
IsSizeBetter(charSize, bestSize, mTargetSize, mStretchHint)) { |
| 1011 |
mGlyphFound = true; |
1329 |
mGlyphFound = true; |
|
Lines 1035-1098
nsMathMLChar::StretchEnumContext::TryVar
|
Link Here
|
|---|
|
| 1035 |
else { |
1353 |
else { |
| 1036 |
#ifdef NOISY_SEARCH |
1354 |
#ifdef NOISY_SEARCH |
| 1037 |
printf(" size:%d Rejected!\n", size); |
1355 |
printf(" size:%d Rejected!\n", size); |
| 1038 |
#endif |
1356 |
#endif |
| 1039 |
if (haveBetter) |
1357 |
if (haveBetter) |
| 1040 |
break; // Not making an futher progress, stop searching |
1358 |
break; // Not making an futher progress, stop searching |
| 1041 |
} |
1359 |
} |
| 1042 |
|
1360 |
|
| 1043 |
// if largeopOnly is set, break now |
1361 |
// If this a largeop only operator, we stop if the glyph is large enough. |
| 1044 |
if (largeopOnly) break; |
1362 |
if (largeopOnly && (bm.ascent + bm.descent) >= displayOperatorMinHeight) { |
|
|
1363 |
break; |
| 1364 |
} |
| 1045 |
++size; |
1365 |
++size; |
| 1046 |
} |
1366 |
} |
| 1047 |
|
1367 |
|
| 1048 |
return haveBetter && |
1368 |
return haveBetter && |
| 1049 |
(largeopOnly || |
1369 |
(largeopOnly || |
| 1050 |
IsSizeOK(mPresContext, bestSize, mTargetSize, mStretchHint)); |
1370 |
IsSizeOK(mPresContext, bestSize, mTargetSize, mStretchHint)); |
| 1051 |
} |
1371 |
} |
| 1052 |
|
1372 |
|
| 1053 |
// 3. Build by parts. |
1373 |
// 3. Build by parts. |
| 1054 |
// Returns true if the size is OK, false to keep searching. |
1374 |
// Returns true if the size is OK, false to keep searching. |
| 1055 |
// Always updates the char if a better match is found. |
1375 |
// Always updates the char if a better match is found. |
| 1056 |
bool |
1376 |
bool |
| 1057 |
nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable, |
1377 |
nsMathMLChar::StretchEnumContext::TryParts(nsGlyphTable* aGlyphTable, |
|
|
1378 |
nsRefPtr<gfxFontGroup>* aFontGroup, |
| 1058 |
const nsAString& aFamily) |
1379 |
const nsAString& aFamily) |
| 1059 |
{ |
1380 |
{ |
| 1060 |
if (!aGlyphTable->HasPartsOf(mChar->mData[0])) |
|
|
| 1061 |
return false; // to next table |
| 1062 |
|
| 1063 |
// See if the parts of this table fit in the desired space ////////////////// |
| 1064 |
|
| 1065 |
// Use our stretchy style context now that stretching is in progress |
1381 |
// Use our stretchy style context now that stretching is in progress |
| 1066 |
nsFont font = mChar->mStyleContext->StyleFont()->mFont; |
1382 |
nsFont font = mChar->mStyleContext->StyleFont()->mFont; |
| 1067 |
// Ensure SetFontFamily will set the font |
1383 |
// Ensure SetFontFamily will set the font |
| 1068 |
font.name.Truncate(); |
1384 |
font.name.Truncate(); |
| 1069 |
|
1385 |
|
| 1070 |
// Compute the bounding metrics of all partial glyphs |
1386 |
// Compute the bounding metrics of all partial glyphs |
| 1071 |
nsAutoPtr<gfxTextRun> textRun[4]; |
1387 |
nsAutoPtr<gfxTextRun> textRun[4]; |
| 1072 |
nsGlyphCode chdata[4]; |
1388 |
nsGlyphCode chdata[4]; |
| 1073 |
nsBoundingMetrics bmdata[4]; |
1389 |
nsBoundingMetrics bmdata[4]; |
| 1074 |
nscoord sizedata[4]; |
1390 |
nscoord sizedata[4]; |
| 1075 |
|
1391 |
|
| 1076 |
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL); |
1392 |
bool isVertical = (mDirection == NS_STRETCH_DIRECTION_VERTICAL); |
|
|
1393 |
nscoord oneDevPixel = mPresContext->AppUnitsPerDevPixel(); |
| 1394 |
char16_t uchar = mChar->mData[0]; |
| 1077 |
bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0; |
1395 |
bool maxWidth = (NS_STRETCH_MAXWIDTH & mStretchHint) != 0; |
| 1078 |
nsRefPtr<gfxFontGroup> fontGroup; |
1396 |
if (!aGlyphTable->HasPartsOf(mThebesContext, oneDevPixel, *aFontGroup, |
|
|
1397 |
uchar, isVertical)) |
| 1398 |
return false; // to next table |
| 1079 |
|
1399 |
|
| 1080 |
for (int32_t i = 0; i < 4; i++) { |
1400 |
for (int32_t i = 0; i < 4; i++) { |
| 1081 |
nsGlyphCode ch = aGlyphTable->ElementAt(mChar->mData[0], i); |
1401 |
nsGlyphCode ch = aGlyphTable->ElementAt(mThebesContext, oneDevPixel, |
|
|
1402 |
*aFontGroup, uchar, isVertical, i); |
| 1082 |
chdata[i] = ch; |
1403 |
chdata[i] = ch; |
| 1083 |
if (ch.Exists()) { |
1404 |
if (ch.Exists()) { |
| 1084 |
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font, |
1405 |
if (!mChar->SetFontFamily(mPresContext, aGlyphTable, ch, aFamily, font, |
| 1085 |
&fontGroup)) |
1406 |
aFontGroup)) |
| 1086 |
return false; |
1407 |
return false; |
| 1087 |
|
1408 |
|
| 1088 |
textRun[i] = aGlyphTable->MakeTextRun(mThebesContext, |
1409 |
textRun[i] = aGlyphTable->MakeTextRun(mThebesContext, oneDevPixel, |
| 1089 |
mPresContext->AppUnitsPerDevPixel(), |
1410 |
*aFontGroup, ch); |
| 1090 |
fontGroup, ch); |
|
|
| 1091 |
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun[i]); |
1411 |
nsBoundingMetrics bm = MeasureTextRun(mThebesContext, textRun[i]); |
| 1092 |
|
1412 |
|
| 1093 |
// TODO: For the generic Unicode table, ideally we should check that the |
1413 |
// TODO: For the generic Unicode table, ideally we should check that the |
| 1094 |
// glyphs are actually found and that they each come from the same |
1414 |
// glyphs are actually found and that they each come from the same |
| 1095 |
// font. |
1415 |
// font. |
| 1096 |
bmdata[i] = bm; |
1416 |
bmdata[i] = bm; |
| 1097 |
sizedata[i] = isVertical ? bm.ascent + bm.descent |
1417 |
sizedata[i] = isVertical ? bm.ascent + bm.descent |
| 1098 |
: bm.rightBearing - bm.leftBearing; |
1418 |
: bm.rightBearing - bm.leftBearing; |
|
Lines 1202-1249
nsMathMLChar::StretchEnumContext::TryPar
|
Link Here
|
|---|
|
| 1202 |
|
1522 |
|
| 1203 |
// This is called for each family, whether it exists or not |
1523 |
// This is called for each family, whether it exists or not |
| 1204 |
bool |
1524 |
bool |
| 1205 |
nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily, |
1525 |
nsMathMLChar::StretchEnumContext::EnumCallback(const nsString& aFamily, |
| 1206 |
bool aGeneric, void *aData) |
1526 |
bool aGeneric, void *aData) |
| 1207 |
{ |
1527 |
{ |
| 1208 |
StretchEnumContext* context = static_cast<StretchEnumContext*>(aData); |
1528 |
StretchEnumContext* context = static_cast<StretchEnumContext*>(aData); |
| 1209 |
|
1529 |
|
| 1210 |
// See if there is a special table for the family, but always use the |
|
|
| 1211 |
// Unicode table for generic fonts. |
| 1212 |
nsGlyphTable* glyphTable = aGeneric ? |
| 1213 |
&gGlyphTableList->mUnicodeTable : |
| 1214 |
gGlyphTableList->GetGlyphTableFor(aFamily); |
| 1215 |
|
| 1216 |
if (context->mTablesTried.Contains(glyphTable)) |
| 1217 |
return true; // already tried this one |
| 1218 |
|
| 1219 |
// Check font family if it is not a generic one |
1530 |
// Check font family if it is not a generic one |
| 1220 |
// We test with the kNullGlyph |
1531 |
// We test with the kNullGlyph |
| 1221 |
nsStyleContext *sc = context->mChar->mStyleContext; |
1532 |
nsStyleContext *sc = context->mChar->mStyleContext; |
| 1222 |
nsFont font = sc->StyleFont()->mFont; |
1533 |
nsFont font = sc->StyleFont()->mFont; |
| 1223 |
nsRefPtr<gfxFontGroup> fontGroup; |
1534 |
nsRefPtr<gfxFontGroup> fontGroup; |
| 1224 |
if (!aGeneric && !context->mChar->SetFontFamily(context->mPresContext, |
1535 |
if (!aGeneric && !context->mChar->SetFontFamily(context->mPresContext, |
| 1225 |
nullptr, kNullGlyph, aFamily, |
1536 |
nullptr, kNullGlyph, aFamily, |
| 1226 |
font, &fontGroup)) |
1537 |
font, &fontGroup)) |
| 1227 |
return true; // Could not set the family |
1538 |
return true; // Could not set the family |
| 1228 |
|
1539 |
|
| 1229 |
// Now see if the table has a glyph that matches the container |
1540 |
// Determine the glyph table to use for this font. |
|
|
1541 |
nsAutoPtr<nsOpenTypeTable> openTypeTable; |
| 1542 |
nsGlyphTable* glyphTable; |
| 1543 |
if (aGeneric) { |
| 1544 |
// This is a generic font, use the Unicode table. |
| 1545 |
glyphTable = &gGlyphTableList->mUnicodeTable; |
| 1546 |
} else { |
| 1547 |
// If the font contains an Open Type MATH table, use it. |
| 1548 |
openTypeTable = nsOpenTypeTable::Create(fontGroup->GetFontAt(0)); |
| 1549 |
if (openTypeTable) { |
| 1550 |
glyphTable = openTypeTable; |
| 1551 |
} else { |
| 1552 |
// Otherwise try to find a .properties file corresponding to that font |
| 1553 |
// family or fallback to the Unicode table. |
| 1554 |
glyphTable = gGlyphTableList->GetGlyphTableFor(aFamily); |
| 1555 |
} |
| 1556 |
} |
| 1230 |
|
1557 |
|
| 1231 |
// Only try this table once. |
1558 |
if (!openTypeTable) { |
| 1232 |
context->mTablesTried.AppendElement(glyphTable); |
1559 |
if (context->mTablesTried.Contains(glyphTable)) |
|
|
1560 |
return true; // already tried this one |
| 1561 |
|
| 1562 |
// Only try this table once. |
| 1563 |
context->mTablesTried.AppendElement(glyphTable); |
| 1564 |
} |
| 1233 |
|
1565 |
|
| 1234 |
// If the unicode table is being used, then search all font families. If a |
1566 |
// If the unicode table is being used, then search all font families. If a |
| 1235 |
// special table is being used then the font in this family should have the |
1567 |
// special table is being used then the font in this family should have the |
| 1236 |
// specified glyphs. |
1568 |
// specified glyphs. |
| 1237 |
const nsAString& family = glyphTable == &gGlyphTableList->mUnicodeTable ? |
1569 |
const nsAString& family = glyphTable == &gGlyphTableList->mUnicodeTable ? |
| 1238 |
context->mFamilies : aFamily; |
1570 |
context->mFamilies : aFamily; |
| 1239 |
|
1571 |
|
| 1240 |
if((context->mTryVariants && context->TryVariants(glyphTable, family)) || |
1572 |
if((context->mTryVariants && |
| 1241 |
(context->mTryParts && context->TryParts(glyphTable, family))) |
1573 |
context->TryVariants(glyphTable, &fontGroup, family)) || |
|
|
1574 |
(context->mTryParts && context->TryParts(glyphTable, &fontGroup, family))) |
| 1242 |
return false; // no need to continue |
1575 |
return false; // no need to continue |
| 1243 |
|
1576 |
|
| 1244 |
return true; // true means continue |
1577 |
return true; // true means continue |
| 1245 |
} |
1578 |
} |
| 1246 |
|
1579 |
|
| 1247 |
nsresult |
1580 |
nsresult |
| 1248 |
nsMathMLChar::StretchInternal(nsPresContext* aPresContext, |
1581 |
nsMathMLChar::StretchInternal(nsPresContext* aPresContext, |
| 1249 |
gfxContext* aThebesContext, |
1582 |
gfxContext* aThebesContext, |
|
Lines 1469-1485
nsMathMLChar::StretchInternal(nsPresCont
|
Link Here
|
|---|
|
| 1469 |
} |
1802 |
} |
| 1470 |
} |
1803 |
} |
| 1471 |
} |
1804 |
} |
| 1472 |
|
1805 |
|
| 1473 |
// We do not have a char variant for this largeop in display mode, so we |
1806 |
// We do not have a char variant for this largeop in display mode, so we |
| 1474 |
// apply a scale transform to the base char. |
1807 |
// apply a scale transform to the base char. |
| 1475 |
if (!glyphFound && largeop) { |
1808 |
if (!glyphFound && largeop) { |
| 1476 |
float scale; |
1809 |
float scale; |
| 1477 |
float largeopFactor = float(M_SQRT2); |
1810 |
float largeopFactor = kLargeOpFactor; |
| 1478 |
|
1811 |
|
| 1479 |
// increase the width if it is not largeopFactor times larger |
1812 |
// increase the width if it is not largeopFactor times larger |
| 1480 |
// than the initial one. |
1813 |
// than the initial one. |
| 1481 |
if ((aDesiredStretchSize.rightBearing - aDesiredStretchSize.leftBearing) < |
1814 |
if ((aDesiredStretchSize.rightBearing - aDesiredStretchSize.leftBearing) < |
| 1482 |
largeopFactor * (initialSize.rightBearing - initialSize.leftBearing)) { |
1815 |
largeopFactor * (initialSize.rightBearing - initialSize.leftBearing)) { |
| 1483 |
scale = (largeopFactor * |
1816 |
scale = (largeopFactor * |
| 1484 |
(initialSize.rightBearing - initialSize.leftBearing)) / |
1817 |
(initialSize.rightBearing - initialSize.leftBearing)) / |
| 1485 |
(aDesiredStretchSize.rightBearing - aDesiredStretchSize.leftBearing); |
1818 |
(aDesiredStretchSize.rightBearing - aDesiredStretchSize.leftBearing); |
|
Lines 1490-1506
nsMathMLChar::StretchInternal(nsPresCont
|
Link Here
|
|---|
|
| 1490 |
aDesiredStretchSize.rightBearing *= scale; |
1823 |
aDesiredStretchSize.rightBearing *= scale; |
| 1491 |
aDesiredStretchSize.width *= scale; |
1824 |
aDesiredStretchSize.width *= scale; |
| 1492 |
} |
1825 |
} |
| 1493 |
|
1826 |
|
| 1494 |
// increase the height if it is not largeopFactor times larger |
1827 |
// increase the height if it is not largeopFactor times larger |
| 1495 |
// than the initial one. |
1828 |
// than the initial one. |
| 1496 |
if (NS_STRETCH_INTEGRAL & aStretchHint) { |
1829 |
if (NS_STRETCH_INTEGRAL & aStretchHint) { |
| 1497 |
// integrals are drawn taller |
1830 |
// integrals are drawn taller |
| 1498 |
largeopFactor = 2.0; |
1831 |
largeopFactor = kIntegralFactor; |
| 1499 |
} |
1832 |
} |
| 1500 |
if ((aDesiredStretchSize.ascent + aDesiredStretchSize.descent) < |
1833 |
if ((aDesiredStretchSize.ascent + aDesiredStretchSize.descent) < |
| 1501 |
largeopFactor * (initialSize.ascent + initialSize.descent)) { |
1834 |
largeopFactor * (initialSize.ascent + initialSize.descent)) { |
| 1502 |
scale = (largeopFactor * |
1835 |
scale = (largeopFactor * |
| 1503 |
(initialSize.ascent + initialSize.descent)) / |
1836 |
(initialSize.ascent + initialSize.descent)) / |
| 1504 |
(aDesiredStretchSize.ascent + aDesiredStretchSize.descent); |
1837 |
(aDesiredStretchSize.ascent + aDesiredStretchSize.descent); |
| 1505 |
if (!maxWidth) { |
1838 |
if (!maxWidth) { |
| 1506 |
mScaleY *= scale; |
1839 |
mScaleY *= scale; |