Attachment #8404795: Part 1: add a gfxMathTable class to read the MATH table. for bug #407059

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

(-)a/gfx/thebes/MathTableStructures.h (+121 lines)
Line     Link Here 
Line 0    Link Here 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
// This file contains the structures described in Microsoft's document
6
// "The MATH table and OpenType Features for Math Processing" (not yet public).
7
//
8
// Arrays of varying size are indicated in comments. Typically, gfxMathTable
9
// will read the header of the structure first, verify that there is enough
10
// space for the specified arrays and then use a pointer to browse these arrays.
11
12
#ifndef MATH_TABLE_STRUCTURE_H
13
#define MATH_TABLE_STRUCTURE_H
14
15
#include "gfxFontUtils.h"
16
17
typedef mozilla::AutoSwap_PRUint16 Count16;
18
typedef mozilla::AutoSwap_PRUint16 GlyphID;
19
typedef mozilla::AutoSwap_PRUint16 Offset;
20
21
struct MathValueRecord {
22
  mozilla::AutoSwap_PRInt16  mValue;
23
  Offset                     mDeviceTable;
24
};
25
26
struct RangeRecord {
27
  GlyphID                    mStart;
28
  GlyphID                    mEnd;
29
  mozilla::AutoSwap_PRUint16 mStartCoverageIndex;
30
};
31
32
struct Coverage {
33
  mozilla::AutoSwap_PRUint16 mFormat;
34
};
35
36
struct CoverageFormat1 {
37
  mozilla::AutoSwap_PRUint16 mFormat;
38
  Count16                    mGlyphCount;
39
  // GlyphID                 mGlyphArray[mGlyphCount]
40
};
41
42
struct CoverageFormat2 {
43
  mozilla::AutoSwap_PRUint16 mFormat;
44
  Count16                    mRangeCount;
45
  // RangeRecord             mRangeArray[mRangeCount];
46
};
47
48
struct MATHTableHeader {
49
  mozilla::AutoSwap_PRUint32 mVersion;
50
  Offset                     mMathConstants;
51
  Offset                     mMathGlyphInfo;
52
  Offset                     mMathVariants;
53
};
54
55
struct MathConstants {
56
  mozilla::AutoSwap_PRInt16  mInt16[gfxFontEntry::ScriptScriptPercentScaleDown -
57
                                    gfxFontEntry::ScriptPercentScaleDown + 1];
58
  mozilla::AutoSwap_PRUint16 mUint16[gfxFontEntry::DisplayOperatorMinHeight -
59
                                     gfxFontEntry::
60
                                     DelimitedSubFormulaMinHeight + 1];
61
  MathValueRecord            mMathValues[gfxFontEntry::RadicalKernAfterDegree -
62
                                         gfxFontEntry::MathLeading + 1];
63
  mozilla::AutoSwap_PRUint16 mRadicalDegreeBottomRaisePercent;
64
};
65
66
struct MathGlyphInfo {
67
  Offset mMathItalicsCorrectionInfo;
68
  Offset mMathTopAccentAttachment;
69
  Offset mExtendedShapeCoverage;
70
  Offset mMathKernInfo;
71
};
72
73
struct MathItalicsCorrectionInfo {
74
  Offset  mCoverage;
75
  Count16 mItalicsCorrectionCount;
76
  // MathValueRecord mItalicsCorrection[mItalicsCorrectionCount]
77
};
78
79
struct MathVariants {
80
  mozilla::AutoSwap_PRUint16 mMinConnectorOverlap;
81
  Offset                     mVertGlyphCoverage;
82
  Offset                     mHorizGlyphCoverage;
83
  Count16                    mVertGlyphCount;
84
  Count16                    mHorizGlyphCount;
85
  // Offset                  mVertGlyphConstruction[mVertGlyphCount];
86
  // Offset                  mHorizGlyphConstruction[mHorizGlyphCount];
87
};
88
89
struct MathGlyphVariantRecord {
90
  GlyphID                    mVariantGlyph;
91
  mozilla::AutoSwap_PRUint16 mAdvanceMeasurement;
92
};
93
94
struct MathGlyphConstruction {
95
  Offset                    mGlyphAssembly;
96
  Count16                   mVariantCount;
97
  // MathGlyphVariantRecord mMathGlyphVariantRecord[mVariantCount]
98
};
99
100
struct GlyphPartRecord {
101
  GlyphID	              mGlyph;
102
  mozilla::AutoSwap_PRUint16 mStartConnectorLength;
103
  mozilla::AutoSwap_PRUint16 mEndConnectorLength;
104
  mozilla::AutoSwap_PRUint16 mFullAdvance;
105
  mozilla::AutoSwap_PRUint16 mPartFlags;
106
};
107
108
// PartFlags enumeration currently uses only one bit:
109
// 0x0001 If set, the part can be skipped or repeated.
110
// 0xFFFE Reserved.
111
enum {
112
  PART_FLAG_EXTENDER = 0x01
113
};
114
115
struct GlyphAssembly {
116
  MathValueRecord    mItalicsCorrection;
117
  Count16            mPartCount;
118
  // GlyphPartRecord mPartRecords[mPartCount]
119
};
120
121
#endif
(-)a/gfx/thebes/gfxFont.cpp (+75 lines)
Line     Link Here 
 Lines 33-48    Link Here 
33
#include "nsStyleConsts.h"
33
#include "nsStyleConsts.h"
34
#include "mozilla/FloatingPoint.h"
34
#include "mozilla/FloatingPoint.h"
35
#include "mozilla/Likely.h"
35
#include "mozilla/Likely.h"
36
#include "mozilla/MemoryReporting.h"
36
#include "mozilla/MemoryReporting.h"
37
#include "mozilla/Preferences.h"
37
#include "mozilla/Preferences.h"
38
#include "mozilla/Services.h"
38
#include "mozilla/Services.h"
39
#include "mozilla/Telemetry.h"
39
#include "mozilla/Telemetry.h"
40
#include "gfxSVGGlyphs.h"
40
#include "gfxSVGGlyphs.h"
41
#include "gfxMathTable.h"
41
#include "gfx2DGlue.h"
42
#include "gfx2DGlue.h"
42
43
43
#if defined(XP_MACOSX)
44
#if defined(XP_MACOSX)
44
#include "nsCocoaFeatures.h"
45
#include "nsCocoaFeatures.h"
45
#endif
46
#endif
46
47
47
#include "cairo.h"
48
#include "cairo.h"
48
#include "gfxFontTest.h"
49
#include "gfxFontTest.h"
 Lines 107-122   gfxFontEntry::gfxFontEntry() : Link Here 
