Attachment #8374988: Part 1: add a gfxMathTable class to read the MATH table. r=jfkthame, b=407059 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
#include "cairo.h"
44
#include "cairo.h"
44
#include "gfxFontTest.h"
45
#include "gfxFontTest.h"
45
46
46
#include "harfbuzz/hb.h"
47
#include "harfbuzz/hb.h"
47
#include "harfbuzz/hb-ot.h"
48
#include "harfbuzz/hb-ot.h"
48
#include "graphite2/Font.h"
49
#include "graphite2/Font.h"
 Lines 95-110   gfxFontEntry::gfxFontEntry() : Link Here 
95
    mIsBadUnderlineFont(false),
96
    mIsBadUnderlineFont(false),
96
    mIsUserFont(false),
97
    mIsUserFont(false),
97
    mIsLocalUserFont(false),
98
    mIsLocalUserFont(false),
98
    mStandardFace(false),
99
    mStandardFace(false),
99
    mSymbolFont(false),
100
    mSymbolFont(false),
100
    mIgnoreGDEF(false),
101
    mIgnoreGDEF(false),
101
    mIgnoreGSUB(false),
102
    mIgnoreGSUB(false),
102
    mSVGInitialized(false),
103
    mSVGInitialized(false),
104
    mMathInitialized(false),
103
    mHasSpaceFeaturesInitialized(false),
105
    mHasSpaceFeaturesInitialized(false),
104
    mHasSpaceFeatures(false),
106
    mHasSpaceFeatures(false),
105
    mHasSpaceFeaturesKerning(false),
107
    mHasSpaceFeaturesKerning(false),
106
    mHasSpaceFeaturesNonKerning(false),
108
    mHasSpaceFeaturesNonKerning(false),
107
    mHasSpaceFeaturesSubDefault(false),
109
    mHasSpaceFeaturesSubDefault(false),
108
    mCheckedForGraphiteTables(false),
110
    mCheckedForGraphiteTables(false),
109
    mHasCmapTable(false),
111
    mHasCmapTable(false),
110
    mGrFaceInitialized(false),
