support Surrogate display on Linux by using FreeType
r=bstell, sr=bryner
This commit is contained in:
katakai%japan.sun.com 2003-02-23 00:07:23 +00:00
Родитель 44f475da93
Коммит dadd6c39ce
13 изменённых файлов: 724 добавлений и 330 удалений

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

@ -113,5 +113,8 @@ interface nsIFreeType2 : nsISupports
in FTC_Face_Requester requester, in FT_Pointer req_data,
out FTC_Manager manager);
void imageCacheNew(in FTC_Manager manager, out FTC_Image_Cache cache);
};
FT_ULong getFirstChar(in FT_Face face, out FT_UInt gindex);
FT_ULong getNextChar(in FT_Face face, in FT_ULong charcode, out FT_UInt gindex);
void supportsExtFunc(out PRBool res);
};

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

@ -40,7 +40,7 @@
#ifndef NSCOMPRESSEDCHARMAP_H
#define NSCOMPRESSEDCHARMAP_H
#include "prtypes.h"
#include "nsICharRepresentable.h"
#define ALU_SIZE PR_BITS_PER_LONG
//#define ALU_SIZE 16
@ -67,7 +67,7 @@ extern PRUint16* CreateEmptyCCMap();
extern PRUint16* MapToCCMap(PRUint32* aMap);
extern PRUint16* MapperToCCMap(nsICharRepresentable *aMapper);
extern void FreeCCMap(PRUint16* &aMap);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint16 *);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint32 *);
extern PRBool IsSameCCMap(PRUint16* ccmap1, PRUint16* ccmap2);
#ifdef DEBUG
void printCCMap(PRUint16* aCCMap);
@ -101,17 +101,22 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
// (256*16 max pages) = 4400 PRUint16
#define CCMAP_MAX_LEN (16+16+16+256+4096)
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
class nsCompressedCharMap {
public:
nsCompressedCharMap();
~nsCompressedCharMap();
PRUint16* NewCCMap();
PRUint16* FillCCMap(PRUint16* aCCMap);
PRUint16 GetSize() {return mUsedLen;};
void SetChar(PRUint16);
void SetChar(PRUint32);
void SetChars(PRUint16*);
void SetChars(PRUint16, ALU_TYPE*);
void SetChars(PRUint32*);
void Extend() {mExtended = PR_TRUE;} // enable surrogate area
protected:
union {
@ -122,6 +127,11 @@ protected:
PRUint16 mUsedLen; // in PRUint16
PRUint16 mAllOnesPage;
PRBool mExtended;
// for surrogate support
PRUint32* mExtMap[EXTENDED_UNICODE_PLANES+1];
PRUint32 mMap[UCS2_MAP_LEN];
};
//
@ -295,7 +305,7 @@ protected:
#define CCMAP_TOTAL_PAGES CCMAP_POW2(CCMAP_BITS_PER_UPPER_LOG2 \
+CCMAP_BITS_PER_MID_LOG2)
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFF
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFFFFFF
//
// Finally, build up the macro to test the bit for a given char
@ -323,9 +333,6 @@ protected:
#define CCMAP_SURROGATE_FLAG 0x0001
#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_FROM_SURROGATE(h) ((((PRUint16)(h) - (PRUint16)0xd800) >> 6) + 1)
@ -345,5 +352,4 @@ protected:
#define CCMAP_HAS_CHAR_EXT(m, ucs4) (((ucs4)&0xffff0000) ? \
(CCMAP_FLAG(m) & CCMAP_SURROGATE_FLAG) && CCMAP_HAS_CHAR(CCMAP_FOR_PLANE_EXT((m), CCMAP_PLANE(ucs4)), (ucs4) & 0xffff) : \
CCMAP_HAS_CHAR(m, (PRUnichar)(ucs4)) )
#endif // NSCOMPRESSEDCHARMAP_H

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