107
    mIsBadUnderlineFont(false),
108
    mIsBadUnderlineFont(false),
108
    mIsUserFont(false),
109
    mIsUserFont(false),
109
    mIsLocalUserFont(false),
110
    mIsLocalUserFont(false),
110
    mStandardFace(false),
111
    mStandardFace(false),
111
    mSymbolFont(false),
112
    mSymbolFont(false),
112
    mIgnoreGDEF(false),
113
    mIgnoreGDEF(false),
113
    mIgnoreGSUB(false),
114
    mIgnoreGSUB(false),
114
    mSVGInitialized(false),
115
    mSVGInitialized(false),
116
    mMathInitialized(false),
115
    mHasSpaceFeaturesInitialized(false),
117
    mHasSpaceFeaturesInitialized(false),
116
    mHasSpaceFeatures(false),
118
    mHasSpaceFeatures(false),
117
    mHasSpaceFeaturesKerning(false),
119
    mHasSpaceFeaturesKerning(false),
118
    mHasSpaceFeaturesNonKerning(false),
120
    mHasSpaceFeaturesNonKerning(false),
119
    mSkipDefaultFeatureSpaceCheck(false),
121
    mSkipDefaultFeatureSpaceCheck(false),
120
    mCheckedForGraphiteTables(false),
122
    mCheckedForGraphiteTables(false),
121
    mHasCmapTable(false),
123
    mHasCmapTable(false),
122
    mGrFaceInitialized(false),
124
    mGrFaceInitialized(false),
 Lines 136-151   gfxFontEntry::gfxFontEntry(const nsAStri Link Here 
136
    mName(aName), mItalic(false), mFixedPitch(false),
138
    mName(aName), mItalic(false), mFixedPitch(false),
137
    mIsProxy(false), mIsValid(true),
139
    mIsProxy(false), mIsValid(true),
138
    mIsBadUnderlineFont(false), mIsUserFont(false),
140
    mIsBadUnderlineFont(false), mIsUserFont(false),
139
    mIsLocalUserFont(false), mStandardFace(aIsStandardFace),
141
    mIsLocalUserFont(false), mStandardFace(aIsStandardFace),
140
    mSymbolFont(false),
142
    mSymbolFont(false),
141
    mIgnoreGDEF(false),
143
    mIgnoreGDEF(false),
142
    mIgnoreGSUB(false),
144
    mIgnoreGSUB(false),
143
    mSVGInitialized(false),
145
    mSVGInitialized(false),
146
    mMathInitialized(false),
144
    mHasSpaceFeaturesInitialized(false),
147
    mHasSpaceFeaturesInitialized(false),
145
    mHasSpaceFeatures(false),
148
    mHasSpaceFeatures(false),
146
    mHasSpaceFeaturesKerning(false),
149
    mHasSpaceFeaturesKerning(false),
147
    mHasSpaceFeaturesNonKerning(false),
150
    mHasSpaceFeaturesNonKerning(false),
148
    mSkipDefaultFeatureSpaceCheck(false),
151
    mSkipDefaultFeatureSpaceCheck(false),
149
    mCheckedForGraphiteTables(false),
152
    mCheckedForGraphiteTables(false),
150
    mHasCmapTable(false),
153
    mHasCmapTable(false),
151
    mGrFaceInitialized(false),
154
    mGrFaceInitialized(false),
 Lines 384-399   void Link Here 
384
gfxFontEntry::NotifyGlyphsChanged()
387
gfxFontEntry::NotifyGlyphsChanged()
385
{
388
{
386
    for (uint32_t i = 0, count = mFontsUsingSVGGlyphs.Length(); i < count; ++i) {
389
    for (uint32_t i = 0, count = mFontsUsingSVGGlyphs.Length(); i < count; ++i) {
387
        gfxFont* font = mFontsUsingSVGGlyphs[i];
390
        gfxFont* font = mFontsUsingSVGGlyphs[i];
388
        font->NotifyGlyphsChanged();
391
        font->NotifyGlyphsChanged();
389
    }
392
    }
390
}
393
}
391
394
395
bool
396
gfxFontEntry::TryGetMathTable(gfxFont* aFont)
397
{
398
    if (!mMathInitialized) {
399
        mMathInitialized = true;
400
401
        // If UnitsPerEm is not known/valid, we can't use MATH table
402
        if (UnitsPerEm() == kInvalidUPEM) {
403
            return false;
404
        }
405
406
        // We don't use AutoTable here because we'll pass ownership of this
407
        // blob to the gfxMathTable, once we've confirmed the table exists
408
        hb_blob_t *mathTable = GetFontTable(TRUETYPE_TAG('M','A','T','H'));
409
        if (!mathTable) {
410
            return false;
411
        }
412
413
        // gfxMathTable will hb_blob_destroy() the table when it is finished
414
        // with it.
415
        mMathTable = new gfxMathTable(mathTable);
416
        if (!mMathTable->HasValidHeaders()) {
417
            mMathTable = nullptr;
418
            return false;
419
        }
420
    }
421
422
    return !!mMathTable;
423
}
424
425
gfxFloat
426
gfxFontEntry::GetMathConstant(gfxFontEntry::MathConstant aConstant)
427
{
428
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
429
    gfxFloat value = mMathTable->GetMathConstant(aConstant);
430
    if (aConstant == gfxFontEntry::ScriptPercentScaleDown ||
431
        aConstant == gfxFontEntry::ScriptScriptPercentScaleDown ||
432
        aConstant == gfxFontEntry::RadicalDegreeBottomRaisePercent) {
433
        return value / 100.0;
434
    }
435
    return value / mUnitsPerEm;
436
}
437
438
bool
439
gfxFontEntry::GetMathItalicsCorrection(uint32_t aGlyphID,
440
                                       gfxFloat* aItalicCorrection)
441
{
442
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
443
    int16_t italicCorrection;
444
    if (!mMathTable->GetMathItalicsCorrection(aGlyphID, &italicCorrection)) {
445
        return false;
446
    }
447
    *aItalicCorrection = gfxFloat(italicCorrection) / mUnitsPerEm;
448
    return true;
449
}
450
451
uint32_t
452
gfxFontEntry::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
453
                                  uint16_t aSize)