112
    mGrFaceInitialized(false),
 Lines 122-137   gfxFontEntry::gfxFontEntry(const nsAStri Link Here 
122
    mName(aName), mItalic(false), mFixedPitch(false),
124
    mName(aName), mItalic(false), mFixedPitch(false),
123
    mIsProxy(false), mIsValid(true),
125
    mIsProxy(false), mIsValid(true),
124
    mIsBadUnderlineFont(false), mIsUserFont(false),
126
    mIsBadUnderlineFont(false), mIsUserFont(false),
125
    mIsLocalUserFont(false), mStandardFace(aIsStandardFace),
127
    mIsLocalUserFont(false), mStandardFace(aIsStandardFace),
126
    mSymbolFont(false),
128
    mSymbolFont(false),
127
    mIgnoreGDEF(false),
129
    mIgnoreGDEF(false),
128
    mIgnoreGSUB(false),
130
    mIgnoreGSUB(false),
129
    mSVGInitialized(false),
131
    mSVGInitialized(false),
132
    mMathInitialized(false),
130
    mHasSpaceFeaturesInitialized(false),
133
    mHasSpaceFeaturesInitialized(false),
131
    mHasSpaceFeatures(false),
134
    mHasSpaceFeatures(false),
132
    mHasSpaceFeaturesKerning(false),
135
    mHasSpaceFeaturesKerning(false),
133
    mHasSpaceFeaturesNonKerning(false),
136
    mHasSpaceFeaturesNonKerning(false),
134
    mHasSpaceFeaturesSubDefault(false),
137
    mHasSpaceFeaturesSubDefault(false),
135
    mCheckedForGraphiteTables(false),
138
    mCheckedForGraphiteTables(false),
136
    mHasCmapTable(false),
139
    mHasCmapTable(false),
137
    mGrFaceInitialized(false),
140
    mGrFaceInitialized(false),
 Lines 369-384   void Link Here 
369
gfxFontEntry::NotifyGlyphsChanged()
372
gfxFontEntry::NotifyGlyphsChanged()
370
{
373
{
371
    for (uint32_t i = 0, count = mFontsUsingSVGGlyphs.Length(); i < count; ++i) {
374
    for (uint32_t i = 0, count = mFontsUsingSVGGlyphs.Length(); i < count; ++i) {
372
        gfxFont* font = mFontsUsingSVGGlyphs[i];
375
        gfxFont* font = mFontsUsingSVGGlyphs[i];
373
        font->NotifyGlyphsChanged();
376
        font->NotifyGlyphsChanged();
374
    }
377
    }
375
}
378
}
376
379
380
bool
381
gfxFontEntry::TryGetMathTable(gfxFont* aFont)
382
{
383
    if (!mMathInitialized) {
384
        mMathInitialized = true;
385
386
        // If UnitsPerEm is not known/valid, we can't use MATH table
387
        if (UnitsPerEm() == kInvalidUPEM) {
388
            return false;
389
        }
390
391
        // We don't use AutoTable here because we'll pass ownership of this
392
        // blob to the gfxMathTable, once we've confirmed the table exists
393
        hb_blob_t *mathTable = GetFontTable(TRUETYPE_TAG('M','A','T','H'));
394
        if (!mathTable) {
395
            return false;
396
        }
397
398
        // gfxMathTable will hb_blob_destroy() the table when it is finished
399
        // with it.
400
        mMathTable = new gfxMathTable(mathTable);
401
        if (!mMathTable->HasValidHeaders()) {
402
            mMathTable = nullptr;
403
            return false;
404
        }
405
    }
406
407
    return !!mMathTable;
408
}
409
410
gfxFloat
411
gfxFontEntry::GetMathConstant(gfxFontEntry::MathConstant aConstant)
412
{
413
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
414
    gfxFloat value = mMathTable->GetMathConstant(aConstant);
415
    if (aConstant == gfxFontEntry::ScriptPercentScaleDown ||
416
        aConstant == gfxFontEntry::ScriptScriptPercentScaleDown ||
417
        aConstant == gfxFontEntry::RadicalDegreeBottomRaisePercent) {
418
        return value / 100.0;
419
    }
420
    return value / mUnitsPerEm;
421
}
422
423
bool
424
gfxFontEntry::GetMathItalicCorrection(uint32_t aGlyphID,
425
                                      gfxFloat* aItalicCorrection)
426
{
427
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
428
    int16_t italicCorrection;
429
    if (!mMathTable->GetMathItalicCorrection(aGlyphID, &italicCorrection)) {
430
        return false;
431
    }
432
    *aItalicCorrection = gfxFloat(italicCorrection) / mUnitsPerEm;
433
    return true;
434
}
435
436
uint32_t
437
gfxFontEntry::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
438
                                  uint16_t aSize)
439
{
440
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
441
    return mMathTable->GetMathVariantsSize(aGlyphID, aVertical, aSize);
442
}
443
444
bool
445
gfxFontEntry::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
446
                                   uint32_t aGlyphs[4])
447
{
448
    NS_ASSERTION(mMathTable, "Math data has not yet been loaded. TryGetMathData() first.");
449
    return mMathTable->GetMathVariantsParts(aGlyphID, aVertical, aGlyphs);
450
}
451
377
/**
452
/**
378
 * FontTableBlobData
453
 * FontTableBlobData
379
 *
454
 *
380
 * See FontTableHashEntry for the general strategy.
455
 * See FontTableHashEntry for the general strategy.
381
 */
456
 */
382
457
383
class gfxFontEntry::FontTableBlobData {
458
class gfxFontEntry::FontTableBlobData {
384
public:
459
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 309-324   public: Link Here 
309
    bool GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
310
    bool GetSVGGlyphExtents(gfxContext *aContext, uint32_t aGlyphId,
310
                            gfxRect *aResult);
311
                            gfxRect *aResult);
311
    bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, int aDrawMode,
312
    bool RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId, int aDrawMode,
312
                        gfxTextContextPaint *aContextPaint);
313
                        gfxTextContextPaint *aContextPaint);
