Attachment #532584: Support for non-BMP stretchy operators (V3) for bug #407439

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

(-)a/layout/mathml/nsMathMLChar.cpp (-24 / +40 lines)
Line     Link Here 
 Lines 69-85    Link Here 
69
#include "nsMathMLOperators.h"
69
#include "nsMathMLOperators.h"
70
#include "nsMathMLChar.h"
70
#include "nsMathMLChar.h"
71
71
72
//#define SHOW_BORDERS 1
72
//#define SHOW_BORDERS 1
73
//#define NOISY_SEARCH 1
73
//#define NOISY_SEARCH 1
74
74
75
// -----------------------------------------------------------------------------------
75
// -----------------------------------------------------------------------------------
76
static const PRUnichar   kSpaceCh   = PRUnichar(' ');
76
static const PRUnichar   kSpaceCh   = PRUnichar(' ');
77
static const nsGlyphCode kNullGlyph = {0, 0};
77
static const nsGlyphCode kNullGlyph = {{0, 0}, 0};
78
typedef enum {eExtension_base, eExtension_variants, eExtension_parts}
78
typedef enum {eExtension_base, eExtension_variants, eExtension_parts}
79
  nsMathfontPrefExtension;
79
  nsMathfontPrefExtension;
80
80
81
// -----------------------------------------------------------------------------------
81
// -----------------------------------------------------------------------------------
82
// nsGlyphTable is a class that provides an interface for accessing glyphs
82
// nsGlyphTable is a class that provides an interface for accessing glyphs
83
// of stretchy chars. It acts like a table that stores the variants of bigger
83
// of stretchy chars. It acts like a table that stores the variants of bigger
84
// sizes (if any) and the partial glyphs needed to build extensible symbols.
84
// sizes (if any) and the partial glyphs needed to build extensible symbols.
85
// An instance of nsGlyphTable is associated to one primary font. Extra glyphs
85
// An instance of nsGlyphTable is associated to one primary font. Extra glyphs
 Lines 243-260   private: Link Here 
243
  // that char. For a property line 'key = value' in the MathFont Property File,
243
  // that char. For a property line 'key = value' in the MathFont Property File,
244
  // mCharCache will retain the 'key' -- which is a Unicode point, while mGlyphCache
244
  // mCharCache will retain the 'key' -- which is a Unicode point, while mGlyphCache
245
  // will retain the 'value', which is a consecutive list of nsGlyphCodes, i.e.,
245
  // will retain the 'value', which is a consecutive list of nsGlyphCodes, i.e.,
246
  // the pairs of 'code@font' needed by the char -- in which 'code@0' can be specified
246
  // the pairs of 'code@font' needed by the char -- in which 'code@0' can be specified
247
  // without the optional '@0'. However, to ease subsequent processing, mGlyphCache
247
  // without the optional '@0'. However, to ease subsequent processing, mGlyphCache
248
  // excludes the '@' symbol and explicitly inserts all optional '0' that indicates
248
  // excludes the '@' symbol and explicitly inserts all optional '0' that indicates
249
  // the primary font identifier. Specifically therefore, the k-th glyph is
249
  // the primary font identifier. Specifically therefore, the k-th glyph is
250
  // characterized by :
250
  // characterized by :
251
  // 1) mGlyphCache[2*k] : its Unicode point (or glyph index -- depending on mType),
251
  // 1) mGlyphCache[3*k],mGlyphCache[3*k+1] : its Unicode point (or glyph index -- depending on mType),
252
  // 2) mGlyphCache[2*k+1] : the numeric identifier of the font where it comes from.
252
  // 2) mGlyphCache[3*k+2] : the numeric identifier of the font where it comes from.
253
  // A font identifier of '0' means the default primary font associated to this
253
  // A font identifier of '0' means the default primary font associated to this
254
  // table. Other digits map to the "external" fonts that may have been specified
254
  // table. Other digits map to the "external" fonts that may have been specified
255
  // in the MathFont Property File.
255
  // in the MathFont Property File.
256
  nsString  mGlyphCache;
256
  nsString  mGlyphCache;