454
{
455
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
456
    return mMathTable->GetMathVariantsSize(aGlyphID, aVertical, aSize);
457
}
458
459
bool
460
gfxFontEntry::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
461
                                   uint32_t aGlyphs[4])
462
{
463
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
464
    return mMathTable->GetMathVariantsParts(aGlyphID, aVertical, aGlyphs);
465
}
466
392
/**
467
/**
393
 * FontTableBlobData
468
 * FontTableBlobData
394
 *
469
 *
395
 * See FontTableHashEntry for the general strategy.
470
 * See FontTableHashEntry for the general strategy.
396
 */
471
 */
397
472
398
class gfxFontEntry::FontTableBlobData {
473
class gfxFontEntry::FontTableBlobData {
399
public:
474
public:
(-)a/gfx/thebes/gfxFont.h (+76 lines)
Line     Link Here 
 Lines 43-58   class gfxTextRun; Link Here 
43
class gfxFont;
43
class gfxFont;
44
class gfxFontFamily;
44
class gfxFontFamily;
45
class gfxFontGroup;
45
class gfxFontGroup;
46
class gfxUserFontSet;
46
class gfxUserFontSet;
47
class gfxUserFontData;
47
class gfxUserFontData;
48
class gfxShapedText;
48
class gfxShapedText;
49
class gfxShapedWord;
49
class gfxShapedWord;
50
class gfxSVGGlyphs;
50
class gfxSVGGlyphs;
51
class gfxMathTable;
51
class gfxTextContextPaint;
52
class gfxTextContextPaint;
52
class FontInfoData;
53
class FontInfoData;
53
54
54
class nsILanguageAtomService;
55
class nsILanguageAtomService;
55
56
56
#define FONT_MAX_SIZE                  2000.0
57
#define FONT_MAX_SIZE                  2000.0
57
58
58
#define NO_FONT_LANGUAGE_OVERRIDE      0
59
#define NO_FONT_LANGUAGE_OVERRIDE      0
 Lines 308-323   public: Link Here 
308
    bool GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
309
    bool GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
309
                            gfxRect *aResult);
310
                            gfxRect *aResult);
310
    bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, int aDrawMode,
311
    bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, int aDrawMode,
311
                        gfxTextContextPaint *aContextPaint);
312
                        gfxTextContextPaint *aContextPaint);
312
    // Call this when glyph geometry or rendering has changed
313
    // Call this when glyph geometry or rendering has changed
313
    // (e.g. animated SVG glyphs)
314
    // (e.g. animated SVG glyphs)
314
    void NotifyGlyphsChanged();
315
    void NotifyGlyphsChanged();
315
316
317
    enum MathConstant {
318
        // The order of the constants must match the order of the fields
319
        // defined in the MATH table.
320
        ScriptPercentScaleDown,
321
        ScriptScriptPercentScaleDown,
322
        DelimitedSubFormulaMinHeight,
323
        DisplayOperatorMinHeight,
324
        MathLeading,
325
        AxisHeight,
326
        AccentBaseHeight,
327
        FlattenedAccentBaseHeight,
328
        SubscriptShiftDown,
329
        SubscriptTopMax,
330
        SubscriptBaselineDropMin,
331
        SuperscriptShiftUp,
332
        SuperscriptShiftUpCramped,
333
        SuperscriptBottomMin,
334
        SuperscriptBaselineDropMax,
335
        SubSuperscriptGapMin,
336
        SuperscriptBottomMaxWithSubscript,
337
        SpaceAfterScript,
338
        UpperLimitGapMin,
339
        UpperLimitBaselineRiseMin,
340
        LowerLimitGapMin,
341
        LowerLimitBaselineDropMin,
342
        StackTopShiftUp,
343
        StackTopDisplayStyleShiftUp,
344
        StackBottomShiftDown,
345
        StackBottomDisplayStyleShiftDown,
346
        StackGapMin,
347
        StackDisplayStyleGapMin,
348
        StretchStackTopShiftUp,
349
        StretchStackBottomShiftDown,
350
        StretchStackGapAboveMin,
351
        StretchStackGapBelowMin,
352
        FractionNumeratorShiftUp,
353
        FractionNumeratorDisplayStyleShiftUp,
354
        FractionDenominatorShiftDown,
355
        FractionDenominatorDisplayStyleShiftDown,
356
        FractionNumeratorGapMin,
357
        FractionNumDisplayStyleGapMin,
358
        FractionRuleThickness,
359
        FractionDenominatorGapMin,
360
        FractionDenomDisplayStyleGapMin,
361
        SkewedFractionHorizontalGap,
362
        SkewedFractionVerticalGap,
363
        OverbarVerticalGap,
364
        OverbarRuleThickness,
365
        OverbarExtraAscender,
366
        UnderbarVerticalGap,
367
        UnderbarRuleThickness,
368
        UnderbarExtraDescender,
369
        RadicalVerticalGap,
370
        RadicalDisplayStyleVerticalGap,
371
        RadicalRuleThickness,
372
        RadicalExtraAscender,
373
        RadicalKernBeforeDegree,
374
        RadicalKernAfterDegree,
375
        RadicalDegreeBottomRaisePercent
376
    };