313
    // Call this when glyph geometry or rendering has changed
314
    // Call this when glyph geometry or rendering has changed
314
    // (e.g. animated SVG glyphs)
315
    // (e.g. animated SVG glyphs)
315
    void NotifyGlyphsChanged();
316
    void NotifyGlyphsChanged();
316
317
318
    enum MathConstant {
319
        // The order of the constants must match the order of the fields
320
        // defined in the MATH table.
321
        ScriptPercentScaleDown,
322
        ScriptScriptPercentScaleDown,
323
        DelimitedSubFormulaMinHeight,
324
        DisplayOperatorMinHeight,
325
        MathLeading,
326
        AxisHeight,
327
        AccentBaseHeight,
328
        FlattenedAccentBaseHeight,
329
        SubscriptShiftDown,
330
        SubscriptTopMax,
331
        SubscriptBaselineDropMin,
332
        SuperscriptShiftUp,
333
        SuperscriptShiftUpCramped,
334
        SuperscriptBottomMin,
335
        SuperscriptBaselineDropMax,
336
        SubSuperscriptGapMin,
337
        SuperscriptBottomMaxWithSubscript,
338
        SpaceAfterScript,
339
        UpperLimitGapMin,
340
        UpperLimitBaselineRiseMin,
341
        LowerLimitGapMin,
342
        LowerLimitBaselineDropMin,
343
        StackTopShiftUp,
344
        StackTopDisplayStyleShiftUp,
345
        StackBottomShiftDown,
346
        StackBottomDisplayStyleShiftDown,
347
        StackGapMin,
348
        StackDisplayStyleGapMin,
349
        StretchStackTopShiftUp,
350
        StretchStackBottomShiftDown,
351
        StretchStackGapAboveMin,
352
        StretchStackGapBelowMin,
353
        FractionNumeratorShiftUp,
354
        FractionNumeratorDisplayStyleShiftUp,
355
        FractionDenominatorShiftDown,
356
        FractionDenominatorDisplayStyleShiftDown,
357
        FractionNumeratorGapMin,
358
        FractionNumDisplayStyleGapMin,
359
        FractionRuleThickness,
360
        FractionDenominatorGapMin,
361
        FractionDenomDisplayStyleGapMin,
362
        SkewedFractionHorizontalGap,
363
        SkewedFractionVerticalGap,
364
        OverbarVerticalGap,
365
        OverbarRuleThickness,
366
        OverbarExtraAscender,
367
        UnderbarVerticalGap,
368
        UnderbarRuleThickness,
369
        UnderbarExtraDescender,
370
        RadicalVerticalGap,
371
        RadicalDisplayStyleVerticalGap,
372
        RadicalRuleThickness,
373
        RadicalExtraAscender,
374
        RadicalKernBeforeDegree,
375
        RadicalKernAfterDegree,
376
        RadicalDegreeBottomRaisePercent
377
    };
378
379
    // Call TryGetMathTable to try to load the Open Type MATH table. The other
380
    // functions forward the call to the gfxMathTable class. The GetMath...()
381
    // functions MUST NOT be called unless TryGetMathTable() has returned true.
382
    bool     TryGetMathTable(gfxFont* aFont);
383
    gfxFloat GetMathConstant(MathConstant aConstant);
384
    bool     GetMathItalicCorrection(uint32_t aGlyphID,
385
                                     gfxFloat* aItalicCorrection);
386
    uint32_t GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
387
                                 uint16_t aSize);
388
    bool     GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
389
                                  uint32_t aGlyphs[4]);
390
317
    virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
391
    virtual bool MatchesGenericFamily(const nsACString& aGeneric) const {
318
        return true;
392
        return true;
319
    }
393
    }
320
    virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
394
    virtual bool SupportsLangGroup(nsIAtom *aLangGroup) const {
321
        return true;
395
        return true;
322
    }
396
    }
323
397
324
    // Access to raw font table data (needed for Harfbuzz):
398
    // Access to raw font table data (needed for Harfbuzz):
 Lines 431-446   public: Link Here 
431
    bool             mIsBadUnderlineFont : 1;