@ -41,6 +41,7 @@
#include "nsIPref.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include "nsICharsetConverterManager.h"
#include "nsIRenderingContext.h"
@ -75,6 +76,7 @@ nsHashtable* nsFreeType2::sFontFamilies = nsnull;
nsHashtable* nsFreeType2::sRange1CharSetNames = nsnull;
nsHashtable* nsFreeType2::sRange2CharSetNames = nsnull;
nsICharsetConverterManager2* nsFreeType2::sCharSetManager = nsnull;
PRBool nsFreeType2::gHasExtFunc = PR_TRUE;
extern nsulCodePageRangeCharSetName ulCodePageRange1CharSetNames[];
extern nsulCodePageRangeCharSetName ulCodePageRange2CharSetNames[];
@ -96,24 +98,26 @@ static NS_DEFINE_CID(kCharSetManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
//
#define NS_FT2_OFFSET(f) (int)&((nsFreeType2*)0)->f
FtFuncList nsFreeType2::FtFuncs [] = {
{"FT_Done_Face", NS_FT2_OFFSET(nsFT_Done_Face)},
{"FT_Done_FreeType", NS_FT2_OFFSET(nsFT_Done_FreeType)},
{"FT_Done_Glyph", NS_FT2_OFFSET(nsFT_Done_Glyph)},
{"FT_Get_Char_Index", NS_FT2_OFFSET(nsFT_Get_Char_Index)},
{"FT_Get_Glyph", NS_FT2_OFFSET(nsFT_Get_Glyph)},
{"FT_Get_Sfnt_Table", NS_FT2_OFFSET(nsFT_Get_Sfnt_Table)},
{"FT_Glyph_Get_CBox", NS_FT2_OFFSET(nsFT_Glyph_Get_CBox)},
{"FT_Init_FreeType", NS_FT2_OFFSET(nsFT_Init_FreeType)},
{"FT_Load_Glyph", NS_FT2_OFFSET(nsFT_Load_Glyph)},
{"FT_New_Face", NS_FT2_OFFSET(nsFT_New_Face)},
{"FT_Outline_Decompose", NS_FT2_OFFSET(nsFT_Outline_Decompose)},
{"FT_Set_Charmap", NS_FT2_OFFSET(nsFT_Set_Charmap)},
{"FTC_Image_Cache_Lookup", NS_FT2_OFFSET(nsFTC_Image_Cache_Lookup)},
{"FTC_Manager_Lookup_Size", NS_FT2_OFFSET(nsFTC_Manager_Lookup_Size)},
{"FTC_Manager_Done", NS_FT2_OFFSET(nsFTC_Manager_Done)},
{"FTC_Manager_New", NS_FT2_OFFSET(nsFTC_Manager_New)},
{"FTC_Image_Cache_New", NS_FT2_OFFSET(nsFTC_Image_Cache_New)},
{nsnull, 0},
{"FT_Done_Face", NS_FT2_OFFSET(nsFT_Done_Face), PR_TRUE},
{"FT_Done_FreeType", NS_FT2_OFFSET(nsFT_Done_FreeType), PR_TRUE},
{"FT_Done_Glyph", NS_FT2_OFFSET(nsFT_Done_Glyph), PR_TRUE},
{"FT_Get_Char_Index", NS_FT2_OFFSET(nsFT_Get_Char_Index), PR_TRUE},
{"FT_Get_Glyph", NS_FT2_OFFSET(nsFT_Get_Glyph), PR_TRUE},
{"FT_Get_Sfnt_Table", NS_FT2_OFFSET(nsFT_Get_Sfnt_Table), PR_TRUE},
{"FT_Glyph_Get_CBox", NS_FT2_OFFSET(nsFT_Glyph_Get_CBox), PR_TRUE},
{"FT_Init_FreeType", NS_FT2_OFFSET(nsFT_Init_FreeType), PR_TRUE},
{"FT_Load_Glyph", NS_FT2_OFFSET(nsFT_Load_Glyph), PR_TRUE},
{"FT_New_Face", NS_FT2_OFFSET(nsFT_New_Face), PR_TRUE},
{"FT_Outline_Decompose", NS_FT2_OFFSET(nsFT_Outline_Decompose), PR_TRUE},
{"FT_Set_Charmap", NS_FT2_OFFSET(nsFT_Set_Charmap), PR_TRUE},
{"FTC_Image_Cache_Lookup", NS_FT2_OFFSET(nsFTC_Image_Cache_Lookup), PR_TRUE},
{"FTC_Manager_Lookup_Size", NS_FT2_OFFSET(nsFTC_Manager_Lookup_Size), PR_TRUE},
{"FTC_Manager_Done", NS_FT2_OFFSET(nsFTC_Manager_Done), PR_TRUE},
{"FTC_Manager_New", NS_FT2_OFFSET(nsFTC_Manager_New), PR_TRUE},
{"FTC_Image_Cache_New", NS_FT2_OFFSET(nsFTC_Image_Cache_New), PR_TRUE},
{"FT_Get_First_Char", NS_FT2_OFFSET(nsFT_Get_First_Char), PR_FALSE},
{"FT_Get_Next_Char", NS_FT2_OFFSET(nsFT_Get_Next_Char), PR_FALSE},
{nsnull, 0, 0},
};
nsTTFontEncoderInfo FEI_Adobe_Symbol_Encoding = {
@ -204,7 +208,7 @@ nsFreeType2::GetCharIndex(FT_Face face, FT_ULong charcode, FT_UInt *index)
*index = nsFT_Get_Char_Index(face, charcode);
return NS_OK;
}
NS_IMETHODIMP
nsFreeType2::GetGlyph(FT_GlyphSlot slot, FT_Glyph *glyph)
{
@ -316,6 +320,29 @@ nsFreeType2::ImageCacheNew(FTC_Manager manager, FTC_Image_Cache *cache)
FT_Error error = nsFTC_Image_Cache_New(manager, cache);
return error ? NS_ERROR_FAILURE : NS_OK;
}
NS_IMETHODIMP
nsFreeType2::GetFirstChar(FT_Face face, FT_UInt *gindex, FT_ULong *charcode)
{
// call the FreeType2 function via the function pointer
*charcode = nsFT_Get_First_Char(face, gindex);
return NS_OK;
}
NS_IMETHODIMP
nsFreeType2::GetNextChar(FT_Face face, FT_ULong charcode, FT_UInt *gindex, FT_ULong *ncharcode)
{
// call the FreeType2 function via the function pointer
*ncharcode = nsFT_Get_Next_Char(face, charcode, gindex);
return NS_OK;
}
NS_IMETHODIMP
nsFreeType2::SupportsExtFunc(PRBool *res)
{
*res = gHasExtFunc;
return NS_OK;
}
NS_IMETHODIMP
nsFreeType2::GetImageCache(FTC_Image_Cache *aCache)
@ -621,15 +648,22 @@ nsFreeType2::LoadSharedLib()
return PR_FALSE;
}
// checking FT_Get_First_Char() and FT_Get_Next_Char() for fast lookup methods
gHasExtFunc = PR_TRUE;
FtFuncList *p;
PRFuncPtr func;
void *ptr = this;
for (p=FtFuncs; p->FuncName; p++) {
func = PR_FindFunctionSymbol(mSharedLib, p->FuncName);
if (!func) {
NS_WARNING("nsFreeType2::LoadSharedLib Error");
ClearFunctions();
return PR_FALSE;
if (p->Required == PR_TRUE) {
NS_WARNING("nsFreeType2::LoadSharedLib Error");
ClearFunctions();
return PR_FALSE;
} else {
// should not return, but disable fast lookup methods
gHasExtFunc = PR_FALSE;
}
}
*((PRFuncPtr*)((char*)ptr+p->FuncOffset)) = func;
}
@ -720,6 +754,9 @@ PRUint16*
nsFreeType2::GetCCMap(nsFontCatalogEntry *aFce)
{
nsCompressedCharMap ccmapObj;
if (aFce->mFlags & FCE_FLAGS_SURROGATE) {
ccmapObj.Extend();
}
ccmapObj.SetChars(aFce->mCCMap);
return ccmapObj.NewCCMap();
}
@ -954,15 +991,32 @@ nsFreeTypeFaceRequester(FTC_FaceID face_id, FT_Library lib,
platform_id = ffei->mEncodingInfo->mCmapPlatformID;
encoding_id = ffei->mEncodingInfo->mCmapEncoding;
}
for (int i=0; i < face->num_charmaps; i++) {
if ( (face->charmaps[i]->platform_id == platform_id)
&& (face->charmaps[i]->encoding_id == encoding_id)) {
rv = ft2->SetCharmap(face, face->charmaps[i]);
if (NS_FAILED(rv)) {
FREETYPE_PRINTF(("failed to set cmap"));
ft2->DoneFace(face);
*aFace = nsnull;
fterror = 1;
if (face->charmaps[i]->platform_id == platform_id) {
#if defined(TT_MS_ID_UCS_4)
if (face->charmaps[i]->encoding_id == TT_MS_ID_UCS_4) {
rv = ft2->SetCharmap(face, face->charmaps[i]);
if (NS_FAILED(rv)) {
FREETYPE_PRINTF(("failed to set cmap"));
ft2->DoneFace(face);
*aFace = nsnull;
fterror = 1;
}
// UCS_4 is the most prefered cmap since it supports surrogates
// so stop here to avoid the possibly of getting UNICODE_CS which
// is the 2nd prefered choice.
break;
} else
#endif /* defined(TT_MS_ID_UCS_4) */
if (face->charmaps[i]->encoding_id == encoding_id) {
rv = ft2->SetCharmap(face, face->charmaps[i]);
if (NS_FAILED(rv)) {
FREETYPE_PRINTF(("failed to set cmap"));
ft2->DoneFace(face);
*aFace = nsnull;
fterror = 1;
}
}
}
}

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

@ -63,9 +63,10 @@ typedef struct {
PRUint16 *mCCMap; // compressed char map
} nsFontCatalogEntry;
#define FCE_FLAGS_ISVALID 0x01
#define FCE_FLAGS_UNICODE 0x02
#define FCE_FLAGS_SYMBOL 0x04
#define FCE_FLAGS_ISVALID 0x01
#define FCE_FLAGS_UNICODE 0x02
#define FCE_FLAGS_SYMBOL 0x04
#define FCE_FLAGS_SURROGATE 0x08
#define FREE_IF(x) if(x) free((void*)x)
typedef struct {
@ -110,6 +111,9 @@ typedef FT_Error (*FTC_Manager_New_t)(FT_Library, FT_UInt, FT_UInt, FT_ULong,
FTC_Face_Requester, FT_Pointer, FTC_Manager*);
typedef FT_Error (*FTC_Image_Cache_New_t)(FTC_Manager, FTC_Image_Cache*);
typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face, FT_UInt*);
typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face, FT_ULong, FT_UInt*);
class nsFreeTypeFace;
nsFreeTypeFace * nsFreeTypeGetFaceID(nsFontCatalogEntry *aFce);
@ -117,6 +121,7 @@ nsFreeTypeFace * nsFreeTypeGetFaceID(nsFontCatalogEntry *aFce);
typedef struct {
const char *FuncName;
int FuncOffset;
const PRBool Required;
} FtFuncList;
// class nsFreeType class definition
@ -155,9 +160,12 @@ protected:
FTC_Manager_Done_t nsFTC_Manager_Done;
FTC_Manager_New_t nsFTC_Manager_New;
FTC_Image_Cache_New_t nsFTC_Image_Cache_New;
FT_Get_First_Char_t nsFT_Get_First_Char;
FT_Get_Next_Char_t nsFT_Get_Next_Char;
// this array needs to be big enough to hold all the function pointers
// plus one extra for the null at the end
static FtFuncList FtFuncs[18];
static FtFuncList FtFuncs[20];
protected:
PRBool mEnableFreeType2;
@ -171,6 +179,7 @@ public:
static double gAATTDarkTextGain;
static PRInt32 gAntiAliasMinimum;
static PRInt32 gEmbeddedBitmapMaximumHeight;
static PRBool gHasExtFunc;
protected:
void ClearGlobals();
@ -217,6 +226,8 @@ public:
PRUint16 *GetCCMap();
nsFontCatalogEntry* GetFce() { return mFce; };
PRBool mHasExtendFuncs;
protected:
nsFontCatalogEntry *mFce;
PRUint16 *mCCMap;

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

@ -73,6 +73,8 @@
#include <X11/Xatom.h>
#include <gdk/gdk.h>
#define IS_SURROGATE(u) (u > 0x10000)
#define UCS2_NOMAPPING 0XFFFD
#ifdef PR_LOGGING
@ -1479,6 +1481,7 @@ NS_IMETHODIMP nsFontMetricsGTK::Init(const nsFont& aFont, nsIAtom* aLangGroup,
return NS_ERROR_FAILURE;
}
mCurrentFont = mWesternFont;
RealizeFont();
@ -1823,7 +1826,7 @@ nsFontMetricsGTK::LocateFont(PRUint32 aChar, PRInt32 & aCount)
// see if one of our loaded fonts can represent the character
for (i = 0; i < aCount; ++i) {
font = (nsFontGTK*)mLoadedFonts[i];
if (CCMAP_HAS_CHAR(font->mCCMap, aChar))
if (CCMAP_HAS_CHAR_EXT(font->mCCMap, aChar))
return font;
}
@ -1865,7 +1868,7 @@ nsFontMetricsGTK::ResolveForwards(const PRUnichar *aString,
//This if block is meant to speedup the process in normal situation, when
//most characters can be found in first font
if (currFont == mLoadedFonts[0]) {
while (currChar < lastChar && CCMAP_HAS_CHAR(currFont->mCCMap,*currChar))
while (currChar < lastChar && CCMAP_HAS_CHAR_EXT(currFont->mCCMap,*currChar))
++currChar;
fontSwitch.mFontGTK = currFont;
if (!(*aFunc)(&fontSwitch, firstChar, currChar - firstChar, aData))
@ -2346,7 +2349,7 @@ DumpTree(void)
struct nsFontSearch
{
nsFontMetricsGTK* mMetrics;
PRUnichar mChar;
PRUint32 mChar;
nsFontGTK* mFont;
};
@ -3131,12 +3134,12 @@ nsFontMetricsGTK::FindNearestSize(nsFontStretch* aStretch, PRUint16 aSize)
static PRBool
SetFontCharsetInfo(nsFontGTK *aFont, nsFontCharSetInfo* aCharSet,
PRUnichar aChar)
PRUint32 aChar)
{
if (aCharSet->mCharSet) {
aFont->mCCMap = aCharSet->mCCMap;
// check that the font is not empty
if (CCMAP_HAS_CHAR(aFont->mCCMap, aChar)) {
if (CCMAP_HAS_CHAR_EXT(aFont->mCCMap, aChar)) {
aFont->LoadFont();
if (!aFont->GetXFont()) {
return PR_FALSE;
@ -3188,7 +3191,7 @@ nsFontMetricsGTK::GetAASBBaseFont(nsFontStretch* aStretch,
nsFontGTK*
nsFontMetricsGTK::PickASizeAndLoad(nsFontStretch* aStretch,
nsFontCharSetInfo* aCharSet, PRUnichar aChar, const char *aName)
nsFontCharSetInfo* aCharSet, PRUint32 aChar, const char *aName)
{
if (aStretch->mFreeTypeFaceID) {
//FREETYPE_FONT_PRINTF(("mFreeTypeFaceID = 0x%p", aStretch->mFreeTypeFaceID));
@ -3218,6 +3221,11 @@ nsFontMetricsGTK::PickASizeAndLoad(nsFontStretch* aStretch,
return AddToLoadedFontsList(ftfont);
}
if (IS_SURROGATE(aChar)) {
// SURROGATE is only supported by FreeType
return nsnull;
}
PRBool use_scaled_font = PR_FALSE;
PRBool have_nearly_rightsized_bitmap = PR_FALSE;
nsFontGTK* base_aafont = nsnull;
@ -3444,13 +3452,24 @@ nsFontMetricsGTK::GetWidth (const PRUnichar* aString, PRUint32 aLength,
PRUint32 start = 0;
PRUint32 i;
for (i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
PRUint32 extraSurrogateLength;
for (i = 0; i < aLength; i+=1+extraSurrogateLength) {
PRUint32 c = aString[i];
extraSurrogateLength=0;
if(i < aLength-1 && IS_HIGH_SURROGATE(c) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] and
// low surrogate aString[i+1]
c = SURROGATE_TO_UCS4(c, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
nsFontGTK* currFont = nsnull;
nsFontGTK** font = mLoadedFonts;
nsFontGTK** end = &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
if (CCMAP_HAS_CHAR_EXT((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -3611,13 +3630,23 @@ nsFontMetricsGTK::DrawString(const PRUnichar* aString, PRUint32 aLength,
PRUint32 start = 0;
PRUint32 i;
for (i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
PRUint32 extraSurrogateLength;
for (i = 0; i < aLength; i+=1+extraSurrogateLength) {
PRUint32 c = aString[i];
extraSurrogateLength=0;
if(i < aLength-1 && IS_HIGH_SURROGATE(c) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] and
// low surrogate aString[i+1]
c = SURROGATE_TO_UCS4(c, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
nsFontGTK* currFont = nsnull;
nsFontGTK** font = mLoadedFonts;
nsFontGTK** lastFont = &mLoadedFonts[mLoadedFontsCount];
while (font < lastFont) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
if (CCMAP_HAS_CHAR_EXT((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -3787,15 +3816,24 @@ nsFontMetricsGTK::GetBoundingMetrics(const PRUnichar *aString,
PRBool firstTime = PR_TRUE;
PRUint32 start = 0;
PRUint32 i;
for (i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
PRUint32 extraSurrogateLength;
for (i = 0; i < aLength; i+=1+extraSurrogateLength) {
PRUint32 c = aString[i];
extraSurrogateLength=0;
if(i < aLength-1 && IS_HIGH_SURROGATE(c) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] and
// low surrogate aString[i+1]
c = SURROGATE_TO_UCS4(c, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
nsFontGTK* currFont = nsnull;
nsFontGTK** font = mLoadedFonts;
nsFontGTK** end = &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
if (CCMAP_HAS_CHAR_EXT((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -3872,14 +3910,24 @@ nsFontMetricsGTK::GetTextDimensions (const PRUnichar* aString,
PRUint32 start = 0;
PRUint32 i;
for (i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
PRUint32 extraSurrogateLength;
for (i = 0; i < aLength; i+=1+extraSurrogateLength) {
PRUint32 c = aString[i];
extraSurrogateLength=0;
if(i < aLength-1 && IS_HIGH_SURROGATE(c) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] and
// low surrogate aString[i+1]
c = SURROGATE_TO_UCS4(c, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
nsFontGTK* currFont = nsnull;
nsFontGTK** font = mLoadedFonts;
nsFontGTK** end = &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
if (CCMAP_HAS_CHAR_EXT((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -4722,7 +4770,7 @@ SetCharsetLangGroup(nsFontCharSetInfo* aCharSetInfo)
} while (0)
nsFontGTK*
nsFontMetricsGTK::SearchNode(nsFontNode* aNode, PRUnichar aChar)
nsFontMetricsGTK::SearchNode(nsFontNode* aNode, PRUint32 aChar)
{
if (aNode->mDummy) {
return nsnull;
@ -4738,6 +4786,12 @@ nsFontMetricsGTK::SearchNode(nsFontNode* aNode, PRUnichar aChar)
* loading a font with the same map.
*/
if (charSetInfo->mCharSet) {
// if SURROGATE char, ignore charSetInfo->mCCMap checking
// because the exact ccmap is never created before loading
// NEED TO FIX: need better way
if (IS_SURROGATE(aChar) ) {
goto check_done;
}
PRUint16* ccmap = charSetInfo->mCCMap;
if (ccmap) {
for (int i = 0; i < mLoadedFontsCount; i++) {
@ -4757,6 +4811,8 @@ nsFontMetricsGTK::SearchNode(nsFontNode* aNode, PRUnichar aChar)
}
}
check_done:
aNode->FillStyleHoles();
nsFontStyle* style = aNode->mStyles[mStyleIndex];
@ -5584,7 +5640,7 @@ FFRESubstituteEncoding(nsACString &aFFREName,
}
nsFontGTK*
nsFontMetricsGTK::TryNodes(nsACString &aFFREName, PRUnichar aChar)
nsFontMetricsGTK::TryNodes(nsACString &aFFREName, PRUint32 aChar)
{
FIND_FONT_PRINTF((" TryNodes aFFREName = %s",
PromiseFlatCString(aFFREName).get()));
@ -5613,7 +5669,7 @@ nsFontMetricsGTK::TryNodes(nsACString &aFFREName, PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::TryNode(nsCString* aName, PRUnichar aChar)
nsFontMetricsGTK::TryNode(nsCString* aName, PRUint32 aChar)
{
FIND_FONT_PRINTF((" TryNode aName = %s", (*aName).get()));
//
@ -5676,7 +5732,7 @@ nsFontMetricsGTK::TryNode(nsCString* aName, PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUnichar aChar)
nsFontMetricsGTK::TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUint32 aChar)
{
//
// for this family check related registry-encoding (for the language)
@ -5691,7 +5747,7 @@ nsFontMetricsGTK::TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUnichar
}
nsFontGTK*
nsFontMetricsGTK::TryFamily(nsCString* aName, PRUnichar aChar)
nsFontMetricsGTK::TryFamily(nsCString* aName, PRUint32 aChar)
{
//
// check the patterh "*-familyname-registry-encoding" for language
@ -5725,7 +5781,7 @@ nsFontMetricsGTK::TryFamily(nsCString* aName, PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::TryAliases(nsCString* aAlias, PRUnichar aChar)
nsFontMetricsGTK::TryAliases(nsCString* aAlias, PRUint32 aChar)
{
nsCStringKey key(*aAlias);
char* name = (char*) gAliases->Get(&key);
@ -5738,7 +5794,7 @@ nsFontMetricsGTK::TryAliases(nsCString* aAlias, PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::FindUserDefinedFont(PRUnichar aChar)
nsFontMetricsGTK::FindUserDefinedFont(PRUint32 aChar)
{
if (mIsUserDefined) {
FIND_FONT_PRINTF((" FindUserDefinedFont"));
@ -5753,7 +5809,7 @@ nsFontMetricsGTK::FindUserDefinedFont(PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::FindStyleSheetSpecificFont(PRUnichar aChar)
nsFontMetricsGTK::FindStyleSheetSpecificFont(PRUint32 aChar)
{
FIND_FONT_PRINTF((" FindStyleSheetSpecificFont"));
while (mFontsIndex < mFonts.Count()) {
@ -5860,7 +5916,7 @@ PrefEnumCallback(const char* aName, void* aClosure)
}
nsFontGTK*
nsFontMetricsGTK::FindStyleSheetGenericFont(PRUnichar aChar)
nsFontMetricsGTK::FindStyleSheetGenericFont(PRUint32 aChar)
{
FIND_FONT_PRINTF((" FindStyleSheetGenericFont"));
nsFontGTK* font;
@ -5932,16 +5988,16 @@ if (gAllowDoubleByteSpecialChars) {
sub_font->mCCMap = gDoubleByteSpecialCharsCCMap;
AddToLoadedFontsList(sub_font);
}
if (western_font && CCMAP_HAS_CHAR(western_font->mCCMap, aChar)) {
if (western_font && CCMAP_HAS_CHAR_EXT(western_font->mCCMap, aChar)) {
return western_font;
}
else if (symbol_font && CCMAP_HAS_CHAR(symbol_font->mCCMap, aChar)) {
else if (symbol_font && CCMAP_HAS_CHAR_EXT(symbol_font->mCCMap, aChar)) {
return symbol_font;
}
else if (euro_font && CCMAP_HAS_CHAR(euro_font->mCCMap, aChar)) {
else if (euro_font && CCMAP_HAS_CHAR_EXT(euro_font->mCCMap, aChar)) {
return euro_font;
}
else if (sub_font && CCMAP_HAS_CHAR(sub_font->mCCMap, aChar)) {
else if (sub_font && CCMAP_HAS_CHAR_EXT(sub_font->mCCMap, aChar)) {
FIND_FONT_PRINTF((" transliterate special chars for single byte docs"));
return sub_font;
}
@ -5992,7 +6048,7 @@ if (gAllowDoubleByteSpecialChars) {
}
nsFontGTK*
nsFontMetricsGTK::FindAnyFont(PRUnichar aChar)
nsFontMetricsGTK::FindAnyFont(PRUint32 aChar)
{
FIND_FONT_PRINTF((" FindAnyFont"));
// XXX If we get to this point, that means that we have exhausted all the
@ -6025,11 +6081,11 @@ nsFontMetricsGTK::FindAnyFont(PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::FindSubstituteFont(PRUnichar aChar)
nsFontMetricsGTK::FindSubstituteFont(PRUint32 aChar)
{
if (!mSubstituteFont) {
for (int i = 0; i < mLoadedFontsCount; i++) {
if (CCMAP_HAS_CHAR(mLoadedFonts[i]->mCCMap, 'a')) {
if (CCMAP_HAS_CHAR_EXT(mLoadedFonts[i]->mCCMap, 'a')) {
mSubstituteFont = new nsFontGTKSubstitute(mLoadedFonts[i]);
break;
}
@ -6063,7 +6119,7 @@ nsFontMetricsGTK::FindSubstituteFont(PRUnichar aChar)
//
nsFontGTK*
nsFontMetricsGTK::FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUnichar aChar)
nsFontMetricsGTK::FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUint32 aChar)
{
nsFontGTK* font;
//
@ -6132,7 +6188,7 @@ nsFontMetricsGTK::FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUnichar aChar)
}
nsFontGTK*
nsFontMetricsGTK::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCString *aName)
nsFontMetricsGTK::FindLangGroupFont(nsIAtom* aLangGroup, PRUint32 aChar, nsCString *aName)
{
nsFontGTK* font;
@ -6207,7 +6263,7 @@ nsFontMetricsGTK::FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCStr
* for the characters (FindSubstituteFont).
*/
nsFontGTK*
nsFontMetricsGTK::FindFont(PRUnichar aChar)
nsFontMetricsGTK::FindFont(PRUint32 aChar)
{
FIND_FONT_PRINTF(("\nFindFont(%c/0x%04x)", aChar, aChar));

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

@ -167,8 +167,8 @@ public:
void LoadFont(void);
PRBool IsEmptyFont(XFontStruct*);
inline int SupportsChar(PRUnichar aChar)
{ return mCCMap && CCMAP_HAS_CHAR(mCCMap, aChar); };
inline int SupportsChar(PRUint32 aChar)
{ return mCCMap && CCMAP_HAS_CHAR_EXT(mCCMap, aChar); };
virtual GdkFont* GetGDKFont(void);
virtual nsXFont* GetXFont(void);
@ -260,21 +260,21 @@ public:
NS_IMETHOD ResolveForwards(const PRUnichar* aString, PRUint32 aLength,
nsFontSwitchCallbackGTK aFunc, void* aData);
nsFontGTK* FindFont(PRUnichar aChar);
nsFontGTK* FindUserDefinedFont(PRUnichar aChar);
nsFontGTK* FindStyleSheetSpecificFont(PRUnichar aChar);
nsFontGTK* FindStyleSheetGenericFont(PRUnichar aChar);
nsFontGTK* FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUnichar aChar);
nsFontGTK* FindLangGroupFont(nsIAtom* aLangGroup, PRUnichar aChar, nsCString* aName);
nsFontGTK* FindAnyFont(PRUnichar aChar);
nsFontGTK* FindSubstituteFont(PRUnichar aChar);
nsFontGTK* FindFont(PRUint32 aChar);
nsFontGTK* FindUserDefinedFont(PRUint32 aChar);
nsFontGTK* FindStyleSheetSpecificFont(PRUint32 aChar);
nsFontGTK* FindStyleSheetGenericFont(PRUint32 aChar);
nsFontGTK* FindLangGroupPrefFont(nsIAtom* aLangGroup, PRUint32 aChar);
nsFontGTK* FindLangGroupFont(nsIAtom* aLangGroup, PRUint32 aChar, nsCString* aName);
nsFontGTK* FindAnyFont(PRUint32 aChar);
nsFontGTK* FindSubstituteFont(PRUint32 aChar);
nsFontGTK* SearchNode(nsFontNode* aNode, PRUnichar aChar);
nsFontGTK* TryAliases(nsCString* aName, PRUnichar aChar);
nsFontGTK* TryFamily(nsCString* aName, PRUnichar aChar);
nsFontGTK* TryNode(nsCString* aName, PRUnichar aChar);
nsFontGTK* TryNodes(nsACString &aFFREName, PRUnichar aChar);
nsFontGTK* TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUnichar aChar);
nsFontGTK* SearchNode(nsFontNode* aNode, PRUint32 aChar);
nsFontGTK* TryAliases(nsCString* aName, PRUint32 aChar);
nsFontGTK* TryFamily(nsCString* aName, PRUint32 aChar);
nsFontGTK* TryNode(nsCString* aName, PRUint32 aChar);
nsFontGTK* TryNodes(nsACString &aFFREName, PRUint32 aChar);
nsFontGTK* TryLangGroup(nsIAtom* aLangGroup, nsCString* aName, PRUint32 aChar);
nsFontGTK* AddToLoadedFontsList(nsFontGTK* aFont);
nsFontGTK* FindNearestSize(nsFontStretch* aStretch, PRUint16 aSize);
@ -282,7 +282,7 @@ public:
nsFontCharSetInfo* aCharSet);
nsFontGTK* PickASizeAndLoad(nsFontStretch* aStretch,
nsFontCharSetInfo* aCharSet,
PRUnichar aChar,
PRUint32 aChar,
const char *aName);
// nsIFontMetricsGTK (calls from the font rendering layer)

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

@ -38,9 +38,9 @@
* ***** END LICENSE BLOCK ***** */
#include "prmem.h"
#include "nsCompressedCharMap.h"
#include "nsCRT.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
void
FreeCCMap(PRUint16* &aMap)
@ -111,47 +111,71 @@ MapperToCCMap(nsICharRepresentable *aMapper)
}
PRBool
NextNonEmptyCCMapPage(PRUint16* aCCMap, PRUint16 *aPageStart)
NextNonEmptyCCMapPage(PRUint16* aCCMap, PRUint32 *aPageStart)
{
int i, j;
int i, j, l;
int planeend = 0;
int planestart = 0;
unsigned int k;
//
// Point to the next page
//
unsigned int upper_index;
unsigned int mid_index;
if (*aPageStart == CCMAP_BEGIN_AT_START_OF_MAP) {
upper_index = 0;
mid_index = 0;
}
else {
upper_index = CCMAP_UPPER_INDEX(*aPageStart);
mid_index = CCMAP_MID_INDEX(*aPageStart) + 1;
PRUint16* ccmap;
PRUint32 pagestart = *aPageStart;
if(CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) {
// for SURROGATE
planeend = EXTENDED_UNICODE_PLANES;
}
if(pagestart != CCMAP_BEGIN_AT_START_OF_MAP) {
planestart = CCMAP_PLANE(pagestart);
}
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=upper_index; i<CCMAP_NUM_UPPER_POINTERS; i++, mid_index=0) {
if (upper[i] == CCMAP_EMPTY_MID) {
continue;
// checking each plane
for(l=planestart; l<=planeend; l++, pagestart = CCMAP_BEGIN_AT_START_OF_MAP) {
if(CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) {
// for SURROGATE - get ccmap per plane
ccmap = CCMAP_FOR_PLANE_EXT(aCCMap, l);
} else {
// only BMP
ccmap = aCCMap;
}
//
// Point to the next page
//
unsigned int upper_index;
unsigned int mid_index;
if (pagestart == CCMAP_BEGIN_AT_START_OF_MAP) {
upper_index = 0;
mid_index = 0;
} else {
upper_index = CCMAP_UPPER_INDEX(pagestart & 0xffff);
mid_index = CCMAP_MID_INDEX(pagestart & 0xffff) + 1;
}
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=mid_index; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
// walk thru the upper pointers
PRUint16 *upper = &ccmap[0];
for (i=upper_index; i<CCMAP_NUM_UPPER_POINTERS; i++, mid_index=0) {
if (upper[i] == CCMAP_EMPTY_MID) {
continue;
}
// walk the page
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
for (k=0; k<CCMAP_NUM_ALUS_PER_PAGE; k++) {
if (page[k] != 0) {
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
*aPageStart = (PRUint16)base;
return PR_TRUE;
// walk the mid array
PRUint16 *mid = &ccmap[upper[i]];
for (j=mid_index; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
continue;
// walk the page
ALU_TYPE *page = (ALU_TYPE*)&ccmap[mid[j]];
for (k=0; k<CCMAP_NUM_ALUS_PER_PAGE; k++) {
if (page[k] != 0) {
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
// return exact UCS4 code point, plane number + base
*aPageStart = (((PRUint32)l)<<16)+base;
return PR_TRUE;
}
}
}
}
@ -185,17 +209,21 @@ PRBool IsSameCCMap(PRUint16* ccmap1, PRUint16* ccmap2)
PRUint16*
nsCompressedCharMap::NewCCMap()
{
PRUint16 *newMap = (PRUint16*)PR_Malloc((CCMAP_EXTRA + mUsedLen) * sizeof(PRUint16));
NS_ASSERTION(newMap, "failed to alloc new CCMap");
if (!newMap)
return nsnull;
if (mExtended) {
return MapToCCMapExt(mMap, mExtMap+1, EXTENDED_UNICODE_PLANES);
} else {
PRUint16 *newMap = (PRUint16*)PR_Malloc((CCMAP_EXTRA + mUsedLen) * sizeof(PRUint16));
NS_ASSERTION(newMap, "failed to alloc new CCMap");
if (!newMap)
return nsnull;
newMap += CCMAP_EXTRA;
CCMAP_SIZE(newMap) = GetSize();
CCMAP_FLAG(newMap) = CCMAP_NONE_FLAG;
newMap += CCMAP_EXTRA;
CCMAP_SIZE(newMap) = GetSize();
CCMAP_FLAG(newMap) = CCMAP_NONE_FLAG;
FillCCMap(newMap);
return newMap;
FillCCMap(newMap);
return newMap;
}
}
PRUint16*
@ -208,6 +236,18 @@ nsCompressedCharMap::FillCCMap(PRUint16* aCCMap)
return aCCMap;
}
nsCompressedCharMap::~nsCompressedCharMap()
{
if(mExtended){
int i;
for (i = 1; i <= EXTENDED_UNICODE_PLANES; ++i) {
if (mExtMap[i]) {
PR_Free(mExtMap[i]);
}
}
}
}
nsCompressedCharMap::nsCompressedCharMap()
{
// initialize map to have:
@ -239,45 +279,70 @@ nsCompressedCharMap::nsCompressedCharMap()
NS_ASSERTION(mUsedLen==CCMAP_EMPTY_PAGE, "empty page offset misconfigured");
// the page was zero'd by the memset above
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
// init extended
mExtended = PR_FALSE;
memset(mExtMap+1, 0, sizeof(PRUint32*) * EXTENDED_UNICODE_PLANES);
memset(mMap, 0, sizeof(mMap));
mExtMap[0] = mMap;
}
void
nsCompressedCharMap::SetChar(PRUint16 aChar)
nsCompressedCharMap::SetChar(PRUint32 aChar)
{
unsigned int i;
unsigned int upper_index = CCMAP_UPPER_INDEX(aChar);
unsigned int mid_index = CCMAP_MID_INDEX(aChar);
PRUint16 mid_offset = u.mCCMap[upper_index];
if (mid_offset == CCMAP_EMPTY_MID) {
mid_offset = u.mCCMap[upper_index] = mUsedLen;
mUsedLen += CCMAP_NUM_MID_POINTERS;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the mid
PRUint16 *mid = &u.mCCMap[mid_offset];
for (i=0; i<CCMAP_NUM_MID_POINTERS; i++) {
NS_ASSERTION(mid[i]==0, "this mid pointer should be unused");
mid[i] = CCMAP_EMPTY_PAGE;
if (mExtended) {
PRUint32 plane_num = CCMAP_PLANE(aChar);
NS_ASSERTION(plane_num <= EXTENDED_UNICODE_PLANES,"invalid plane");
if (plane_num <= EXTENDED_UNICODE_PLANES) {
if (mExtMap[plane_num] == 0) {
mExtMap[plane_num] = (PRUint32*)PR_Malloc(sizeof(PRUint32)*UCS2_MAP_LEN);
NS_ASSERTION(mExtMap[plane_num], "failed to alloc new mExtMap");
if (!mExtMap[plane_num]) {
return;
}
memset(mExtMap[plane_num], 0, sizeof(PRUint32)*UCS2_MAP_LEN);
}
SET_REPRESENTABLE(mExtMap[plane_num], aChar & 0xffff);
}
}
} else {
NS_ASSERTION(aChar <= 0xffff, "extended char is passed");
PRUint16 page_offset = u.mCCMap[mid_offset+mid_index];
if (page_offset == CCMAP_EMPTY_PAGE) {
page_offset = u.mCCMap[mid_offset+mid_index] = mUsedLen;
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the page
PRUint16 *page = &u.mCCMap[page_offset];
for (i=0; i<CCMAP_NUM_PRUINT16S_PER_PAGE; i++) {
NS_ASSERTION(page[i]==0, "this page should be unused");
page[i] = 0;
unsigned int i;
unsigned int upper_index = CCMAP_UPPER_INDEX(aChar);
unsigned int mid_index = CCMAP_MID_INDEX(aChar);
PRUint16 mid_offset = u.mCCMap[upper_index];
if (mid_offset == CCMAP_EMPTY_MID) {
mid_offset = u.mCCMap[upper_index] = mUsedLen;
mUsedLen += CCMAP_NUM_MID_POINTERS;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the mid
PRUint16 *mid = &u.mCCMap[mid_offset];
for (i=0; i<CCMAP_NUM_MID_POINTERS; i++) {
NS_ASSERTION(mid[i]==0, "this mid pointer should be unused");
mid[i] = CCMAP_EMPTY_PAGE;
}
}
PRUint16 page_offset = u.mCCMap[mid_offset+mid_index];
if (page_offset == CCMAP_EMPTY_PAGE) {
page_offset = u.mCCMap[mid_offset+mid_index] = mUsedLen;
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the page
PRUint16 *page = &u.mCCMap[page_offset];
for (i=0; i<CCMAP_NUM_PRUINT16S_PER_PAGE; i++) {
NS_ASSERTION(page[i]==0, "this page should be unused");
page[i] = 0;
}
}
}
#undef CCMAP_SET_CHAR
#define CCMAP_SET_CHAR(m,c) (CCMAP_TO_ALU(m,c) |= (CCMAP_POW2(CCMAP_BIT_INDEX(c))))
CCMAP_SET_CHAR(u.mCCMap,aChar);
CCMAP_SET_CHAR(u.mCCMap,aChar);
#undef CCMAP_SET_CHAR
NS_ASSERTION(CCMAP_HAS_CHAR(u.mCCMap,aChar), "failed to set bit");
NS_ASSERTION(CCMAP_HAS_CHAR(u.mCCMap,aChar), "failed to set bit");
}
}
void
@ -359,26 +424,40 @@ void
nsCompressedCharMap::SetChars(PRUint16* aCCMap)
{
int i, j;
//
// Copy the input CCMap
//
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=0; i<CCMAP_NUM_UPPER_POINTERS; i++) {
if (upper[i] == CCMAP_EMPTY_MID)
continue;
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=0; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
if(mExtended){
PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
while (NextNonEmptyCCMapPage(aCCMap, &page)) {
PRUint32 pagechar = page;
for (i=0; i<(CCMAP_BITS_PER_PAGE/8); i++) {
for (j=0; j<8; j++) {
if (CCMAP_HAS_CHAR_EXT(aCCMap, pagechar)) {
SetChar(pagechar);
}
pagechar++;
}
}
}
} else {
//
// Copy the input CCMap
//
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=0; i<CCMAP_NUM_UPPER_POINTERS; i++) {
if (upper[i] == CCMAP_EMPTY_MID)
continue;
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
SetChars((PRUint16)base, page);
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=0; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
continue;
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
SetChars((PRUint16)base, page);
}
}
}
}
@ -436,7 +515,7 @@ nsCompressedCharMap::SetChars(PRUint32* aMap)
void
printCCMap(PRUint16* aCCMap)
{
PRUint16 page = CCMAP_BEGIN_AT_START_OF_MAP;
PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
while (NextNonEmptyCCMapPage(aCCMap, &page)) {
//FONT_SCAN_PRINTF(("page starting at 0x%04x has chars", page));
int i;

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

@ -40,7 +40,7 @@
#ifndef NSCOMPRESSEDCHARMAP_H
#define NSCOMPRESSEDCHARMAP_H
#include "prtypes.h"
#include "nsICharRepresentable.h"
#define ALU_SIZE PR_BITS_PER_LONG
//#define ALU_SIZE 16
@ -67,7 +67,7 @@ extern PRUint16* CreateEmptyCCMap();
extern PRUint16* MapToCCMap(PRUint32* aMap);
extern PRUint16* MapperToCCMap(nsICharRepresentable *aMapper);
extern void FreeCCMap(PRUint16* &aMap);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint16 *);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint32 *);
extern PRBool IsSameCCMap(PRUint16* ccmap1, PRUint16* ccmap2);
#ifdef DEBUG
void printCCMap(PRUint16* aCCMap);
@ -101,17 +101,22 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
// (256*16 max pages) = 4400 PRUint16
#define CCMAP_MAX_LEN (16+16+16+256+4096)
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
class nsCompressedCharMap {
public:
nsCompressedCharMap();
~nsCompressedCharMap();
PRUint16* NewCCMap();
PRUint16* FillCCMap(PRUint16* aCCMap);
PRUint16 GetSize() {return mUsedLen;};
void SetChar(PRUint16);
void SetChar(PRUint32);
void SetChars(PRUint16*);
void SetChars(PRUint16, ALU_TYPE*);
void SetChars(PRUint32*);
void Extend() {mExtended = PR_TRUE;} // enable surrogate area
protected:
union {
@ -122,6 +127,11 @@ protected:
PRUint16 mUsedLen; // in PRUint16
PRUint16 mAllOnesPage;
PRBool mExtended;
// for surrogate support
PRUint32* mExtMap[EXTENDED_UNICODE_PLANES+1];
PRUint32 mMap[UCS2_MAP_LEN];
};
//
@ -295,7 +305,7 @@ protected:
#define CCMAP_TOTAL_PAGES CCMAP_POW2(CCMAP_BITS_PER_UPPER_LOG2 \
+CCMAP_BITS_PER_MID_LOG2)
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFF
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFFFFFF
//
// Finally, build up the macro to test the bit for a given char
@ -323,9 +333,6 @@ protected:
#define CCMAP_SURROGATE_FLAG 0x0001
#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_FROM_SURROGATE(h) ((((PRUint16)(h) - (PRUint16)0xd800) >> 6) + 1)
@ -345,5 +352,4 @@ protected:
#define CCMAP_HAS_CHAR_EXT(m, ucs4) (((ucs4)&0xffff0000) ? \
(CCMAP_FLAG(m) & CCMAP_SURROGATE_FLAG) && CCMAP_HAS_CHAR(CCMAP_FOR_PLANE_EXT((m), CCMAP_PLANE(ucs4)), (ucs4) & 0xffff) : \
CCMAP_HAS_CHAR(m, (PRUnichar)(ucs4)) )
#endif // NSCOMPRESSEDCHARMAP_H

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

@ -1303,7 +1303,7 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
const char *aFontFileName,
int aFaceIndex, int * aNumFaces)
{
int i, len;
PRUint32 i, len;
nsFontCatalogEntry *fce;
FT_Error fterror;
FT_Face face = nsnull;
@ -1360,14 +1360,27 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
}
else {
for (i=0; i < face->num_charmaps; i++) {
if ( (face->charmaps[i]->platform_id == TT_PLATFORM_MICROSOFT)
&& (face->charmaps[i]->encoding_id == TT_MS_ID_UNICODE_CS)) {
fce->mFlags = FCE_FLAGS_ISVALID | FCE_FLAGS_UNICODE;
rv = mFt2->SetCharmap(face, face->charmaps[i]);
if (NS_FAILED(rv)) {
FONT_SCAN_PRINTF(("failed to select unicode charmap"));
goto cleanup_and_return;
if (face->charmaps[i]->platform_id == TT_PLATFORM_MICROSOFT) {
if (face->charmaps[i]->encoding_id == TT_MS_ID_UNICODE_CS) {
fce->mFlags = FCE_FLAGS_ISVALID | FCE_FLAGS_UNICODE;
fterror = mFt2->SetCharmap(face, face->charmaps[i]);
if (fterror) {
FONT_SCAN_PRINTF(("failed to select unicode charmap"));
goto cleanup_and_return;
}
}
#if defined(TT_MS_ID_UCS_4)
else if (face->charmaps[i]->encoding_id == TT_MS_ID_UCS_4) {
fce->mFlags = FCE_FLAGS_ISVALID | FCE_FLAGS_UNICODE | FCE_FLAGS_SURROGATE;
fterror = mFt2->SetCharmap(face, face->charmaps[i]);
if (fterror) {
FONT_SCAN_PRINTF(("failed to select unicode charmap"));
goto cleanup_and_return;
}
break;
}
#endif
}
}
}
@ -1420,20 +1433,46 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
fce->mEmbeddedBitmapHeights[i] = face->available_sizes[i].height;
}
if (fce->mFlags & FCE_FLAGS_UNICODE) {
/* get the Unicode char map */
blank_chars = 0;
if ((fce->mFlags & FCE_FLAGS_UNICODE) || (fce->mFlags & FCE_FLAGS_SURROGATE)) {
if (fce->mFlags & FCE_FLAGS_SURROGATE) {
ccmapObj.Extend();
}
// check fast methods are defined
PRBool has_fast_methods;
mFt2->SupportsExtFunc(&has_fast_methods);
PRBool scan_done = PR_FALSE;
if (has_fast_methods) {
mFt2->GetFirstChar(face, &glyph_index, (FT_ULong*)&i);
if (glyph_index == 0) {
// no glyph in the font
scan_done = PR_TRUE;
}
} else {
i=0;
}
len = NUM_UNICODE_CHARS;
if(fce->mFlags & FCE_FLAGS_SURROGATE) {
len = 0xFFFFF;
}
blank_chars = 0;
slot = face->glyph;
FONT_SCAN_PRINTF((" "));
for (i=0; i<len; i++) {
mFt2->GetCharIndex(face, (FT_ULong)i, &glyph_index);
//FONT_CATALOG_PRINTF(("i=%d, glyph_index=%d", i, glyph_index));
if (!glyph_index)
continue;
while (!scan_done && i < len) {
if (!has_fast_methods) {
mFt2->GetCharIndex(face, (FT_ULong)i, &glyph_index);
//FONT_CATALOG_PRINTF(("i=%d, glyph_index=%d", i, glyph_index));
if (glyph_index == 0) {
goto next_char;
}
}
if (gFontDebug & NS_FONT_DEBUG_FONT_SCAN) {
if ((num_checked % 1000) == 0) {
FONT_SCAN_PRINTF(("\b\b\b\b\b\b\b\b\b\b\b\b%5d glyphs", num_checked));
FONT_SCAN_PRINTF(("\b\b\b\b\b\b\b\b\b\b\b\b\b\b%7d glyphs", num_checked));
}
}
num_checked++;
@ -1443,7 +1482,7 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
if (NS_FAILED(rv)) {
FONT_CATALOG_PRINTF(("error loading %d (glyph index = %d)",
i, glyph_index));
continue;
goto next_char;
}
if (slot->format == ft_glyph_format_outline) {
//FONT_CATALOG_PRINTF(("n_contours=%d", slot->outline.n_contours));
@ -1456,7 +1495,7 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
mFt2->DoneGlyph(glyph);
if((bbox.xMax==0) && (bbox.xMin==0)
&& (bbox.yMax==0) && (bbox.yMin==0)) {
continue;
goto next_char;
}
FONT_SCAN_PRINTF(("no contours %d (glyph index = %d)\n", i,
glyph_index));
@ -1472,7 +1511,7 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
FONT_CATALOG_PRINTF(("continue at line %d", __LINE__));
FONT_SCAN_PRINTF(("empty bitmap %d (glyph index = %d)\n",
i, glyph_index));
continue;
goto next_char;
}
}
else {
@ -1480,15 +1519,28 @@ nsFT2FontCatalog::NewFceFromFontFile(FT_Library aFreeTypeLibrary,
}
ccmapObj.SetChar(i);
fce->mNumUsableGlyphs++;
next_char:
if (has_fast_methods) {
FT_ULong ncharcode;
mFt2->GetNextChar(face, (FT_ULong)i, &glyph_index, &ncharcode);
i = ncharcode;
if (glyph_index == 0) {
// no more glyph in the font
scan_done = PR_TRUE;
}
} else {
i++;
}
}
if (gFontDebug & NS_FONT_DEBUG_FONT_SCAN) {
FONT_SCAN_PRINTF(("\b\b\b\b\b\b\b\b\b\b\b\b%5d glyphs", num_checked));
FONT_SCAN_PRINTF(("\b\b\b\b\b\b\b\b\b\b\b\b\b\b%7d glyphs", num_checked));
if (blank_chars) {
FONT_SCAN_PRINTF((" (%d invalid)", blank_chars));
}
}
if (fce->mNumUsableGlyphs == 0)
fce->mFlags |= FCE_FLAGS_ISVALID;
fce->mCCMap = ccmapObj.NewCCMap();
}
else if (fce->mFlags & FCE_FLAGS_SYMBOL) {
@ -1555,7 +1607,7 @@ nsFT2FontCatalog::NewFceFromSummary(nsNameValuePairDB *aDB)
nsFontCatalogEntry *fce = nsnull;
long longVal;
unsigned long uLongVal;
int num, intVal;
int num, intVal, i;
nsCompressedCharMap ccmapObj;
fce = (nsFontCatalogEntry *)calloc(1, sizeof(nsFontCatalogEntry));
@ -1566,6 +1618,7 @@ nsFT2FontCatalog::NewFceFromSummary(nsNameValuePairDB *aDB)
FONT_CATALOG_PRINTF(("file garbled: expected begin=Font_, got %s", type));
goto cleanup_and_return;
}
while (aDB->GetNextElement(&name, &value) > 0) {
if (STRMATCH(name,"FamilyName")) {
if (fce->mFamilyName) {
@ -1583,12 +1636,15 @@ nsFT2FontCatalog::NewFceFromSummary(nsNameValuePairDB *aDB)
fce->mFontFileName?fce->mFontFileName:""));
goto cleanup_and_return;
}
num = sscanf(value, "%lu", &uLongVal);
num = sscanf(value, "%lx", &uLongVal);
if (num != 1) {
FONT_CATALOG_PRINTF(("failed to parse Flags (%s)",value));
goto cleanup_and_return;
}
fce->mFlags = uLongVal;
if (fce->mFlags & FCE_FLAGS_SURROGATE) {
ccmapObj.Extend();
}
}
else if (STRMATCH(name,"FontFileName")) {
if (fce->mFontFileName) {
@ -1822,6 +1878,7 @@ nsFT2FontCatalog::NewFceFromSummary(nsNameValuePairDB *aDB)
}
fce->mCCMap = ccmapObj.NewCCMap();
if (!fce->mCCMap) {
FONT_CATALOG_PRINTF(("missing char map"));
goto cleanup_and_return;
@ -1855,7 +1912,8 @@ nsFT2FontCatalog::NewFceFromSummary(nsNameValuePairDB *aDB)
goto cleanup_and_return;
}
if (fce->mFlags&FCE_FLAGS_ISVALID
&& (fce->mFlags & FCE_FLAGS_UNICODE) && (fce->mNumUsableGlyphs == 0)) {
&& ((fce->mFlags & FCE_FLAGS_UNICODE) || (fce->mFlags & FCE_FLAGS_SURROGATE))
&& (fce->mNumUsableGlyphs == 0)) {
FONT_CATALOG_PRINTF(("missing num usable glyphs"));
goto cleanup_and_return;
}
@ -1889,7 +1947,7 @@ nsFT2FontCatalog::ParseCCMapLine(nsCompressedCharMap *aCCMapObj, long base,
{
int i, j, len;
unsigned int byte;
PRUint16 pagechar = (PRUint16)base;
PRUint32 pagechar = (PRUint32)base;
// check we have the right number of chars
len = strlen(valString);
@ -1942,7 +2000,7 @@ nsFT2FontCatalog::PrintCCMap(nsNameValuePairDB *aDB, PRUint16 *aCCMap)
if (!aCCMap)
return;
PRUint16 page = CCMAP_BEGIN_AT_START_OF_MAP;
PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
while (NextNonEmptyCCMapPage(aCCMap, &page)) {
//FONT_CATALOG_PRINTF(("page starting at 0x%04x has chars", page));
PrintPageBits(aDB, aCCMap, page);
@ -2044,7 +2102,7 @@ nsFT2FontCatalog::PrintPageBits(nsNameValuePairDB *aDB, PRUint16 *aCCMap,
for (i=0; i<(CCMAP_BITS_PER_PAGE/8); i++) {
unsigned char val = 0;
for (int j=0; j<8; j++) {
if (CCMAP_HAS_CHAR(aCCMap, pagechar)) {
if (CCMAP_HAS_CHAR_EXT(aCCMap, pagechar)) {
val |= 1 << j;
}
pagechar++;

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

@ -45,8 +45,8 @@
#if (defined(MOZ_ENABLE_FREETYPE2))
#include "nsFreeType.h"
#include "nsCompressedCharMap.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include "nsString.h"
#include "nsIPref.h"

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

@ -44,6 +44,7 @@
#endif
#include "nsFontFreeType.h"
#include "nsUnicharUtils.h"
#if (!defined(MOZ_ENABLE_FREETYPE2))
@ -316,13 +317,25 @@ nsFreeTypeFont::doGetBoundingMetrics(const PRUnichar* aString, PRUint32 aLength,
return NS_ERROR_FAILURE;
// get the text size
PRUint32 i;
for (i=0; i<aLength; i++) {
PRUint32 i, extraSurrogateLength;
for (i=0; i<aLength; i+=1+extraSurrogateLength) {
FT_UInt glyph_index;
FT_Glyph glyph;
FT_BBox glyph_bbox;
FT_Pos advance;
mFt2->GetCharIndex(face, (FT_ULong)aString[i], &glyph_index);
extraSurrogateLength=0;
FT_ULong code_point = aString[i];
if(i<aLength-1 && IS_HIGH_SURROGATE(code_point) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] surrogate and
// low surrogate aString[i+1]
code_point = SURROGATE_TO_UCS4(code_point, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
mFt2->GetCharIndex(face, code_point, &glyph_index);
//NS_ASSERTION(glyph_index,"failed to get glyph");
if (glyph_index) {
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph);
@ -392,8 +405,19 @@ nsFreeTypeFont::GetWidth(const PRUnichar* aString, PRUint32 aLength)
if (!icache)
return 0;
for (PRUint32 i=0; i<aLength; i++) {
mFt2->GetCharIndex((FT_Face)face, (FT_ULong)aString[i], &glyph_index);
PRUint32 i, extraSurrogateLength;
for (i=0; i<aLength; i+=1+extraSurrogateLength) {
extraSurrogateLength=0;
FT_ULong code_point = aString[i];
if(i<aLength-1 && IS_HIGH_SURROGATE(code_point) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] surrogate and
// low surrogate aString[i+1]
code_point = SURROGATE_TO_UCS4(code_point, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
mFt2->GetCharIndex((FT_Face)face, code_point, &glyph_index);
nsresult rv;
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph);
NS_ASSERTION(NS_SUCCEEDED(rv),"error loading glyph");
@ -709,13 +733,25 @@ nsFreeTypeXImage::DrawString(nsRenderingContextGTK* aContext,
// Get aa glyphs and blend with background
//
blendGlyph blendGlyph = nsX11AlphaBlend::GetBlendGlyph();
PRUint32 i;
for (i=0; i<aLength; i++) {
PRUint32 i, extraSurrogateLength;
for (i=0; i<aLength; i+=1+extraSurrogateLength) {
FT_UInt glyph_index;
FT_Glyph glyph;
nsresult rv;
FT_BBox glyph_bbox;
mFt2->GetCharIndex(face, (FT_ULong)aString[i], &glyph_index);
FT_ULong code_point = aString[i];
extraSurrogateLength = 0;
if(i<aLength-1 && IS_HIGH_SURROGATE(code_point) && IS_LOW_SURROGATE(aString[i+1])) {
// if surrogate, make UCS4 code point from high aString[i] surrogate and
// low surrogate aString[i+1]
code_point = SURROGATE_TO_UCS4(code_point, aString[i+1]);
// skip aString[i+1], it is already used as low surrogate
extraSurrogateLength = 1;
}
mFt2->GetCharIndex(face, code_point, &glyph_index);
if (glyph_index) {
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph);
}

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

@ -38,9 +38,9 @@
* ***** END LICENSE BLOCK ***** */
#include "prmem.h"
#include "nsCompressedCharMap.h"
#include "nsCRT.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
void
FreeCCMap(PRUint16* &aMap)
@ -111,47 +111,71 @@ MapperToCCMap(nsICharRepresentable *aMapper)
}
PRBool
NextNonEmptyCCMapPage(PRUint16* aCCMap, PRUint16 *aPageStart)
NextNonEmptyCCMapPage(PRUint16* aCCMap, PRUint32 *aPageStart)
{
int i, j;
int i, j, l;
int planeend = 0;
int planestart = 0;
unsigned int k;
//
// Point to the next page
//
unsigned int upper_index;
unsigned int mid_index;
if (*aPageStart == CCMAP_BEGIN_AT_START_OF_MAP) {
upper_index = 0;
mid_index = 0;
}
else {
upper_index = CCMAP_UPPER_INDEX(*aPageStart);
mid_index = CCMAP_MID_INDEX(*aPageStart) + 1;
PRUint16* ccmap;
PRUint32 pagestart = *aPageStart;
if(CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) {
// for SURROGATE
planeend = EXTENDED_UNICODE_PLANES;
}
if(pagestart != CCMAP_BEGIN_AT_START_OF_MAP) {
planestart = CCMAP_PLANE(pagestart);
}
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=upper_index; i<CCMAP_NUM_UPPER_POINTERS; i++, mid_index=0) {
if (upper[i] == CCMAP_EMPTY_MID) {
continue;
// checking each plane
for(l=planestart; l<=planeend; l++, pagestart = CCMAP_BEGIN_AT_START_OF_MAP) {
if(CCMAP_FLAG(aCCMap) & CCMAP_SURROGATE_FLAG) {
// for SURROGATE - get ccmap per plane
ccmap = CCMAP_FOR_PLANE_EXT(aCCMap, l);
} else {
// only BMP
ccmap = aCCMap;
}
//
// Point to the next page
//
unsigned int upper_index;
unsigned int mid_index;
if (pagestart == CCMAP_BEGIN_AT_START_OF_MAP) {
upper_index = 0;
mid_index = 0;
} else {
upper_index = CCMAP_UPPER_INDEX(pagestart & 0xffff);
mid_index = CCMAP_MID_INDEX(pagestart & 0xffff) + 1;
}
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=mid_index; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
// walk thru the upper pointers
PRUint16 *upper = &ccmap[0];
for (i=upper_index; i<CCMAP_NUM_UPPER_POINTERS; i++, mid_index=0) {
if (upper[i] == CCMAP_EMPTY_MID) {
continue;
}
// walk the page
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
for (k=0; k<CCMAP_NUM_ALUS_PER_PAGE; k++) {
if (page[k] != 0) {
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
*aPageStart = (PRUint16)base;
return PR_TRUE;
// walk the mid array
PRUint16 *mid = &ccmap[upper[i]];
for (j=mid_index; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
continue;
// walk the page
ALU_TYPE *page = (ALU_TYPE*)&ccmap[mid[j]];
for (k=0; k<CCMAP_NUM_ALUS_PER_PAGE; k++) {
if (page[k] != 0) {
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
// return exact UCS4 code point, plane number + base
*aPageStart = (((PRUint32)l)<<16)+base;
return PR_TRUE;
}
}
}
}
@ -185,17 +209,21 @@ PRBool IsSameCCMap(PRUint16* ccmap1, PRUint16* ccmap2)
PRUint16*
nsCompressedCharMap::NewCCMap()
{
PRUint16 *newMap = (PRUint16*)PR_Malloc((CCMAP_EXTRA + mUsedLen) * sizeof(PRUint16));
NS_ASSERTION(newMap, "failed to alloc new CCMap");
if (!newMap)
return nsnull;
if (mExtended) {
return MapToCCMapExt(mMap, mExtMap+1, EXTENDED_UNICODE_PLANES);
} else {
PRUint16 *newMap = (PRUint16*)PR_Malloc((CCMAP_EXTRA + mUsedLen) * sizeof(PRUint16));
NS_ASSERTION(newMap, "failed to alloc new CCMap");
if (!newMap)
return nsnull;
newMap += CCMAP_EXTRA;
CCMAP_SIZE(newMap) = GetSize();
CCMAP_FLAG(newMap) = CCMAP_NONE_FLAG;
newMap += CCMAP_EXTRA;
CCMAP_SIZE(newMap) = GetSize();
CCMAP_FLAG(newMap) = CCMAP_NONE_FLAG;
FillCCMap(newMap);
return newMap;
FillCCMap(newMap);
return newMap;
}
}
PRUint16*
@ -208,6 +236,18 @@ nsCompressedCharMap::FillCCMap(PRUint16* aCCMap)
return aCCMap;
}
nsCompressedCharMap::~nsCompressedCharMap()
{
if(mExtended){
int i;
for (i = 1; i <= EXTENDED_UNICODE_PLANES; ++i) {
if (mExtMap[i]) {
PR_Free(mExtMap[i]);
}
}
}
}
nsCompressedCharMap::nsCompressedCharMap()
{
// initialize map to have:
@ -239,45 +279,70 @@ nsCompressedCharMap::nsCompressedCharMap()
NS_ASSERTION(mUsedLen==CCMAP_EMPTY_PAGE, "empty page offset misconfigured");
// the page was zero'd by the memset above
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
// init extended
mExtended = PR_FALSE;
memset(mExtMap+1, 0, sizeof(PRUint32*) * EXTENDED_UNICODE_PLANES);
memset(mMap, 0, sizeof(mMap));
mExtMap[0] = mMap;
}
void
nsCompressedCharMap::SetChar(PRUint16 aChar)
nsCompressedCharMap::SetChar(PRUint32 aChar)
{
unsigned int i;
unsigned int upper_index = CCMAP_UPPER_INDEX(aChar);
unsigned int mid_index = CCMAP_MID_INDEX(aChar);
PRUint16 mid_offset = u.mCCMap[upper_index];
if (mid_offset == CCMAP_EMPTY_MID) {
mid_offset = u.mCCMap[upper_index] = mUsedLen;
mUsedLen += CCMAP_NUM_MID_POINTERS;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the mid
PRUint16 *mid = &u.mCCMap[mid_offset];
for (i=0; i<CCMAP_NUM_MID_POINTERS; i++) {
NS_ASSERTION(mid[i]==0, "this mid pointer should be unused");
mid[i] = CCMAP_EMPTY_PAGE;
if (mExtended) {
PRUint32 plane_num = CCMAP_PLANE(aChar);
NS_ASSERTION(plane_num <= EXTENDED_UNICODE_PLANES,"invalid plane");
if (plane_num <= EXTENDED_UNICODE_PLANES) {
if (mExtMap[plane_num] == 0) {
mExtMap[plane_num] = (PRUint32*)PR_Malloc(sizeof(PRUint32)*UCS2_MAP_LEN);
NS_ASSERTION(mExtMap[plane_num], "failed to alloc new mExtMap");
if (!mExtMap[plane_num]) {
return;
}
memset(mExtMap[plane_num], 0, sizeof(PRUint32)*UCS2_MAP_LEN);
}
SET_REPRESENTABLE(mExtMap[plane_num], aChar & 0xffff);
}
}
} else {
NS_ASSERTION(aChar <= 0xffff, "extended char is passed");
PRUint16 page_offset = u.mCCMap[mid_offset+mid_index];
if (page_offset == CCMAP_EMPTY_PAGE) {
page_offset = u.mCCMap[mid_offset+mid_index] = mUsedLen;
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the page
PRUint16 *page = &u.mCCMap[page_offset];
for (i=0; i<CCMAP_NUM_PRUINT16S_PER_PAGE; i++) {
NS_ASSERTION(page[i]==0, "this page should be unused");
page[i] = 0;
unsigned int i;
unsigned int upper_index = CCMAP_UPPER_INDEX(aChar);
unsigned int mid_index = CCMAP_MID_INDEX(aChar);
PRUint16 mid_offset = u.mCCMap[upper_index];
if (mid_offset == CCMAP_EMPTY_MID) {
mid_offset = u.mCCMap[upper_index] = mUsedLen;
mUsedLen += CCMAP_NUM_MID_POINTERS;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the mid
PRUint16 *mid = &u.mCCMap[mid_offset];
for (i=0; i<CCMAP_NUM_MID_POINTERS; i++) {
NS_ASSERTION(mid[i]==0, "this mid pointer should be unused");
mid[i] = CCMAP_EMPTY_PAGE;
}
}
PRUint16 page_offset = u.mCCMap[mid_offset+mid_index];
if (page_offset == CCMAP_EMPTY_PAGE) {
page_offset = u.mCCMap[mid_offset+mid_index] = mUsedLen;
mUsedLen += CCMAP_NUM_PRUINT16S_PER_PAGE;
NS_ASSERTION(mUsedLen<=CCMAP_MAX_LEN,"length too long");
// init the page
PRUint16 *page = &u.mCCMap[page_offset];
for (i=0; i<CCMAP_NUM_PRUINT16S_PER_PAGE; i++) {
NS_ASSERTION(page[i]==0, "this page should be unused");
page[i] = 0;
}
}
}
#undef CCMAP_SET_CHAR
#define CCMAP_SET_CHAR(m,c) (CCMAP_TO_ALU(m,c) |= (CCMAP_POW2(CCMAP_BIT_INDEX(c))))
CCMAP_SET_CHAR(u.mCCMap,aChar);
CCMAP_SET_CHAR(u.mCCMap,aChar);
#undef CCMAP_SET_CHAR
NS_ASSERTION(CCMAP_HAS_CHAR(u.mCCMap,aChar), "failed to set bit");
NS_ASSERTION(CCMAP_HAS_CHAR(u.mCCMap,aChar), "failed to set bit");
}
}
void
@ -359,26 +424,40 @@ void
nsCompressedCharMap::SetChars(PRUint16* aCCMap)
{
int i, j;
//
// Copy the input CCMap
//
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=0; i<CCMAP_NUM_UPPER_POINTERS; i++) {
if (upper[i] == CCMAP_EMPTY_MID)
continue;
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=0; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
if(mExtended){
PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
while (NextNonEmptyCCMapPage(aCCMap, &page)) {
PRUint32 pagechar = page;
for (i=0; i<(CCMAP_BITS_PER_PAGE/8); i++) {
for (j=0; j<8; j++) {
if (CCMAP_HAS_CHAR_EXT(aCCMap, pagechar)) {
SetChar(pagechar);
}
pagechar++;
}
}
}
} else {
//
// Copy the input CCMap
//
// walk thru the upper pointers
PRUint16 *upper = &aCCMap[0];
for (i=0; i<CCMAP_NUM_UPPER_POINTERS; i++) {
if (upper[i] == CCMAP_EMPTY_MID)
continue;
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
SetChars((PRUint16)base, page);
// walk the mid array
PRUint16 *mid = &aCCMap[upper[i]];
for (j=0; j<CCMAP_NUM_MID_POINTERS; j++) {
if (mid[j] == CCMAP_EMPTY_PAGE)
continue;
PRUint32 base = (i*CCMAP_NUM_UCHARS_PER_MID) + (j*CCMAP_NUM_UCHARS_PER_PAGE);
NS_ASSERTION(base<NUM_UNICODE_CHARS, "invalid page address");
ALU_TYPE *page = (ALU_TYPE*)&aCCMap[mid[j]];
SetChars((PRUint16)base, page);
}
}
}
}
@ -436,7 +515,7 @@ nsCompressedCharMap::SetChars(PRUint32* aMap)
void
printCCMap(PRUint16* aCCMap)
{
PRUint16 page = CCMAP_BEGIN_AT_START_OF_MAP;
PRUint32 page = CCMAP_BEGIN_AT_START_OF_MAP;
while (NextNonEmptyCCMapPage(aCCMap, &page)) {
//FONT_SCAN_PRINTF(("page starting at 0x%04x has chars", page));
int i;

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

@ -40,7 +40,7 @@
#ifndef NSCOMPRESSEDCHARMAP_H
#define NSCOMPRESSEDCHARMAP_H
#include "prtypes.h"
#include "nsICharRepresentable.h"
#define ALU_SIZE PR_BITS_PER_LONG
//#define ALU_SIZE 16
@ -67,7 +67,7 @@ extern PRUint16* CreateEmptyCCMap();
extern PRUint16* MapToCCMap(PRUint32* aMap);
extern PRUint16* MapperToCCMap(nsICharRepresentable *aMapper);
extern void FreeCCMap(PRUint16* &aMap);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint16 *);
extern PRBool NextNonEmptyCCMapPage(PRUint16 *, PRUint32 *);
extern PRBool IsSameCCMap(PRUint16* ccmap1, PRUint16* ccmap2);
#ifdef DEBUG
void printCCMap(PRUint16* aCCMap);
@ -101,17 +101,22 @@ MapToCCMapExt(PRUint32* aBmpPlaneMap, PRUint32** aOtherPlaneMaps, PRUint32 aOthe
// (256*16 max pages) = 4400 PRUint16
#define CCMAP_MAX_LEN (16+16+16+256+4096)
// non-bmp unicode support extension
#define EXTENDED_UNICODE_PLANES 16
class nsCompressedCharMap {
public:
nsCompressedCharMap();
~nsCompressedCharMap();
PRUint16* NewCCMap();
PRUint16* FillCCMap(PRUint16* aCCMap);
PRUint16 GetSize() {return mUsedLen;};
void SetChar(PRUint16);
void SetChar(PRUint32);
void SetChars(PRUint16*);
void SetChars(PRUint16, ALU_TYPE*);
void SetChars(PRUint32*);
void Extend() {mExtended = PR_TRUE;} // enable surrogate area
protected:
union {
@ -122,6 +127,11 @@ protected:
PRUint16 mUsedLen; // in PRUint16
PRUint16 mAllOnesPage;
PRBool mExtended;
// for surrogate support
PRUint32* mExtMap[EXTENDED_UNICODE_PLANES+1];
PRUint32 mMap[UCS2_MAP_LEN];
};
//
@ -295,7 +305,7 @@ protected:
#define CCMAP_TOTAL_PAGES CCMAP_POW2(CCMAP_BITS_PER_UPPER_LOG2 \
+CCMAP_BITS_PER_MID_LOG2)
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFF
#define CCMAP_BEGIN_AT_START_OF_MAP 0xFFFFFFFF
//
// Finally, build up the macro to test the bit for a given char
@ -323,9 +333,6 @@ protected:
#define CCMAP_SURROGATE_FLAG 0x0001
#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_FROM_SURROGATE(h) ((((PRUint16)(h) - (PRUint16)0xd800) >> 6) + 1)
@ -345,5 +352,4 @@ protected:
#define CCMAP_HAS_CHAR_EXT(m, ucs4) (((ucs4)&0xffff0000) ? \
(CCMAP_FLAG(m) & CCMAP_SURROGATE_FLAG) && CCMAP_HAS_CHAR(CCMAP_FOR_PLANE_EXT((m), CCMAP_PLANE(ucs4)), (ucs4) & 0xffff) : \
CCMAP_HAS_CHAR(m, (PRUnichar)(ucs4)) )
#endif // NSCOMPRESSEDCHARMAP_H