#118606 support opentype format 12 CMAP table

r=rbs, sr=attinasi
This commit is contained in:
shanjian%netscape.com 2002-01-10 22:06:58 +00:00
Родитель 11f32ac178
Коммит 7df3a4d014
7 изменённых файлов: 190 добавлений и 94 удалений

Просмотреть файл

@ -324,6 +324,8 @@ protected:
#define CCMAP_NONE_FLAG 0x0000
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
// get plane number from ccmap, bmp excluded, so plane 1's number is 0.
#define CCMAP_PLANE(h) (((PRUint16)(h) - (PRUint16)0xd800) >> 6)

Просмотреть файл

@ -460,8 +460,6 @@ printCCMap(PRUint16* aCCMap)
#endif
#define EXTENDED_UNICODE_PLANES 16
// Non-BMP unicode support extension, create ccmap for both BMP and extended planes
PRUint16*
MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOtherPlaneNum)
@ -502,6 +500,8 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
otherPlaneObj[i]->SetChars(aOtherPlaneMaps[i]);
totalSize += otherPlaneObj[i]->GetSize();
}
} else {
otherPlaneObj[i] = nsnull;
}
}
@ -566,7 +566,10 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
for (l = 0; l < 0x400; l++) {
plane = h >> 6;
offset = (h*0x400 + l) & 0xffff;
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
if (aOtherPlaneMaps[plane])
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
else
oldb = 0;
newb = CCMAP_HAS_CHAR_EXT(ccmap, h+0xd800, l+0xdc00);
NS_ASSERTION(oldb==newb, "failed to generate extension map correctly");
}

Просмотреть файл

@ -460,8 +460,6 @@ printCCMap(PRUint16* aCCMap)
#endif
#define EXTENDED_UNICODE_PLANES 16
// Non-BMP unicode support extension, create ccmap for both BMP and extended planes
PRUint16*
MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOtherPlaneNum)
@ -502,6 +500,8 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
otherPlaneObj[i]->SetChars(aOtherPlaneMaps[i]);
totalSize += otherPlaneObj[i]->GetSize();
}
} else {
otherPlaneObj[i] = nsnull;
}
}
@ -566,7 +566,10 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
for (l = 0; l < 0x400; l++) {
plane = h >> 6;
offset = (h*0x400 + l) & 0xffff;
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
if (aOtherPlaneMaps[plane])
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
else
oldb = 0;
newb = CCMAP_HAS_CHAR_EXT(ccmap, h+0xd800, l+0xdc00);
NS_ASSERTION(oldb==newb, "failed to generate extension map correctly");
}

Просмотреть файл

@ -324,6 +324,8 @@ protected:
#define CCMAP_NONE_FLAG 0x0000
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
// get plane number from ccmap, bmp excluded, so plane 1's number is 0.
#define CCMAP_PLANE(h) (((PRUint16)(h) - (PRUint16)0xd800) >> 6)

Просмотреть файл