505
    bool             mIsBadUnderlineFont : 1;
432
    bool             mIsUserFont  : 1;
506
    bool             mIsUserFont  : 1;
433
    bool             mIsLocalUserFont  : 1;
507
    bool             mIsLocalUserFont  : 1;
434
    bool             mStandardFace : 1;
508
    bool             mStandardFace : 1;
435
    bool             mSymbolFont  : 1;
509
    bool             mSymbolFont  : 1;
436
    bool             mIgnoreGDEF  : 1;
510
    bool             mIgnoreGDEF  : 1;
437
    bool             mIgnoreGSUB  : 1;
511
    bool             mIgnoreGSUB  : 1;
438
    bool             mSVGInitialized : 1;
512
    bool             mSVGInitialized : 1;
513
    bool             mMathInitialized : 1;
439
    bool             mHasSpaceFeaturesInitialized : 1;
514
    bool             mHasSpaceFeaturesInitialized : 1;
440
    bool             mHasSpaceFeatures : 1;
515
    bool             mHasSpaceFeatures : 1;
441
    bool             mHasSpaceFeaturesKerning : 1;
516
    bool             mHasSpaceFeaturesKerning : 1;
442
    bool             mHasSpaceFeaturesNonKerning : 1;
517
    bool             mHasSpaceFeaturesNonKerning : 1;
443
    bool             mHasSpaceFeaturesSubDefault : 1;
518
    bool             mHasSpaceFeaturesSubDefault : 1;
444
    bool             mHasGraphiteTables : 1;
519
    bool             mHasGraphiteTables : 1;
445
    bool             mCheckedForGraphiteTables : 1;
520
    bool             mCheckedForGraphiteTables : 1;
446
    bool             mHasCmapTable : 1;
521
    bool             mHasCmapTable : 1;
 Lines 454-469   public: Link Here 
454
529
455
    nsRefPtr<gfxCharacterMap> mCharacterMap;
530
    nsRefPtr<gfxCharacterMap> mCharacterMap;
456
    uint32_t         mUVSOffset;
531
    uint32_t         mUVSOffset;
457
    nsAutoArrayPtr<uint8_t> mUVSData;
532
    nsAutoArrayPtr<uint8_t> mUVSData;
458
    nsAutoPtr<gfxUserFontData> mUserFontData;
533
    nsAutoPtr<gfxUserFontData> mUserFontData;
459
    nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
534
    nsAutoPtr<gfxSVGGlyphs> mSVGGlyphs;
460
    // list of gfxFonts that are using SVG glyphs
535
    // list of gfxFonts that are using SVG glyphs
461
    nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
536
    nsTArray<gfxFont*> mFontsUsingSVGGlyphs;
537
    nsAutoPtr<gfxMathTable> mMathTable;
462
    nsTArray<gfxFontFeature> mFeatureSettings;
538
    nsTArray<gfxFontFeature> mFeatureSettings;
463
    uint32_t         mLanguageOverride;
539
    uint32_t         mLanguageOverride;
464
540
465
protected:
541
protected:
466
    friend class gfxPlatformFontList;
542
    friend class gfxPlatformFontList;
467
    friend class gfxMacPlatformFontList;
543
    friend class gfxMacPlatformFontList;
468
    friend class gfxUserFcFontEntry;
544
    friend class gfxUserFcFontEntry;
469
    friend class gfxFontFamily;
545
    friend class gfxFontFamily;
(-)a/gfx/thebes/gfxMathTable.cpp (+457 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 uint16_t(mathconstants->mUint16[aConstant]);
83
  }
84
85
  if (aConstant <= gfxFontEntry::RadicalKernAfterDegree) {
86
    return int16_t(mathconstants->
87
                   mMathValues[aConstant - gfxFontEntry::MathLeading].mValue);
88
  }
89
90
  return uint16_t(mathconstants->mRadicalDegreeBottomRaisePercent);
91
}
92
93
bool
94
gfxMathTable::GetMathItalicCorrection(uint32_t aGlyphID,
95
                                      int16_t* aItalicCorrection)