377
378
    // Call TryGetMathTable to try to load the Open Type MATH table. The other
379
    // functions forward the call to the gfxMathTable class. The GetMath...()
380
    // functions MUST NOT be called unless TryGetMathTable() has returned true.
381
    bool     TryGetMathTable(gfxFont* aFont);
382
    gfxFloat GetMathConstant(MathConstant aConstant);
383
    bool     GetMathItalicsCorrection(uint32_t aGlyphID,
384
                                      gfxFloat* aItalicCorrection);
385
    uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
386
                                 uint16_t aSize);
387
    bool     GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
388
                                  uint32_t aGlyphs[4]);
389
316
    virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
390
    virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
317
        return true;
391
        return true;
318
    }
392
    }
319
    virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
393
    virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
320
        return true;
394
        return true;
321
    }
395
    }
322
396
323
    // Access to raw font table data (needed for Harfbuzz):
397
    // Access to raw font table data (needed for Harfbuzz):
 Lines 430-445   public: Link Here 
430
    bool             mIsBadUnderlineFont : 1;
504
    bool             mIsBadUnderlineFont : 1;
431
    bool             mIsUserFont  : 1;
505
    bool             mIsUserFont  : 1;
432
    bool             mIsLocalUserFont  : 1;
506
    bool             mIsLocalUserFont  : 1;
433
    bool             mStandardFace : 1;
507
    bool             mStandardFace : 1;
434
    bool             mSymbolFont  : 1;
508
    bool             mSymbolFont  : 1;
435
    bool             mIgnoreGDEF  : 1;
509
    bool             mIgnoreGDEF  : 1;
436
    bool             mIgnoreGSUB  : 1;
510
    bool             mIgnoreGSUB  : 1;
437
    bool             mSVGInitialized : 1;
511
    bool             mSVGInitialized : 1;
512
    bool             mMathInitialized : 1;
438
    bool             mHasSpaceFeaturesInitialized : 1;
513
    bool             mHasSpaceFeaturesInitialized : 1;
439
    bool             mHasSpaceFeatures : 1;
514
    bool             mHasSpaceFeatures : 1;
440
    bool             mHasSpaceFeaturesKerning : 1;
515
    bool             mHasSpaceFeaturesKerning : 1;
441
    bool             mHasSpaceFeaturesNonKerning : 1;
516
    bool             mHasSpaceFeaturesNonKerning : 1;
442
    bool             mSkipDefaultFeatureSpaceCheck : 1;
517
    bool             mSkipDefaultFeatureSpaceCheck : 1;
443
    bool             mHasGraphiteTables : 1;
518
    bool             mHasGraphiteTables : 1;
444
    bool             mCheckedForGraphiteTables : 1;
519
    bool             mCheckedForGraphiteTables : 1;
445
    bool             mHasCmapTable : 1;
520
    bool             mHasCmapTable : 1;
 Lines 455-470   public: Link Here 
455
530
456
    nsRefPtr<gfxCharacterMap> mCharacterMap;
531
    nsRefPtr<gfxCharacterMap> mCharacterMap;
457
    uint32_t         mUVSOffset;
532
    uint32_t         mUVSOffset;
458
    nsAutoArrayPtr<uint8_t> mUVSData;
533
    nsAutoArrayPtr<uint8_t> mUVSData;
459
    nsAutoPtr<gfxUserFontData> mUserFontData;
534
    nsAutoPtr<gfxUserFontData> mUserFontData;
460
    nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
535
    nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
461
    // list of gfxFonts that are using SVG glyphs
536
    // list of gfxFonts that are using SVG glyphs
462
    nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
537
    nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
538
    nsAutoPtr<gfxMathTable> mMathTable;
463
    nsTArray<gfxFontFeature> mFeatureSettings;
539
    nsTArray<gfxFontFeature> mFeatureSettings;
464
    uint32_t         mLanguageOverride;
540
    uint32_t         mLanguageOverride;
465
541
466
protected:
542
protected:
467
    friend class gfxPlatformFontList;
543
    friend class gfxPlatformFontList;
468
    friend class gfxMacPlatformFontList;
544
    friend class gfxMacPlatformFontList;
469
    friend class gfxUserFcFontEntry;
545
    friend class gfxUserFcFontEntry;
470
    friend class gfxFontFamily;
546
    friend class gfxFontFamily;
(-)a/gfx/thebes/gfxMathTable.cpp (+459 lines)
Line     Link Here 
Line 0    Link Here 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "gfxMathTable.h"
6
7
#include "MathTableStructures.h"
8
#include "harfbuzz/hb.h"
9
#include <algorithm>
10
11
using namespace mozilla;
12
13
gfxMathTable::gfxMathTable(hb_blob_t* aMathTable)
14
  : mMathTable(aMathTable)
15
  , mGlyphConstruction(nullptr)
16
  , mGlyphID(-1)
17
  , mVertical(false)