257
  PRUnichar mCharCache;
257
  PRUnichar mCharCache;
258
};
258
};
259
259
260
nsGlyphCode
260
nsGlyphCode
 Lines 306-331   nsGlyphTable::ElementAt(nsPresContext* a Link Here 
306
    nsAutoString value;
306
    nsAutoString value;
307
    nsresult rv = mGlyphProperties->GetStringProperty(nsDependentCString(key), value);
307
    nsresult rv = mGlyphProperties->GetStringProperty(nsDependentCString(key), value);
308
    if (NS_FAILED(rv)) return kNullGlyph;
308
    if (NS_FAILED(rv)) return kNullGlyph;
309
    Clean(value);
309
    Clean(value);
310
    // See if this char uses external fonts; e.g., if the 2nd glyph is taken from the
310
    // See if this char uses external fonts; e.g., if the 2nd glyph is taken from the
311
    // external font '1', the property line looks like \uNNNN = \uNNNN\uNNNN@1\uNNNN.
311
    // external font '1', the property line looks like \uNNNN = \uNNNN\uNNNN@1\uNNNN.
312
    // This is where mGlyphCache is pre-processed to explicitly store all glyph codes
312
    // This is where mGlyphCache is pre-processed to explicitly store all glyph codes
313
    // as combined pairs of 'code@font', excluding the '@' separator. This means that
313
    // as combined pairs of 'code@font', excluding the '@' separator. This means that
314
    // mGlyphCache[2*k] will later be rendered with mFontName[mGlyphCache[2*k+1]]
314
    // mGlyphCache[3*k],mGlyphCache[3*k+1] will later be rendered with mFontName[mGlyphCache[3*k+2]]
315
    // Note: font identifier is internally an ASCII digit to avoid the null char issue
315
    // Note: font identifier is internally an ASCII digit to avoid the null char issue
316
    nsAutoString buffer;
316
    nsAutoString buffer;
317
    PRInt32 length = value.Length();
317
    PRInt32 length = value.Length();
318
    PRInt32 i = 0; // index in value
318
    PRInt32 i = 0; // index in value
319
    PRInt32 j = 0; // part/variant index
319
    PRInt32 j = 0; // part/variant index
320
    while (i < length) {
320
    while (i < length) {
321
      PRUnichar code = value[i];
321
      PRUnichar code = value[i];
322
      ++i;
322
      ++i;
323
      PRUnichar font = 0;
323
      buffer.Append(code);
324
      // see if we are at the beginning of a child char
324
      // see if we are at the beginning of a child char
325
      if (code == kSpaceCh) {
325
      if (code == kSpaceCh) {
326
        // reset the annotation indicator to be 0 for the next code point
326
        // reset the annotation indicator to be 0 for the next code point
327
        j = -1;
327
        j = -1;
328
      }
328
      }
329
#if 0 // If we want this then the nsGlyphTableList must be declared
329
#if 0 // If we want this then the nsGlyphTableList must be declared
330
      // or the UnicodeTable could be made a global.
330
      // or the UnicodeTable could be made a global.
331
      // See if this code point is an *indirect reference* to the Unicode
331
      // See if this code point is an *indirect reference* to the Unicode
 Lines 341-373   nsGlyphTable::ElementAt(nsPresContext* a Link Here 
341
        ++i;
341
        ++i;
342
        // Need to implement this if we want it:
342
        // Need to implement this if we want it:
343
        // Set (new) code from the value[i] position for (current) code.
343
        // Set (new) code from the value[i] position for (current) code.
344
        if (1)
344
        if (1)
345
          return kNullGlyph;
345
          return kNullGlyph;
346
        ++i;
346
        ++i;
347
      }
347
      }
348
#endif
348
#endif
349
      // Read the next word, if we have a non-BMP character.
350
      if (i < length &&
351
          PRUnichar(0xD800) <= code && code <= PRUnichar(0xDBFF)) {
352
        code = value[i];
353
        ++i;
354
      } else {
355
        code = PRUnichar('\0');
356
      }
357
      buffer.Append(code);
358
349
      // See if an external font is needed for the code point.
359
      // See if an external font is needed for the code point.
350
      // Limit of 9 external fonts
360
      // Limit of 9 external fonts
361
      PRUnichar font = 0;
351
      if (i+1 < length && value[i] == PRUnichar('@') &&
362
      if (i+1 < length && value[i] == PRUnichar('@') &&
352
          value[i+1] >= PRUnichar('0') && value[i+1] <= PRUnichar('9')) {
363
          value[i+1] >= PRUnichar('0') && value[i+1] <= PRUnichar('9')) {
353
        ++i;
364
        ++i;
354
        font = value[i] - '0';
365
        font = value[i] - '0';
355
        ++i;
366
        ++i;
356
        if (font >= mFontName.Length()) {
367
        if (font >= mFontName.Length()) {
357
          NS_ERROR("Nonexistent font referenced in glyph table");
368
          NS_ERROR("Nonexistent font referenced in glyph table");
358
          return kNullGlyph;
369
          return kNullGlyph;
359
        }
370
        }
360
        // The char cannot be handled if this font is not installed
371
        // The char cannot be handled if this font is not installed
361
        if (!mFontName[font].Length()) {
372
        if (!mFontName[font].Length()) {
362
          return kNullGlyph;
373
          return kNullGlyph;
363
        }
374
        }
364
      }
375
      }
365
      buffer.Append(code);
366
      buffer.Append(font);
376
      buffer.Append(font);
367
      ++j;
377
      ++j;
368
    }
378
    }
