Bug 236403 Clean up nsFontMetricsOS2 array usage (r=mkaply, sr=blizzard)
git-svn-id: svn://10.0.0.236/trunk@153704 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -27,8 +27,6 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsILanguageAtomService.h"
|
||||
#include "nsICharsetConverterManager.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsLocaleCID.h"
|
||||
#include "nsILocaleService.h"
|
||||
#include "nsICharRepresentable.h"
|
||||
@@ -54,7 +52,6 @@
|
||||
|
||||
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
|
||||
static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID);
|
||||
|
||||
#define NS_MAX_FONT_WEIGHT 900
|
||||
@@ -65,11 +62,9 @@ static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID);
|
||||
|
||||
|
||||
/***** Global variables *****/
|
||||
nsVoidArray *nsFontMetricsOS2::gGlobalFonts = nsnull;
|
||||
nsTHashtable<GlobalFontEntry>* nsFontMetricsOS2::gGlobalFonts = nsnull;
|
||||
PRBool nsFontMetricsOS2::gSubstituteVectorFonts = PR_TRUE;
|
||||
PLHashTable *nsFontMetricsOS2::gFamilyNames = nsnull;
|
||||
int nsFontMetricsOS2::gCachedIndex = 0;
|
||||
nsICollation *nsFontMetricsOS2::gCollation = nsnull;
|
||||
|
||||
static nsIPref *gPref = nsnull;
|
||||
static nsIAtom *gUsersLocale = nsnull;
|
||||
@@ -143,13 +138,9 @@ FreeGlobals(void)
|
||||
NS_IF_RELEASE(gUsersLocale);
|
||||
NS_IF_RELEASE(gSystemLocale);
|
||||
NS_IF_RELEASE(gUserDefined);
|
||||
NS_IF_RELEASE(nsFontMetricsOS2::gCollation);
|
||||
|
||||
if (nsFontMetricsOS2::gGlobalFonts) {
|
||||
for (int i = nsFontMetricsOS2::gGlobalFonts->Count()-1; i >= 0; --i) {
|
||||
nsGlobalFont* font = (nsGlobalFont*)nsFontMetricsOS2::gGlobalFonts->ElementAt(i);
|
||||
delete font;
|
||||
}
|
||||
nsFontMetricsOS2::gGlobalFonts->Clear();
|
||||
delete nsFontMetricsOS2::gGlobalFonts;
|
||||
nsFontMetricsOS2::gGlobalFonts = nsnull;
|
||||
}
|
||||
@@ -349,20 +340,6 @@ nsFontMetricsOS2::Destroy()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLHashNumber PR_CALLBACK
|
||||
HashKey(const void* aString)
|
||||
{
|
||||
const nsString* str = (const nsString*)aString;
|
||||
return (PLHashNumber) nsCRT::HashCode(str->get());
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK
|
||||
CompareKeys(const void* aStr1, const void* aStr2)
|
||||
{
|
||||
return nsCRT::strcmp(((const nsString*) aStr1)->get(),
|
||||
((const nsString*) aStr2)->get()) == 0;
|
||||
}
|
||||
|
||||
// Utility; delete [] when done.
|
||||
static FONTMETRICS* getMetrics( long &lFonts, PCSZ facename, HPS hps)
|
||||
{
|
||||
@@ -440,7 +417,7 @@ nsFontMetricsOS2::SetFontHandle(HPS aPS, nsFontOS2* aFont)
|
||||
// record the min/max point size available for given font
|
||||
if (pMetrics[i].lEmHeight > maxSize)
|
||||
maxSize = pMetrics[i].lEmHeight;
|
||||
else if (pMetrics[i].lEmHeight < minSize)
|
||||
if (pMetrics[i].lEmHeight < minSize)
|
||||
minSize = pMetrics[i].lEmHeight;
|
||||
}
|
||||
|
||||
@@ -515,7 +492,7 @@ nsFontMetricsOS2::SetFontHandle(HPS aPS, nsFontOS2* aFont)
|
||||
nsFontOS2*
|
||||
nsFontMetricsOS2::LoadFont(HPS aPS, const nsString& aFontname)
|
||||
{
|
||||
nsFontOS2* fh = nsnull;
|
||||
nsFontOS2* font = nsnull;
|
||||
char alias[FACESIZE];
|
||||
|
||||
// set style flags
|
||||
@@ -523,199 +500,124 @@ nsFontMetricsOS2::LoadFont(HPS aPS, const nsString& aFontname)
|
||||
PRBool bItalic = (mFont.style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE));
|
||||
USHORT flags = bBold ? FM_SEL_BOLD : 0;
|
||||
flags |= bItalic ? FM_SEL_ITALIC : 0;
|
||||
|
||||
|
||||
// always pass vector fonts to the printer
|
||||
if (!mDeviceContext->SupportsRasterFonts() &&
|
||||
GetVectorSubstitute(aPS, aFontname, alias))
|
||||
{
|
||||
fh = new nsFontOS2();
|
||||
strcpy( fh->mFattrs.szFacename, alias );
|
||||
fh->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
|
||||
SetFontHandle(aPS, fh);
|
||||
return fh;
|
||||
font = new nsFontOS2();
|
||||
strcpy(font->mFattrs.szFacename, alias);
|
||||
font->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE |
|
||||
FATTR_FONTUSE_TRANSFORMABLE;
|
||||
SetFontHandle(aPS, font);
|
||||
return font;
|
||||
}
|
||||
|
||||
/* rather than doing string compare all the way through the loop, create
|
||||
* a collation key out of the incoming fontname, and compare with that. */
|
||||
nsAutoString tempname(aFontname);
|
||||
PRUint8* key;
|
||||
PRUint32 keylen;
|
||||
if (aFontname.Find("@", PR_FALSE, 0, 1) != kNotFound) {
|
||||
tempname.Trim( "@", PR_TRUE, PR_FALSE ); /* remove leading "@" */
|
||||
tempname.Append( NS_LITERAL_STRING(" ") );
|
||||
}
|
||||
|
||||
PRInt32 res = gCollation->AllocateRawSortKey( kCollationCaseInSensitive,
|
||||
tempname, &key,
|
||||
&keylen );
|
||||
NS_ASSERTION( NS_SUCCEEDED(res), "Create collation keys failed!" );
|
||||
|
||||
int i = gCachedIndex;
|
||||
int count = gGlobalFonts->Count();
|
||||
int limit = count + gCachedIndex;
|
||||
|
||||
while( i < limit && !fh )
|
||||
{
|
||||
nsGlobalFont* font = (nsGlobalFont*)gGlobalFonts->ElementAt(i%count);
|
||||
|
||||
gCollation->CompareRawSortKey(key, keylen, font->key, font->len, &res);
|
||||
if( res == 0 )
|
||||
{
|
||||
/* Save current index such that next time LoadFont() is called, we
|
||||
* start the loop at the last used index */
|
||||
gCachedIndex = i % count;
|
||||
int plainIndex = -1;
|
||||
|
||||
for( int j = i%count; j < font->nextFamily; j++ )
|
||||
{
|
||||
nsGlobalFont* fontj = (nsGlobalFont*)gGlobalFonts->ElementAt(j);
|
||||
nsMiniFontMetrics *fm = &(fontj->metrics);
|
||||
if( (fm->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD)) == flags )
|
||||
{
|
||||
fh = new nsFontOS2();
|
||||
FATTRS* fattrs = &(fh->mFattrs);
|
||||
|
||||
strcpy( fattrs->szFacename, fm->szFacename );
|
||||
if( fm->fsDefn & FM_DEFN_OUTLINE ||
|
||||
!mDeviceContext->SupportsRasterFonts() )
|
||||
fh->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
|
||||
if( fm->fsType & FM_TYPE_MBCS )
|
||||
fh->mFattrs.fsType |= FATTR_TYPE_MBCS;
|
||||
if( fm->fsType & FM_TYPE_DBCS )
|
||||
fh->mFattrs.fsType |= FATTR_TYPE_DBCS;
|
||||
fh->mFattrs.usCodePage = fm->usCodePage;
|
||||
|
||||
SetFontHandle(aPS, fh);
|
||||
break;
|
||||
GlobalFontEntry* globalEntry = gGlobalFonts->GetEntry(aFontname);
|
||||
if (globalEntry) {
|
||||
nsMiniMetrics* metrics = globalEntry->mMetrics;
|
||||
nsMiniMetrics* plainFont = nsnull;
|
||||
while (metrics) {
|
||||
if ((metrics->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD)) == flags) {
|
||||
font = new nsFontOS2();
|
||||
FATTRS* fattrs = &(font->mFattrs);
|
||||
|
||||
strcpy(fattrs->szFacename, metrics->szFacename);
|
||||
if (metrics->fsDefn & FM_DEFN_OUTLINE ||
|
||||
!mDeviceContext->SupportsRasterFonts()) {
|
||||
font->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE |
|
||||
FATTR_FONTUSE_TRANSFORMABLE;
|
||||
}
|
||||
if (metrics->fsType & FM_TYPE_MBCS)
|
||||
font->mFattrs.fsType |= FATTR_TYPE_MBCS;
|
||||
if (metrics->fsType & FM_TYPE_DBCS)
|
||||
font->mFattrs.fsType |= FATTR_TYPE_DBCS;
|
||||
font->mFattrs.usCodePage = globalEntry->mCodePage;
|
||||
|
||||
/* Set index for 'plain' font (non-bold, non-italic) */
|
||||
if( plainIndex == -1 && !(fm->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD)))
|
||||
plainIndex = j;
|
||||
}
|
||||
|
||||
// A font of family "familyname" and with the applied effects (bold &
|
||||
// italic) was not found. Therefore, just look for a 'regular' font
|
||||
// (that is not italic and not bold), and then have the
|
||||
// system simulate the appropriate effects (see RealizeFont()).
|
||||
if( !fh && plainIndex != -1 )
|
||||
{
|
||||
nsGlobalFont* fontm = (nsGlobalFont*)gGlobalFonts->ElementAt(plainIndex);
|
||||
nsMiniFontMetrics *fm = &(fontm->metrics);
|
||||
|
||||
fh = new nsFontOS2();
|
||||
FATTRS* fattrs = &(fh->mFattrs);
|
||||
|
||||
strcpy( fattrs->szFacename, fm->szFacename );
|
||||
if( fm->fsDefn & FM_DEFN_OUTLINE ||
|
||||
!mDeviceContext->SupportsRasterFonts() )
|
||||
fattrs->fsFontUse = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
|
||||
else
|
||||
fattrs->fsFontUse = 0;
|
||||
if( fm->fsType & FM_TYPE_MBCS )
|
||||
fattrs->fsType |= FATTR_TYPE_MBCS;
|
||||
if( fm->fsType & FM_TYPE_DBCS )
|
||||
fattrs->fsType |= FATTR_TYPE_DBCS;
|
||||
|
||||
// fake the effects
|
||||
if( bBold )
|
||||
fattrs->fsSelection |= FATTR_SEL_BOLD;
|
||||
if( bItalic )
|
||||
fattrs->fsSelection |= FATTR_SEL_ITALIC;
|
||||
fh->mFattrs.usCodePage = fm->usCodePage;
|
||||
|
||||
SetFontHandle(aPS, fh);
|
||||
SetFontHandle(aPS, font);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( i < count )
|
||||
i = font->nextFamily;
|
||||
else
|
||||
i = font->nextFamily + count;
|
||||
} // end while
|
||||
|
||||
PR_FREEIF(key);
|
||||
if (fh) {
|
||||
mLoadedFonts.AppendElement(fh);
|
||||
return fh;
|
||||
// Save ref to 'plain' font (non-bold, non-italic)
|
||||
if (!plainFont && !(metrics->fsSelection & (FM_SEL_ITALIC | FM_SEL_BOLD)))
|
||||
plainFont = metrics;
|
||||
|
||||
metrics = metrics->mNext;
|
||||
}
|
||||
|
||||
// A font of family "familyname" and with the applied effects (bold &
|
||||
// italic) was not found. Therefore, just look for a 'regular' font
|
||||
// (that is not italic and not bold), and then have the
|
||||
// system simulate the appropriate effects (see RealizeFont()).
|
||||
if (!font && plainFont) {
|
||||
font = new nsFontOS2();
|
||||
FATTRS* fattrs = &(font->mFattrs);
|
||||
|
||||
strcpy(fattrs->szFacename, plainFont->szFacename);
|
||||
if (plainFont->fsDefn & FM_DEFN_OUTLINE ||
|
||||
!mDeviceContext->SupportsRasterFonts()) {
|
||||
fattrs->fsFontUse = FATTR_FONTUSE_OUTLINE |
|
||||
FATTR_FONTUSE_TRANSFORMABLE;
|
||||
} else {
|
||||
fattrs->fsFontUse = 0;
|
||||
}
|
||||
if (plainFont->fsType & FM_TYPE_MBCS)
|
||||
fattrs->fsType |= FATTR_TYPE_MBCS;
|
||||
if (plainFont->fsType & FM_TYPE_DBCS)
|
||||
fattrs->fsType |= FATTR_TYPE_DBCS;
|
||||
|
||||
// fake the effects
|
||||
if (bBold)
|
||||
fattrs->fsSelection |= FATTR_SEL_BOLD;
|
||||
if (bItalic)
|
||||
fattrs->fsSelection |= FATTR_SEL_ITALIC;
|
||||
fattrs->usCodePage = globalEntry->mCodePage;
|
||||
|
||||
SetFontHandle(aPS, font);
|
||||
}
|
||||
}
|
||||
|
||||
// If a font was not found, then maybe "familyname" is really a face name.
|
||||
// See if a font with that facename exists on system and fake any applied
|
||||
// effects
|
||||
if (font) {
|
||||
mLoadedFonts.AppendElement(font);
|
||||
return font;
|
||||
}
|
||||
|
||||
// If a font was not found, then maybe "familyname" is really a face name.
|
||||
// See if a font with that facename exists on system and fake any applied
|
||||
// effects
|
||||
long lFonts = 0;
|
||||
char fontname[FACESIZE];
|
||||
WideCharToMultiByte(0, aFontname.get(), aFontname.Length() + 1,
|
||||
fontname, FACESIZE);
|
||||
FONTMETRICS* pMetrics = getMetrics( lFonts, fontname, aPS );
|
||||
char* fontname = ToNewCString(aFontname);
|
||||
FONTMETRICS* pMetrics = getMetrics(lFonts, fontname, aPS);
|
||||
|
||||
if( lFonts > 0 )
|
||||
{
|
||||
fh = new nsFontOS2();
|
||||
strcpy( fh->mFattrs.szFacename, fontname );
|
||||
fh->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE;
|
||||
if (lFonts > 0) {
|
||||
font = new nsFontOS2();
|
||||
strcpy(font->mFattrs.szFacename, fontname);
|
||||
font->mFattrs.fsFontUse = FATTR_FONTUSE_OUTLINE |
|
||||
FATTR_FONTUSE_TRANSFORMABLE;
|
||||
|
||||
if( bBold )
|
||||
fh->mFattrs.fsSelection |= FATTR_SEL_BOLD;
|
||||
if( bItalic )
|
||||
fh->mFattrs.fsSelection |= FATTR_SEL_ITALIC;
|
||||
if (bBold)
|
||||
font->mFattrs.fsSelection |= FATTR_SEL_BOLD;
|
||||
if (bItalic)
|
||||
font->mFattrs.fsSelection |= FATTR_SEL_ITALIC;
|
||||
|
||||
if( mDeviceContext->SupportsRasterFonts() )
|
||||
{
|
||||
for (int i = 0 ; i < lFonts ; i++)
|
||||
if( !(pMetrics[i].fsDefn & FM_DEFN_OUTLINE) )
|
||||
{
|
||||
fh->mFattrs.fsFontUse = 0;
|
||||
if (mDeviceContext->SupportsRasterFonts()) {
|
||||
for (int i = 0 ; i < lFonts ; i++) {
|
||||
if (!(pMetrics[i].fsDefn & FM_DEFN_OUTLINE)) {
|
||||
font->mFattrs.fsFontUse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsMemory::Free(pMetrics);
|
||||
|
||||
if (fh) {
|
||||
SetFontHandle(aPS, fh);
|
||||
mLoadedFonts.AppendElement(fh);
|
||||
if (font) {
|
||||
SetFontHandle(aPS, font);
|
||||
mLoadedFonts.AppendElement(font);
|
||||
}
|
||||
|
||||
return fh;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetCollation(void)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsILocale> locale = nsnull;
|
||||
nsICollationFactory * collationFactory = nsnull;
|
||||
|
||||
nsCOMPtr<nsILocaleService> localeServ =
|
||||
do_GetService(kLocaleServiceCID, &res);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = localeServ->GetApplicationLocale(getter_AddRefs(locale));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = nsComponentManager::CreateInstance(kCollationFactoryCID, NULL,
|
||||
NS_GET_IID(nsICollationFactory), (void**) &collationFactory);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = collationFactory->CreateCollation(locale, &nsFontMetricsOS2::gCollation);
|
||||
NS_RELEASE(collationFactory);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int PR_CALLBACK
|
||||
CompareFontFamilyNames(const void* aArg1, const void* aArg2, void* aData)
|
||||
{
|
||||
PRInt32 res;
|
||||
nsICollation * collation = (nsICollation *) aData;
|
||||
nsGlobalFont* font1 = (nsGlobalFont*) aArg1;
|
||||
nsGlobalFont* font2 = (nsGlobalFont*) aArg2;
|
||||
|
||||
collation->CompareRawSortKey(font1->key, font1->len, font2->key, font2->len, &res);
|
||||
|
||||
return res;
|
||||
return font;
|
||||
}
|
||||
|
||||
typedef struct nsFontFamilyName
|
||||
@@ -754,51 +656,79 @@ static nsFontFamilyName gBadDBCSFontMapping[] =
|
||||
{ nsnull, nsnull }
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
DebugOutputEnumerator(GlobalFontEntry* aEntry, void* aData)
|
||||
{
|
||||
printf("---------------------------------------------------------------------\n");
|
||||
printf(" [[]] %s\n", NS_LossyConvertUCS2toASCII(aEntry->GetKey()).get());
|
||||
nsMiniMetrics* metrics = aEntry->mMetrics;
|
||||
while (metrics) {
|
||||
printf(" %32s", metrics->szFacename);
|
||||
|
||||
if (metrics->fsDefn & FM_DEFN_OUTLINE)
|
||||
printf(" : vector");
|
||||
else
|
||||
printf(" : bitmap");
|
||||
|
||||
if (metrics->fsSelection & FM_SEL_BOLD)
|
||||
printf(" : bold");
|
||||
else
|
||||
printf(" : ");
|
||||
|
||||
if (metrics->fsSelection & FM_SEL_ITALIC)
|
||||
printf(" : italic");
|
||||
else
|
||||
printf(" : ");
|
||||
|
||||
if (metrics->fsType & FM_TYPE_DBCS ||
|
||||
metrics->fsType & FM_TYPE_MBCS)
|
||||
printf(" : M/DBCS");
|
||||
else
|
||||
printf(" : ");
|
||||
|
||||
printf(" : cp=%5d\n", aEntry->mCodePage );
|
||||
|
||||
metrics = metrics->mNext;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsFontMetricsOS2::InitializeGlobalFonts()
|
||||
{
|
||||
gGlobalFonts = new nsVoidArray();
|
||||
gGlobalFonts = new nsTHashtable<GlobalFontEntry>;
|
||||
if (!gGlobalFonts->Init(64))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
HPS ps = ::WinGetScreenPS(HWND_DESKTOP);
|
||||
LONG lRemFonts = 0, lNumFonts;
|
||||
lNumFonts = GFX (::GpiQueryFonts (ps, QF_PUBLIC, NULL, &lRemFonts, 0, 0),
|
||||
lNumFonts = GFX (::GpiQueryFonts(ps, QF_PUBLIC, NULL, &lRemFonts, 0, 0),
|
||||
GPI_ALTERROR);
|
||||
FONTMETRICS* pFontMetrics = (PFONTMETRICS) nsMemory::Alloc(lNumFonts * sizeof(FONTMETRICS));
|
||||
lRemFonts = GFX (::GpiQueryFonts (ps, QF_PUBLIC, NULL, &lNumFonts,
|
||||
sizeof (FONTMETRICS), pFontMetrics),
|
||||
lRemFonts = GFX (::GpiQueryFonts(ps, QF_PUBLIC, NULL, &lNumFonts,
|
||||
sizeof (FONTMETRICS), pFontMetrics),
|
||||
GPI_ALTERROR);
|
||||
|
||||
PRUnichar* str = (PRUnichar*)nsMemory::Alloc((FACESIZE+1) * sizeof(PRUnichar));
|
||||
|
||||
PRInt32 res = GetCollation();
|
||||
NS_ASSERTION( NS_SUCCEEDED(res), "GetCollation failed!" );
|
||||
|
||||
int convertedLength;
|
||||
for( int i = 0; i < lNumFonts; i++ )
|
||||
{
|
||||
FONTMETRICS* font = &(pFontMetrics[i]);
|
||||
// The discrepencies between the Courier bitmap and outline fonts are
|
||||
// too much to deal with, so we only use the outline font
|
||||
if( stricmp(pFontMetrics[i].szFamilyname, "Courier") == 0 &&
|
||||
!(pFontMetrics[i].fsDefn & FM_DEFN_OUTLINE))
|
||||
if (strcmp(font->szFamilyname, "Courier") == 0 &&
|
||||
!(font->fsDefn & FM_DEFN_OUTLINE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stricmp(pFontMetrics[i].szFamilyname, "Roman") == 0 ||
|
||||
stricmp(pFontMetrics[i].szFamilyname, "Swiss") == 0)
|
||||
// The facenames for Roman are "Tms Rmn...", for Swiss "Helv...". This
|
||||
// conflicts with the actual "Tms Rmn" and "Helv" font families. So, we
|
||||
// skip over these.
|
||||
if (strcmp(pFontMetrics[i].szFamilyname, "Roman") == 0 ||
|
||||
strcmp(pFontMetrics[i].szFamilyname, "Swiss") == 0) {
|
||||
continue;
|
||||
|
||||
nsGlobalFont* font = new nsGlobalFont;
|
||||
strcpy(font->metrics.szFamilyname, pFontMetrics[i].szFamilyname);
|
||||
strcpy(font->metrics.szFacename, pFontMetrics[i].szFacename);
|
||||
font->metrics.fsType = pFontMetrics[i].fsType;
|
||||
font->metrics.fsDefn = pFontMetrics[i].fsDefn;
|
||||
font->metrics.fsSelection = pFontMetrics[i].fsSelection;
|
||||
font->metrics.usCodePage = pFontMetrics[i].usCodePage;
|
||||
|
||||
// Set the FM_SEL_BOLD flag in fsSelection. This makes the check for
|
||||
// bold and italic much easier in LoadFont
|
||||
if( pFontMetrics[i].usWeightClass > 5 )
|
||||
font->metrics.fsSelection |= FM_SEL_BOLD;
|
||||
}
|
||||
|
||||
// Problem: OS/2 has many non-standard fonts that do not follow the
|
||||
// normal Family-name/Face-name conventions (i.e. 'foo',
|
||||
@@ -812,29 +742,34 @@ nsFontMetricsOS2::InitializeGlobalFonts()
|
||||
// 'italic', 'oblique', 'regular'). If the Facename contains
|
||||
// one of these indicators, then we will create the sort key
|
||||
// based on the Familyname. Otherwise, use the Facename.
|
||||
char* fontptr = nsnull;
|
||||
if (PL_strcasestr(font->metrics.szFacename, "bold") != nsnull ||
|
||||
PL_strcasestr(font->metrics.szFacename, "italic") != nsnull ||
|
||||
PL_strcasestr(font->metrics.szFacename, "oblique") != nsnull ||
|
||||
PL_strcasestr(font->metrics.szFacename, "regular") != nsnull ||
|
||||
PL_strcasestr(font->metrics.szFacename, "-normal") != nsnull)
|
||||
nsAutoString fontptr;
|
||||
if (PL_strcasestr(font->szFacename, "bold") != nsnull ||
|
||||
PL_strcasestr(font->szFacename, "italic") != nsnull ||
|
||||
PL_strcasestr(font->szFacename, "oblique") != nsnull ||
|
||||
PL_strcasestr(font->szFacename, "regular") != nsnull ||
|
||||
PL_strcasestr(font->szFacename, "-normal") != nsnull)
|
||||
{
|
||||
fontptr = font->metrics.szFamilyname;
|
||||
CopyASCIItoUCS2(nsDependentCString(NS_STATIC_CAST(char*, font->szFamilyname)),
|
||||
fontptr);
|
||||
} else {
|
||||
fontptr = font->metrics.szFacename;
|
||||
CopyASCIItoUCS2(nsDependentCString(NS_STATIC_CAST(char*, font->szFacename)),
|
||||
fontptr);
|
||||
}
|
||||
|
||||
// The fonts in gBadDBCSFontMapping do not display well in non-Chinese
|
||||
// systems. Map them to a more intelligible name.
|
||||
if (font->metrics.fsType & FM_TYPE_DBCS)
|
||||
|
||||
// The fonts in gBadDBCSFontMapping do not display well in non-Chinese
|
||||
// systems. Map them to a more intelligible name.
|
||||
if (font->fsType & FM_TYPE_DBCS)
|
||||
{
|
||||
if ((gSystemCodePage != 1386) &&
|
||||
(gSystemCodePage != 1381) &&
|
||||
(gSystemCodePage != 950)) {
|
||||
int j=0;
|
||||
while (gBadDBCSFontMapping[j].mName) {
|
||||
if ((strcmp(fontptr, gBadDBCSFontMapping[j].mName) == 0)) {
|
||||
fontptr = gBadDBCSFontMapping[j].mWinName;
|
||||
if (fontptr.Equals(NS_ConvertASCIItoUCS2(gBadDBCSFontMapping[j].mName),
|
||||
nsCaseInsensitiveStringComparator()))
|
||||
{
|
||||
CopyASCIItoUCS2(nsDependentCString(gBadDBCSFontMapping[j].mWinName),
|
||||
fontptr);
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
@@ -842,106 +777,44 @@ nsFontMetricsOS2::InitializeGlobalFonts()
|
||||
}
|
||||
}
|
||||
|
||||
// For vertical DBCS fonts (those that start with '@'), we want them to
|
||||
// appear directly below the non-vertical font of the same family.
|
||||
convertedLength = MultiByteToWideChar(0, fontptr, strlen(fontptr), str, FACESIZE);
|
||||
if (fontptr[0] == '@')
|
||||
{
|
||||
font->name.Assign( str + 1, convertedLength-1 );
|
||||
font->name.Append( NS_LITERAL_STRING(" ") );
|
||||
} else {
|
||||
font->name.Assign( str, convertedLength );
|
||||
// Create entry for family name, or retrieve already created entry
|
||||
GlobalFontEntry* globalEntry = gGlobalFonts->PutEntry(fontptr);
|
||||
if (!globalEntry)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Init the nsMiniMetrics structure...
|
||||
nsMiniMetrics* metrics = new nsMiniMetrics;
|
||||
strcpy(metrics->szFacename, font->szFacename);
|
||||
metrics->fsType = font->fsType;
|
||||
metrics->fsDefn = font->fsDefn;
|
||||
metrics->fsSelection = font->fsSelection;
|
||||
// Set the FM_SEL_BOLD flag in fsSelection. This makes the check for
|
||||
// bold and italic much easier in LoadFont
|
||||
if (font->usWeightClass > 5)
|
||||
metrics->fsSelection |= FM_SEL_BOLD;
|
||||
|
||||
// The 'Lucida' set of fonts does not set the bold flag correctly on OS/2,
|
||||
// so we'll just set it properly.
|
||||
if (strncmp(font->szFamilyname, "Lucida", 6) == 0 &&
|
||||
PL_strcasestr(font->szFacename, "bold") != nsnull) {
|
||||
metrics->fsSelection |= FM_SEL_BOLD;
|
||||
}
|
||||
|
||||
// Create collation sort key
|
||||
res = gCollation->AllocateRawSortKey(kCollationCaseInSensitive,
|
||||
font->name, &font->key, &font->len);
|
||||
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
// reset DBCS name to actual value
|
||||
if (fontptr[0] == '@')
|
||||
font->name.Insert( NS_LITERAL_STRING("@"), 0 );
|
||||
}
|
||||
|
||||
gGlobalFonts->AppendElement(font);
|
||||
// ... and add it to globalEntry
|
||||
metrics->mNext = globalEntry->mMetrics;
|
||||
globalEntry->mMetrics = metrics;
|
||||
globalEntry->mCodePage = font->usCodePage;
|
||||
}
|
||||
|
||||
gGlobalFonts->Sort(CompareFontFamilyNames, gCollation);
|
||||
|
||||
// Set nextFamily in the array, such that we can skip from family to
|
||||
// family in order to speed up searches.
|
||||
int prevIndex = 0;
|
||||
nsGlobalFont* font = (nsGlobalFont*)gGlobalFonts->ElementAt(0);
|
||||
PRUint8* lastkey = font->key;
|
||||
PRUint32 lastlen = font->len;
|
||||
|
||||
int count = gGlobalFonts->Count();
|
||||
for( int j = 0; j < count; j++ )
|
||||
{
|
||||
font = (nsGlobalFont*)gGlobalFonts->ElementAt(j);
|
||||
|
||||
gCollation->CompareRawSortKey(font->key, font->len, lastkey, lastlen, &res);
|
||||
if( res != 0 )
|
||||
{
|
||||
lastkey = font->key;
|
||||
lastlen = font->len;
|
||||
|
||||
font = (nsGlobalFont*)gGlobalFonts->ElementAt(prevIndex);
|
||||
font->nextFamily = j;
|
||||
prevIndex = j;
|
||||
}
|
||||
else
|
||||
font->nextFamily = 0;
|
||||
}
|
||||
|
||||
font = (nsGlobalFont*)gGlobalFonts->ElementAt(prevIndex);
|
||||
font->nextFamily = count;
|
||||
::WinReleasePS(ps);
|
||||
|
||||
|
||||
#ifdef DEBUG_pedemont
|
||||
for( int k = 0; k < gGlobalFonts->Count(); k++ )
|
||||
{
|
||||
font = (nsGlobalFont*)gGlobalFonts->ElementAt(k);
|
||||
nsMiniFontMetrics* fm = &(font->metrics);
|
||||
printf( " %3d: %32s :", k, fm->szFamilyname );
|
||||
printf( " %32s", fm->szFacename );
|
||||
|
||||
if( fm->fsDefn & FM_DEFN_OUTLINE )
|
||||
printf( " : vector" );
|
||||
else
|
||||
printf( " : bitmap" );
|
||||
|
||||
if( fm->fsSelection & FM_SEL_BOLD )
|
||||
printf( " : bold" );
|
||||
else
|
||||
printf( " : " );
|
||||
|
||||
if( fm->fsSelection & FM_SEL_ITALIC )
|
||||
printf( " : italic" );
|
||||
else
|
||||
printf( " : " );
|
||||
|
||||
if( fm->fsType & FM_TYPE_DBCS ||
|
||||
fm->fsType & FM_TYPE_MBCS )
|
||||
printf( " : M/DBCS" );
|
||||
else
|
||||
printf( " : " );
|
||||
|
||||
printf( " : %5d", fm->usCodePage );
|
||||
|
||||
if( font->nextFamily )
|
||||
printf( " : %d", font->nextFamily );
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
fflush( stdout );
|
||||
gGlobalFonts->EnumerateEntries(DebugOutputEnumerator, nsnull);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
nsMemory::Free(str);
|
||||
nsMemory::Free(pFontMetrics);
|
||||
|
||||
return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFontOS2*
|
||||
@@ -1000,7 +873,20 @@ static nsFontFamilyName gFamilyNameTableDBCS[] =
|
||||
/*-----------------------
|
||||
** Hash table allocation
|
||||
**----------------------*/
|
||||
//-- Font FamilyNames
|
||||
static PLHashNumber PR_CALLBACK
|
||||
HashKey(const void* aString)
|
||||
{
|
||||
const nsString* str = (const nsString*)aString;
|
||||
return (PLHashNumber) nsCRT::HashCode(str->get());
|
||||
}
|
||||
|
||||
static PRIntn PR_CALLBACK
|
||||
CompareKeys(const void* aStr1, const void* aStr2)
|
||||
{
|
||||
return nsCRT::strcmp(((const nsString*) aStr1)->get(),
|
||||
((const nsString*) aStr2)->get()) == 0;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void*) familyname_AllocTable(void *pool, size_t size)
|
||||
{
|
||||
return nsMemory::Alloc(size);
|
||||
@@ -1330,10 +1216,7 @@ PRBool
|
||||
nsFontMetricsOS2::GetVectorSubstitute(HPS aPS, const nsString& aFamilyname,
|
||||
char* alias)
|
||||
{
|
||||
char fontname[FACESIZE];
|
||||
WideCharToMultiByte(0, aFamilyname.get(), aFamilyname.Length() + 1,
|
||||
fontname, FACESIZE);
|
||||
|
||||
char* fontname = ToNewCString(aFamilyname);
|
||||
return GetVectorSubstitute(aPS, fontname, alias);
|
||||
}
|
||||
|
||||
@@ -1462,7 +1345,7 @@ nsFontMetricsOS2::RealizeFont()
|
||||
nsFontOS2* font = FindFont(ps);
|
||||
NS_ASSERTION(font, "FindFont() returned null. THIS IS BAD!");
|
||||
if (!font) {
|
||||
if( mDeviceContext->mPrintDC == NULL) {
|
||||
if (mDeviceContext->mPrintDC == NULL) {
|
||||
::WinReleasePS(ps);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
@@ -2074,6 +1957,33 @@ nsFontEnumeratorOS2::nsFontEnumeratorOS2()
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsFontEnumeratorOS2, nsIFontEnumerator)
|
||||
|
||||
// We want vertical fonts (those whose name start with '@') to appear
|
||||
// immediately following the non-vertical font of the same name.
|
||||
static int
|
||||
CompareFontNames(const void* aArg1, const void* aArg2, void* aClosure)
|
||||
{
|
||||
const PRUnichar* str1 = *((const PRUnichar**) aArg1);
|
||||
const PRUnichar* str2 = *((const PRUnichar**) aArg2);
|
||||
|
||||
int rc = 9;
|
||||
if ((char)str1[0] == '@') {
|
||||
str1++;
|
||||
rc = nsCRT::strcmp(str1, str2);
|
||||
if (rc == 0)
|
||||
return 1;
|
||||
}
|
||||
if ((char)str2[0] == '@') {
|
||||
str2++;
|
||||
rc = nsCRT::strcmp(str1, str2);
|
||||
if (rc == 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc == 9)
|
||||
rc = nsCRT::strcmp(str1, str2);
|
||||
return rc;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFontEnumeratorOS2::EnumerateFonts(const char* aLangGroup,
|
||||
const char* aGeneric, PRUint32* aCount, PRUnichar*** aResult)
|
||||
@@ -2081,36 +1991,48 @@ nsFontEnumeratorOS2::EnumerateFonts(const char* aLangGroup,
|
||||
return EnumerateAllFonts(aCount, aResult);
|
||||
}
|
||||
|
||||
struct EnumerateAllFontsData
|
||||
{
|
||||
PRUnichar** array;
|
||||
int count;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
EnumerateAllFontsCallback(GlobalFontEntry* aEntry, void* aData)
|
||||
{
|
||||
EnumerateAllFontsData* data = NS_STATIC_CAST(EnumerateAllFontsData*, aData);
|
||||
|
||||
data->array[data->count++] = ToNewUnicode(aEntry->GetKey());
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFontEnumeratorOS2::EnumerateAllFonts(PRUint32* aCount, PRUnichar*** aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCount);
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
||||
if( !nsFontMetricsOS2::gGlobalFonts )
|
||||
{
|
||||
if (!nsFontMetricsOS2::gGlobalFonts) {
|
||||
nsresult res = nsFontMetricsOS2::InitializeGlobalFonts();
|
||||
if( NS_FAILED(res) )
|
||||
{
|
||||
if (NS_FAILED(res)) {
|
||||
FreeGlobals();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
int count = nsFontMetricsOS2::gGlobalFonts->Count();
|
||||
PRUnichar** array = (PRUnichar**)nsMemory::Alloc(count * sizeof(PRUnichar*));
|
||||
NS_ENSURE_TRUE( array, NS_ERROR_OUT_OF_MEMORY );
|
||||
*aCount = nsFontMetricsOS2::gGlobalFonts->Count();
|
||||
PRUnichar** array = (PRUnichar**)nsMemory::Alloc(*aCount * sizeof(PRUnichar*));
|
||||
NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while( i < count )
|
||||
{
|
||||
nsGlobalFont* font = (nsGlobalFont*)nsFontMetricsOS2::gGlobalFonts->ElementAt(i);
|
||||
array[j++] = ToNewUnicode( font->name );
|
||||
i = font->nextFamily;
|
||||
}
|
||||
EnumerateAllFontsData data;
|
||||
data.array = array;
|
||||
data.count = 0;
|
||||
nsFontMetricsOS2::gGlobalFonts->EnumerateEntries(EnumerateAllFontsCallback,
|
||||
&data);
|
||||
|
||||
NS_QuickSort(array, *aCount, sizeof(PRUnichar*), CompareFontNames, nsnull);
|
||||
|
||||
*aCount = j;
|
||||
*aResult = array;
|
||||
|
||||
return NS_OK;
|
||||
|
||||
@@ -43,8 +43,10 @@
|
||||
#include "nsDeviceContextOS2.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsDrawingSurfaceOS2.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#ifndef FM_DEFN_LATIN1
|
||||
#define FM_DEFN_LATIN1 0x0010 /* Base latin character set */
|
||||
@@ -68,29 +70,48 @@
|
||||
//#define DEBUG_FONT_SELECTION
|
||||
//#define DEBUG_FONT_STRUCT_ALLOCS
|
||||
|
||||
struct nsMiniFontMetrics
|
||||
struct nsMiniMetrics
|
||||
{
|
||||
char szFamilyname[FACESIZE];
|
||||
char szFacename[FACESIZE];
|
||||
USHORT fsType;
|
||||
USHORT fsDefn;
|
||||
USHORT fsSelection;
|
||||
USHORT usCodePage;
|
||||
char szFacename[FACESIZE];
|
||||
USHORT fsType;
|
||||
USHORT fsDefn;
|
||||
USHORT fsSelection;
|
||||
nsMiniMetrics* mNext;
|
||||
};
|
||||
|
||||
class nsGlobalFont
|
||||
// GlobalFontEntry->mStr is an nsString which contains the family name of font.
|
||||
class GlobalFontEntry : public nsStringHashKey
|
||||
{
|
||||
public:
|
||||
nsGlobalFont(void) { key = nsnull; };
|
||||
~nsGlobalFont(void) { if(key) nsMemory::Free(key); };
|
||||
|
||||
nsAutoString name;
|
||||
nsMiniFontMetrics metrics;
|
||||
int nextFamily;
|
||||
PRUint8* key;
|
||||
PRUint32 len;
|
||||
};
|
||||
public:
|
||||
GlobalFontEntry(KeyTypePointer aStr) : nsStringHashKey(aStr) { }
|
||||
GlobalFontEntry(const GlobalFontEntry& aToCopy)
|
||||
: nsStringHashKey(aToCopy) { }
|
||||
~GlobalFontEntry()
|
||||
{
|
||||
nsMiniMetrics* metrics = mMetrics;
|
||||
while (metrics) {
|
||||
nsMiniMetrics* nextMetrics = metrics->mNext;
|
||||
if (metrics)
|
||||
delete metrics;
|
||||
metrics = nextMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
// Override, since we want to compare font names as case insensitive
|
||||
PRBool KeyEquals(const KeyTypePointer aKey) const
|
||||
{
|
||||
return GetKeyPointer()->Equals(*aKey, nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
nsAutoString low(*aKey);
|
||||
ToLowerCase(low);
|
||||
return HashString(low);
|
||||
}
|
||||
|
||||
USHORT mCodePage;
|
||||
nsMiniMetrics* mMetrics;
|
||||
};
|
||||
|
||||
// An nsFontHandle is actually a pointer to one of these.
|
||||
// It knows how to select itself into a ps.
|
||||
@@ -214,9 +235,8 @@ class nsFontMetricsOS2 : public nsIFontMetrics
|
||||
nsFontOS2* LoadUnicodeFont(HPS aPS, const nsString& aName);
|
||||
static nsresult InitializeGlobalFonts();
|
||||
|
||||
static nsVoidArray* gGlobalFonts;
|
||||
static nsTHashtable<GlobalFontEntry>* gGlobalFonts;
|
||||
static PLHashTable* gFamilyNames;
|
||||
static nsICollation* gCollation;
|
||||
static PRBool gSubstituteVectorFonts;
|
||||
|
||||
nsCOMPtr<nsIAtom> mLangGroup;
|
||||
@@ -270,7 +290,6 @@ class nsFontMetricsOS2 : public nsIFontMetrics
|
||||
nsFontOS2 *mFontHandle;
|
||||
nsDeviceContextOS2 *mDeviceContext;
|
||||
|
||||
static int gCachedIndex;
|
||||
#ifdef DEBUG_FONT_STRUCT_ALLOCS
|
||||
static unsigned long mRefCount;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user