bug 95518, r=yokoyama@netscape.com,r=Roland.Mainz@informatik.med.uni-giessen.de,

sr=brendan@mozilla.org,

Compress font char maps by folding the empty spaces on top of each other.
This commit is contained in:
bstell%netscape.com 2001-09-19 03:01:54 +00:00
parent 7e55d42206
commit 879d1c6b94
6 changed files with 177 additions and 162 deletions

View File

@ -113,7 +113,7 @@ struct nsFontCharSetInfo
const char* mCharSet;
nsFontCharSetConverter Convert;
PRUint8 mSpecialUnderline;
PRUint32* mMap;
PRUint16* mCCMap;
nsIUnicodeEncoder* mConverter;
nsIAtom* mLangGroup;
PRBool mInitedSizeInfo;
@ -583,9 +583,9 @@ atomToName(nsIAtom* aAtom)
return ToNewUTF8String(nsDependentString(namePRU));
}
static PRUint32 gUserDefinedMap[2048];
static PRUint32 gEmptyMap[2048];
static PRUint32 gDoubleByteSpecialCharsMap[2048];
static PRUint16* gUserDefinedCCMap = nsnull;
static PRUint16* gEmptyCCMap = nsnull;
static PRUint16* gDoubleByteSpecialCharsCCMap = nsnull;
//
// smart quotes (and other special chars) in Asian (double byte)
@ -607,7 +607,7 @@ FreeCharSetMap(nsHashKey* aKey, void* aData, void* aClosure)
nsFontCharSetMap* charsetMap = (nsFontCharSetMap*) aData;
NS_IF_RELEASE(charsetMap->mInfo->mConverter);
NS_IF_RELEASE(charsetMap->mInfo->mLangGroup);
PR_FREEIF(charsetMap->mInfo->mMap);
FreeCCMap(charsetMap->mInfo->mCCMap);
return PR_TRUE;
}
@ -762,6 +762,9 @@ FreeGlobals(void)
NS_IF_RELEASE(charSetMap->mFontLangGroup->mFontLangGroupAtom);
charSetMap->mFontLangGroup->mFontLangGroupAtom = nsnull;
}
FreeCCMap(gUserDefinedCCMap);
FreeCCMap(gEmptyCCMap);
FreeCCMap(gDoubleByteSpecialCharsCCMap);
}
/*
@ -790,10 +793,10 @@ InitGlobals(void)
return NS_ERROR_FAILURE;
}
PRUint32 i; // XXX no local scope in |for| on some compilers
// clear the "empty" char map
for (i=0; i<(sizeof(gEmptyMap)/sizeof(gEmptyMap[0])); i++)
gEmptyMap[i] = 0;
nsCompressedCharMap empty_ccmapObj;
gEmptyCCMap = empty_ccmapObj.NewCCMap();
if (!gEmptyCCMap)
return NS_ERROR_OUT_OF_MEMORY;
// get the "disable double byte font special chars" setting
PRBool val = PR_TRUE;
@ -802,9 +805,13 @@ InitGlobals(void)
gAllowDoubleByteSpecialChars = val;
// setup the double byte font special chars glyph map
for (i=0; gDoubleByteSpecialChars[i]; i++) {
SET_REPRESENTABLE(gDoubleByteSpecialCharsMap, gDoubleByteSpecialChars[i]);
nsCompressedCharMap specialchars_ccmapObj;
for (int i=0; gDoubleByteSpecialChars[i]; i++) {
specialchars_ccmapObj.SetChar(gDoubleByteSpecialChars[i]);
}
gDoubleByteSpecialCharsCCMap = specialchars_ccmapObj.NewCCMap();
if (!gDoubleByteSpecialCharsCCMap)
return NS_ERROR_OUT_OF_MEMORY;
PRInt32 scale_minimum = 0;
rv = gPref->GetIntPref("font.scale.outline.min", &scale_minimum);
@ -1096,7 +1103,9 @@ NS_IMETHODIMP nsFontMetricsGTK::Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsCOMPtr<nsICharRepresentable> mapper =
do_QueryInterface(gUserDefinedConverter);
if (mapper) {
res = mapper->FillInfo(gUserDefinedMap);
gUserDefinedCCMap = MapperToCCMap(mapper);
if (!gUserDefinedCCMap)
return NS_ERROR_OUT_OF_MEMORY;
}
}
else {
@ -1648,7 +1657,7 @@ CheckSelf(void)
#endif /* DEBUG */
static void
static PRBool
SetUpFontCharSetInfo(nsFontCharSetInfo* aSelf)
{
@ -1671,23 +1680,26 @@ SetUpFontCharSetInfo(nsFontCharSetInfo* aSelf)
nsnull, '?');
nsCOMPtr<nsICharRepresentable> mapper = do_QueryInterface(converter);
if (mapper) {
res = mapper->FillInfo(aSelf->mMap);
aSelf->mCCMap = MapperToCCMap(mapper);
if (!aSelf->mCCMap)
return PR_FALSE;
DEBUG_PRINTF(("\n\ncharset = %s", atomToName(charset)));
/*
* XXX This is a bit of a hack. Documents containing the CP1252
* extensions of Latin-1 (e.g. smart quotes) will display with those
* special characters way too large. This is because they happen to
* be in these large double byte fonts. So, we disable those
* characters here. Revisit this decision later.
* We used to disable special characters like smart quotes
* in CJK fonts because if they are quite a bit larger than
* western glyphs and we did not want glyph fill-in to use them
* in single byte documents.
*
* Now, single byte documents find these special chars before
* the CJK fonts are searched so this is no longer needed
* and should be removed, as requested in bug 100233
*/
if ((aSelf->Convert == DoubleByteConvert)
&& (!gAllowDoubleByteSpecialChars)) {
PRUint32* map = aSelf->mMap;
#undef REMOVE_CHAR
#define REMOVE_CHAR(map, c) (map)[(c) >> 5] &= ~(1L << ((c) & 0x1f))
PRUint16* ccmap = aSelf->mCCMap;
for (int i=0; gDoubleByteSpecialChars[i]; i++) {
REMOVE_CHAR(map, gDoubleByteSpecialChars[i]);
CCMAP_UNSET_CHAR(ccmap, gDoubleByteSpecialChars[i]);
}
}
}
@ -1702,6 +1714,7 @@ SetUpFontCharSetInfo(nsFontCharSetInfo* aSelf)
else {
NS_WARNING("cannot get atom");
}
return PR_TRUE;
}
#undef DEBUG_DUMP_TREE
@ -1803,34 +1816,29 @@ GetUnderlineInfo(XFontStruct* aFont, unsigned long* aPositionX2,
}
#endif /* 0 */
static PRUint32*
static PRUint16*
GetMapFor10646Font(XFontStruct* aFont)
{
PRUint32* map = (PRUint32*) PR_Calloc(2048, 4);
if (map) {
if (aFont->per_char) {
PRInt32 minByte1 = aFont->min_byte1;
PRInt32 maxByte1 = aFont->max_byte1;
PRInt32 minByte2 = aFont->min_char_or_byte2;
PRInt32 maxByte2 = aFont->max_char_or_byte2;
PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
for (PRInt32 row = minByte1; row <= maxByte1; row++) {
PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
XCharStruct* bounds = &aFont->per_char[offset + cell];
if (bounds->ascent || bounds->descent) {
SET_REPRESENTABLE(map, (row << 8) | cell);
}
}
if (!aFont->per_char)
return nsnull;
nsCompressedCharMap ccmapObj;
PRInt32 minByte1 = aFont->min_byte1;
PRInt32 maxByte1 = aFont->max_byte1;
PRInt32 minByte2 = aFont->min_char_or_byte2;
PRInt32 maxByte2 = aFont->max_char_or_byte2;
PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
for (PRInt32 row = minByte1; row <= maxByte1; row++) {
PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
XCharStruct* bounds = &aFont->per_char[offset + cell];
if (bounds->ascent || bounds->descent) {
ccmapObj.SetChar((row << 8) | cell);
}
}
else {
PR_Free(map);
map = nsnull;
}
}
return map;
PRUint16 *ccmap = ccmapObj.NewCCMap();
return ccmap;
}
PRBool
@ -1878,8 +1886,8 @@ nsFontGTK::LoadFont(void)
if (gdkFont) {
XFontStruct* xFont = (XFontStruct*) GDK_FONT_XFONT(gdkFont);
if (mCharSetInfo == &ISO106461) {
mMap = GetMapFor10646Font(xFont);
if (!mMap) {
mCCMap = GetMapFor10646Font(xFont);
if (!mCCMap) {
::gdk_font_unref(gdkFont);
return;
}
@ -1969,7 +1977,7 @@ nsFontGTK::~nsFontGTK()
gdk_font_unref(mFont);
}
if (mCharSetInfo == &ISO106461) {
PR_FREEIF(mMap);
FreeCCMap(mCCMap);
}
if (mName) {
PR_smprintf_free(mName);
@ -2300,12 +2308,12 @@ nsFontGTKUserDefined::Init(nsFontGTK* aFont)
if (!aFont->GetGDKFont()) {
aFont->LoadFont();
if (!aFont->GetGDKFont()) {
mMap = gEmptyMap;
mCCMap = gEmptyCCMap;
return PR_FALSE;
}
}
mFont = aFont->GetGDKFont();
mMap = gUserDefinedMap;
mCCMap = gUserDefinedCCMap;
mName = aFont->mName;
return PR_TRUE;
@ -2533,8 +2541,8 @@ nsFontMetricsGTK::PickASizeAndLoad(nsFontStretch* aStretch,
}
if (aCharSet->mCharSet) {
font->mMap = aCharSet->mMap;
if (FONT_HAS_GLYPH(font->mMap, aChar)) {
font->mCCMap = aCharSet->mCCMap;
if (CCMAP_HAS_CHAR(font->mCCMap, aChar)) {
font->LoadFont();
if (!font->GetGDKFont()) {
return nsnull;
@ -2809,27 +2817,23 @@ nsFontMetricsGTK::SearchNode(nsFontNode* aNode, PRUnichar aChar)
/*
* mCharSet is set if we know which glyphs will be found in these fonts.
* If mMap has already been created for this charset, we compare it with
* the mMaps of the previously loaded fonts. If it is the same as any of
* If mCCMap has already been created for this charset, we compare it with
* the mCCMaps of the previously loaded fonts. If it is the same as any of
* the previous ones, we return nsnull because there is no point in
* loading a font with the same map.
*/
if (charSetInfo->mCharSet) {
PRUint32* map = charSetInfo->mMap;
if (map) {
PRUint16* ccmap = charSetInfo->mCCMap;
if (ccmap) {
for (int i = 0; i < mLoadedFontsCount; i++) {
if (mLoadedFonts[i]->mMap == map) {
if (mLoadedFonts[i]->mCCMap == ccmap) {
return nsnull;
}
}
}
else {
map = (PRUint32*) PR_Calloc(2048, 4);
if (!map) {
if (!SetUpFontCharSetInfo(charSetInfo))
return nsnull;
}
charSetInfo->mMap = map;
SetUpFontCharSetInfo(charSetInfo);
}
}
else {
@ -3267,7 +3271,7 @@ GetFontNames(const char* aPattern, nsFontNodeArray* aNodes)
// size->mFont is initialized in the constructor
size->mSize = pixels;
size->mBaselineAdjust = 0;
size->mMap = nsnull;
size->mCCMap = nsnull;
size->mCharSetInfo = charSetInfo;
}
XFreeFontNames(list);
@ -3713,16 +3717,16 @@ if (gAllowDoubleByteSpecialChars) {
nsFontGTK* sub_font = FindSubstituteFont(aChar);
NS_ASSERTION(sub_font, "failed to get a special chars substitute font");
if (sub_font) {
sub_font->mMap = gDoubleByteSpecialCharsMap;
sub_font->mCCMap = gDoubleByteSpecialCharsCCMap;
AddToLoadedFontsList(sub_font);
}
if (western_font && FONT_HAS_GLYPH(western_font->mMap, aChar)) {
if (western_font && CCMAP_HAS_CHAR(western_font->mCCMap, aChar)) {
return western_font;
}
else if (symbol_font && FONT_HAS_GLYPH(symbol_font->mMap, aChar)) {
else if (symbol_font && CCMAP_HAS_CHAR(symbol_font->mCCMap, aChar)) {
return symbol_font;
}
else if (sub_font && FONT_HAS_GLYPH(sub_font->mMap, aChar)) {
else if (sub_font && CCMAP_HAS_CHAR(sub_font->mCCMap, aChar)) {
FIND_FONT_PRINTF((" transliterate special chars for single byte docs"));
return sub_font;
}
@ -3830,7 +3834,7 @@ nsFontMetricsGTK::FindSubstituteFont(PRUnichar aChar)
{
if (!mSubstituteFont) {
for (int i = 0; i < mLoadedFontsCount; i++) {
if (FONT_HAS_GLYPH(mLoadedFonts[i]->mMap, 'a')) {
if (CCMAP_HAS_CHAR(mLoadedFonts[i]->mCCMap, 'a')) {
mSubstituteFont = new nsFontGTKSubstitute(mLoadedFonts[i]);
break;
}
@ -3841,11 +3845,11 @@ nsFontMetricsGTK::FindSubstituteFont(PRUnichar aChar)
// Thus we reparse *all* font glyph maps every time we see
// a character that ends up using a substitute font.
// future work:
// create an empty mMap and every time we determine a
// create an empty mCCMap and every time we determine a
// character will get its "glyph" from the substitute font
// mark that character in the mMap.
// mark that character in the mCCMap.
}
// mark the mMap to indicate that this character has a "glyph"
// mark the mCCMap to indicate that this character has a "glyph"
// If we know that mLoadedFonts has every font's glyph map loaded
// then we can now set all the bit in the substitute font's glyph map
@ -3853,7 +3857,7 @@ nsFontMetricsGTK::FindSubstituteFont(PRUnichar aChar)
// font (without the font search).
// if tried all glyphs {
// create a substitute font with all bits set
// set all bits in mMap
// set all bits in mCCMap
// }
return mSubstituteFont;

View File

@ -35,6 +35,7 @@
#include "nsCOMPtr.h"
#include "nsRenderingContextGTK.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
@ -67,7 +68,7 @@ public:
PRBool IsEmptyFont(GdkFont*);
inline int SupportsChar(PRUnichar aChar)
{ return mFont && FONT_HAS_GLYPH(mMap, aChar); };
{ return mFont && CCMAP_HAS_CHAR(mCCMap, aChar); };
virtual GdkFont* GetGDKFont(void);
virtual PRBool GetGDKFontIs10646(void);
@ -86,7 +87,7 @@ public:
nsBoundingMetrics& aBoundingMetrics) = 0;
#endif
PRUint32* mMap;
PRUint16* mCCMap;
nsFontCharSetInfo* mCharSetInfo;
char* mName;
nsFontGTKUserDefined* mUserDefinedFont;

View File

@ -25,7 +25,7 @@
#include "nsRegionGTK.h"
#include "nsImageGTK.h"
#include "nsGraphicsStateGTK.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include <math.h>
#include "nsGCCache.h"
#include <gtk/gtk.h>
@ -1307,7 +1307,7 @@ nsRenderingContextGTK::GetWidth(const PRUnichar* aString, PRUint32 aLength,
nsFontGTK** font = metrics->mLoadedFonts;
nsFontGTK** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -1469,7 +1469,7 @@ nsRenderingContextGTK::DrawString(const PRUnichar* aString, PRUint32 aLength,
nsFontGTK** font = metrics->mLoadedFonts;
nsFontGTK** lastFont = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < lastFont) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -1834,7 +1834,7 @@ nsRenderingContextGTK::GetBoundingMetrics(const PRUnichar* aString,
nsFontGTK** font = metrics->mLoadedFonts;
nsFontGTK** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}

View File

@ -63,6 +63,7 @@ static PRLogModuleInfo * FontMetricsXlibLM = PR_NewLogModule("FontMetricsXlib");
#endif /* PR_LOGGING */
#define UCS2_NOMAPPING 0XFFFD
#undef USER_DEFINED
#define USER_DEFINED "x-user-def"
@ -90,7 +91,7 @@ struct nsFontCharSetXlibInfo
const char* mCharSet;
nsFontCharSetXlibConverter Convert;
PRUint8 mSpecialUnderline;
PRUint32* mMap;
PRUint16* mCCMap;
nsIUnicodeEncoder* mConverter;
nsIAtom* mLangGroup;
PRBool mInitedSizeInfo;
@ -555,9 +556,9 @@ static nsFontPropertyNameXlib gWeightNames[] =
{ nsnull, 0 }
};
static PRUint32 gUserDefinedMap[2048];
static PRUint32 gEmptyMap[2048];
static PRUint32 gDoubleByteSpecialCharsMap[2048];
static PRUint16* gUserDefinedCCMap = nsnull;
static PRUint16* gEmptyCCMap = nsnull;
static PRUint16* gDoubleByteSpecialCharsCCMap = nsnull;
//
// smart quotes (and other special chars) in Asian (double byte)
@ -579,7 +580,7 @@ FreeCharSetMap(nsHashKey* aKey, void* aData, void* aClosure)
nsFontCharSetMapXlib* charsetMap = (nsFontCharSetMapXlib*) aData;
NS_IF_RELEASE(charsetMap->mInfo->mConverter);
NS_IF_RELEASE(charsetMap->mInfo->mLangGroup);
PR_FREEIF(charsetMap->mInfo->mMap);
FreeCCMap(charsetMap->mInfo->mCCMap);
return PR_TRUE;
}
@ -745,6 +746,9 @@ nsFontMetricsXlib::FreeGlobals(void)
NS_IF_RELEASE(charSetMap->mFontLangGroup->mFontLangGroupAtom);
charSetMap->mFontLangGroup->mFontLangGroupAtom = nsnull;
}
FreeCCMap(gUserDefinedCCMap);
FreeCCMap(gEmptyCCMap);
FreeCCMap(gDoubleByteSpecialCharsCCMap);
gXlibRgbHandle = nsnull;
}
@ -773,9 +777,10 @@ nsFontMetricsXlib::InitGlobals(void)
}
PRUint32 i; // XXX no local scope in |for| on some compilers
// clear the "empty" char map
for (i = 0; i < (sizeof(gEmptyMap) / sizeof(gEmptyMap[0])); i++)
gEmptyMap[i] = 0;
nsCompressedCharMap empty_ccmapObj;
gEmptyCCMap = empty_ccmapObj.NewCCMap();
if (!gEmptyCCMap)
return NS_ERROR_OUT_OF_MEMORY;
// get the "disable double byte font special chars" setting
PRBool val = PR_TRUE;
@ -784,8 +789,13 @@ nsFontMetricsXlib::InitGlobals(void)
gAllowDoubleByteSpecialChars = val;
// setup the double byte font special chars glyph map
for (i = 0; gDoubleByteSpecialChars[i]; i++)
SET_REPRESENTABLE(gDoubleByteSpecialCharsMap, gDoubleByteSpecialChars[i]);
nsCompressedCharMap specialchars_ccmapObj;
for (int i=0; gDoubleByteSpecialChars[i]; i++) {
specialchars_ccmapObj.SetChar(gDoubleByteSpecialChars[i]);
}
gDoubleByteSpecialCharsCCMap = specialchars_ccmapObj.NewCCMap();
if (!gDoubleByteSpecialCharsCCMap)
return NS_ERROR_OUT_OF_MEMORY;
PRInt32 scale_minimum = 0;
rv = gPref->GetIntPref("font.scale.outline.min", &scale_minimum);
@ -1123,8 +1133,11 @@ nsFontMetricsXlib::Init(const nsFont& aFont, nsIAtom* aLangGroup,
nsCOMPtr<nsICharRepresentable> mapper =
do_QueryInterface(gUserDefinedConverter);
if (mapper)
res = mapper->FillInfo(gUserDefinedMap);
if (mapper) {
gUserDefinedCCMap = MapperToCCMap(mapper);
if (!gUserDefinedCCMap)
return NS_ERROR_OUT_OF_MEMORY;
}
}
else
return res;
@ -1682,22 +1695,25 @@ SetUpFontCharSetInfo(nsFontCharSetXlibInfo* aSelf)
nsnull, '?');
nsCOMPtr<nsICharRepresentable> mapper = do_QueryInterface(converter);
if (mapper) {
res = mapper->FillInfo(aSelf->mMap);
aSelf->mCCMap = MapperToCCMap(mapper);
if (!aSelf->mCCMap)
return;
/*
* XXX This is a bit of a hack. Documents containing the CP1252
* extensions of Latin-1 (e.g. smart quotes) will display with those
* special characters way too large. This is because they happen to
* be in these large double byte fonts. So, we disable those
* characters here. Revisit this decision later.
*/
* We used to disable special characters like smart quotes
* in CJK fonts because if they are quite a bit larger than
* western glyphs and we did not want glyph fill-in to use them
* in single byte documents.
*
* Now, single byte documents find these special chars before
* the CJK fonts are searched so this is no longer needed
* and should be removed, as requested in bug 100233
*/
if ((aSelf->Convert == DoubleByteConvert)
&& (!gAllowDoubleByteSpecialChars)) {
PRUint32* map = aSelf->mMap;
#undef REMOVE_CHAR
#define REMOVE_CHAR(map, c) (map)[(c) >> 5] &= ~(1L << ((c) & 0x1f))
PRUint16* ccmap = aSelf->mCCMap;
for (int i=0; gDoubleByteSpecialChars[i]; i++)
REMOVE_CHAR(map, gDoubleByteSpecialChars[i]);
CCMAP_UNSET_CHAR(ccmap, gDoubleByteSpecialChars[i]);
}
}
else
@ -1809,35 +1825,30 @@ GetUnderlineInfo(XFontStruct* aFont, unsigned long* aPositionX2,
}
#endif /* 0 */
static PRUint32*
static PRUint16*
GetMapFor10646Font(XFontStruct* aFont)
{
PRUint32* map = (PRUint32*) PR_Calloc(2048, 4);
if (map) {
if (aFont->per_char) {
PRInt32 minByte1 = aFont->min_byte1;
PRInt32 maxByte1 = aFont->max_byte1;
PRInt32 minByte2 = aFont->min_char_or_byte2;
PRInt32 maxByte2 = aFont->max_char_or_byte2;
PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
for (PRInt32 row = minByte1; row <= maxByte1; row++) {
PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
XCharStruct* bounds = &aFont->per_char[offset + cell];
if (bounds->ascent || bounds->descent) {
SET_REPRESENTABLE(map, (row << 8) | cell);
}
}
if (!aFont->per_char)
return nsnull;
nsCompressedCharMap ccmapObj;
PRInt32 minByte1 = aFont->min_byte1;
PRInt32 maxByte1 = aFont->max_byte1;
PRInt32 minByte2 = aFont->min_char_or_byte2;
PRInt32 maxByte2 = aFont->max_char_or_byte2;
PRInt32 charsPerRow = maxByte2 - minByte2 + 1;
for (PRInt32 row = minByte1; row <= maxByte1; row++) {
PRInt32 offset = (((row - minByte1) * charsPerRow) - minByte2);
for (PRInt32 cell = minByte2; cell <= maxByte2; cell++) {
XCharStruct* bounds = &aFont->per_char[offset + cell];
if (bounds->ascent || bounds->descent) {
ccmapObj.SetChar((row << 8) | cell);
}
}
else {
// XXX look at glyph ranges property, if any
PR_Free(map);
map = nsnull;
}
}
}
return map;
PRUint16 *ccmap = ccmapObj.NewCCMap();
return ccmap;
}
PRBool
@ -1906,9 +1917,8 @@ nsFontXlib::LoadFont(void)
if (xlibFont) {
if (mCharSetInfo == &ISO106461) {
mMap = GetMapFor10646Font(xlibFont);
NS_ASSERTION(!mMap, "GetMapFor10646Font() failed.\n");
if (!mMap) {
mCCMap = GetMapFor10646Font(xlibFont);
if (!mCCMap) {
::XFreeFont(aDisplay, xlibFont);
return;
}
@ -1958,7 +1968,7 @@ nsFontXlib::nsFontXlib()
{
MOZ_COUNT_CTOR(nsFontXlib);
mFont = nsnull;
mMap = nsnull;
mCCMap = nsnull;
mCharSetInfo = nsnull;
mName = nsnull;
mUserDefinedFont = nsnull;
@ -1972,7 +1982,7 @@ nsFontXlib::~nsFontXlib()
XFreeFont(xxlib_rgb_get_display(gXlibRgbHandle), mFont);
if (mCharSetInfo == &ISO106461)
PR_FREEIF(mMap);
FreeCCMap(mCCMap);
if (mName)
PR_smprintf_free(mName);
@ -2357,12 +2367,14 @@ nsFontXlibUserDefined::Init(nsFontXlib* aFont)
{
if(!aFont->mFont) {
aFont->LoadFont();
if (!aFont->mFont)
if (!aFont->mFont) {
mCCMap = gEmptyCCMap;
return PR_FALSE;
}
}
mFont = aFont->mFont;
mMap = gUserDefinedMap;
mCCMap = gUserDefinedCCMap;
mName = aFont->mName;
return PR_TRUE;
@ -2620,8 +2632,8 @@ nsFontMetricsXlib::PickASizeAndLoad(nsFontStretchXlib* aStretch,
}
if (aCharSet->mCharSet) {
font->mMap = aCharSet->mMap;
if (FONT_HAS_GLYPH(font->mMap, aChar)) {
font->mCCMap = aCharSet->mCCMap;
if (CCMAP_HAS_CHAR(font->mCCMap, aChar)) {
font->LoadFont();
if (!font->mFont)
return nsnull;
@ -2898,27 +2910,24 @@ nsFontMetricsXlib::SearchNode(nsFontNodeXlib* aNode, PRUnichar aChar)
/*
* mCharSet is set if we know which glyphs will be found in these fonts.
* If mMap has already been created for this charset, we compare it with
* the mMaps of the previously loaded fonts. If it is the same as any of
* If mCCMap has already been created for this charset, we compare it with
* the mCCMaps of the previously loaded fonts. If it is the same as any of
* the previous ones, we return nsnull because there is no point in
* loading a font with the same map.
*/
if (charSetInfo->mCharSet) {
PRUint32* map = charSetInfo->mMap;
if (map) {
PRUint16* ccmap = charSetInfo->mCCMap;
if (ccmap) {
for (int i = 0; i < mLoadedFontsCount; i++) {
if (mLoadedFonts[i]->mMap == map) {
if (mLoadedFonts[i]->mCCMap == ccmap) {
return nsnull;
}
}
}
else {
map = (PRUint32*) PR_Calloc(2048, 4);
if (!map) {
return nsnull;
}
charSetInfo->mMap = map;
SetUpFontCharSetInfo(charSetInfo);
if (!charSetInfo->mCCMap)
return nsnull;
}
}
else {
@ -3350,7 +3359,7 @@ GetFontNames(const char* aPattern, nsFontNodeArrayXlib* aNodes)
size->mFont = nsnull;
size->mSize = pixels;
size->mBaselineAdjust = 0;
size->mMap = nsnull;
size->mCCMap = nsnull;
size->mCharSetInfo = charSetInfo;
}
XFreeFontNames(list);
@ -3752,16 +3761,16 @@ nsFontMetricsXlib::FindStyleSheetGenericFont(PRUnichar aChar)
nsFontXlib* sub_font = FindSubstituteFont(aChar);
NS_ASSERTION(sub_font, "failed to get a special chars substitute font");
if (sub_font) {
sub_font->mMap = gDoubleByteSpecialCharsMap;
sub_font->mCCMap = gDoubleByteSpecialCharsCCMap;
AddToLoadedFontsList(sub_font);
}
if (western_font && FONT_HAS_GLYPH(western_font->mMap, aChar)) {
if (western_font && CCMAP_HAS_CHAR(western_font->mCCMap, aChar)) {
return western_font;
}
else if (symbol_font && FONT_HAS_GLYPH(symbol_font->mMap, aChar)) {
else if (symbol_font && CCMAP_HAS_CHAR(symbol_font->mCCMap, aChar)) {
return symbol_font;
}
else if (sub_font && FONT_HAS_GLYPH(sub_font->mMap, aChar)) {
else if (sub_font && CCMAP_HAS_CHAR(sub_font->mCCMap, aChar)) {
return sub_font;
}
}
@ -3855,7 +3864,7 @@ nsFontMetricsXlib::FindSubstituteFont(PRUnichar aChar)
{
if (!mSubstituteFont) {
for (int i = 0; i < mLoadedFontsCount; i++) {
if (FONT_HAS_GLYPH(mLoadedFonts[i]->mMap, 'a')) {
if (CCMAP_HAS_CHAR(mLoadedFonts[i]->mCCMap, 'a')) {
mSubstituteFont = new nsFontXlibSubstitute(mLoadedFonts[i]);
break;
}
@ -3866,11 +3875,11 @@ nsFontMetricsXlib::FindSubstituteFont(PRUnichar aChar)
// Thus we reparse *all* font glyph maps every time we see
// a character that ends up using a substitute font.
// future work:
// create an empty mMap and every time we determine a
// create an empty mCCMap and every time we determine a
// character will get its "glyph" from the substitute font
// mark that character in the mMap.
}
// mark the mMap to indicate that this character has a "glyph"
// mark that character in the mCCMap.
}
// mark the mCCMap to indicate that this character has a "glyph"
// If we know that mLoadedFonts has every font's glyph map loaded
// then we can now set all the bit in the substitute font's glyph map
@ -3878,7 +3887,7 @@ nsFontMetricsXlib::FindSubstituteFont(PRUnichar aChar)
// font (without the font search).
// if tried all glyphs {
// create a substitute font with all bits set
// set all bits in mMap
// set all bits in mCCMap
// }
return mSubstituteFont;

View File

@ -28,6 +28,7 @@
#define nsFontMetricsXlib_h__
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include "nsIDeviceContext.h"
#include "nsIFontMetrics.h"
#include "nsIFontEnumerator.h"
@ -77,7 +78,7 @@ public:
PRBool IsEmptyFont(XFontStruct*);
inline int SupportsChar(PRUnichar aChar)
{ return mFont && FONT_HAS_GLYPH(mMap, aChar); };
{ return mFont && CCMAP_HAS_CHAR(mCCMap, aChar); };
virtual PRBool GetXlibFontIs10646(void);
virtual int GetWidth(const PRUnichar* aString, PRUint32 aLength) = 0;
@ -97,7 +98,7 @@ public:
#endif /* MOZ_MATHML */
XFontStruct *mFont;
PRUint32 *mMap;
PRUint16 *mCCMap;
nsFontCharSetXlibInfo *mCharSetInfo;
char *mName;
nsFontXlibUserDefined *mUserDefinedFont;

View File

@ -29,7 +29,7 @@
#include "nsRenderingContextXlib.h"
#include "nsFontMetricsXlib.h"
#include "nsICharRepresentable.h"
#include "nsCompressedCharMap.h"
#include "xlibrgb.h"
#include "prprf.h"
#include "prmem.h"
@ -1299,7 +1299,7 @@ nsRenderingContextXlib::GetWidth(const PRUnichar* aString, PRUint32 aLength,
nsFontXlib** font = metrics->mLoadedFonts;
nsFontXlib** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -1469,7 +1469,7 @@ nsRenderingContextXlib::DrawString(const PRUnichar *aString, PRUint32 aLength,
nsFontXlib** font = metrics->mLoadedFonts;
nsFontXlib** lastFont = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < lastFont) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
@ -1864,7 +1864,7 @@ nsRenderingContextXlib::GetBoundingMetrics(const PRUnichar* aString,
nsFontXlib** font = metrics->mLoadedFonts;
nsFontXlib** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
if (CCMAP_HAS_CHAR((*font)->mCCMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}