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