18
{
19
}
20
21
gfxMathTable::~gfxMathTable()
22
{
23
  hb_blob_destroy(mMathTable);
24
}
25
26
bool
27
gfxMathTable::HasValidHeaders()
28
{
29
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
30
  // Verify the MATH table header.
31
  if (!ValidStructure(mathData, sizeof(MATHTableHeader))) {
32
    return false;
33
  }
34
  const MATHTableHeader* header = GetMATHTableHeader();
35
  if (uint32_t(header->mVersion) != 0x00010000 ||
36
      !ValidOffset(mathData, uint16_t(header->mMathConstants)) ||
37
      !ValidOffset(mathData, uint16_t(header->mMathGlyphInfo)) ||
38
      !ValidOffset(mathData, uint16_t(header->mMathVariants))) {
39
    return false;
40
  }
41
42
  // Verify the MathConstants header.
43
  const MathConstants* mathconstants = GetMathConstants();
44
  const char* start = reinterpret_cast<const char*>(mathconstants);
45
  if (!ValidStructure(start, sizeof(MathConstants))) {
46
    return false;
47
  }
48
49
  // Verify the MathGlyphInfo header.
50
  const MathGlyphInfo* mathglyphinfo = GetMathGlyphInfo();
51
  start = reinterpret_cast<const char*>(mathglyphinfo);
52
  if (!ValidStructure(start, sizeof(MathGlyphInfo))) {
53
    return false;
54
  }
55
56
  // Verify the MathVariants header.
57
  const MathVariants* mathvariants = GetMathVariants();
58
  start = reinterpret_cast<const char*>(mathvariants);
59
  if (!ValidStructure(start, sizeof(MathVariants)) ||
60
      !ValidStructure(start,
61
                      sizeof(MathVariants) + sizeof(Offset) *
62
                      (uint16_t(mathvariants->mVertGlyphCount) +
63
                       uint16_t(mathvariants->mHorizGlyphCount))) ||
64
      !ValidOffset(start, uint16_t(mathvariants->mVertGlyphCoverage)) ||
65
      !ValidOffset(start, uint16_t(mathvariants->mHorizGlyphCoverage))) {
66
    return false;
67
  }
68
69
  return true;
70
}
71
72
int32_t
73
gfxMathTable::GetMathConstant(gfxFontEntry::MathConstant aConstant)
74
{
75
  const MathConstants* mathconstants = GetMathConstants();
76
77
  if (aConstant <= gfxFontEntry::ScriptScriptPercentScaleDown) {
78
    return int16_t(mathconstants->mInt16[aConstant]);
79
  }
80
81
  if (aConstant <= gfxFontEntry::DisplayOperatorMinHeight) {
82
    return
83
      uint16_t(mathconstants->
84
               mUint16[aConstant - gfxFontEntry::DelimitedSubFormulaMinHeight]);
85
  }
86
87
  if (aConstant <= gfxFontEntry::RadicalKernAfterDegree) {
88
    return int16_t(mathconstants->
89
                   mMathValues[aConstant - gfxFontEntry::MathLeading].mValue);
90
  }
91
92
  return uint16_t(mathconstants->mRadicalDegreeBottomRaisePercent);
93
}
94
95
bool
96
gfxMathTable::GetMathItalicsCorrection(uint32_t aGlyphID,
97
                                       int16_t* aItalicCorrection)
98
{
99
  const MathGlyphInfo* mathglyphinfo = GetMathGlyphInfo();
100
101
  // Get the offset of the italic correction and verify whether it is valid.
102
  const char* start = reinterpret_cast<const char*>(mathglyphinfo);
103
  uint16_t offset = mathglyphinfo->mMathItalicsCorrectionInfo;
104
  if (offset == 0 || !ValidOffset(start, offset)) {
105
    return false;
106
  }
107
  start += offset;
108
109
  // Verify the validity of the MathItalicsCorrectionInfo and retrieve it.
110
  if (!ValidStructure(start, sizeof(MathItalicsCorrectionInfo))) {
111
    return false;
112
  }
113
  const MathItalicsCorrectionInfo* italicsCorrectionInfo =
114
    reinterpret_cast<const MathItalicsCorrectionInfo*>(start);
115
116
  // Get the coverage index for the glyph.
117
  offset = italicsCorrectionInfo->mCoverage;
118
  const Coverage* coverage =
119
    reinterpret_cast<const Coverage*>(start + offset);
120
  int32_t i = GetCoverageIndex(coverage, aGlyphID);
121
122
  // Get the ItalicsCorrection.
123
  uint16_t count = italicsCorrectionInfo->mItalicsCorrectionCount;
124
  if (i < 0 || i >= count) {
125
    return false;
126
  }
127
  start = reinterpret_cast<const char*>(italicsCorrectionInfo + 1);
128
  if (!ValidStructure(start, count * sizeof(MathValueRecord))) {
129
    return false;
130
  }
131
  const MathValueRecord* mathValueRecordArray =
132
    reinterpret_cast<const MathValueRecord*>(start);
133
134
  *aItalicCorrection = int16_t(mathValueRecordArray[i].mValue);
135
  return true;
136
}
137
138
uint32_t
139
gfxMathTable::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
140
                                  uint16_t aSize)
141
{
142
  // Select the glyph construction.
143
  SelectGlyphConstruction(aGlyphID, aVertical);
144
  if (!mGlyphConstruction) {
145
    return 0;
146
  }
147
148
  // Verify the validity of the array of the MathGlyphVariantRecord's and
149
  // whether there is a variant of the requested size.
150
  uint16_t count = mGlyphConstruction->mVariantCount;
151
  const char* start = reinterpret_cast<const char*>(mGlyphConstruction + 1);
152
  if (aSize >= count ||
153
      !ValidStructure(start, count * sizeof(MathGlyphVariantRecord))) {
154
    return 0;
155
  }
156
157
  // Return the glyph index of the requested size variant.
158
  const MathGlyphVariantRecord* recordArray =
159
    reinterpret_cast<const MathGlyphVariantRecord*>(start);
160
  return uint32_t(recordArray[aSize].mVariantGlyph);
161
}
162
163
bool
164
gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
165
                                   uint32_t aGlyphs[4])
