зеркало из https://github.com/mozilla/pjs.git
bug 552460 - part 3 - implement Variation Sequence support in Windows font backend. r=jfkthame
This commit is contained in:
Родитель
dd7dd2083e
Коммит
caca11adda
|
@ -79,7 +79,6 @@ public:
|
|||
mFTFontIndex = 0;
|
||||
}
|
||||
|
||||
FontEntry(const FontEntry& aFontEntry);
|
||||
~FontEntry();
|
||||
|
||||
const nsString& GetName() const {
|
||||
|
|
|
@ -171,22 +171,12 @@ public:
|
|||
mStandardFace(aIsStandardFace),
|
||||
mSymbolFont(PR_FALSE),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCmapInitialized(PR_FALSE), mUserFontData(nsnull),
|
||||
mCmapInitialized(PR_FALSE),
|
||||
mUVSOffset(0), mUVSData(nsnull),
|
||||
mUserFontData(nsnull),
|
||||
mFamily(aFamily)
|
||||
{ }
|
||||
|
||||
gfxFontEntry(const gfxFontEntry& aEntry) :
|
||||
mName(aEntry.mName), mItalic(aEntry.mItalic),
|
||||
mFixedPitch(aEntry.mFixedPitch), mIsProxy(aEntry.mIsProxy),
|
||||
mIsValid(aEntry.mIsValid), mIsBadUnderlineFont(aEntry.mIsBadUnderlineFont),
|
||||
mIsUserFont(aEntry.mIsUserFont),
|
||||
mStandardFace(aEntry.mStandardFace),
|
||||
mSymbolFont(aEntry.mSymbolFont),
|
||||
mWeight(aEntry.mWeight), mCmapInitialized(aEntry.mCmapInitialized),
|
||||
mCharacterMap(aEntry.mCharacterMap), mUserFontData(aEntry.mUserFontData),
|
||||
mFamily(aEntry.mFamily)
|
||||
{ }
|
||||
|
||||
virtual ~gfxFontEntry();
|
||||
|
||||
// unique name for the face, *not* the family
|
||||
|
@ -204,11 +194,13 @@ public:
|
|||
inline PRBool HasCharacter(PRUint32 ch) {
|
||||
if (mCharacterMap.test(ch))
|
||||
return PR_TRUE;
|
||||
|
||||
|
||||
return TestCharacterMap(ch);
|
||||
}
|
||||
|
||||
virtual PRBool TestCharacterMap(PRUint32 aCh);
|
||||
nsresult InitializeUVSMap();
|
||||
PRUint16 GetUVSGlyph(PRUint32 aCh, PRUint32 aVS);
|
||||
virtual nsresult ReadCMAP();
|
||||
|
||||
virtual PRBool MatchesGenericFamily(const nsACString& aGeneric) const {
|
||||
|
@ -242,6 +234,8 @@ public:
|
|||
|
||||
PRPackedBool mCmapInitialized;
|
||||
gfxSparseBitSet mCharacterMap;
|
||||
PRUint32 mUVSOffset;
|
||||
nsAutoArrayPtr<PRUint8> mUVSData;
|
||||
gfxUserFontData* mUserFontData;
|
||||
|
||||
protected:
|
||||
|
@ -260,6 +254,7 @@ protected:
|
|||
mSymbolFont(PR_FALSE),
|
||||
mWeight(500), mStretch(NS_FONT_STRETCH_NORMAL),
|
||||
mCmapInitialized(PR_FALSE),
|
||||
mUVSOffset(0), mUVSData(nsnull),
|
||||
mUserFontData(nsnull),
|
||||
mFamily(nsnull)
|
||||
{ }
|
||||
|
@ -274,6 +269,10 @@ protected:
|
|||
}
|
||||
|
||||
gfxFontFamily *mFamily;
|
||||
|
||||
private:
|
||||
gfxFontEntry(const gfxFontEntry&);
|
||||
gfxFontEntry& operator=(const gfxFontEntry&);
|
||||
};
|
||||
|
||||
|
||||
|
@ -925,6 +924,13 @@ public:
|
|||
return mFontEntry->HasCharacter(ch);
|
||||
}
|
||||
|
||||
PRUint16 GetUVSGlyph(PRUint32 aCh, PRUint32 aVS) {
|
||||
if (!mIsValid) {
|
||||
return 0;
|
||||
}
|
||||
return mFontEntry->GetUVSGlyph(aCh, aVS);
|
||||
}
|
||||
|
||||
// Default implementation simply calls mShaper->InitTextRun().
|
||||
// Override if the font class wants to give special handling
|
||||
// to shaper failure.
|
||||
|
|
|
@ -350,6 +350,13 @@ struct AutoSwap_PRUint64 {
|
|||
PRUint64 value;
|
||||
};
|
||||
|
||||
struct AutoSwap_PRUint24 {
|
||||
operator PRUint32() const { return value[0] << 16 | value[1] << 8 | value[2]; }
|
||||
private:
|
||||
AutoSwap_PRUint24() { }
|
||||
PRUint8 value[3];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -453,13 +460,13 @@ public:
|
|||
};
|
||||
|
||||
// for reading big-endian font data on either big or little-endian platforms
|
||||
|
||||
|
||||
static inline PRUint16
|
||||
ReadShortAt(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return (aBuf[aIndex] << 8) | aBuf[aIndex + 1];
|
||||
}
|
||||
|
||||
|
||||
static inline PRUint16
|
||||
ReadShortAt16(const PRUint16 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
|
@ -467,33 +474,49 @@ public:
|
|||
PRUint32 index = aIndex << 1;
|
||||
return (buf[index] << 8) | buf[index+1];
|
||||
}
|
||||
|
||||
|
||||
static inline PRUint32
|
||||
ReadUint24At(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return ((aBuf[aIndex] << 16) | (aBuf[aIndex + 1] << 8) |
|
||||
(aBuf[aIndex + 2]));
|
||||
}
|
||||
|
||||
static inline PRUint32
|
||||
ReadLongAt(const PRUint8 *aBuf, PRUint32 aIndex)
|
||||
{
|
||||
return ((aBuf[aIndex] << 24) | (aBuf[aIndex + 1] << 16) |
|
||||
(aBuf[aIndex + 2] << 8) | (aBuf[aIndex + 3]));
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat12(PRUint8 *aBuf, PRUint32 aLength,
|
||||
gfxSparseBitSet& aCharacterMap);
|
||||
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat4(PRUint8 *aBuf, PRUint32 aLength,
|
||||
gfxSparseBitSet& aCharacterMap);
|
||||
|
||||
static nsresult
|
||||
ReadCMAPTableFormat14(PRUint8 *aBuf, PRUint32 aLength,
|
||||
PRUint8*& aTable);
|
||||
|
||||
static PRUint32
|
||||
FindPreferredSubtable(PRUint8 *aBuf, PRUint32 aBufLength,
|
||||
PRUint32 *aTableOffset, PRBool *aSymbolEncoding);
|
||||
PRUint32 *aTableOffset, PRUint32 *aUVSTableOffset,
|
||||
PRBool *aSymbolEncoding);
|
||||
|
||||
static nsresult
|
||||
ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||
PRUint32& aUVSOffset,
|
||||
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont);
|
||||
|
||||
static PRUint32
|
||||
MapCharToGlyphFormat4(const PRUint8 *aBuf, PRUnichar aCh);
|
||||
|
||||
static PRUint16
|
||||
MapUVSToGlyphFormat14(const PRUint8 *aBuf, PRUint32 aCh, PRUint32 aVS);
|
||||
|
||||
static PRUint32
|
||||
MapCharToGlyph(PRUint8 *aBuf, PRUint32 aBufLength, PRUnichar aCh);
|
||||
|
||||
|
@ -553,6 +576,18 @@ public:
|
|||
return (ch == 0x200D);
|
||||
}
|
||||
|
||||
enum {
|
||||
kUnicodeVS1 = 0xFE00,
|
||||
kUnicodeVS16 = 0xFE0F,
|
||||
kUnicodeVS17 = 0xE0100,
|
||||
kUnicodeVS256 = 0xE01EF
|
||||
};
|
||||
|
||||
static inline bool IsVarSelector(PRUint32 ch) {
|
||||
return (ch >= kUnicodeVS1 && ch <= kUnicodeVS16) ||
|
||||
(ch >= kUnicodeVS17 && ch <= kUnicodeVS256);
|
||||
}
|
||||
|
||||
static inline bool IsInvalid(PRUint32 ch) {
|
||||
return (ch == 0xFFFD);
|
||||
}
|
||||
|
|
|
@ -287,6 +287,7 @@ gfxDWriteFontEntry::ReadCMAP()
|
|||
rv = gfxFontUtils::ReadCMAP(tableData,
|
||||
len,
|
||||
mCharacterMap,
|
||||
mUVSOffset,
|
||||
isUnicode,
|
||||
isSymbol);
|
||||
}
|
||||
|
|
|
@ -95,16 +95,6 @@ static const char *sCJKLangGroup[] = {
|
|||
* FontEntry
|
||||
*/
|
||||
|
||||
FontEntry::FontEntry(const FontEntry& aFontEntry) :
|
||||
gfxFontEntry(aFontEntry)
|
||||
{
|
||||
mFTFace = aFontEntry.mFTFace;
|
||||
if (aFontEntry.mFontFace)
|
||||
mFontFace = cairo_font_face_reference(aFontEntry.mFontFace);
|
||||
else
|
||||
mFontFace = nsnull;
|
||||
}
|
||||
|
||||
FontEntry::~FontEntry()
|
||||
{
|
||||
// Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
|
||||
|
@ -273,7 +263,7 @@ FontEntry::ReadCMAP()
|
|||
|
||||
PRPackedBool unicodeFont;
|
||||
PRPackedBool symbolFont;
|
||||
return gfxFontUtils::ReadCMAP(buf, len, mCharacterMap,
|
||||
return gfxFontUtils::ReadCMAP(buf, len, mCharacterMap, mUVSOffset,
|
||||
unicodeFont, symbolFont);
|
||||
}
|
||||
|
||||
|
|
|
@ -100,6 +100,55 @@ PRBool gfxFontEntry::TestCharacterMap(PRUint32 aCh)
|
|||
}
|
||||
|
||||
|
||||
nsresult gfxFontEntry::InitializeUVSMap()
|
||||
{
|
||||
// mUVSOffset will not be initialized
|
||||
// until cmap is initialized.
|
||||
if (!mCmapInitialized) {
|
||||
ReadCMAP();
|
||||
}
|
||||
|
||||
if (!mUVSOffset) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!mUVSData) {
|
||||
const PRUint32 kCmapTag = TRUETYPE_TAG('c','m','a','p');
|
||||
nsAutoTArray<PRUint8,16384> buffer;
|
||||
if (GetFontTable(kCmapTag, buffer) != NS_OK) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PRUint8* uvsData;
|
||||
nsresult rv = gfxFontUtils::ReadCMAPTableFormat14(
|
||||
buffer.Elements() + mUVSOffset,
|
||||
buffer.Length() - mUVSOffset,
|
||||
uvsData);
|
||||
if (NS_FAILED(rv)) {
|
||||
mUVSOffset = 0; // don't bother to read the table again
|
||||
return rv;
|
||||
}
|
||||
|
||||
mUVSData = uvsData;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRUint16 gfxFontEntry::GetUVSGlyph(PRUint32 aCh, PRUint32 aVS)
|
||||
{
|
||||
InitializeUVSMap();
|
||||
|
||||
if (mUVSData) {
|
||||
return gfxFontUtils::MapUVSToGlyphFormat14(mUVSData, aCh, aVS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
nsresult gfxFontEntry::ReadCMAP()
|
||||
{
|
||||
mCmapInitialized = PR_TRUE;
|
||||
|
@ -2001,6 +2050,18 @@ gfxFontGroup::FindFontForChar(PRUint32 aCh, PRUint32 aPrevCh, PRUint32 aNextCh,
|
|||
}
|
||||
}
|
||||
|
||||
// if this character is a variation selector,
|
||||
// use the previous font regardless of whether it supports VS or not.
|
||||
// otherwise the text run will be divided.
|
||||
if (gfxFontUtils::IsVarSelector(aCh)) {
|
||||
if (aPrevMatchedFont) {
|
||||
selectedFont = aPrevMatchedFont;
|
||||
return selectedFont.forget();
|
||||
}
|
||||
// VS alone. it's meaningless to search different fonts
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// 1. check fonts in the font group
|
||||
for (PRUint32 i = 0; i < FontListLength(); i++) {
|
||||
nsRefPtr<gfxFont> font = GetFontAt(i);
|
||||
|
|
|
@ -359,29 +359,124 @@ gfxFontUtils::ReadCMAPTableFormat4(PRUint8 *aBuf, PRUint32 aLength, gfxSparseBit
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadCMAPTableFormat14(PRUint8 *aBuf, PRUint32 aLength,
|
||||
PRUint8*& aTable)
|
||||
{
|
||||
enum {
|
||||
OffsetFormat = 0,
|
||||
OffsetTableLength = 2,
|
||||
OffsetNumVarSelectorRecords = 6,
|
||||
OffsetVarSelectorRecords = 10,
|
||||
|
||||
SizeOfVarSelectorRecord = 11,
|
||||
VSRecOffsetVarSelector = 0,
|
||||
VSRecOffsetDefUVSOffset = 3,
|
||||
VSRecOffsetNonDefUVSOffset = 7,
|
||||
|
||||
SizeOfDefUVSTable = 4,
|
||||
DefUVSOffsetStartUnicodeValue = 0,
|
||||
DefUVSOffsetAdditionalCount = 3,
|
||||
|
||||
SizeOfNonDefUVSTable = 5,
|
||||
NonDefUVSOffsetUnicodeValue = 0,
|
||||
NonDefUVSOffsetGlyphID = 3
|
||||
};
|
||||
NS_ENSURE_TRUE(aLength >= OffsetVarSelectorRecords,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
|
||||
NS_ENSURE_TRUE(ReadShortAt(aBuf, OffsetFormat) == 14,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
|
||||
PRUint32 tablelen = ReadLongAt(aBuf, OffsetTableLength);
|
||||
NS_ENSURE_TRUE(tablelen <= aLength, NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
NS_ENSURE_TRUE(tablelen >= OffsetVarSelectorRecords,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
|
||||
const PRUint32 numVarSelectorRecords = ReadLongAt(aBuf, OffsetNumVarSelectorRecords);
|
||||
NS_ENSURE_TRUE((tablelen - OffsetVarSelectorRecords) /
|
||||
SizeOfVarSelectorRecord >= numVarSelectorRecords,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
|
||||
const PRUint8 *records = aBuf + OffsetVarSelectorRecords;
|
||||
for (PRUint32 i = 0; i < numVarSelectorRecords;
|
||||
i++, records += SizeOfVarSelectorRecord) {
|
||||
const PRUint32 varSelector = ReadUint24At(records, VSRecOffsetVarSelector);
|
||||
const PRUint32 defUVSOffset = ReadLongAt(records, VSRecOffsetDefUVSOffset);
|
||||
const PRUint32 nonDefUVSOffset = ReadLongAt(records, VSRecOffsetNonDefUVSOffset);
|
||||
NS_ENSURE_TRUE(varSelector <= CMAP_MAX_CODEPOINT &&
|
||||
defUVSOffset <= tablelen - 4 &&
|
||||
nonDefUVSOffset <= tablelen - 4,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
|
||||
if (defUVSOffset) {
|
||||
const PRUint32 numUnicodeValueRanges = ReadLongAt(aBuf, defUVSOffset);
|
||||
NS_ENSURE_TRUE((tablelen - defUVSOffset) /
|
||||
SizeOfDefUVSTable >= numUnicodeValueRanges,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
const PRUint8 *tables = aBuf + defUVSOffset + 4;
|
||||
PRUint32 prevEndUnicode = 0;
|
||||
for (PRUint32 j = 0; j < numUnicodeValueRanges; j++, tables += SizeOfDefUVSTable) {
|
||||
const PRUint32 startUnicode = ReadUint24At(tables, DefUVSOffsetStartUnicodeValue);
|
||||
const PRUint32 endUnicode = startUnicode + tables[DefUVSOffsetAdditionalCount];
|
||||
NS_ENSURE_TRUE((prevEndUnicode < startUnicode || j == 0) &&
|
||||
endUnicode <= CMAP_MAX_CODEPOINT,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
prevEndUnicode = endUnicode;
|
||||
}
|
||||
}
|
||||
|
||||
if (nonDefUVSOffset) {
|
||||
const PRUint32 numUVSMappings = ReadLongAt(aBuf, nonDefUVSOffset);
|
||||
NS_ENSURE_TRUE((tablelen - nonDefUVSOffset) /
|
||||
SizeOfNonDefUVSTable >= numUVSMappings,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
const PRUint8 *tables = aBuf + nonDefUVSOffset + 4;
|
||||
PRUint32 prevUnicode = 0;
|
||||
for (PRUint32 j = 0; j < numUVSMappings; j++, tables += SizeOfNonDefUVSTable) {
|
||||
const PRUint32 unicodeValue = ReadUint24At(tables, NonDefUVSOffsetUnicodeValue);
|
||||
const PRUint16 glyphID = ReadShortAt(tables, NonDefUVSOffsetGlyphID);
|
||||
NS_ENSURE_TRUE((prevUnicode < unicodeValue || j == 0) &&
|
||||
unicodeValue <= CMAP_MAX_CODEPOINT,
|
||||
NS_ERROR_GFX_CMAP_MALFORMED);
|
||||
prevUnicode = unicodeValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aTable = new PRUint8[tablelen];
|
||||
memcpy(aTable, aBuf, tablelen);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Windows requires fonts to have a format-4 cmap with a Microsoft ID (3). On the Mac, fonts either have
|
||||
// a format-4 cmap with Microsoft platform/encoding id or they have one with a platformID == Unicode (0)
|
||||
// For fonts with two format-4 tables, the first one (Unicode platform) is preferred on the Mac.
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#define acceptablePlatform(p) ((p) == PLATFORM_ID_UNICODE || (p) == PLATFORM_ID_MICROSOFT)
|
||||
#define acceptableFormat4(p,e,k) ( ((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDMicrosoft && (k) != 4) || \
|
||||
((p) == PLATFORM_ID_UNICODE) )
|
||||
#define isSymbol(p,e) ((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDSymbol)
|
||||
#define acceptableFormat4(p,e,k) (((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDMicrosoft && !(k)) || \
|
||||
((p) == PLATFORM_ID_UNICODE))
|
||||
|
||||
#define acceptableUCS4Encoding(p, e, k) \
|
||||
(((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDUCS4ForMicrosoftPlatform) && (k) != 12 || \
|
||||
((p) == PLATFORM_ID_UNICODE && \
|
||||
((e) == EncodingIDDefaultForUnicodePlatform || (e) >= EncodingIDUCS4ForUnicodePlatform)))
|
||||
#else
|
||||
#define acceptablePlatform(p) ((p) == PLATFORM_ID_MICROSOFT)
|
||||
#define acceptableFormat4(p,e,k) ((e) == EncodingIDMicrosoft)
|
||||
#define isSymbol(p,e) ((e) == EncodingIDSymbol)
|
||||
#define acceptableFormat4(p,e,k) ((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDMicrosoft)
|
||||
|
||||
#define acceptableUCS4Encoding(p, e, k) \
|
||||
((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDUCS4ForMicrosoftPlatform)
|
||||
#endif
|
||||
|
||||
#define acceptableUCS4Encoding(p, e) \
|
||||
((platformID == PLATFORM_ID_MICROSOFT && encodingID == EncodingIDUCS4ForMicrosoftPlatform) || \
|
||||
(platformID == PLATFORM_ID_UNICODE && \
|
||||
(encodingID == EncodingIDDefaultForUnicodePlatform || encodingID >= EncodingIDUCS4ForUnicodePlatform)))
|
||||
#define acceptablePlatform(p) ((p) == PLATFORM_ID_UNICODE || (p) == PLATFORM_ID_MICROSOFT)
|
||||
#define isSymbol(p,e) ((p) == PLATFORM_ID_MICROSOFT && (e) == EncodingIDSymbol)
|
||||
#define isUVSEncoding(p, e) ((p) == PLATFORM_ID_UNICODE && (e) == EncodingIDUVSForUnicodePlatform)
|
||||
|
||||
PRUint32
|
||||
gfxFontUtils::FindPreferredSubtable(PRUint8 *aBuf, PRUint32 aBufLength,
|
||||
PRUint32 *aTableOffset, PRBool *aSymbolEncoding)
|
||||
PRUint32 *aTableOffset, PRUint32 *aUVSTableOffset,
|
||||
PRBool *aSymbolEncoding)
|
||||
{
|
||||
enum {
|
||||
OffsetVersion = 0,
|
||||
|
@ -400,9 +495,14 @@ gfxFontUtils::FindPreferredSubtable(PRUint8 *aBuf, PRUint32 aBufLength,
|
|||
EncodingIDMicrosoft = 1,
|
||||
EncodingIDDefaultForUnicodePlatform = 0,
|
||||
EncodingIDUCS4ForUnicodePlatform = 3,
|
||||
EncodingIDUVSForUnicodePlatform = 5,
|
||||
EncodingIDUCS4ForMicrosoftPlatform = 10
|
||||
};
|
||||
|
||||
if (aUVSTableOffset) {
|
||||
*aUVSTableOffset = nsnull;
|
||||
}
|
||||
|
||||
// PRUint16 version = ReadShortAt(aBuf, OffsetVersion); // Unused: self-documenting.
|
||||
PRUint16 numTables = ReadShortAt(aBuf, OffsetNumTables);
|
||||
|
||||
|
@ -433,11 +533,18 @@ gfxFontUtils::FindPreferredSubtable(PRUint8 *aBuf, PRUint32 aBufLength,
|
|||
keepFormat = format;
|
||||
*aTableOffset = offset;
|
||||
*aSymbolEncoding = PR_FALSE;
|
||||
} else if (format == 12 && acceptableUCS4Encoding(platformID, encodingID)) {
|
||||
} else if (format == 12 && acceptableUCS4Encoding(platformID, encodingID, keepFormat)) {
|
||||
keepFormat = format;
|
||||
*aTableOffset = offset;
|
||||
*aSymbolEncoding = PR_FALSE;
|
||||
break; // we don't want to try anything else when this format is available.
|
||||
if (platformID > PLATFORM_ID_UNICODE || !aUVSTableOffset || *aUVSTableOffset) {
|
||||
break; // we don't want to try anything else when this format is available.
|
||||
}
|
||||
} else if (format == 14 && isUVSEncoding(platformID, encodingID) && aUVSTableOffset) {
|
||||
*aUVSTableOffset = offset;
|
||||
if (keepFormat == 12) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,12 +552,13 @@ gfxFontUtils::FindPreferredSubtable(PRUint8 *aBuf, PRUint32 aBufLength,
|
|||
}
|
||||
|
||||
nsresult
|
||||
gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||
gfxFontUtils::ReadCMAP(PRUint8 *aBuf, PRUint32 aBufLength, gfxSparseBitSet& aCharacterMap,
|
||||
PRUint32& aUVSOffset,
|
||||
PRPackedBool& aUnicodeFont, PRPackedBool& aSymbolFont)
|
||||
{
|
||||
PRUint32 offset;
|
||||
PRBool symbol;
|
||||
PRUint32 format = FindPreferredSubtable(aBuf, aBufLength, &offset, &symbol);
|
||||
PRUint32 format = FindPreferredSubtable(aBuf, aBufLength, &offset, &aUVSOffset, &symbol);
|
||||
|
||||
if (format == 4) {
|
||||
if (symbol) {
|
||||
|
@ -488,6 +596,31 @@ typedef struct {
|
|||
AutoSwap_PRUint16 arrays[1];
|
||||
} Format4Cmap;
|
||||
|
||||
typedef struct {
|
||||
AutoSwap_PRUint16 format;
|
||||
AutoSwap_PRUint32 length;
|
||||
AutoSwap_PRUint32 numVarSelectorRecords;
|
||||
|
||||
typedef struct {
|
||||
AutoSwap_PRUint24 varSelector;
|
||||
AutoSwap_PRUint32 defaultUVSOffset;
|
||||
AutoSwap_PRUint32 nonDefaultUVSOffset;
|
||||
} VarSelectorRecord;
|
||||
|
||||
VarSelectorRecord varSelectorRecords[1];
|
||||
} Format14Cmap;
|
||||
|
||||
typedef struct {
|
||||
AutoSwap_PRUint32 numUVSMappings;
|
||||
|
||||
typedef struct {
|
||||
AutoSwap_PRUint24 unicodeValue;
|
||||
AutoSwap_PRUint16 glyphID;
|
||||
} UVSMapping;
|
||||
|
||||
UVSMapping uvsMappings[1];
|
||||
} NonDefUVSTable;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
PRUint32
|
||||
|
@ -551,12 +684,60 @@ gfxFontUtils::MapCharToGlyphFormat4(const PRUint8 *aBuf, PRUnichar aCh)
|
|||
return 0;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
gfxFontUtils::MapUVSToGlyphFormat14(const PRUint8 *aBuf, PRUint32 aCh, PRUint32 aVS)
|
||||
{
|
||||
const Format14Cmap *cmap14 = reinterpret_cast<const Format14Cmap*>(aBuf);
|
||||
|
||||
// binary search in varSelectorRecords
|
||||
PRUint32 min = 0;
|
||||
PRUint32 max = cmap14->numVarSelectorRecords;
|
||||
PRUint32 nonDefUVSOffset = 0;
|
||||
while (min < max) {
|
||||
PRUint32 index = (min + max) >> 1;
|
||||
PRUint32 varSelector = cmap14->varSelectorRecords[index].varSelector;
|
||||
if (aVS == varSelector) {
|
||||
nonDefUVSOffset = cmap14->varSelectorRecords[index].nonDefaultUVSOffset;
|
||||
break;
|
||||
}
|
||||
if (aVS < varSelector) {
|
||||
max = index;
|
||||
} else {
|
||||
min = index + 1;
|
||||
}
|
||||
}
|
||||
if (!nonDefUVSOffset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NonDefUVSTable *table = reinterpret_cast<const NonDefUVSTable*>
|
||||
(aBuf + nonDefUVSOffset);
|
||||
|
||||
// binary search in uvsMappings
|
||||
min = 0;
|
||||
max = table->numUVSMappings;
|
||||
while (min < max) {
|
||||
PRUint32 index = (min + max) >> 1;
|
||||
PRUint32 unicodeValue = table->uvsMappings[index].unicodeValue;
|
||||
if (aCh == unicodeValue) {
|
||||
return table->uvsMappings[index].glyphID;
|
||||
}
|
||||
if (aCh < unicodeValue) {
|
||||
max = index;
|
||||
} else {
|
||||
min = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRUint32
|
||||
gfxFontUtils::MapCharToGlyph(PRUint8 *aBuf, PRUint32 aBufLength, PRUnichar aCh)
|
||||
{
|
||||
PRUint32 offset;
|
||||
PRBool symbol;
|
||||
PRUint32 format = FindPreferredSubtable(aBuf, aBufLength, &offset, &symbol);
|
||||
PRUint32 format = FindPreferredSubtable(aBuf, aBufLength, &offset, nsnull, &symbol);
|
||||
|
||||
if (format == 4)
|
||||
return MapCharToGlyphFormat4(aBuf + offset, aCh);
|
||||
|
|
|
@ -226,7 +226,7 @@ GDIFontEntry::ReadCMAP()
|
|||
|
||||
PRPackedBool unicodeFont = PR_FALSE, symbolFont = PR_FALSE;
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
|
||||
mCharacterMap, unicodeFont, symbolFont);
|
||||
mCharacterMap, mUVSOffset, unicodeFont, symbolFont);
|
||||
mUnicodeFont = unicodeFont;
|
||||
mSymbolFont = symbolFont;
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ MacOSFontEntry::ReadCMAP()
|
|||
|
||||
PRPackedBool unicodeFont, symbolFont; // currently ignored
|
||||
nsresult rv = gfxFontUtils::ReadCMAP(cmap.Elements(), cmap.Length(),
|
||||
mCharacterMap, unicodeFont, symbolFont);
|
||||
mCharacterMap, mUVSOffset, unicodeFont, symbolFont);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
mCharacterMap.reset();
|
||||
|
|
|
@ -1087,7 +1087,7 @@ gfxPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aStri
|
|||
ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
|
||||
surrogatePair = PR_TRUE;
|
||||
}
|
||||
if (i > 0 && gc->Get(aString[i]) == nsIUGenCategory::kMark) {
|
||||
if (i > 0 && gc->Get(ch) == nsIUGenCategory::kMark) {
|
||||
gfxTextRun::CompressedGlyph g;
|
||||
aTextRun->SetGlyphs(i, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull);
|
||||
}
|
||||
|
|
|
@ -76,14 +76,14 @@ public:
|
|||
UniscribeItem(gfxContext *aContext, HDC aDC,
|
||||
gfxUniscribeShaper *aShaper,
|
||||
const PRUnichar *aString, PRUint32 aLength,
|
||||
SCRIPT_ITEM *aItem) :
|
||||
SCRIPT_ITEM *aItem, PRUint32 aIVS) :
|
||||
mContext(aContext), mDC(aDC),
|
||||
mShaper(aShaper),
|
||||
mItemString(aString), mItemLength(aLength),
|
||||
mAlternativeString(nsnull), mScriptItem(aItem),
|
||||
mScript(aItem->a.eScript),
|
||||
mNumGlyphs(0), mMaxGlyphs(ESTIMATE_MAX_GLYPHS(aLength)),
|
||||
mFontSelected(PR_FALSE)
|
||||
mFontSelected(PR_FALSE), mIVS(aIVS)
|
||||
{
|
||||
NS_ASSERTION(mMaxGlyphs < 65535, "UniscribeItem is too big, ScriptShape() will fail!");
|
||||
}
|
||||
|
@ -166,6 +166,20 @@ public:
|
|||
continue;
|
||||
}
|
||||
|
||||
// Prior to Windows 7, Uniscribe didn't support Ideographic Variation
|
||||
// Selectors. Replace the UVS glyph manually.
|
||||
if (mIVS) {
|
||||
PRUint32 lastChar = str[mItemLength - 1];
|
||||
if (NS_IS_LOW_SURROGATE(lastChar)
|
||||
&& NS_IS_HIGH_SURROGATE(str[mItemLength - 2])) {
|
||||
lastChar = SURROGATE_TO_UCS4(str[mItemLength - 2], lastChar);
|
||||
}
|
||||
PRUint16 glyphId = mShaper->GetFont()->GetUVSGlyph(lastChar, mIVS);
|
||||
if (glyphId) {
|
||||
mGlyphs[mNumGlyphs - 1] = glyphId;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
@ -375,6 +389,7 @@ private:
|
|||
|
||||
int mMaxGlyphs;
|
||||
int mNumGlyphs;
|
||||
PRUint32 mIVS;
|
||||
|
||||
PRPackedBool mFontSelected;
|
||||
};
|
||||
|
@ -554,11 +569,34 @@ gfxUniscribeShaper::InitTextRun(gfxContext *aContext,
|
|||
int numItems = us.Itemize();
|
||||
|
||||
SaveDC(aDC);
|
||||
PRUint32 ivs = 0;
|
||||
for (int i = 0; i < numItems; ++i) {
|
||||
int iCharPos = us.ScriptItem(i)->iCharPos;
|
||||
int iCharPosNext = us.ScriptItem(i+1)->iCharPos;
|
||||
|
||||
if (ivs) {
|
||||
iCharPos += 2;
|
||||
if (iCharPos >= iCharPosNext) {
|
||||
ivs = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (i+1 < numItems && aRunStart + iCharPosNext <= aRunLength - 2
|
||||
&& aString[aRunStart + iCharPosNext] == H_SURROGATE(kUnicodeVS17)
|
||||
&& PRUint32(aString[aRunStart + iCharPosNext + 1]) - L_SURROGATE(kUnicodeVS17)
|
||||
<= L_SURROGATE(kUnicodeVS256) - L_SURROGATE(kUnicodeVS17)) {
|
||||
|
||||
ivs = SURROGATE_TO_UCS4(aString[aRunStart + iCharPosNext],
|
||||
aString[aRunStart + iCharPosNext + 1]);
|
||||
} else {
|
||||
ivs = 0;
|
||||
}
|
||||
|
||||
UniscribeItem item(aContext, aDC, this,
|
||||
aString + aRunStart + us.ScriptItem(i)->iCharPos,
|
||||
us.ScriptItem(i+1)->iCharPos - us.ScriptItem(i)->iCharPos,
|
||||
us.ScriptItem(i));
|
||||
aString + aRunStart + iCharPos,
|
||||
iCharPosNext - iCharPos,
|
||||
us.ScriptItem(i), ivs);
|
||||
if (!item.AllocateBuffers()) {
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
|
|
|
@ -76,6 +76,11 @@ public:
|
|||
|
||||
private:
|
||||
SCRIPT_CACHE mScriptCache;
|
||||
|
||||
enum {
|
||||
kUnicodeVS17 = gfxFontUtils::kUnicodeVS17,
|
||||
kUnicodeVS256 = gfxFontUtils::kUnicodeVS256
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* GFX_UNISCRIBESHAPER_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче