Attachment #8410215: Part 2: make nsMathMLChar use the MATH table. for bug #407059

View | Details | Raw Unified | Return to bug 407059
Collapse All | Expand All

(-)a/layout/mathml/nsMathMLChar.cpp (-98 / +431 lines)
Line     Link Here 
 Lines 23-80    Link Here 
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(&params, 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()
 Lines 331-355   public: Link Here 
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
 Lines 400-424   nsGlyphTable* Link Here 
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,
 Lines 925-942   public: Link Here 
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;
 Lines 952-1011   private: Link Here 
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;
(-)a/layout/mathml/nsMathMLChar.h (+2 lines)
Line     Link Here 
 Lines 194-209   public: Link Here 
194
  // the Get/Set AdditionalStyleContext() APIs. Owners of MathMLChars
194
  // the Get/Set AdditionalStyleContext() APIs. Owners of MathMLChars
195
  // should honor these APIs.
195
  // should honor these APIs.
196
  nsStyleContext* GetStyleContext() const;
196
  nsStyleContext* GetStyleContext() const;
197
197
198
  void SetStyleContext(nsStyleContext* aStyleContext);
198
  void SetStyleContext(nsStyleContext* aStyleContext);
199
199
200
protected:
200
protected:
201
  friend class nsGlyphTable;
201
  friend class nsGlyphTable;
202
  friend class nsPropertiesTable;
203
  friend class nsOpenTypeTable;
202
  nsString           mData;
204
  nsString           mData;
203
205
204
private:
206
private:
205
  nsRect             mRect;
207
  nsRect             mRect;
206
  nsStretchDirection mDirection;
208
  nsStretchDirection mDirection;
207
  nsBoundingMetrics  mBoundingMetrics;
209
  nsBoundingMetrics  mBoundingMetrics;
208
  nsStyleContext*    mStyleContext;
210
  nsStyleContext*    mStyleContext;
209
  // mGlyphs/mBmData are arrays describing the glyphs used to draw the operator.
211
  // mGlyphs/mBmData are arrays describing the glyphs used to draw the operator.

Return to bug 407059