166
{
167
  // Get the glyph assembly corresponding to that (aGlyphID, aVertical) pair.
168
  const GlyphAssembly* glyphAssembly = GetGlyphAssembly(aGlyphID, aVertical);
169
  if (!glyphAssembly) {
170
    return false;
171
  }
172
173
  // Verify the validity of the array of GlyphPartRecord's and retrieve it.
174
  uint16_t count = glyphAssembly->mPartCount;
175
  const char* start = reinterpret_cast<const char*>(glyphAssembly + 1);
176
  if (!ValidStructure(start, count * sizeof(GlyphPartRecord))) {
177
    return false;
178
  }
179
  const GlyphPartRecord* recordArray =
180
    reinterpret_cast<const GlyphPartRecord*>(start);
181
182
  // XXXfredw The structure of the Open Type Math table is a bit more general
183
  // than the one currently used by the nsMathMLChar code, so we try to fallback
184
  // in reasonable way. We use the approach of the copyComponents function in
185
  // github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
186
  //
187
  // The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
188
  // aGlyphs[1] and aGlyphs[2]) and the extenders between these pieces should
189
  // all be the same (aGlyphs[4]). Also, the parts of vertical assembly are
190
  // stored from bottom to top in the Open Type MATH table while they are
191
  // stored from top to bottom in nsMathMLChar.
192
193
  // Count the number of non extender pieces
194
  uint16_t nonExtenderCount = 0;
195
  for (uint16_t i = 0; i < count; i++) {
196
    if (!(uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER)) {
197
      nonExtenderCount++;
198
    }
199
  }
200
  if (nonExtenderCount > 3) {
201
    // Not supported: too many pieces
202
    return false;
203
  }
204
205
  // Now browse the list of pieces
206
207
  // 0 = look for a left/bottom glyph
208
  // 1 = look for an extender between left/bottom and mid
209
  // 2 = look for a middle glyph
210
  // 3 = look for an extender between middle and right/top
211
  // 4 = look for a right/top glyph
212
  // 5 = no more piece expected
213
  uint8_t state = 0;
214
215
  // First extender char found.
216
  uint32_t extenderChar = 0;
217
218
  // Clear the aGlyphs table.
219
  memset(aGlyphs, 0, sizeof(uint32_t) * 4);
220
221
  for (uint16_t i = 0; i < count; i++) {
222
223
    bool isExtender = uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER;
224
    uint32_t glyph = recordArray[i].mGlyph;
225
226
    if ((state == 1 || state == 2) && nonExtenderCount < 3) {
227
      // do not try to find a middle glyph
228
      state += 2;
229
    }
230
231
    if (isExtender) {
232
      if (!extenderChar) {
233
        extenderChar = glyph;
234
        aGlyphs[3] = extenderChar;
235
      } else if (extenderChar != glyph)  {
236
        // Not supported: different extenders
237
        return false;
238
      }
239
240
      if (state == 0) { // or state == 1
241
        // ignore left/bottom piece and multiple successive extenders
242
        state = 1;
243
      } else if (state == 2) { // or state == 3
244
        // ignore middle piece and multiple successive extenders
245
        state = 3;
246
      } else if (state >= 4) {
247
        // Not supported: unexpected extender
248
        return false;
249
      }
250
251
      continue;
252
    }
253
254
    if (state == 0) {
255
      // copy left/bottom part
256
      aGlyphs[mVertical ? 2 : 0] = glyph;
257
      state = 1;
258
      continue;
259
    }
260
261
    if (state == 1 || state == 2) {
262
      // copy middle part
263
      aGlyphs[1] = glyph;
264
      state = 3;
265
      continue;
266
    }
267
268
    if (state == 3 || state == 4) {
269
      // copy right/top part
270
      aGlyphs[mVertical ? 0 : 2] = glyph;
271
      state = 5;
272
    }
273
274
  }
275
276
  return true;
277
}
278
279
bool
280
gfxMathTable::ValidStructure(const char* aStart, uint16_t aSize)
281
{
282
  unsigned int mathDataLength;
283
  const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
284
  return (mathData <= aStart &&
285
          aStart + aSize <= mathData + mathDataLength);
286
}
287
288
bool
289
gfxMathTable::ValidOffset(const char* aStart, uint16_t aOffset)
290
{
291
  unsigned int mathDataLength;
292
  const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
293
  return (mathData <= aStart + aOffset &&
294
          aStart + aOffset < mathData + mathDataLength);
295
}
296
297
const MATHTableHeader*
298
gfxMathTable::GetMATHTableHeader()
299
{
300
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
301
  return reinterpret_cast<const MATHTableHeader*>(mathData);
302
}
303
304
const MathConstants*
305
gfxMathTable::GetMathConstants()
306
{
307
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
308
  return
309
    reinterpret_cast<const MathConstants*>(mathData +
310
                                           uint16_t(GetMATHTableHeader()->
311
                                                    mMathConstants));
312
}
313
314
const MathGlyphInfo*
315
gfxMathTable::GetMathGlyphInfo()
316
{
317
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
318
  return
319
    reinterpret_cast<const MathGlyphInfo*>(mathData +
320
                                           uint16_t(GetMATHTableHeader()->
321
                                                    mMathGlyphInfo));
322
}
323
324
const MathVariants*
325
gfxMathTable::GetMathVariants()
326
{
327
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
328
  return
329
    reinterpret_cast<const MathVariants*>(mathData +
330
                                          uint16_t(GetMATHTableHeader()->
331
                                                   mMathVariants));
332
}
333
334
const GlyphAssembly*
335
gfxMathTable::GetGlyphAssembly(uint32_t aGlyphID, bool aVertical)
336
{
337
  // Select the glyph construction.
338
  SelectGlyphConstruction(aGlyphID, aVertical);
339
  if (!mGlyphConstruction) {
340
    return nullptr;
341
  }
342
343
  // Get the offset of the glyph assembly and verify whether it is valid.
344
  const char* start = reinterpret_cast<const char*>(mGlyphConstruction);
345
  uint16_t offset = mGlyphConstruction->mGlyphAssembly;
346
  if (offset == 0 || !ValidOffset(start, offset)) {
347
    return nullptr;
348
  }
349
  start += offset;
350
351
  // Verify the validity of the GlyphAssembly and return it.
352
  if (!ValidStructure(start, sizeof(GlyphAssembly))) {
353
    return nullptr;
354
  }
355
  return reinterpret_cast<const GlyphAssembly*>(start);
356
}
357
358
int32_t
359
gfxMathTable::GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph)
360
{
361
  if (uint16_t(aCoverage->mFormat) == 1) {
362
    // Coverage Format 1: list of individual glyph indices in the glyph set.
363
    const CoverageFormat1* table =
364
      reinterpret_cast<const CoverageFormat1*>(aCoverage);
365
    uint16_t count = table->mGlyphCount;
366
    const char* start = reinterpret_cast<const char*>(table + 1);
367
    if (ValidStructure(start, count * sizeof(GlyphID))) {
368
      const GlyphID* glyphArray =
369
        reinterpret_cast<const GlyphID*>(start);
370
      uint32_t imin = 0, imax = count;
371
      while (imin < imax) {
372
        uint32_t imid = (imin + imax) >> 1;
373
        uint16_t glyphMid = glyphArray[imid];
374
        if (glyphMid == aGlyph) {
375
          return imid;
376
        }
377
        if (glyphMid < aGlyph) {
378
          imin = imid + 1;
379
        } else {
380
          imax = imid;
381
        }
382
      }
383
    }
384
  } else if (uint16_t(aCoverage->mFormat) == 2) {
385
    // Coverage Format 2: ranges of consecutive indices.
386
    const CoverageFormat2* table =
387
      reinterpret_cast<const CoverageFormat2*>(aCoverage);
388
    uint16_t count = table->mRangeCount;
389
    const char* start = reinterpret_cast<const char*>(table + 1);
390
    if (ValidStructure(start, count * sizeof(RangeRecord))) {
391
      const RangeRecord* rangeArray =
392
        reinterpret_cast<const RangeRecord*>(start);
393
      uint32_t imin = 0, imax = count;
394
      while (imin < imax) {
395
        uint32_t imid = (imin + imax) >> 1;
396
        uint16_t rStart = rangeArray[imid].mStart;
397
        uint16_t rEnd = rangeArray[imid].mEnd;
398
        if (rEnd < aGlyph) {
399
          imin = imid + 1;
400
        } else if (aGlyph < rStart) {
401
          imax = imid;
402
        } else {
403
          return (uint16_t(rangeArray[imid].mStartCoverageIndex) +
404
                  aGlyph - rStart);
405
        }
406
      }
407
    }
408
  }
409
  return -1;
410
}
411
412
void
413
gfxMathTable::SelectGlyphConstruction(uint32_t aGlyphID, bool aVertical)
414
{
415
  if (mGlyphID == aGlyphID && mVertical == aVertical) {
416
    // The (glyph, direction) pair is already selected: nothing to do.
417
    return;
418
  }
419
420
  // Update our cached values.
421
  mVertical = aVertical;
422
  mGlyphID = aGlyphID;
423
  mGlyphConstruction = nullptr;
424
425
  // Get the coverage index for the new values.
426
  const MathVariants* mathvariants = GetMathVariants();
427
  const char* start = reinterpret_cast<const char*>(mathvariants);
428
  uint16_t offset = (aVertical ?
429
                     mathvariants->mVertGlyphCoverage :
430
                     mathvariants->mHorizGlyphCoverage);
431
  const Coverage* coverage =
432
    reinterpret_cast<const Coverage*>(start + offset);
433
  int32_t i = GetCoverageIndex(coverage, aGlyphID);
434
435
  // Get the offset to the glyph construction.
436
  uint16_t count = (aVertical ?
437
                    mathvariants->mVertGlyphCount :
438
                    mathvariants->mHorizGlyphCount);
439
  start = reinterpret_cast<const char*>(mathvariants + 1);
440
  if (i < 0 || i >= count) {
441
    return;
442
  }
443
  if (!aVertical) {
444
    start += uint16_t(mathvariants->mVertGlyphCount) * sizeof(Offset);
445
  }
446
  if (!ValidStructure(start, count * sizeof(Offset))) {
447
    return;
448
  }
449
  const Offset* offsetArray = reinterpret_cast<const Offset*>(start);
450
  offset = uint16_t(offsetArray[i]);
451
452
  // Make mGlyphConstruction point to the desired glyph construction.
453
  start = reinterpret_cast<const char*>(mathvariants);
454
  if (!ValidStructure(start + offset, sizeof(MathGlyphConstruction))) {
455
    return;
456
  }
457
  mGlyphConstruction =
458
    reinterpret_cast<const MathGlyphConstruction*>(start + offset);
459
}
(-)a/gfx/thebes/gfxMathTable.h (+122 lines)
Line     Link Here 
Line 0    Link Here 
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#ifndef GFX_MATH_TABLE_H
6
#define GFX_MATH_TABLE_H
7
8
#include "gfxFont.h"
9
10
struct Coverage;
11
struct GlyphAssembly;
12
struct MATHTableHeader;
13
struct MathConstants;
14
struct MathGlyphConstruction;
15
struct MathGlyphInfo;
16
struct MathVariants;
17
18
/**
19
 * Used by |gfxFontEntry| to represent the MATH table of an OpenType font.
20
 * Each |gfxFontEntry| owns at most one |gfxMathTable| instance.
21
 */