96
{
97
  const MathGlyphInfo* mathglyphinfo = GetMathGlyphInfo();
98
99
  // Get the offset of the italic correction and verify whether it is valid.
100
  const char* start = reinterpret_cast<const char*>(mathglyphinfo);
101
  uint16_t offset = mathglyphinfo->mMathItalicsCorrectionInfo;
102
  if (offset == 0 || !ValidOffset(start, offset)) {
103
    return false;
104
  }
105
  start += offset;
106
107
  // Verify the validity of the MathItalicsCorrectionInfo and retrieve it.
108
  if (!ValidStructure(start, sizeof(MathItalicsCorrectionInfo))) {
109
    return false;
110
  }
111
  const MathItalicsCorrectionInfo* italicsCorrectionInfo =
112
    reinterpret_cast<const MathItalicsCorrectionInfo*>(start);
113
114
  // Get the coverage index for the glyph.
115
  offset = italicsCorrectionInfo->mCoverage;
116
  const Coverage* coverage =
117
    reinterpret_cast<const Coverage*>(start + offset);
118
  int32_t i = GetCoverageIndex(coverage, aGlyphID);
119
120
  // Get the ItalicsCorrection.
121
  uint16_t count = italicsCorrectionInfo->mItalicsCorrectionCount;
122
  if (i < 0 || i >= count) {
123
    return false;
124
  }
125
  start = reinterpret_cast<const char*>(italicsCorrectionInfo + 1);
126
  if (!ValidStructure(start, count * sizeof(MathValueRecord))) {
127
    return false;
128
  }
129
  const MathValueRecord* mathValueRecordArray =
130
    reinterpret_cast<const MathValueRecord*>(start);
131
132
  *aItalicCorrection = int16_t(mathValueRecordArray[i].mValue);
133
  return true;
134
}
135
136
uint32_t
137
gfxMathTable::GetMathVariantsSize(uint32_t aGlyphID, bool aVertical,
138
                                  uint16_t aSize)
139
{
140
  // Select the glyph construction.
141
  SelectGlyphConstruction(aGlyphID, aVertical);
142
  if (!mGlyphConstruction) {
143
    return 0;
144
  }
145
146
  // Verify the validity of the array of the MathGlyphVariantRecord's and
147
  // whether there is a variant of the requested size.
148
  uint16_t count = mGlyphConstruction->mVariantCount;
149
  const char* start = reinterpret_cast<const char*>(mGlyphConstruction + 1);
150
  if (aSize >= count ||
151
      !ValidStructure(start, count * sizeof(MathGlyphVariantRecord))) {
152
    return 0;
153
  }
154
155
  // Return the glyph index of the requested size variant.
156
  const MathGlyphVariantRecord* recordArray =
157
    reinterpret_cast<const MathGlyphVariantRecord*>(start);
158
  return uint32_t(recordArray[aSize].mVariantGlyph);
159
}
160
161
bool
162
gfxMathTable::GetMathVariantsParts(uint32_t aGlyphID, bool aVertical,
163
                                   uint32_t aGlyphs[4])