369
    // update our cache with the new settings
379
    // update our cache with the new settings
370
    mGlyphCache.Assign(buffer);
380
    mGlyphCache.Assign(buffer);
371
    mCharCache = uchar;
381
    mCharCache = uchar;
372
  }
382
  }
373
383
 Lines 385-422   nsGlyphTable::ElementAt(nsPresContext* a Link Here 
385
  PRUint32 length = mGlyphCache.Length();
395
  PRUint32 length = mGlyphCache.Length();
386
  if (aChar->mParent) {
396
  if (aChar->mParent) {
387
    nsMathMLChar* child = aChar->mParent->mSibling;
397
    nsMathMLChar* child = aChar->mParent->mSibling;
388
    // XXXkt composite chars can't have size variants
398
    // XXXkt composite chars can't have size variants
389
    while (child && (child != aChar)) {
399
    while (child && (child != aChar)) {
390
      offset += 5; // skip the 4 partial glyphs + the whitespace separator
400
      offset += 5; // skip the 4 partial glyphs + the whitespace separator
391
      child = child->mSibling;
401
      child = child->mSibling;
392
    }
402
    }
393
    length = 2*(offset + 4); // stay confined in the 4 partial glyphs of this child
403
    length = 3*(offset + 4); // stay confined in the 4 partial glyphs of this child
394
  }
404
  }
395
  PRUint32 index = 2*(offset + aPosition); // 2* is to account for the code@font pairs
405
  PRUint32 index = 3*(offset + aPosition); // 3* is to account for the code@font pairs
396
  if (index+1 >= length) return kNullGlyph;
406
  if (index+2 >= length) return kNullGlyph;
397
  nsGlyphCode ch;
407
  nsGlyphCode ch;
398
  ch.code = mGlyphCache.CharAt(index);
408
  ch.code[0] = mGlyphCache.CharAt(index);
399
  ch.font = mGlyphCache.CharAt(index + 1);
409
  ch.code[1] = mGlyphCache.CharAt(index + 1);
400
  return (ch.code == PRUnichar(0xFFFD)) ? kNullGlyph : ch;
410
  ch.font = mGlyphCache.CharAt(index + 2);
411
  return (ch.code[0] == PRUnichar(0xFFFD) &&
412
          ch.Length() == 1) ? kNullGlyph : ch;
401
}
413
}
402
414
403
PRBool
415
PRBool
404
nsGlyphTable::IsComposite(nsPresContext* aPresContext, nsMathMLChar* aChar)
416
nsGlyphTable::IsComposite(nsPresContext* aPresContext, nsMathMLChar* aChar)
405
{
417
{
406
  // there is only one level of recursion in our model. a child
418
  // there is only one level of recursion in our model. a child
407
  // cannot be composite because it cannot have its own children
419
  // cannot be composite because it cannot have its own children
408
  if (aChar->mParent) return PR_FALSE;
420
  if (aChar->mParent) return PR_FALSE;
409
  // shortcut to sync the cache with this char...
421
  // shortcut to sync the cache with this char...
410
  mCharCache = 0; mGlyphCache.Truncate(); ElementAt(aPresContext, aChar, 0);
422
  mCharCache = 0; mGlyphCache.Truncate(); ElementAt(aPresContext, aChar, 0);
411
  // the cache remained empty if the char wasn't found in this table
423
  // the cache remained empty if the char wasn't found in this table
412
  if (8 >= mGlyphCache.Length()) return PR_FALSE;
424
  if (4*3 >= mGlyphCache.Length()) return PR_FALSE;
413
  // the lists of glyphs of a composite char are space-separated
425
  // the lists of glyphs of a composite char are space-separated
414
  return (kSpaceCh == mGlyphCache.CharAt(8));
426
  return (kSpaceCh == mGlyphCache.CharAt(4*3));
415
}
427
}
416
428
417
PRInt32
429
PRInt32
418
nsGlyphTable::ChildCountOf(nsPresContext* aPresContext, nsMathMLChar* aChar)
430
nsGlyphTable::ChildCountOf(nsPresContext* aPresContext, nsMathMLChar* aChar)
419
{
431
{
420
  // this will sync the cache as well ...
432
  // this will sync the cache as well ...
421
  if (!IsComposite(aPresContext, aChar)) return 0;
433
  if (!IsComposite(aPresContext, aChar)) return 0;
422
  // the lists of glyphs of a composite char are space-separated
434
  // the lists of glyphs of a composite char are space-separated
 Lines 1147-1167   nsMathMLChar::StretchEnumContext::TryVar Link Here 
1147
#endif
1159
#endif
1148
1160
1149
  nsGlyphCode ch;
1161
  nsGlyphCode ch;
1150
  while ((ch = aGlyphTable->BigOf(mPresContext, mChar, size)).Exists()) {
1162
  while ((ch = aGlyphTable->BigOf(mPresContext, mChar, size)).Exists()) {
1151
1163
1152
    SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
1164
    SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
1153
                  font, aGlyphTable, ch, aFamily);
1165
                  font, aGlyphTable, ch, aFamily);
1154
1166
1155
    NS_ASSERTION(maxWidth || ch.code != mChar->mGlyph.code ||
1167
    NS_ASSERTION(maxWidth || ch.code[0] != mChar->mGlyph.code[0] ||
1168
                 ch.code[1] != mChar->mGlyph.code[1] ||
1156
                 !font.name.Equals(mChar->mFamily),
1169
                 !font.name.Equals(mChar->mFamily),
1157
                 "glyph table incorrectly set -- duplicate found");
1170
                 "glyph table incorrectly set -- duplicate found");
1158
1171
1159
    nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(&ch.code, 1);
1172
    nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(ch.code,
1173
                                                                ch.Length());
1160
    nscoord charSize =
1174
    nscoord charSize =
1161
      isVertical ? bm.ascent + bm.descent
1175
      isVertical ? bm.ascent + bm.descent
1162
      : bm.rightBearing - bm.leftBearing;
1176
      : bm.rightBearing - bm.leftBearing;
1163
1177
1164
    if (largeopOnly ||
1178
    if (largeopOnly ||
1165
        IsSizeBetter(charSize, bestSize, mTargetSize, mStretchHint)) {
1179
        IsSizeBetter(charSize, bestSize, mTargetSize, mStretchHint)) {
1166
      mGlyphFound = PR_TRUE;
1180
      mGlyphFound = PR_TRUE;
1167
      if (maxWidth) {
1181
      if (maxWidth) {
 Lines 1269-1285   nsMathMLChar::StretchEnumContext::TryPar Link Here 
1269
    if (!ch.Exists()) {
1283
    if (!ch.Exists()) {
1270
      // Null glue indicates that a rule will be drawn, which can stretch to
1284
      // Null glue indicates that a rule will be drawn, which can stretch to
1271
      // fill any space.  Leave bounding metrics at 0.
1285
      // fill any space.  Leave bounding metrics at 0.
1272
      sizedata[i] = mTargetSize;
1286
      sizedata[i] = mTargetSize;
1273
    }
1287
    }
1274
    else {
1288
    else {
1275
      SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
1289
      SetFontFamily(mChar->mStyleContext->PresContext(), mRenderingContext,
1276
                    font, aGlyphTable, ch, aFamily);
1290
                    font, aGlyphTable, ch, aFamily);
1277
      nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(&ch.code, 1);
1291
      nsBoundingMetrics bm = mRenderingContext.GetBoundingMetrics(ch.code,
1292
                                                                  ch.Length());
1278
1293
1279
      // TODO: For the generic Unicode table, ideally we should check that the
1294
      // TODO: For the generic Unicode table, ideally we should check that the
1280
      // glyphs are actually found and that they each come from the same
1295
      // glyphs are actually found and that they each come from the same
1281
      // font.
1296
      // font.
1282
      bmdata[i] = bm;
1297
      bmdata[i] = bm;
1283
      sizedata[i] = isVertical ? bm.ascent + bm.descent
1298
      sizedata[i] = isVertical ? bm.ascent + bm.descent
1284
                               : bm.rightBearing - bm.leftBearing;
1299
                               : bm.rightBearing - bm.leftBearing;
1285
    }
1300
    }
 Lines 2081-2097   nsMathMLChar::PaintForeground(nsPresCont Link Here 
2081
    aRenderingContext.DrawString(mData.get(), len, 0, mUnscaledAscent);
2096
    aRenderingContext.DrawString(mData.get(), len, 0, mUnscaledAscent);
2082
  }
2097
  }
2083
  else {
2098
  else {
2084
    // Grab some metrics to adjust the placements ...
2099
    // Grab some metrics to adjust the placements ...
2085
    // if there is a glyph of appropriate size, paint that glyph
2100
    // if there is a glyph of appropriate size, paint that glyph
2086
    if (mGlyph.Exists()) {
2101
    if (mGlyph.Exists()) {
2087
//printf("Painting %04X with a glyph of appropriate size\n", mData[0]);
2102
//printf("Painting %04X with a glyph of appropriate size\n", mData[0]);
2088
//aRenderingContext.SetColor(NS_RGB(0,0,255));
2103
//aRenderingContext.SetColor(NS_RGB(0,0,255));
2089
      aRenderingContext.DrawString(&mGlyph.code, 1, 0, mUnscaledAscent);
2104
      aRenderingContext.DrawString(mGlyph.code, mGlyph.Length(),
2105
                                   0, mUnscaledAscent);
2090
    }
2106
    }
2091
    else { // paint by parts
2107
    else { // paint by parts
2092
//aRenderingContext.SetColor(NS_RGB(0,255,0));
2108
//aRenderingContext.SetColor(NS_RGB(0,255,0));
2093
      if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
2109
      if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
2094
        PaintVertically(aPresContext, aRenderingContext, theFont, styleContext,
2110
        PaintVertically(aPresContext, aRenderingContext, theFont, styleContext,
2095
                        mGlyphTable, r);
2111
                        mGlyphTable, r);
2096
      else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
2112
      else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
2097
        PaintHorizontally(aPresContext, aRenderingContext, theFont, styleContext,
2113
        PaintHorizontally(aPresContext, aRenderingContext, theFont, styleContext,
 Lines 2171-2187   nsMathMLChar::PaintVertically(nsPresCont Link Here 
2171
        break;
2187
        break;
2172
    }
2188
    }
2173
    // empty slots are filled with the glue if it is not null
2189
    // empty slots are filled with the glue if it is not null
2174
    if (!ch.Exists()) ch = chGlue;
2190
    if (!ch.Exists()) ch = chGlue;
2175
    // if (!ch.Exists()) glue is null, leave bounding metrics at 0
2191
    // if (!ch.Exists()) glue is null, leave bounding metrics at 0
2176
    if (ch.Exists()) {
2192
    if (ch.Exists()) {
2177
      SetFontFamily(aPresContext, aRenderingContext,
2193
      SetFontFamily(aPresContext, aRenderingContext,
2178
                    aFont, aGlyphTable, ch, mFamily);
2194
                    aFont, aGlyphTable, ch, mFamily);
2179
      bmdata[i] = aRenderingContext.GetBoundingMetrics(&ch.code, 1);
2195
      bmdata[i] = aRenderingContext.GetBoundingMetrics(ch.code, ch.Length());
2180
    }
2196
    }
2181
    chdata[i] = ch;
2197
    chdata[i] = ch;
2182
    ++i;
2198
    ++i;
2183
  }
2199
  }
2184
  nscoord dx = aRect.x;
2200
  nscoord dx = aRect.x;
2185
  nscoord offset[3], start[3], end[3];
2201
  nscoord offset[3], start[3], end[3];
2186
  nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
2202
  nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
2187
  for (i = 0; i <= bottom; ++i) {
2203
  for (i = 0; i <= bottom; ++i) {
 Lines 2256-2272   nsMathMLChar::PaintVertically(nsPresCont Link Here 
2256
          clipRect.y = start[i];
2272
          clipRect.y = start[i];
2257
          clipRect.height = end[i] - start[i];
2273
          clipRect.height = end[i] - start[i];
2258
        }
2274
        }
2259
      }
2275
      }
2260
      if (!clipRect.IsEmpty()) {
2276
      if (!clipRect.IsEmpty()) {
2261
        AutoPushClipRect clip(aRenderingContext, clipRect);
2277
        AutoPushClipRect clip(aRenderingContext, clipRect);
2262
        SetFontFamily(aPresContext, aRenderingContext,
2278
        SetFontFamily(aPresContext, aRenderingContext,
2263
                      aFont, aGlyphTable, ch, mFamily);
2279
                      aFont, aGlyphTable, ch, mFamily);
2264
        aRenderingContext.DrawString(&ch.code, 1, dx, dy);
2280
        aRenderingContext.DrawString(ch.code, ch.Length(), dx, dy);
2265
      }
2281
      }
2266
    }
2282
    }
2267
  }
2283
  }
2268
2284
2269
  ///////////////
2285
  ///////////////
2270
  // fill the gap between top and middle, and between middle and bottom.
2286
  // fill the gap between top and middle, and between middle and bottom.
2271
  if (!chGlue.Exists()) { // null glue : draw a rule
2287
  if (!chGlue.Exists()) { // null glue : draw a rule
2272
    // figure out the dimensions of the rule to be drawn :
2288
    // figure out the dimensions of the rule to be drawn :
 Lines 2332-2348   nsMathMLChar::PaintVertically(nsPresCont Link Here 
2332
      aRenderingContext.DrawRect(clipRect);
2348
      aRenderingContext.DrawRect(clipRect);
2333
      {
2349
      {
2334
#endif
2350
#endif
2335
      while (dy < fillEnd) {
2351
      while (dy < fillEnd) {
2336
        clipRect.y = dy;
2352
        clipRect.y = dy;
2337
        clipRect.height = NS_MIN(bm.ascent + bm.descent, fillEnd - dy);
2353
        clipRect.height = NS_MIN(bm.ascent + bm.descent, fillEnd - dy);
2338
        AutoPushClipRect clip(aRenderingContext, clipRect);
2354
        AutoPushClipRect clip(aRenderingContext, clipRect);
2339
        dy += bm.ascent;
2355
        dy += bm.ascent;
2340
        aRenderingContext.DrawString(&chGlue.code, 1, dx, dy);
2356
        aRenderingContext.DrawString(chGlue.code, chGlue.Length(), dx, dy);
2341
        dy += bm.descent;
2357
        dy += bm.descent;
2342
      }
2358
      }
2343
#ifdef SHOW_BORDERS
2359
#ifdef SHOW_BORDERS
2344
      }
2360
      }
2345
      // last glyph that may cross past its boundary and collide with the next
2361
      // last glyph that may cross past its boundary and collide with the next
2346
      nscoord height = bm.ascent + bm.descent;
2362
      nscoord height = bm.ascent + bm.descent;
2347
      aRenderingContext.SetColor(NS_RGB(0,255,0));
2363
      aRenderingContext.SetColor(NS_RGB(0,255,0));
2348
      aRenderingContext.DrawRect(nsRect(dx, dy-bm.ascent, aRect.width, height));
2364
      aRenderingContext.DrawRect(nsRect(dx, dy-bm.ascent, aRect.width, height));
 Lines 2399-2415   nsMathMLChar::PaintHorizontally(nsPresCo Link Here 
2399
        break;
2415
        break;
2400
    }
2416
    }
2401
    // empty slots are filled with the glue if it is not null
2417
    // empty slots are filled with the glue if it is not null
2402
    if (!ch.Exists()) ch = chGlue;
2418
    if (!ch.Exists()) ch = chGlue;
2403
    // if (!ch.Exists()) glue is null, leave bounding metrics at 0.
2419
    // if (!ch.Exists()) glue is null, leave bounding metrics at 0.
2404
    if (ch.Exists()) {
2420
    if (ch.Exists()) {
2405
      SetFontFamily(aPresContext, aRenderingContext,
2421
      SetFontFamily(aPresContext, aRenderingContext,
2406
                    aFont, aGlyphTable, ch, mFamily);
2422
                    aFont, aGlyphTable, ch, mFamily);
2407
      bmdata[i] = aRenderingContext.GetBoundingMetrics(&ch.code, 1);
2423
      bmdata[i] = aRenderingContext.GetBoundingMetrics(ch.code, ch.Length());
2408
    }
2424
    }
2409
    chdata[i] = ch;
2425
    chdata[i] = ch;
2410
    ++i;
2426
    ++i;
2411
  }
2427
  }
2412
  nscoord dy = aRect.y + mBoundingMetrics.ascent;
2428
  nscoord dy = aRect.y + mBoundingMetrics.ascent;
2413
  nscoord offset[3], start[3], end[3];
2429
  nscoord offset[3], start[3], end[3];
2414
  nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
2430
  nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
2415
  for (i = 0; i <= right; ++i) {
2431
  for (i = 0; i <= right; ++i) {
 Lines 2479-2495   nsMathMLChar::PaintHorizontally(nsPresCo Link Here 
2479
          clipRect.x = start[i];
2495
          clipRect.x = start[i];
2480
          clipRect.width = end[i] - start[i];
2496
          clipRect.width = end[i] - start[i];
2481
        }
2497
        }
2482
      }
2498
      }
2483
      if (!clipRect.IsEmpty()) {
2499
      if (!clipRect.IsEmpty()) {
2484
        AutoPushClipRect clip(aRenderingContext, clipRect);
2500
        AutoPushClipRect clip(aRenderingContext, clipRect);
2485
        SetFontFamily(aPresContext, aRenderingContext,
2501
        SetFontFamily(aPresContext, aRenderingContext,
2486
                      aFont, aGlyphTable, ch, mFamily);
2502
                      aFont, aGlyphTable, ch, mFamily);
2487
        aRenderingContext.DrawString(&ch.code, 1, dx, dy);
2503
        aRenderingContext.DrawString(ch.code, ch.Length(), dx, dy);
2488
      }
2504
      }
2489
    }