22
class gfxMathTable
23
{
24
public:
25
    /**
26
     * @param aMathTable The MATH table from the OpenType font
27
     *
28
     * The gfxMathTable object takes over ownership of the blob references
29
     * that are passed in, and will hb_blob_destroy() them when finished;
30
     * the caller should -not- destroy this reference.
31
     */
32
    gfxMathTable(hb_blob_t* aMathTable);
33
34
    /**
35
     * Releases our reference to the MATH table and cleans up everything else.
36
     */
37
    ~gfxMathTable();
38
39
    /**
40
     * Returns the value of the specified constant from the MATH table.
41
     */
42
    int32_t GetMathConstant(gfxFontEntry::MathConstant aConstant);
43
44
    /**
45
     *  If the MATH table contains an italic correction for that glyph, this
46
     *  function gets the value and returns true. Otherwise it returns false.
47
     */
48
    bool
49
    GetMathItalicsCorrection(uint32_t aGlyphID, int16_t* aItalicCorrection);
50
51
    /**
52
     * @param aGlyphID  glyph index of the character we want to stretch
53
     * @param aVertical direction of the stretching (vertical/horizontal)
54
     * @param aSize     the desired size variant
55
     *
56
     * Returns the glyph index of the desired size variant or 0 if there is not
57
     * any such size variant.
58
     */
59
    uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
60
                                 uint16_t aSize);