@ -1255,6 +1255,7 @@ enum {
// the name of the following enum is from
// http://www.microsoft.com/typography/otspec/cmap.htm
enum {
eTTFormatUninitialize = -1,
eTTFormat0ByteEncodingTable = 0,
eTTFormat2HighbyteMappingThroughTable = 2,
eTTFormat4SegmentMappingToDeltaValues = 4,
@ -1264,10 +1265,138 @@ enum {
eTTFormat12SegmentedCoverage = 12,
};
nsresult
ReadCMAPTableFormat12(PRUint8* aBuf, PRInt32 len, PRUint32 **aExtMap)
{
PRUint8* p = aBuf;
PRUint8* end = aBuf + len;
PRUint32 i;
PRUint16 format = GET_SHORT(p);
p += sizeof(PRUint16);
if (format != eTTFormat12SegmentedCoverage) {
nsMemory::Free(aBuf);
return nsnull;
}
p += sizeof(PRUint16); // skip reserve field
PRUint32 tabLen = GET_LONG(p);
p += sizeof(PRUint32); // skip tableLen
p += sizeof(PRUint32); // skip language
PRUint32 nGroup = GET_LONG(p);
p += sizeof(PRUint32);
PRUint32 plane;
PRUint32 startCode;
PRUint32 endCode;
PRUint32 c;
for (i = 0; i < nGroup; i++) {
startCode = GET_LONG(p);
p += sizeof(PRUint32);
endCode = GET_LONG(p);
p += sizeof(PRUint32);
for ( c = startCode; c <= endCode; ++c) {
plane = c >> 16;
if (!aExtMap[plane]) {
aExtMap[plane] = new PRUint32[UCS2_MAP_LEN];
if (!aExtMap[plane])
return NS_ERROR_FAILURE;
}
ADD_GLYPH(aExtMap[plane], c & 0xffff);
}
p += sizeof(PRUint32); // skip startGlyphID field
}
return NS_OK;
}
nsresult
ReadCMAPTableFormat4(PRUint8* aBuf, PRInt32 aLength, PRUint32* aMap, PRUint8* aIsSpace)
{
PRUint8* p;
PRUint8* end = aBuf + aLength;
PRUint32 i;
p = aBuf;
PRUint16 format = GET_SHORT(p);
if (format != eTTFormat4SegmentMappingToDeltaValues) {
nsMemory::Free(aBuf);
return nsnull;
}
// XXX byte swapping only required for little endian (ifdef?)
while (p < end) {
PRUint8 tmp = p[0];
p[0] = p[1];
p[1] = tmp;
p += 2; // every two bytes
}
PRUint16* s = (PRUint16*) aBuf;
PRUint16 segCount = s[3] / 2;
PRUint16* endCode = &s[7];
PRUint16* startCode = endCode + segCount + 1;
PRUint16* idDelta = startCode + segCount;
PRUint16* idRangeOffset = idDelta + segCount;
PRUint16* glyphIdArray = idRangeOffset + segCount;
for (i = 0; i < segCount; ++i) {
if (idRangeOffset[i]) {
PRUint16 startC = startCode[i];
PRUint16 endC = endCode[i];
for (PRUint32 c = startC; c <= endC; ++c) {
PRUint16* g =
(idRangeOffset[i]/2 + (c - startC) + &idRangeOffset[i]);
if ((PRUint8*) g < end) {
if (*g) {
PRUint16 glyph = idDelta[i] + *g;
if (aIsSpace[glyph]) {
if (SHOULD_BE_SPACE_CHAR(c)) {
ADD_GLYPH(aMap, c);
}
}
else {
ADD_GLYPH(aMap, c);
}
}
else {
// index 0 also applies to space character
if (SHOULD_BE_SPACE_CHAR(c))
ADD_GLYPH(aMap, c);
}
}
else {
// XXX should we trust this font at all if it does this?
}
}
//printf("0x%04X-0x%04X ", startC, endC);
}
else {
PRUint16 endC = endCode[i];
for (PRUint32 c = startCode[i]; c <= endC; ++c) {
PRUint16 glyph = idDelta[i] + c;
if (aIsSpace[glyph]) {
if (SHOULD_BE_SPACE_CHAR(c)) {
ADD_GLYPH(aMap, c);
}
}
else {
ADD_GLYPH(aMap, c);
}
}
//printf("0x%04X-0x%04X ", startCode[i], endC);
}
}
//printf("\n");
return NS_OK;
}
PRUint16*
nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFontType, PRUint8& aCharset)
{
PRUint32 map[UCS2_MAP_LEN];
PRUint16 *ccmap = nsnull;
DWORD len = GetFontData(aDC, CMAP, 0, nsnull, 0);
if ((len == GDI_ERROR) || (!len)) {
@ -1289,7 +1418,10 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
PRUint16 n = GET_SHORT(p); // get numberSubtables
p += sizeof(PRUint16); // skip numberSubtables, move to the encoding subtables
PRUint16 i;
PRUint32 keepOffset;
PRUint32 offset;
PRUint32 keepFormat = eTTFormatUninitialize;
for (i = 0; i < n; ++i) {
PRUint16 platformID = GET_SHORT(p); // get platformID
p += sizeof(PRUint16); // move to platformSpecificID
@ -1299,7 +1431,6 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
p += sizeof(PRUint32); // move to next entry
if (platformID == eTTPlatformIDMicrosoft) {
if (encodingID == eTTMicrosoftEncodingUnicode) { // Unicode
// Some fonts claim to be unicode when they are actually
// 'pseudo-unicode' fonts that require a converter...
// Here, we check if this font is a pseudo-unicode font that
@ -1312,107 +1443,57 @@ nsFontMetricsWin::GetFontCCMAP(HDC aDC, const char* aShortName, eFontType& aFont
nsMemory::Free(buf);
return GetCCMapThroughConverter(aShortName);
} // if GetEncoding();
break; // break out from for(;;) loop
keepFormat = eTTFormat4SegmentMappingToDeltaValues;
keepOffset = offset;
} // if (encodingID == eTTMicrosoftEncodingUnicode)
else if (encodingID == eTTMicrosoftEncodingSymbol) { // symbol
aCharset = SYMBOL_CHARSET;
aFontType = eFontType_NonUnicode;
nsMemory::Free(buf);
return GetCCMapThroughConverter(aShortName);
} // if (encodingID == eTTMicrosoftEncodingSymbol)
else if (encodingID == eTTMicrosoftEncodingUCS4) {
keepFormat = eTTFormat12SegmentedCoverage;
keepOffset = offset;
// we don't want to try anything else when this format is available.
break;
}
} // if (platformID == eTTPlatformIDMicrosoft)
} // for loop
if (i == n) {
nsMemory::Free(buf);
return nsnull;
}
p = buf + offset;
PRUint16 format = GET_SHORT(p);
if (format != eTTFormat4SegmentMappingToDeltaValues) {
nsMemory::Free(buf);
return nsnull;
}
PRUint8* end = buf + len;
// XXX byte swapping only required for little endian (ifdef?)
while (p < end) {
PRUint8 tmp = p[0];
p[0] = p[1];
p[1] = tmp;
p += 2; // every two bytes
}
PRUint16* s = (PRUint16*) (buf + offset);
PRUint16 segCount = s[3] / 2;
PRUint16* endCode = &s[7];
PRUint16* startCode = endCode + segCount + 1;
PRUint16* idDelta = startCode + segCount;
PRUint16* idRangeOffset = idDelta + segCount;
PRUint16* glyphIdArray = idRangeOffset + segCount;
PRUint32 maxGlyph;
PRUint8* isSpace = GetSpaces(aDC, &maxGlyph);
if (!isSpace) {
nsMemory::Free(buf);
return nsnull;
}
for (i = 0; i < segCount; ++i) {
if (idRangeOffset[i]) {
PRUint16 startC = startCode[i];
PRUint16 endC = endCode[i];
for (PRUint32 c = startC; c <= endC; ++c) {
PRUint16* g =
(idRangeOffset[i]/2 + (c - startC) + &idRangeOffset[i]);
if ((PRUint8*) g < end) {
if (*g) {
PRUint16 glyph = idDelta[i] + *g;
if (glyph < maxGlyph) {
if (isSpace[glyph]) {
if (SHOULD_BE_SPACE_CHAR(c)) {
ADD_GLYPH(map, c);
}
}
else {
ADD_GLYPH(map, c);
}
}
}
}
else {
// XXX should we trust this font at all if it does this?
}
}
//printf("0x%04X-0x%04X ", startC, endC);
nsresult res;
if (eTTFormat12SegmentedCoverage == keepFormat) {
PRUint32* extMap[EXTENDED_UNICODE_PLANES+1];
extMap[0] = map;
nsCRT::memset(extMap+1, 0, sizeof(PRUint32*)*EXTENDED_UNICODE_PLANES);
res = ReadCMAPTableFormat12(buf+keepOffset, len-keepOffset, extMap);
if (NS_SUCCEEDED(res)) {
ccmap = MapToCCMapExt(map, extMap+1, EXTENDED_UNICODE_PLANES);
aCharset = DEFAULT_CHARSET;
aFontType = eFontType_Unicode;
}
else {
PRUint16 endC = endCode[i];
for (PRUint32 c = startCode[i]; c <= endC; ++c) {
PRUint16 glyph = idDelta[i] + c;
if (glyph < maxGlyph) {
if (isSpace[glyph]) {
if (SHOULD_BE_SPACE_CHAR(c)) {
ADD_GLYPH(map, c);
}
}
else {
ADD_GLYPH(map, c);
}
}
}
//printf("0x%04X-0x%04X ", startCode[i], endC);
for (i = 1; i <= EXTENDED_UNICODE_PLANES; ++i) {
if (extMap[i])
delete [] extMap[i];
}
}
else if (eTTFormat4SegmentMappingToDeltaValues == keepFormat) {
PRUint32 maxGlyph;
PRUint8* isSpace = GetSpaces(aDC, &maxGlyph);
if (isSpace) {
res = ReadCMAPTableFormat4(buf+keepOffset, len-keepOffset, map, isSpace);
nsMemory::Free(isSpace);
if (NS_SUCCEEDED(res))
ccmap = MapToCCMap(map);
aCharset = DEFAULT_CHARSET;
aFontType = eFontType_Unicode;
}
}
//printf("\n");
nsMemory::Free(buf);
nsMemory::Free(isSpace);
aCharset = DEFAULT_CHARSET;
aFontType = eFontType_Unicode;
return MapToCCMap(map);
return ccmap;
}
// Maps that are successfully returned by GetCCMAP() are also cached in the

Просмотреть файл

@ -460,8 +460,6 @@ printCCMap(PRUint16* aCCMap)
#endif
#define EXTENDED_UNICODE_PLANES 16
// Non-BMP unicode support extension, create ccmap for both BMP and extended planes
PRUint16*
MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOtherPlaneNum)
@ -502,6 +500,8 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
otherPlaneObj[i]->SetChars(aOtherPlaneMaps[i]);
totalSize += otherPlaneObj[i]->GetSize();
}
} else {
otherPlaneObj[i] = nsnull;
}
}
@ -566,7 +566,10 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
for (l = 0; l < 0x400; l++) {
plane = h >> 6;
offset = (h*0x400 + l) & 0xffff;
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
if (aOtherPlaneMaps[plane])
oldb = IS_REPRESENTABLE(aOtherPlaneMaps[plane], offset);
else
oldb = 0;
newb = CCMAP_HAS_CHAR_EXT(ccmap, h+0xd800, l+0xdc00);
NS_ASSERTION(oldb==newb, "failed to generate extension map correctly");
}

Просмотреть файл

@ -324,6 +324,8 @@ protected:
#define CCMAP_NONE_FLAG 0x0000
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
// get plane number from ccmap, bmp excluded, so plane 1's number is 0.
#define CCMAP_PLANE(h) (((PRUint16)(h) - (PRUint16)0xd800) >> 6)