Fixes for bugs 4800 and 4810. Was crashing on Japanese Windows 95 because

GetTextExtentPoint32W and ExtTextOutW are not properly implemented on that
version of Windows. This is a workaround.
This commit is contained in:
erik%netscape.com 1999-04-27 21:44:20 +00:00
Родитель ca63b7e7b6
Коммит 32b1be8ffc
5 изменённых файлов: 1201 добавлений и 93 удалений

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

@ -22,16 +22,11 @@
static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
typedef struct nsGlobalFont
{
nsString* name;
LOGFONT logFont;
PRUint8* map;
} nsGlobalFont;
static nsGlobalFont* gGlobalFonts = nsnull;
nsGlobalFont* nsFontMetricsWin::gGlobalFonts = nsnull;
static int gGlobalFontsAlloc = 0;
static int gGlobalFontsCount = 0;
int nsFontMetricsWin::gGlobalFontsCount = 0;
PLHashTable* nsFontMetricsWin::gFamilyNames = nsnull;
nsFontMetricsWin :: nsFontMetricsWin()
{
@ -53,12 +48,13 @@ nsFontMetricsWin :: ~nsFontMetricsWin()
}
if (mLoadedFonts) {
nsFontWin* font = mLoadedFonts;
nsFontWin* end = &mLoadedFonts[mLoadedFontsCount];
nsFontWin** font = mLoadedFonts;
nsFontWin** end = &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
if (font->font) {
::DeleteObject(font->font);
if ((*font)->font) {
::DeleteObject((*font)->font);
}
delete *font;
font++;
}
PR_Free(mLoadedFonts);
@ -353,8 +349,8 @@ GetSpaces(HDC aDC)
#undef SHOULD_BE_SPACE
#define SHOULD_BE_SPACE(c) FONT_HAS_GLYPH(spaces, c)
static PRUint8*
GetCMAP(HDC aDC)
PRUint8*
nsFontMetricsWin::GetCMAP(HDC aDC)
{
static PLHashTable* fontMaps = nsnull;
static int initialized = 0;
@ -542,20 +538,26 @@ nsFontMetricsWin::LoadFont(HDC aDC, nsString* aName)
HFONT hfont = ::CreateFontIndirect(&logFont);
if (hfont) {
HFONT oldFont = (HFONT) ::SelectObject(aDC, (HGDIOBJ) hfont);
if (mLoadedFontsCount == mLoadedFontsAlloc) {
int newSize = 2 * (mLoadedFontsAlloc ? mLoadedFontsAlloc : 1);
nsFontWin* newPointer = (nsFontWin*) PR_Realloc(mLoadedFonts,
newSize * sizeof(nsFontWin));
nsFontWin** newPointer = (nsFontWin**) PR_Realloc(mLoadedFonts,
newSize * sizeof(nsFontWin*));
if (newPointer) {
mLoadedFonts = newPointer;
mLoadedFontsAlloc = newSize;
}
else {
::DeleteObject(hfont);
return nsnull;
}
}
nsFontWin* font = &mLoadedFonts[mLoadedFontsCount++];
nsFontWin* font = new nsFontWin;
if (!font) {
::DeleteObject(hfont);
return nsnull;
}
mLoadedFonts[mLoadedFontsCount++] = font;
HFONT oldFont = (HFONT) ::SelectObject(aDC, (HGDIOBJ) hfont);
font->font = hfont;
font->map = GetCMAP(aDC);
if (!font->map) {
@ -583,36 +585,40 @@ static int CALLBACK enumProc(const LOGFONT* logFont, const TEXTMETRIC* metrics,
// XXX make this smarter: don't add font to list if we already have a font
// with the same font signature -- erik
if (gGlobalFontsCount == gGlobalFontsAlloc) {
if (nsFontMetricsWin::gGlobalFontsCount == gGlobalFontsAlloc) {
int newSize = 2 * (gGlobalFontsAlloc ? gGlobalFontsAlloc : 1);
nsGlobalFont* newPointer = (nsGlobalFont*) PR_Realloc(gGlobalFonts,
newSize * sizeof(nsGlobalFont));
nsGlobalFont* newPointer = (nsGlobalFont*)
PR_Realloc(nsFontMetricsWin::gGlobalFonts, newSize*sizeof(nsGlobalFont));
if (newPointer) {
gGlobalFonts = newPointer;
nsFontMetricsWin::gGlobalFonts = newPointer;
gGlobalFontsAlloc = newSize;
}
else {
return 0;
}
}
nsGlobalFont* font = &gGlobalFonts[gGlobalFontsCount++];
nsGlobalFont* font =
&nsFontMetricsWin::gGlobalFonts[nsFontMetricsWin::gGlobalFontsCount++];
// XXX do correct character encoding conversion here
font->name = new nsString(logFont->lfFaceName);
if (!font->name) {
gGlobalFontsCount--;
nsFontMetricsWin::gGlobalFontsCount--;
return 0;
}
font->map = nsnull;
font->logFont = *logFont;
font->skip = 0;
return 1;
}
nsFontWin*
nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUnichar c)
nsGlobalFont*
nsFontMetricsWin::InitializeGlobalFonts(HDC aDC)
{
if (!gGlobalFonts) {
static int gInitialized = 0;
if (!gInitialized) {
gInitialized = 1;
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfFaceName[0] = 0;
@ -624,22 +630,66 @@ nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUnichar c)
*/
EnumFontFamiliesEx(aDC, &logFont, enumProc, nsnull, 0);
}
for (int i = 0; i < gGlobalFontsCount; i++) {
if (!gGlobalFonts[i].map) {
HFONT font = ::CreateFontIndirect(&gGlobalFonts[i].logFont);
if (!font) {
continue;
return gGlobalFonts;
}
int
nsFontMetricsWin::SameAsPreviousMap(int aIndex)
{
for (int i = 0; i < aIndex; i++) {
if (!gGlobalFonts[i].skip) {
if (gGlobalFonts[i].map == gGlobalFonts[aIndex].map) {
gGlobalFonts[aIndex].skip = 1;
return 1;
}
HFONT oldFont = (HFONT) ::SelectObject(aDC, font);
gGlobalFonts[i].map = GetCMAP(aDC);
::SelectObject(aDC, oldFont);
::DeleteObject(font);
if (!gGlobalFonts[i].map) {
continue;
PRUint8* map1 = gGlobalFonts[i].map;
PRUint8* map2 = gGlobalFonts[aIndex].map;
int j;
for (j = 0; j < 8192; j++) {
if (map1[j] != map2[j]) {
break;
}
}
if (j == 8192) {
gGlobalFonts[aIndex].skip = 1;
return 1;
}
}
if (FONT_HAS_GLYPH(gGlobalFonts[i].map, c)) {
return LoadFont(aDC, gGlobalFonts[i].name);
}
return 0;
}
nsFontWin*
nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUnichar c)
{
if (!gGlobalFonts) {
if (!InitializeGlobalFonts(aDC)) {
return nsnull;
}
}
for (int i = 0; i < gGlobalFontsCount; i++) {
if (!gGlobalFonts[i].skip) {
if (!gGlobalFonts[i].map) {
HFONT font = ::CreateFontIndirect(&gGlobalFonts[i].logFont);
if (!font) {
continue;
}
HFONT oldFont = (HFONT) ::SelectObject(aDC, font);
gGlobalFonts[i].map = GetCMAP(aDC);
::SelectObject(aDC, oldFont);
::DeleteObject(font);
if (!gGlobalFonts[i].map) {
continue;
}
if (SameAsPreviousMap(i)) {
continue;
}
}
if (FONT_HAS_GLYPH(gGlobalFonts[i].map, c)) {
return LoadFont(aDC, gGlobalFonts[i].name);
}
}
}
@ -671,16 +721,17 @@ static nsFontFamilyName gFamilyNameTable[] =
{ nsnull, nsnull }
};
static PLHashTable* gFamilyNames = nsnull;
nsFontWin*
nsFontMetricsWin::FindLocalFont(HDC aDC, PRUnichar aChar)
PLHashTable*
nsFontMetricsWin::InitializeFamilyNames(void)
{
static int gInitialized = 0;
if (!gInitialized) {
gInitialized = 1;
gFamilyNames = PL_NewHashTable(0, HashKey, CompareKeys, nsnull, nsnull,
nsnull);
if (!gFamilyNames) {
return nsnull;
}
nsFontFamilyName* f = gFamilyNameTable;
while (f->mName) {
nsString* name = new nsString(f->mName);
@ -692,6 +743,18 @@ nsFontMetricsWin::FindLocalFont(HDC aDC, PRUnichar aChar)
}
}
return gFamilyNames;
}
nsFontWin*
nsFontMetricsWin::FindLocalFont(HDC aDC, PRUnichar aChar)
{
if (!gFamilyNames) {
if (!InitializeFamilyNames()) {
return nsnull;
}
}
while (mFontsIndex < mFontsCount) {
nsString* name = &mFonts[mFontsIndex++];
nsString* low = new nsString(*name);
@ -907,3 +970,719 @@ nsFontMetricsWin::GetFontHandle(nsFontHandle &aHandle)
aHandle = mFontHandle;
return NS_OK;
}
// The following is a workaround for a Japanese Windows 95 problem.
PRUint8 bitToCharSet[64] =
{
/*00*/ ANSI_CHARSET,
/*01*/ EASTEUROPE_CHARSET,
/*02*/ RUSSIAN_CHARSET,
/*03*/ GREEK_CHARSET,
/*04*/ TURKISH_CHARSET,
/*05*/ HEBREW_CHARSET,
/*06*/ ARABIC_CHARSET,
/*07*/ BALTIC_CHARSET,
/*08*/ DEFAULT_CHARSET,
/*09*/ DEFAULT_CHARSET,
/*10*/ DEFAULT_CHARSET,
/*11*/ DEFAULT_CHARSET,
/*12*/ DEFAULT_CHARSET,
/*13*/ DEFAULT_CHARSET,
/*14*/ DEFAULT_CHARSET,
/*15*/ DEFAULT_CHARSET,
/*16*/ DEFAULT_CHARSET,
/*17*/ THAI_CHARSET,
/*18*/ SHIFTJIS_CHARSET,
/*19*/ GB2312_CHARSET,
/*20*/ HANGEUL_CHARSET,
/*21*/ CHINESEBIG5_CHARSET,
/*22*/ JOHAB_CHARSET,
/*23*/ DEFAULT_CHARSET,
/*24*/ DEFAULT_CHARSET,
/*25*/ DEFAULT_CHARSET,
/*26*/ DEFAULT_CHARSET,
/*27*/ DEFAULT_CHARSET,
/*28*/ DEFAULT_CHARSET,
/*29*/ DEFAULT_CHARSET,
/*30*/ DEFAULT_CHARSET,
/*31*/ DEFAULT_CHARSET,
/*32*/ DEFAULT_CHARSET,
/*33*/ DEFAULT_CHARSET,
/*34*/ DEFAULT_CHARSET,
/*35*/ DEFAULT_CHARSET,
/*36*/ DEFAULT_CHARSET,
/*37*/ DEFAULT_CHARSET,
/*38*/ DEFAULT_CHARSET,
/*39*/ DEFAULT_CHARSET,
/*40*/ DEFAULT_CHARSET,
/*41*/ DEFAULT_CHARSET,
/*42*/ DEFAULT_CHARSET,
/*43*/ DEFAULT_CHARSET,
/*44*/ DEFAULT_CHARSET,
/*45*/ DEFAULT_CHARSET,
/*46*/ DEFAULT_CHARSET,
/*47*/ DEFAULT_CHARSET,
/*48*/ DEFAULT_CHARSET,
/*49*/ DEFAULT_CHARSET,
/*50*/ DEFAULT_CHARSET,
/*51*/ DEFAULT_CHARSET,
/*52*/ DEFAULT_CHARSET,
/*53*/ DEFAULT_CHARSET,
/*54*/ DEFAULT_CHARSET,
/*55*/ DEFAULT_CHARSET,
/*56*/ DEFAULT_CHARSET,
/*57*/ DEFAULT_CHARSET,
/*58*/ DEFAULT_CHARSET,
/*59*/ DEFAULT_CHARSET,
/*60*/ DEFAULT_CHARSET,
/*61*/ DEFAULT_CHARSET,
/*62*/ DEFAULT_CHARSET,
/*63*/ DEFAULT_CHARSET
};
enum nsCharSet
{
eCharSet_DEFAULT = 0,
eCharSet_ANSI,
eCharSet_EASTEUROPE,
eCharSet_RUSSIAN,
eCharSet_GREEK,
eCharSet_TURKISH,
eCharSet_HEBREW,
eCharSet_ARABIC,
eCharSet_BALTIC,
eCharSet_THAI,
eCharSet_SHIFTJIS,
eCharSet_GB2312,
eCharSet_HANGEUL,
eCharSet_CHINESEBIG5,
eCharSet_JOHAB,
eCharSet_COUNT
};
static nsCharSet gCharSetToIndex[256] =
{
/* 000 */ eCharSet_ANSI,
/* 001 */ eCharSet_DEFAULT,
/* 002 */ eCharSet_DEFAULT, // SYMBOL
/* 003 */ eCharSet_DEFAULT,
/* 004 */ eCharSet_DEFAULT,
/* 005 */ eCharSet_DEFAULT,
/* 006 */ eCharSet_DEFAULT,
/* 007 */ eCharSet_DEFAULT,
/* 008 */ eCharSet_DEFAULT,
/* 009 */ eCharSet_DEFAULT,
/* 010 */ eCharSet_DEFAULT,
/* 011 */ eCharSet_DEFAULT,
/* 012 */ eCharSet_DEFAULT,
/* 013 */ eCharSet_DEFAULT,
/* 014 */ eCharSet_DEFAULT,
/* 015 */ eCharSet_DEFAULT,
/* 016 */ eCharSet_DEFAULT,
/* 017 */ eCharSet_DEFAULT,
/* 018 */ eCharSet_DEFAULT,
/* 019 */ eCharSet_DEFAULT,
/* 020 */ eCharSet_DEFAULT,
/* 021 */ eCharSet_DEFAULT,
/* 022 */ eCharSet_DEFAULT,
/* 023 */ eCharSet_DEFAULT,
/* 024 */ eCharSet_DEFAULT,
/* 025 */ eCharSet_DEFAULT,
/* 026 */ eCharSet_DEFAULT,
/* 027 */ eCharSet_DEFAULT,
/* 028 */ eCharSet_DEFAULT,
/* 029 */ eCharSet_DEFAULT,
/* 030 */ eCharSet_DEFAULT,
/* 031 */ eCharSet_DEFAULT,
/* 032 */ eCharSet_DEFAULT,
/* 033 */ eCharSet_DEFAULT,
/* 034 */ eCharSet_DEFAULT,
/* 035 */ eCharSet_DEFAULT,
/* 036 */ eCharSet_DEFAULT,
/* 037 */ eCharSet_DEFAULT,
/* 038 */ eCharSet_DEFAULT,
/* 039 */ eCharSet_DEFAULT,
/* 040 */ eCharSet_DEFAULT,
/* 041 */ eCharSet_DEFAULT,
/* 042 */ eCharSet_DEFAULT,
/* 043 */ eCharSet_DEFAULT,
/* 044 */ eCharSet_DEFAULT,
/* 045 */ eCharSet_DEFAULT,
/* 046 */ eCharSet_DEFAULT,
/* 047 */ eCharSet_DEFAULT,
/* 048 */ eCharSet_DEFAULT,
/* 049 */ eCharSet_DEFAULT,
/* 050 */ eCharSet_DEFAULT,
/* 051 */ eCharSet_DEFAULT,
/* 052 */ eCharSet_DEFAULT,
/* 053 */ eCharSet_DEFAULT,
/* 054 */ eCharSet_DEFAULT,
/* 055 */ eCharSet_DEFAULT,
/* 056 */ eCharSet_DEFAULT,
/* 057 */ eCharSet_DEFAULT,
/* 058 */ eCharSet_DEFAULT,
/* 059 */ eCharSet_DEFAULT,
/* 060 */ eCharSet_DEFAULT,
/* 061 */ eCharSet_DEFAULT,
/* 062 */ eCharSet_DEFAULT,
/* 063 */ eCharSet_DEFAULT,
/* 064 */ eCharSet_DEFAULT,
/* 065 */ eCharSet_DEFAULT,
/* 066 */ eCharSet_DEFAULT,
/* 067 */ eCharSet_DEFAULT,
/* 068 */ eCharSet_DEFAULT,
/* 069 */ eCharSet_DEFAULT,
/* 070 */ eCharSet_DEFAULT,
/* 071 */ eCharSet_DEFAULT,
/* 072 */ eCharSet_DEFAULT,
/* 073 */ eCharSet_DEFAULT,
/* 074 */ eCharSet_DEFAULT,
/* 075 */ eCharSet_DEFAULT,
/* 076 */ eCharSet_DEFAULT,
/* 077 */ eCharSet_DEFAULT, // MAC
/* 078 */ eCharSet_DEFAULT,
/* 079 */ eCharSet_DEFAULT,
/* 080 */ eCharSet_DEFAULT,
/* 081 */ eCharSet_DEFAULT,
/* 082 */ eCharSet_DEFAULT,
/* 083 */ eCharSet_DEFAULT,
/* 084 */ eCharSet_DEFAULT,
/* 085 */ eCharSet_DEFAULT,
/* 086 */ eCharSet_DEFAULT,
/* 087 */ eCharSet_DEFAULT,
/* 088 */ eCharSet_DEFAULT,
/* 089 */ eCharSet_DEFAULT,
/* 090 */ eCharSet_DEFAULT,
/* 091 */ eCharSet_DEFAULT,
/* 092 */ eCharSet_DEFAULT,
/* 093 */ eCharSet_DEFAULT,
/* 094 */ eCharSet_DEFAULT,
/* 095 */ eCharSet_DEFAULT,
/* 096 */ eCharSet_DEFAULT,
/* 097 */ eCharSet_DEFAULT,
/* 098 */ eCharSet_DEFAULT,
/* 099 */ eCharSet_DEFAULT,
/* 100 */ eCharSet_DEFAULT,
/* 101 */ eCharSet_DEFAULT,
/* 102 */ eCharSet_DEFAULT,
/* 103 */ eCharSet_DEFAULT,
/* 104 */ eCharSet_DEFAULT,
/* 105 */ eCharSet_DEFAULT,
/* 106 */ eCharSet_DEFAULT,
/* 107 */ eCharSet_DEFAULT,
/* 108 */ eCharSet_DEFAULT,
/* 109 */ eCharSet_DEFAULT,
/* 110 */ eCharSet_DEFAULT,
/* 111 */ eCharSet_DEFAULT,
/* 112 */ eCharSet_DEFAULT,
/* 113 */ eCharSet_DEFAULT,
/* 114 */ eCharSet_DEFAULT,
/* 115 */ eCharSet_DEFAULT,
/* 116 */ eCharSet_DEFAULT,
/* 117 */ eCharSet_DEFAULT,
/* 118 */ eCharSet_DEFAULT,
/* 119 */ eCharSet_DEFAULT,
/* 120 */ eCharSet_DEFAULT,
/* 121 */ eCharSet_DEFAULT,
/* 122 */ eCharSet_DEFAULT,
/* 123 */ eCharSet_DEFAULT,
/* 124 */ eCharSet_DEFAULT,
/* 125 */ eCharSet_DEFAULT,
/* 126 */ eCharSet_DEFAULT,
/* 127 */ eCharSet_DEFAULT,
/* 128 */ eCharSet_SHIFTJIS,
/* 129 */ eCharSet_HANGEUL,
/* 130 */ eCharSet_JOHAB,
/* 131 */ eCharSet_DEFAULT,
/* 132 */ eCharSet_DEFAULT,
/* 133 */ eCharSet_DEFAULT,
/* 134 */ eCharSet_GB2312,
/* 135 */ eCharSet_DEFAULT,
/* 136 */ eCharSet_CHINESEBIG5,
/* 137 */ eCharSet_DEFAULT,
/* 138 */ eCharSet_DEFAULT,
/* 139 */ eCharSet_DEFAULT,
/* 140 */ eCharSet_DEFAULT,
/* 141 */ eCharSet_DEFAULT,
/* 142 */ eCharSet_DEFAULT,
/* 143 */ eCharSet_DEFAULT,
/* 144 */ eCharSet_DEFAULT,
/* 145 */ eCharSet_DEFAULT,
/* 146 */ eCharSet_DEFAULT,
/* 147 */ eCharSet_DEFAULT,
/* 148 */ eCharSet_DEFAULT,
/* 149 */ eCharSet_DEFAULT,
/* 150 */ eCharSet_DEFAULT,
/* 151 */ eCharSet_DEFAULT,
/* 152 */ eCharSet_DEFAULT,
/* 153 */ eCharSet_DEFAULT,
/* 154 */ eCharSet_DEFAULT,
/* 155 */ eCharSet_DEFAULT,
/* 156 */ eCharSet_DEFAULT,
/* 157 */ eCharSet_DEFAULT,
/* 158 */ eCharSet_DEFAULT,
/* 159 */ eCharSet_DEFAULT,
/* 160 */ eCharSet_DEFAULT,
/* 161 */ eCharSet_GREEK,
/* 162 */ eCharSet_TURKISH,
/* 163 */ eCharSet_DEFAULT, // VIETNAMESE
/* 164 */ eCharSet_DEFAULT,
/* 165 */ eCharSet_DEFAULT,
/* 166 */ eCharSet_DEFAULT,
/* 167 */ eCharSet_DEFAULT,
/* 168 */ eCharSet_DEFAULT,
/* 169 */ eCharSet_DEFAULT,
/* 170 */ eCharSet_DEFAULT,
/* 171 */ eCharSet_DEFAULT,
/* 172 */ eCharSet_DEFAULT,
/* 173 */ eCharSet_DEFAULT,
/* 174 */ eCharSet_DEFAULT,
/* 175 */ eCharSet_DEFAULT,
/* 176 */ eCharSet_DEFAULT,
/* 177 */ eCharSet_HEBREW,
/* 178 */ eCharSet_ARABIC,
/* 179 */ eCharSet_DEFAULT,
/* 180 */ eCharSet_DEFAULT,
/* 181 */ eCharSet_DEFAULT,
/* 182 */ eCharSet_DEFAULT,
/* 183 */ eCharSet_DEFAULT,
/* 184 */ eCharSet_DEFAULT,
/* 185 */ eCharSet_DEFAULT,
/* 186 */ eCharSet_BALTIC,
/* 187 */ eCharSet_DEFAULT,
/* 188 */ eCharSet_DEFAULT,
/* 189 */ eCharSet_DEFAULT,
/* 190 */ eCharSet_DEFAULT,
/* 191 */ eCharSet_DEFAULT,
/* 192 */ eCharSet_DEFAULT,
/* 193 */ eCharSet_DEFAULT,
/* 194 */ eCharSet_DEFAULT,
/* 195 */ eCharSet_DEFAULT,
/* 196 */ eCharSet_DEFAULT,
/* 197 */ eCharSet_DEFAULT,
/* 198 */ eCharSet_DEFAULT,
/* 199 */ eCharSet_DEFAULT,
/* 200 */ eCharSet_DEFAULT,
/* 201 */ eCharSet_DEFAULT,
/* 202 */ eCharSet_DEFAULT,
/* 203 */ eCharSet_DEFAULT,
/* 204 */ eCharSet_RUSSIAN,
/* 205 */ eCharSet_DEFAULT,
/* 206 */ eCharSet_DEFAULT,
/* 207 */ eCharSet_DEFAULT,
/* 208 */ eCharSet_DEFAULT,
/* 209 */ eCharSet_DEFAULT,
/* 210 */ eCharSet_DEFAULT,
/* 211 */ eCharSet_DEFAULT,
/* 212 */ eCharSet_DEFAULT,
/* 213 */ eCharSet_DEFAULT,
/* 214 */ eCharSet_DEFAULT,
/* 215 */ eCharSet_DEFAULT,
/* 216 */ eCharSet_DEFAULT,
/* 217 */ eCharSet_DEFAULT,
/* 218 */ eCharSet_DEFAULT,
/* 219 */ eCharSet_DEFAULT,
/* 220 */ eCharSet_DEFAULT,
/* 221 */ eCharSet_DEFAULT,
/* 222 */ eCharSet_THAI,
/* 223 */ eCharSet_DEFAULT,
/* 224 */ eCharSet_DEFAULT,
/* 225 */ eCharSet_DEFAULT,
/* 226 */ eCharSet_DEFAULT,
/* 227 */ eCharSet_DEFAULT,
/* 228 */ eCharSet_DEFAULT,
/* 229 */ eCharSet_DEFAULT,
/* 230 */ eCharSet_DEFAULT,
/* 231 */ eCharSet_DEFAULT,
/* 232 */ eCharSet_DEFAULT,
/* 233 */ eCharSet_DEFAULT,
/* 234 */ eCharSet_DEFAULT,
/* 235 */ eCharSet_DEFAULT,
/* 236 */ eCharSet_DEFAULT,
/* 237 */ eCharSet_DEFAULT,
/* 238 */ eCharSet_EASTEUROPE,
/* 239 */ eCharSet_DEFAULT,
/* 240 */ eCharSet_DEFAULT,
/* 241 */ eCharSet_DEFAULT,
/* 242 */ eCharSet_DEFAULT,
/* 243 */ eCharSet_DEFAULT,
/* 244 */ eCharSet_DEFAULT,
/* 245 */ eCharSet_DEFAULT,
/* 246 */ eCharSet_DEFAULT,
/* 247 */ eCharSet_DEFAULT,
/* 248 */ eCharSet_DEFAULT,
/* 249 */ eCharSet_DEFAULT,
/* 250 */ eCharSet_DEFAULT,
/* 251 */ eCharSet_DEFAULT,
/* 252 */ eCharSet_DEFAULT,
/* 253 */ eCharSet_DEFAULT,
/* 254 */ eCharSet_DEFAULT,
/* 255 */ eCharSet_DEFAULT // OEM
};
typedef struct nsCharSetInfo nsCharSetInfo;
struct nsCharSetInfo
{
char* mName;
PRUint16 mCodePage;
void (*GenerateMap)(nsCharSetInfo* aSelf);
PRUint8* mMap;
};
static void
GenerateDefault(nsCharSetInfo* aSelf)
{
printf("%s defaulted\n", aSelf->mName);
PRUint8* map = aSelf->mMap;
for (int i = 0; i < 8192; i++) {
map[i] = 0xFF;
}
}
static void
GenerateSingleByte(nsCharSetInfo* aSelf)
{
PRUint8 mb[256];
PRUint16 wc[256];
int i;
for (i = 0; i < 256; i++) {
mb[i] = i;
}
int len = MultiByteToWideChar(aSelf->mCodePage, 0, (char*) mb, 256, wc, 256);
if (len != 256) {
printf("%s: MultiByteToWideChar returned %d\n", aSelf->mName, len);
}
PRUint8* map = aSelf->mMap;
for (i = 0; i < 256; i++) {
ADD_GLYPH(map, wc[i]);
}
}
static void
GenerateMultiByte(nsCharSetInfo* aSelf)
{
PRUint8* map = aSelf->mMap;
for (PRUint16 c = 0; c < 0xFFFF; c++) {
BOOL defaulted = FALSE;
WideCharToMultiByte(aSelf->mCodePage, 0, &c, 1, nsnull, 0, nsnull,
&defaulted);
if (!defaulted) {
ADD_GLYPH(map, c);
}
}
}
static nsCharSetInfo gCharSetInfo[eCharSet_COUNT] =
{
{ "DEFAULT", 0, GenerateDefault },
{ "ANSI", 1252, GenerateSingleByte },
{ "EASTEUROPE", 1250, GenerateSingleByte },
{ "RUSSIAN", 1251, GenerateSingleByte },
{ "GREEK", 1253, GenerateSingleByte },
{ "TURKISH", 1254, GenerateSingleByte },
{ "HEBREW", 1255, GenerateSingleByte },
{ "ARABIC", 1256, GenerateSingleByte },
{ "BALTIC", 1257, GenerateSingleByte },
{ "THAI", 874, GenerateSingleByte },
{ "SHIFTJIS", 932, GenerateMultiByte },
{ "GB2312", 936, GenerateMultiByte },
{ "HANGEUL", 949, GenerateMultiByte },
{ "CHINESEBIG5", 950, GenerateMultiByte },
{ "JOHAB", 0, GenerateMultiByte }
};
static int
HaveConverterFor(PRUint8 aCharSet)
{
PRUint16 wc = 'a';
char mb[8];
if (WideCharToMultiByte(gCharSetInfo[gCharSetToIndex[aCharSet]].mCodePage, 0,
&wc, 1, mb, sizeof(mb), nsnull, nsnull)) {
return 1;
}
return 0;
}
int
nsFontWinA::GetSubsets(HDC aDC)
{
FONTSIGNATURE signature;
if (::GetTextCharsetInfo(aDC, &signature, 0) == DEFAULT_CHARSET) {
return 0;
}
int dword;
DWORD* array = signature.fsCsb;
mSubsetsCount = 0;
for (dword = 0; dword < 2; dword++) {
for (int bit = 0; bit < sizeof(DWORD) * 8; bit++) {
if ((array[dword] >> bit) & 1) {
PRUint8 charSet = bitToCharSet[bit];
if (charSet != DEFAULT_CHARSET) {
if (HaveConverterFor(charSet)) {
mSubsetsCount++;
}
}
}
}
}
mSubsets = (nsFontSubset*) PR_Calloc(mSubsetsCount, sizeof(nsFontSubset));
if (!mSubsets) {
mSubsetsCount = 0;
return 0;
}
int i = 0;
for (dword = 0; dword < 2; dword++) {
for (int bit = 0; bit < sizeof(DWORD) * 8; bit++) {
if ((array[dword] >> bit) & 1) {
PRUint8 charSet = bitToCharSet[bit];
if (charSet != DEFAULT_CHARSET) {
if (HaveConverterFor(charSet)) {
mSubsets[i].mCharSet = charSet;
i++;
}
}
}
}
}
return 1;
}
static void
FreeFont(nsFontWinA* aFont)
{
nsFontSubset* subset = aFont->mSubsets;
nsFontSubset* endSubsets = &(aFont->mSubsets[aFont->mSubsetsCount]);
while (subset < endSubsets) {
if (subset->mFont) {
::DeleteObject(subset->mFont);
}
if (subset->mMap) {
PR_Free(subset->mMap);
}
subset++;
}
PR_Free(aFont->mSubsets);
delete aFont;
}
nsFontMetricsWinA::~nsFontMetricsWinA()
{
if (nsnull != mFont) {
delete mFont;
mFont = nsnull;
}
mFontHandle = nsnull; // released below
if (mFonts) {
delete [] mFonts;
mFonts = nsnull;
}
if (mLoadedFonts) {
nsFontWinA** font = (nsFontWinA**) mLoadedFonts;
nsFontWinA** end = (nsFontWinA**) &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
FreeFont(*font);
font++;
}
PR_Free(mLoadedFonts);
mLoadedFonts = nsnull;
}
mDeviceContext = nsnull;
}
nsFontWin*
nsFontMetricsWinA::LoadFont(HDC aDC, nsString* aName)
{
LOGFONT logFont;
FillLogFont(&logFont);
// XXX need to preserve Unicode chars in face name (use LOGFONTW) -- erik
aName->ToCString(logFont.lfFaceName, LF_FACESIZE);
HFONT hfont = ::CreateFontIndirect(&logFont);
if (hfont) {
if (mLoadedFontsCount == mLoadedFontsAlloc) {
int newSize = 2 * (mLoadedFontsAlloc ? mLoadedFontsAlloc : 1);
nsFontWinA** newPointer = (nsFontWinA**) PR_Realloc(mLoadedFonts,
newSize * sizeof(nsFontWinA*));
if (newPointer) {
mLoadedFonts = (nsFontWin**) newPointer;
mLoadedFontsAlloc = newSize;
}
else {
::DeleteObject(hfont);
return nsnull;
}
}
nsFontWinA* font = new nsFontWinA;
if (!font) {
::DeleteObject(hfont);
return nsnull;
}
mLoadedFonts[mLoadedFontsCount++] = (nsFontWin*) font;
HFONT oldFont = (HFONT) ::SelectObject(aDC, (HGDIOBJ) hfont);
font->mFont = hfont;
font->mLogFont = logFont;
if (!font->GetSubsets(aDC)) {
mLoadedFontsCount--;
::SelectObject(aDC, (HGDIOBJ) oldFont);
::DeleteObject(hfont);
return nsnull;
}
font->mMap = GetCMAP(aDC);
if (!font->mMap) {
mLoadedFontsCount--;
::SelectObject(aDC, (HGDIOBJ) oldFont);
::DeleteObject(hfont);
return nsnull;
}
::SelectObject(aDC, (HGDIOBJ) oldFont);
return (nsFontWin*) font;
}
return nsnull;
}
int
nsFontSubset::Load(nsFontWinA* aFont)
{
LOGFONT* logFont = &aFont->mLogFont;
logFont->lfCharSet = mCharSet;
HFONT hfont = ::CreateFontIndirect(logFont);
if (hfont) {
int i = gCharSetToIndex[mCharSet];
PRUint8* charSetMap = gCharSetInfo[i].mMap;
if (!charSetMap) {
charSetMap = (PRUint8*) PR_Calloc(8192, 1);
if (charSetMap) {
gCharSetInfo[i].mMap = charSetMap;
gCharSetInfo[i].GenerateMap(&gCharSetInfo[i]);
}
else {
::DeleteObject(hfont);
return 0;
}
}
mMap = (PRUint8*) PR_Malloc(8192);
if (!mMap) {
::DeleteObject(hfont);
return 0;
}
PRUint8* fontMap = aFont->mMap;
for (int j = 0; j < 8192; j++) {
mMap[j] = (charSetMap[j] & fontMap[j]);
}
mCodePage = gCharSetInfo[i].mCodePage;
mFont = hfont;
return 1;
}
return 0;
}
nsFontWin*
nsFontMetricsWinA::FindLocalFont(HDC aDC, PRUnichar aChar)
{
if (!gFamilyNames) {
if (!InitializeFamilyNames()) {
return nsnull;
}
}
while (mFontsIndex < mFontsCount) {
nsString* name = &mFonts[mFontsIndex++];
nsString* low = new nsString(*name);
if (low) {
low->ToLowerCase();
nsString* winName = (nsString*) PL_HashTableLookup(gFamilyNames, low);
delete low;
if (!winName) {
winName = name;
}
nsFontWinA* font = (nsFontWinA*) LoadFont(aDC, winName);
if (font && FONT_HAS_GLYPH(font->mMap, aChar)) {
nsFontSubset* subset = font->mSubsets;
nsFontSubset* endSubsets = &(font->mSubsets[font->mSubsetsCount]);
while (subset < endSubsets) {
if (!subset->mMap) {
if (!subset->Load(font)) {
subset++;
continue;
}
}
if (FONT_HAS_GLYPH(subset->mMap, aChar)) {
return (nsFontWin*) subset;
}
subset++;
}
}
}
}
return nsnull;
}
nsFontWin*
nsFontMetricsWinA::FindGlobalFont(HDC aDC, PRUnichar c)
{
if (!gGlobalFonts) {
if (!InitializeGlobalFonts(aDC)) {
return nsnull;
}
}
for (int i = 0; i < gGlobalFontsCount; i++) {
if (!gGlobalFonts[i].skip) {
if (!gGlobalFonts[i].map) {
HFONT font = ::CreateFontIndirect(&gGlobalFonts[i].logFont);
if (!font) {
continue;
}
HFONT oldFont = (HFONT) ::SelectObject(aDC, font);
gGlobalFonts[i].map = GetCMAP(aDC);
::SelectObject(aDC, oldFont);
::DeleteObject(font);
if (!gGlobalFonts[i].map) {
continue;
}
if (SameAsPreviousMap(i)) {
continue;
}
}
if (FONT_HAS_GLYPH(gGlobalFonts[i].map, c)) {
nsFontWinA* font = (nsFontWinA*) LoadFont(aDC, gGlobalFonts[i].name);
if (font) {
nsFontSubset* subset = font->mSubsets;
nsFontSubset* endSubsets = &(font->mSubsets[font->mSubsetsCount]);
while (subset < endSubsets) {
if (!subset->mMap) {
if (!subset->Load(font)) {
subset++;
continue;
}
}
if (FONT_HAS_GLYPH(subset->mMap, c)) {
return (nsFontWin*) subset;
}
subset++;
}
mLoadedFontsCount--;
FreeFont(font);
}
}
}
}
return nsnull;
}

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

@ -21,6 +21,7 @@
#include <windows.h>
#include "plhash.h"
#include "nsIFontMetrics.h"
#include "nsFont.h"
#include "nsString.h"
@ -45,11 +46,19 @@ typedef struct nsFontWin
PRUint8* map;
} nsFontWin;
typedef struct nsGlobalFont
{
nsString* name;
LOGFONT logFont;
PRUint8* map;
PRUint8 skip;
} nsGlobalFont;
class nsFontMetricsWin : public nsIFontMetrics
{
public:
nsFontMetricsWin();
~nsFontMetricsWin();
virtual ~nsFontMetricsWin();
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
@ -72,12 +81,14 @@ public:
NS_IMETHOD GetFont(const nsFont *&aFont);
NS_IMETHOD GetFontHandle(nsFontHandle &aHandle);
nsFontWin* FindGlobalFont(HDC aDC, PRUnichar aChar);
nsFontWin* FindLocalFont(HDC aDC, PRUnichar aChar);
nsFontWin* FindFont(HDC aDC, PRUnichar aChar);
nsFontWin* LoadFont(HDC aDC, nsString* aName);
virtual nsFontWin* FindGlobalFont(HDC aDC, PRUnichar aChar);
virtual nsFontWin* FindLocalFont(HDC aDC, PRUnichar aChar);
nsFontWin* FindFont(HDC aDC, PRUnichar aChar);
virtual nsFontWin* LoadFont(HDC aDC, nsString* aName);
nsFontWin *mLoadedFonts;
int SameAsPreviousMap(int aIndex);
nsFontWin **mLoadedFonts;
PRUint16 mLoadedFontsAlloc;
PRUint16 mLoadedFontsCount;
@ -86,6 +97,9 @@ public:
PRUint16 mFontsCount;
PRUint16 mFontsIndex;
static nsGlobalFont* gGlobalFonts;
static int gGlobalFontsCount;
protected:
void FillLogFont(LOGFONT* aLogFont);
void RealizeFont();
@ -107,6 +121,50 @@ protected:
nscoord mUnderlineSize;
nscoord mUnderlineOffset;
HFONT mFontHandle;
static PLHashTable* InitializeFamilyNames(void);
static PLHashTable* gFamilyNames;
static nsGlobalFont* InitializeGlobalFonts(HDC aDC);
static PRUint8* GetCMAP(HDC aDC);
};
#endif
// The following is a workaround for a Japanse Windows 95 problem.
typedef struct nsFontWinA nsFontWinA;
// must start with same fields as nsFontWin
struct nsFontSubset
{
int Load(nsFontWinA* aFont);
HFONT mFont;
PRUint8* mMap;
BYTE mCharSet;
PRUint16 mCodePage;
};
struct nsFontWinA
{
int GetSubsets(HDC aDC);
LOGFONT mLogFont;
HFONT mFont;
PRUint8* mMap;
nsFontSubset* mSubsets;
PRUint16 mSubsetsCount;
};
class nsFontMetricsWinA : public nsFontMetricsWin
{
public:
virtual ~nsFontMetricsWinA();
virtual nsFontWin* FindLocalFont(HDC aDC, PRUnichar aChar);
virtual nsFontWin* FindGlobalFont(HDC aDC, PRUnichar aChar);
virtual nsFontWin* LoadFont(HDC aDC, nsString* aName);
};
#endif /* nsFontMetricsWin_h__ */

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

@ -66,8 +66,24 @@ class nsGfxFactoryWin : public nsIFactory
nsCID mClassID;
};
static int gUseAFunctions = 0;
nsGfxFactoryWin::nsGfxFactoryWin(const nsCID &aClass)
{
static int init = 0;
if (!init) {
init = 1;
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(os);
::GetVersionEx(&os);
if ((os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
(os.dwMajorVersion == 4) &&
(os.dwMinorVersion == 0) && // Windows 95 (not 98)
(::GetACP() == 932)) { // Shift-JIS (Japanese)
gUseAFunctions = 1;
}
}
mRefCnt = 0;
mClassID = aClass;
}
@ -129,7 +145,12 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter,
if (mClassID.Equals(kCFontMetrics)) {
nsFontMetricsWin* fm;
NS_NEWXPCOM(fm, nsFontMetricsWin);
if (gUseAFunctions) {
NS_NEWXPCOM(fm, nsFontMetricsWinA);
}
else {
NS_NEWXPCOM(fm, nsFontMetricsWin);
}
inst = (nsISupports *)fm;
}
else if (mClassID.Equals(kCDeviceContext)) {
@ -139,7 +160,12 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter,
}
else if (mClassID.Equals(kCRenderingContext)) {
nsRenderingContextWin* rc;
NS_NEWXPCOM(rc, nsRenderingContextWin);
if (gUseAFunctions) {
NS_NEWXPCOM(rc, nsRenderingContextWinA);
}
else {
NS_NEWXPCOM(rc, nsRenderingContextWin);
}
inst = (nsISupports *)((nsIRenderingContext*)rc);
}
else if (mClassID.Equals(kCImage)) {

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

@ -1454,7 +1454,7 @@ NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString,
if (nsnull != mFontMetrics)
{
nsFontMetricsWin* metrics = (nsFontMetricsWin*) mFontMetrics;
HFONT prevFont = nsnull;
nsFontWin* prevFont = nsnull;
SIZE size;
SetupFontAndColor();
@ -1463,32 +1463,22 @@ NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString,
PRUint32 start = 0;
for (PRUint32 i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
HFONT currFont = mCurrFont;
nsFontWin* font = metrics->mLoadedFonts;
nsFontWin* end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
nsFontWin* currFont = nsnull;
nsFontWin** font = metrics->mLoadedFonts;
nsFontWin** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (FONT_HAS_GLYPH(font->map, c)) {
currFont = font->font;
if (FONT_HAS_GLYPH((*font)->map, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
font++;
}
font = metrics->FindLocalFont(mDC, c);
if (font) {
currFont = font->font;
}
else {
// XXX get CSS to pass inherited or default font list?
font = metrics->FindGlobalFont(mDC, c);
if (font) {
currFont = font->font;
}
}
currFont = metrics->FindFont(mDC, c);
FoundFont:
// XXX avoid this test by duplicating code
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont);
::SelectObject(mDC, prevFont->font);
::GetTextExtentPoint32W(mDC, &aString[start], i - start, &size);
width += size.cx;
prevFont = currFont;
@ -1502,7 +1492,7 @@ FoundFont:
}
if (prevFont) {
::SelectObject(mDC, prevFont);
::SelectObject(mDC, prevFont->font);
::GetTextExtentPoint32W(mDC, &aString[start], i - start, &size);
width += size.cx;
}
@ -1560,7 +1550,7 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUi
PRInt32 y = aY;
mTMatrix->TransformCoord(&x, &y);
nsFontMetricsWin* metrics = (nsFontMetricsWin*) mFontMetrics;
HFONT prevFont = nsnull;
nsFontWin* prevFont = nsnull;
SIZE size;
SetupFontAndColor();
@ -1568,31 +1558,21 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUi
PRUint32 start = 0;
for (PRUint32 i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
HFONT currFont = mCurrFont;
nsFontWin* font = metrics->mLoadedFonts;
nsFontWin* end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
nsFontWin* currFont = nsnull;
nsFontWin** font = metrics->mLoadedFonts;
nsFontWin** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (FONT_HAS_GLYPH(font->map, c)) {
currFont = font->font;
if (FONT_HAS_GLYPH((*font)->map, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
font++;
}
font = metrics->FindLocalFont(mDC, c);
if (font) {
currFont = font->font;
}
else {
// XXX get CSS to pass UA's default font list?
font = metrics->FindGlobalFont(mDC, c);
if (font) {
currFont = font->font;
}
}
currFont = metrics->FindFont(mDC, c);
FoundFont:
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont);
::SelectObject(mDC, prevFont->font);
if (aSpacing) {
// XXX Fix path to use a twips transform in the DC and use the
// spacing values directly and let windows deal with the sub-pixel
@ -1628,7 +1608,7 @@ FoundFont:
}
if (prevFont) {
::SelectObject(mDC, prevFont);
::SelectObject(mDC, prevFont->font);
if (aSpacing) {
// XXX Fix path to use a twips transform in the DC and use the
// spacing values directly and let windows deal with the sub-pixel
@ -2027,3 +2007,252 @@ NS_IMETHODIMP nsRenderingContextWin :: CreateDrawingSurface(HDC aDC, nsDrawingSu
return NS_OK;
}
// The following is a workaround for a Japanese Windows 95 problem.
NS_IMETHODIMP nsRenderingContextWinA :: GetWidth(const PRUnichar *aString,
PRUint32 aLength,
nscoord &aWidth,
PRInt32 *aFontID)
{
if (nsnull != mFontMetrics)
{
nsFontMetricsWinA* metrics = (nsFontMetricsWinA*) mFontMetrics;
nsFontSubset* prevFont = nsnull;
SIZE size;
SetupFontAndColor();
LONG width = 0;
PRUint32 start = 0;
for (PRUint32 i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
nsFontSubset* currFont = nsnull;
nsFontWinA** font = (nsFontWinA**) metrics->mLoadedFonts;
nsFontWinA** end = (nsFontWinA**) &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (FONT_HAS_GLYPH((*font)->mMap, c)) {
nsFontSubset* subset = (*font)->mSubsets;
nsFontSubset* endSubsets = &((*font)->mSubsets[(*font)->mSubsetsCount]);
while (subset < endSubsets) {
if (!subset->mMap) {
if (!subset->Load(*font)) {
subset++;
continue;
}
}
if (FONT_HAS_GLYPH(subset->mMap, c)) {
currFont = subset;
goto FoundFont; // for speed -- avoid "if" statement
}
subset++;
}
}
font++;
}
currFont = (nsFontSubset*) metrics->FindFont(mDC, c);
FoundFont:
// XXX avoid this test by duplicating code
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont->mFont);
char str[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0, &aString[start],
i - start, str, sizeof(str), nsnull, nsnull);
if (len) {
::GetTextExtentPoint32A(mDC, str, len, &size);
width += size.cx;
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
prevFont = currFont;
start = i;
}
}
else {
prevFont = currFont;
start = i;
}
}
if (prevFont) {
::SelectObject(mDC, prevFont->mFont);
char str[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0, &aString[start],
i - start, str, sizeof(str), nsnull, nsnull);
if (len) {
::GetTextExtentPoint32A(mDC, str, len, &size);
width += size.cx;
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
}
aWidth = NSToCoordRound(float(width) * mP2T);
::SelectObject(mDC, mCurrFont);
if (nsnull != aFontID)
*aFontID = 0;
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsRenderingContextWinA :: DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing)
{
if (nsnull != mFontMetrics)
{
PRInt32 x = aX;
PRInt32 y = aY;
mTMatrix->TransformCoord(&x, &y);
nsFontMetricsWinA* metrics = (nsFontMetricsWinA*) mFontMetrics;
nsFontSubset* prevFont = nsnull;
SIZE size;
SetupFontAndColor();
PRUint32 start = 0;
for (PRUint32 i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
nsFontSubset* currFont = nsnull;
nsFontWinA** font = (nsFontWinA**) metrics->mLoadedFonts;
nsFontWinA** end = (nsFontWinA**) &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (FONT_HAS_GLYPH((*font)->mMap, c)) {
nsFontSubset* subset = (*font)->mSubsets;
nsFontSubset* endSubsets = &((*font)->mSubsets[(*font)->mSubsetsCount]);
while (subset < endSubsets) {
if (!subset->mMap) {
if (!subset->Load(*font)) {
subset++;
continue;
}
}
if (FONT_HAS_GLYPH(subset->mMap, c)) {
currFont = subset;
goto FoundFont; // for speed -- avoid "if" statement
}
subset++;
}
}
font++;
}
currFont = (nsFontSubset*) metrics->FindFont(mDC, c);
FoundFont:
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont->mFont);
if (aSpacing) {
// XXX Fix path to use a twips transform in the DC and use the
// spacing values directly and let windows deal with the sub-pixel
// positioning.
// Slow, but accurate rendering
const PRUnichar* str = &aString[start];
const PRUnichar* end = &aString[i];
while (str < end) {
// XXX can shave some cycles by inlining a version of transform
// coord where y is constant and transformed once
x = aX;
y = aY;
mTMatrix->TransformCoord(&x, &y);
char mb[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0, str, 1, mb,
sizeof(mb), nsnull, nsnull);
if (len) {
::ExtTextOutA(mDC, x, y, 0, NULL, mb, len, NULL);
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
aX += *aSpacing++;
str++;
}
}
else {
char mb[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0,
&aString[start], i - start, mb, sizeof(mb), nsnull, nsnull);
if (len) {
::ExtTextOutA(mDC, x, y, 0, NULL, mb, len, NULL);
::GetTextExtentPoint32A(mDC, mb, len, &size);
x += size.cx;
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
}
prevFont = currFont;
start = i;
}
}
else {
prevFont = currFont;
start = i;
}
}
if (prevFont) {
::SelectObject(mDC, prevFont->mFont);
if (aSpacing) {
// XXX Fix path to use a twips transform in the DC and use the
// spacing values directly and let windows deal with the sub-pixel
// positioning.
// Slow, but accurate rendering
const PRUnichar* str = &aString[start];
const PRUnichar* end = &aString[i];
while (str < end) {
// XXX can shave some cycles by inlining a version of transform
// coord where y is constant and transformed once
x = aX;
y = aY;
mTMatrix->TransformCoord(&x, &y);
char mb[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0, str, 1, mb,
sizeof(mb), nsnull, nsnull);
if (len) {
::ExtTextOutA(mDC, x, y, 0, NULL, mb, len, NULL);
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
aX += *aSpacing++;
str++;
}
}
else {
char mb[1024];
int len = WideCharToMultiByte(prevFont->mCodePage, 0,
&aString[start], i - start, mb, sizeof(mb), nsnull, nsnull);
if (len) {
::ExtTextOutA(mDC, x, y, 0, NULL, mb, len, NULL);
}
else {
// XXX failed
printf("%d: WideCharToMultiByte failed\n", prevFont->mCodePage);
}
}
}
::SelectObject(mDC, mCurrFont);
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}

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

@ -162,6 +162,9 @@ public:
// nsIRenderingContextWin
NS_IMETHOD CreateDrawingSurface(HDC aDC, nsDrawingSurface &aSurface);
protected:
void SetupFontAndColor(void);
private:
~nsRenderingContextWin();
@ -172,7 +175,6 @@ private:
HPEN SetupSolidPen(void);
HPEN SetupDashedPen(void);
HPEN SetupDottedPen(void);
void SetupFontAndColor(void);
void PushClipState(void);
protected:
@ -218,4 +220,18 @@ protected:
void* mScriptObject;
};
// The following is a workaround for a Japanese Windows 95 problem.
class nsRenderingContextWinA : public nsRenderingContextWin
{
public:
NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
nscoord& aWidth, PRInt32 *aFontID);
NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY,
PRInt32 aFontID,
const nscoord* aSpacing);
};
#endif /* nsRenderingContextWin_h___ */