61
62
    /**
63
     * @param aGlyphID  glyph index of the character we want to stretch
64
     * @param aVertical direction of the stretching (vertical/horizontal)
65
     * @param aGlyphs   pre-allocated buffer of 4 elements where the glyph
66
     * indexes (or 0 for absent parts) will be stored. The parts are stored in
67
     * the order expected by the nsMathMLChar: Top (or Left), Middle, Bottom
68
     * (or Right), Glue.
69
     *
70
     * Tries to fill-in aGlyphs with the relevant glyph indexes and returns
71
     * whether the operation was successful. The function returns false if
72
     * there is not any assembly for the character we want to stretch or if
73
     * the format is not supported by the nsMathMLChar code.
74
     *
75
     */
76
    bool GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
77
                              uint32_t aGlyphs[4]);
78
79
protected:
80
    friend class gfxFontEntry;
81
    // This allows gfxFontEntry to verify the validity of the main headers
82
    // before starting to use the MATH table.
83
    bool HasValidHeaders();
84
85
private:
86
    // HarfBuzz blob where the MATH table is stored.
87
    hb_blob_t*    mMathTable;
88
89
    // Cached values for the latest (mGlyphID, mVertical) pair that has been
90
    // accessed and the corresponding glyph construction. These are verified
91
    // by SelectGlyphConstruction and updated if necessary.
92
    // mGlyphConstruction will be set to nullptr if no construction is defined
93
    // for the glyph. If non-null, its mGlyphAssembly and mVariantCount fields
94
    // may be safely read, but no further validation will have been done.
95
    const MathGlyphConstruction* mGlyphConstruction;
96
    uint32_t mGlyphID;
97
    bool     mVertical;
98
    void     SelectGlyphConstruction(uint32_t aGlyphID, bool aVertical);
99
100
    // Access to some structures of the MATH table.
101
    // These accessors just return a pointer, but do NOT themselves check the
102
    // validity of anything. Until we've checked that HasValidHeaders (which
103
    // does validate them) returns true, they might return pointers that cannot
104
    // even safely be dereferenced. GetGlyphAssembly may return nullptr if the
105
    // given glyph has no assembly defined.
106
    const MATHTableHeader* GetMATHTableHeader();
107
    const MathConstants*   GetMathConstants();
108
    const MathGlyphInfo*   GetMathGlyphInfo();
109
    const MathVariants*    GetMathVariants();
110
    const GlyphAssembly*   GetGlyphAssembly(uint32_t aGlyphID, bool aVertical);
111
112
    // Verify whether a structure or an offset belongs to the math data and can
113
    // be read safely.
114
    bool ValidStructure(const char* aStructStart, uint16_t aStructSize);
115
    bool ValidOffset(const char* aOffsetStart, uint16_t aOffset);
116
117
    // Get the coverage index of a glyph index from an Open Type coverage table
118
    // or -1 if the glyph index is not found.
119
    int32_t GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph);
120
};
121
122
#endif
(-)a/gfx/thebes/moz.build (+2 lines)
Line     Link Here 
 Lines 21-36   EXPORTS += [ Link Here 
21
    'gfxFontConstants.h',
21
    'gfxFontConstants.h',
22
    'gfxFontFeatures.h',
22
    'gfxFontFeatures.h',
23
    'gfxFontInfoLoader.h',
23
    'gfxFontInfoLoader.h',
24
    'gfxFontTest.h',
24
    'gfxFontTest.h',
25
    'gfxFontUtils.h',
25
    'gfxFontUtils.h',
26
    'gfxGradientCache.h',
26
    'gfxGradientCache.h',
27
    'gfxImageSurface.h',
27
    'gfxImageSurface.h',
28
    'gfxLineSegment.h',
28
    'gfxLineSegment.h',
29
    'gfxMathTable.h',
29
    'gfxMatrix.h',
30
    'gfxMatrix.h',
30
    'gfxPath.h',
31
    'gfxPath.h',
31
    'gfxPattern.h',
32
    'gfxPattern.h',
32
    'gfxPlatform.h',
33
    'gfxPlatform.h',
33
    'gfxPoint.h',
34
    'gfxPoint.h',
34
    'gfxPoint3D.h',
35
    'gfxPoint3D.h',
35
    'gfxPointH3D.h',
36
    'gfxPointH3D.h',
36
    'gfxPrefs.h',
37
    'gfxPrefs.h',
 Lines 230-245   UNIFIED_SOURCES += [ Link Here 
230
    'gfxFontFeatures.cpp',
231
    'gfxFontFeatures.cpp',
231
    'gfxFontInfoLoader.cpp',
232
    'gfxFontInfoLoader.cpp',
232
    'gfxFontMissingGlyphs.cpp',
233
    'gfxFontMissingGlyphs.cpp',
233
    'gfxFontTest.cpp',
234
    'gfxFontTest.cpp',
234
    'gfxGradientCache.cpp',
235
    'gfxGradientCache.cpp',
235
    'gfxGraphiteShaper.cpp',
236
    'gfxGraphiteShaper.cpp',
236
    'gfxHarfBuzzShaper.cpp',
237
    'gfxHarfBuzzShaper.cpp',
237
    'gfxImageSurface.cpp',
238
    'gfxImageSurface.cpp',
239
    'gfxMathTable.cpp',
238
    'gfxMatrix.cpp',
240
    'gfxMatrix.cpp',
239
    'gfxPath.cpp',
241
    'gfxPath.cpp',
240
    'gfxPattern.cpp',
242
    'gfxPattern.cpp',
241
    'gfxRect.cpp',
243
    'gfxRect.cpp',
242
    'gfxReusableImageSurfaceWrapper.cpp',
244
    'gfxReusableImageSurfaceWrapper.cpp',
243
    'gfxReusableSharedImageSurfaceWrapper.cpp',
245
    'gfxReusableSharedImageSurfaceWrapper.cpp',
244
    'gfxScriptItemizer.cpp',
246
    'gfxScriptItemizer.cpp',
245
    'gfxSkipChars.cpp',
247
    'gfxSkipChars.cpp',

Return to bug 407059