164
{
165
  // Get the glyph assembly corresponding to that (aGlyphID, aVertical) pair.
166
  const GlyphAssembly* glyphAssembly = GetGlyphAssembly(aGlyphID, aVertical);
167
  if (!glyphAssembly) {
168
    return false;
169
  }
170
171
  // Verify the validity of the array of GlyphPartRecord's and retrieve it.
172
  uint16_t count = glyphAssembly->mPartCount;
173
  const char* start = reinterpret_cast<const char*>(glyphAssembly + 1);
174
  if (!ValidStructure(start, count * sizeof(GlyphPartRecord))) {
175
    return false;
176
  }
177
  const GlyphPartRecord* recordArray =
178
    reinterpret_cast<const GlyphPartRecord*>(start);
179
180
  // XXXfredw The structure of the Open Type Math table is a bit more general
181
  // than the one currently used by the nsMathMLChar code, so we try to fallback
182
  // in reasonable way. We use the approach of the copyComponents function in
183
  // github.com/mathjax/MathJax-dev/blob/master/fonts/OpenTypeMath/fontUtil.py
184
  //
185
  // The nsMathMLChar code can use at most 3 non extender pieces (aGlyphs[0],
186
  // aGlyphs[1] and aGlyphs[2]) and the extenders between these pieces should
187
  // all be the same (aGlyphs[4]). Also, the parts of vertical assembly are
188
  // stored from bottom to top in the Open Type MATH table while they are
189
  // stored from top to bottom in nsMathMLChar.
190
191
  // Count the number of non extender pieces
192
  uint16_t nonExtenderCount = 0;
193
  for (uint16_t i = 0; i < count; i++) {
194
    if (!(uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER)) {
195
      nonExtenderCount++;
196
    }
197
  }
198
  if (nonExtenderCount > 3) {
199
    // Not supported: too many pieces
200
    return false;
201
  }
202
203
  // Now browse the list of pieces
204
205
  // 0 = look for a left/bottom glyph
206
  // 1 = look for an extender between left/bottom and mid
207
  // 2 = look for a middle glyph
208
  // 3 = look for an extender between middle and right/top
209
  // 4 = look for a right/top glyph
210
  // 5 = no more piece expected
211
  uint8_t state = 0;
212
213
  // First extender char found.
214
  uint32_t extenderChar = 0;
215
216
  // Clear the aGlyphs table.
217
  memset(aGlyphs, 0, sizeof(uint32_t) * 4);
218
219
  for (uint16_t i = 0; i < count; i++) {
220
221
    bool isExtender = uint16_t(recordArray[i].mPartFlags) & PART_FLAG_EXTENDER;
222
    uint32_t glyph = recordArray[i].mGlyph;
223
224
    if ((state == 1 || state == 2) && nonExtenderCount < 3) {
225
      // do not try to find a middle glyph
226
      state += 2;
227
    }
228
229
    if (isExtender) {
230
      if (!extenderChar) {
231
        extenderChar = glyph;
232
        aGlyphs[3] = extenderChar;
233
      } else if (extenderChar != glyph)  {
234
        // Not supported: different extenders
235
        return false;
236
      }
237
238
      if (state == 0) { // or state == 1
239
        // ignore left/bottom piece and multiple successive extenders
240
        state = 1;
241
      } else if (state == 2) { // or state == 3
242
        // ignore middle piece and multiple successive extenders
243
        state = 3;
244
      } else if (state >= 4) {
245
        // Not supported: unexpected extender
246
        return false;
247
      }
248
249
      continue;
250
    }
251
252
    if (state == 0) {
253
      // copy left/bottom part
254
      aGlyphs[mVertical ? 2 : 0] = glyph;
255
      state = 1;
256
      continue;
257
    }
258
259
    if (state == 1 || state == 2) {
260
      // copy middle part
261
      aGlyphs[1] = glyph;
262
      state = 3;
263
      continue;
264
    }
265
266
    if (state == 3 || state == 4) {
267
      // copy right/top part
268
      aGlyphs[mVertical ? 0 : 2] = glyph;
269
      state = 5;
270
    }
271
272
  }
273
274
  return true;
275
}
276
277
bool
278
gfxMathTable::ValidStructure(const char* aStart, uint16_t aSize)
279
{
280
  unsigned int mathDataLength;
281
  const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
282
  return (mathData <= aStart &&
283
          aStart + aSize <= mathData + mathDataLength);
284
}
285
286
bool
287
gfxMathTable::ValidOffset(const char* aStart, uint16_t aOffset)
288
{
289
  unsigned int mathDataLength;
290
  const char* mathData = hb_blob_get_data(mMathTable, &mathDataLength);
291
  return (mathData <= aStart + aOffset &&
292
          aStart + aOffset < mathData + mathDataLength);
293
}
294
295
const MATHTableHeader*
296
gfxMathTable::GetMATHTableHeader()
297
{
298
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
299
  return reinterpret_cast<const MATHTableHeader*>(mathData);
300
}
301
302
const MathConstants*
303
gfxMathTable::GetMathConstants()
304
{
305
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
306
  return
307
    reinterpret_cast<const MathConstants*>(mathData +
308
                                           uint16_t(GetMATHTableHeader()->
309
                                                    mMathConstants));
310
}
311
312
const MathGlyphInfo*
313
gfxMathTable::GetMathGlyphInfo()
314
{
315
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
316
  return
317
    reinterpret_cast<const MathGlyphInfo*>(mathData +
318
                                           uint16_t(GetMATHTableHeader()->
319
                                                    mMathGlyphInfo));
320
}
321
322
const MathVariants*
323
gfxMathTable::GetMathVariants()
324
{
325
  const char* mathData = hb_blob_get_data(mMathTable, nullptr);
326
  return
327
    reinterpret_cast<const MathVariants*>(mathData +
328
                                          uint16_t(GetMATHTableHeader()->
329
                                                   mMathVariants));
330
}
331
332
const GlyphAssembly*
333
gfxMathTable::GetGlyphAssembly(uint32_t aGlyphID, bool aVertical)
334
{
335
  // Select the glyph construction.
336
  SelectGlyphConstruction(aGlyphID, aVertical);
337
  if (!mGlyphConstruction) {
338
    return nullptr;
339
  }
340
341
  // Get the offset of the glyph assembly and verify whether it is valid.
342
  const char* start = reinterpret_cast<const char*>(mGlyphConstruction);
343
  uint16_t offset = mGlyphConstruction->mGlyphAssembly;
344
  if (offset == 0 || !ValidOffset(start, offset)) {
345
    return nullptr;
346
  }
347
  start += offset;
348
349
  // Verify the validity of the GlyphAssembly and return it.
350
  if (!ValidStructure(start, sizeof(GlyphAssembly))) {
351
    return nullptr;
352
  }
353
  return reinterpret_cast<const GlyphAssembly*>(start);
354
}
355
356
int32_t
357
gfxMathTable::GetCoverageIndex(const Coverage* aCoverage, uint32_t aGlyph)
358
{
359
  if (uint16_t(aCoverage->mFormat) == 1) {
360
    // Coverage Format 1: list of individual glyph indices in the glyph set.
361
    const CoverageFormat1* table =
362
      reinterpret_cast<const CoverageFormat1*>(aCoverage);
363
    uint16_t count = table->mGlyphCount;
364
    const char* start = reinterpret_cast<const char*>(table + 1);
365
    if (ValidStructure(start, count * sizeof(GlyphID))) {
366
      const GlyphID* glyphArray =
367
        reinterpret_cast<const GlyphID*>(start);
368
      uint32_t imin = 0, imax = count;
369
      while (imin < imax) {
370
        uint32_t imid = (imin + imax) >> 1;
371
        uint16_t glyphMid = glyphArray[imid];
372
        if (glyphMid == aGlyph) {
373
          return imid;
374
        }
375
        if (glyphMid < aGlyph) {
376
          imin = imid + 1;
377
        } else {
378
          imax = imid;
379
        }
380
      }
381
    }
382
  } else if (uint16_t(aCoverage->mFormat) == 2) {
383
    // Coverage Format 2: ranges of consecutive indices.
384
    const CoverageFormat2* table =
385
      reinterpret_cast<const CoverageFormat2*>(aCoverage);
386
    uint16_t count = table->mRangeCount;
387
    const char* start = reinterpret_cast<const char*>(table + 1);
388
    if (ValidStructure(start, count * sizeof(RangeRecord))) {
389
      const RangeRecord* rangeArray =
390
        reinterpret_cast<const RangeRecord*>(start);
391
      uint32_t imin = 0, imax = count;
392
      while (imin < imax) {
393
        uint32_t imid = (imin + imax) >> 1;
394
        uint16_t rStart = rangeArray[imid].mStart;
395
        uint16_t rEnd = rangeArray[imid].mEnd;
396
        if (rEnd < aGlyph) {
397
          imin = imid + 1;
398
        } else if (aGlyph < rStart) {
399
          imax = imid;
400
        } else {
401
          return (uint16_t(rangeArray[imid].mStartCoverageIndex) +
402
                  aGlyph - rStart);
403
        }
404
      }
405
    }
406
  }
407
  return -1;
408
}
409
410
void
411
gfxMathTable::SelectGlyphConstruction(uint32_t aGlyphID, bool aVertical)
412
{
413
  if (mGlyphID == aGlyphID && mVertical == aVertical) {
414
    // The (glyph, direction) pair is already selected: nothing to do.
415
    return;
416
  }
417
418
  // Update our cached values.
419
  mVertical = aVertical;
420
  mGlyphID = aGlyphID;
421
  mGlyphConstruction = nullptr;
422
423
  // Get the coverage index for the new values.
424
  const MathVariants* mathvariants = GetMathVariants();
425
  const char* start = reinterpret_cast<const char*>(mathvariants);
426
  uint16_t offset = (aVertical ?
427
                     mathvariants->mVertGlyphCoverage :
428
                     mathvariants->mHorizGlyphCoverage);
429
  const Coverage* coverage =
430
    reinterpret_cast<const Coverage*>(start + offset);
431
  int32_t i = GetCoverageIndex(coverage, aGlyphID);
432
433
  // Get the offset to the glyph construction.
434
  uint16_t count = (aVertical ?
435
                    mathvariants->mVertGlyphCount :
436
                    mathvariants->mHorizGlyphCount);
437
  start = reinterpret_cast<const char*>(mathvariants + 1);
438
  if (i < 0 || i >= count) {
439
    return;
440
  }
441
  if (!aVertical) {
442
    start += uint16_t(mathvariants->mVertGlyphCount) * sizeof(Offset);
443
  }
444
  if (!ValidStructure(start, count * sizeof(Offset))) {
445
    return;
446
  }
447
  const Offset* offsetArray = reinterpret_cast<const Offset*>(start);
448
  offset = uint16_t(offsetArray[i]);
449
450
  // Make mGlyphConstruction point to the desired glyph construction.
451
  start = reinterpret_cast<const char*>(mathvariants);
452
  if (!ValidStructure(start + offset, sizeof(MathGlyphConstruction))) {
453
    return;
454
  }
455
  mGlyphConstruction =
456
    reinterpret_cast<const MathGlyphConstruction*>(start + offset);
457
}
(-)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
    GetMathItalicCorrection(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
    'gfxQuad.h',
37
    'gfxQuad.h',
 Lines 247-262   UNIFIED_SOURCES += [ Link Here 
247
    'gfxFontFeatures.cpp',
248
    'gfxFontFeatures.cpp',
248
    'gfxFontInfoLoader.cpp',
249
    'gfxFontInfoLoader.cpp',
249
    'gfxFontMissingGlyphs.cpp',
250
    'gfxFontMissingGlyphs.cpp',
250
    'gfxFontTest.cpp',
251
    'gfxFontTest.cpp',
251
    'gfxGradientCache.cpp',
252
    'gfxGradientCache.cpp',
252
    'gfxGraphiteShaper.cpp',
253
    'gfxGraphiteShaper.cpp',
253
    'gfxHarfBuzzShaper.cpp',
254
    'gfxHarfBuzzShaper.cpp',
254
    'gfxImageSurface.cpp',
255
    'gfxImageSurface.cpp',
256
    'gfxMathTable.cpp',
255
    'gfxMatrix.cpp',
257
    'gfxMatrix.cpp',
256
    'gfxPath.cpp',
258
    'gfxPath.cpp',
257
    'gfxPattern.cpp',
259
    'gfxPattern.cpp',
258
    'gfxRect.cpp',
260
    'gfxRect.cpp',
259
    'gfxReusableImageSurfaceWrapper.cpp',
261
    'gfxReusableImageSurfaceWrapper.cpp',
260
    'gfxReusableSharedImageSurfaceWrapper.cpp',
262
    'gfxReusableSharedImageSurfaceWrapper.cpp',
261
    'gfxScriptItemizer.cpp',
263
    'gfxScriptItemizer.cpp',
262
    'gfxSkipChars.cpp',
264
    'gfxSkipChars.cpp',

Return to bug 407059