2505
    }
2490
  }
2506
  }
2491
2507
2492
  ////////////////
2508
  ////////////////
2493
  // fill the gap between left and middle, and between middle and right.
2509
  // fill the gap between left and middle, and between middle and right.
2494
  if (!chGlue.Exists()) { // null glue : draw a rule
2510
  if (!chGlue.Exists()) { // null glue : draw a rule
2495
    // figure out the dimensions of the rule to be drawn :
2511
    // figure out the dimensions of the rule to be drawn :
 Lines 2554-2570   nsMathMLChar::PaintHorizontally(nsPresCo Link Here 
2554
      aRenderingContext.DrawRect(clipRect);
2570
      aRenderingContext.DrawRect(clipRect);
2555
      {
2571
      {
2556
#endif
2572
#endif
2557
      while (dx < fillEnd) {
2573
      while (dx < fillEnd) {
2558
        clipRect.x = dx;
2574
        clipRect.x = dx;
2559
        clipRect.width = NS_MIN(bm.rightBearing - bm.leftBearing, fillEnd - dx);
2575
        clipRect.width = NS_MIN(bm.rightBearing - bm.leftBearing, fillEnd - dx);
2560
        AutoPushClipRect clip(aRenderingContext, clipRect);
2576
        AutoPushClipRect clip(aRenderingContext, clipRect);
2561
        dx -= bm.leftBearing;
2577
        dx -= bm.leftBearing;
2562
        aRenderingContext.DrawString(&chGlue.code, 1, dx, dy);
2578
        aRenderingContext.DrawString(chGlue.code, chGlue.Length(), dx, dy);
2563
        dx += bm.rightBearing;
2579
        dx += bm.rightBearing;
2564
      }
2580
      }
2565
#ifdef SHOW_BORDERS
2581
#ifdef SHOW_BORDERS
2566
      }
2582
      }
2567
      // last glyph that may cross past its boundary and collide with the next
2583
      // last glyph that may cross past its boundary and collide with the next
2568
      nscoord width = bm.rightBearing - bm.leftBearing;
2584
      nscoord width = bm.rightBearing - bm.leftBearing;
2569
      aRenderingContext.SetColor(NS_RGB(0,255,0));
2585
      aRenderingContext.SetColor(NS_RGB(0,255,0));
2570
      aRenderingContext.DrawRect(nsRect(dx + bm.leftBearing, aRect.y, width, aRect.height));
2586
      aRenderingContext.DrawRect(nsRect(dx + bm.leftBearing, aRect.y, width, aRect.height));
(-)a/layout/mathml/nsMathMLChar.h (-3 / +5 lines)
Line     Link Here 
 Lines 66-91   enum { Link Here 
66
  NS_STRETCH_MAXWIDTH = 0x40
66
  NS_STRETCH_MAXWIDTH = 0x40
67
};
67
};
68
68
69
// A single glyph in our internal representation is characterized by a 'code@font' 
69
// A single glyph in our internal representation is characterized by a 'code@font' 
70
// pair. The 'code' is interpreted as a Unicode point or as the direct glyph index
70
// pair. The 'code' is interpreted as a Unicode point or as the direct glyph index
71
// (depending on the type of nsGlyphTable where this comes from). The 'font' is a
71
// (depending on the type of nsGlyphTable where this comes from). The 'font' is a
72
// numeric identifier given to the font to which the glyph belongs.
72
// numeric identifier given to the font to which the glyph belongs.
73
struct nsGlyphCode {
73
struct nsGlyphCode {
74
  PRUnichar code; 
74
  PRUnichar code[2]; 
75
  PRInt32   font;
75
  PRInt32   font;
76
76
77
  PRInt32 Length() { return (code[1] == PRUnichar('\0') ? 1 : 2); }
77
  PRBool Exists() const
78
  PRBool Exists() const
78
  {
79
  {
79
    return (code != 0);
80
    return (code[0] != 0);
80
  }
81
  }
81
  PRBool operator==(const nsGlyphCode& other) const
82
  PRBool operator==(const nsGlyphCode& other) const
82
  {
83
  {
83
    return other.code == code && other.font == font;
84
    return (other.code[0] == code[0] && other.code[1] == code[1] && 
85
            other.font == font);
84
  }
86
  }
85
  PRBool operator!=(const nsGlyphCode& other) const
87
  PRBool operator!=(const nsGlyphCode& other) const
86
  {
88
  {
87
    return ! operator==(other);
89
    return ! operator==(other);
88
  }
90
  }
89
};
91
};
90
92
91
// Class used to handle stretchy symbols (accent, delimiter and boundary symbols).
93
// Class used to handle stretchy symbols (accent, delimiter and boundary symbols).

Return to bug 407439