Unicode support for fonts on Windows. Reviewed by Michael Plitkins.

This commit is contained in:
erik%netscape.com 1999-03-25 23:41:36 +00:00
Родитель 1bc67ead98
Коммит 7d226e6cb9
3 изменённых файлов: 963 добавлений и 44 удалений

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

@ -17,9 +17,461 @@
*/ */
#include "nsFontMetricsWin.h" #include "nsFontMetricsWin.h"
#include "prmem.h"
static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID); static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
typedef struct UnicodeRange
{
#ifdef NS_DEBUG
PRUint8 bit;
char* description;
#endif
PRUint16 begin;
PRUint16 end;
} UnicodeRange;
static UnicodeRange unicodeRanges[] =
{
{
#ifdef NS_DEBUG
0, "Basic Latin",
#endif
0x0020, 0x007E
},
{
#ifdef NS_DEBUG
1, "Latin-1 Supplement",
#endif
0x00A0, 0x00FF
},
{
#ifdef NS_DEBUG
2, "Latin Extended-A",
#endif
0x0100, 0x017F
},
{
#ifdef NS_DEBUG
3, "Latin Extended-B",
#endif
0x0180, 0x024F
},
{
#ifdef NS_DEBUG
4, "IPA Extensions",
#endif
0x0250, 0x02AF
},
{
#ifdef NS_DEBUG
5, "Spacing Modifier Letters",
#endif
0x02B0, 0x02FF
},
{
#ifdef NS_DEBUG
6, "Combining Diacritical Marks",
#endif
0x0300, 0x036F
},
{
#ifdef NS_DEBUG
7, "Basic Greek",
#endif
0x0370, 0x03CF
},
{
#ifdef NS_DEBUG
8, "Greek Symbols and Coptic",
#endif
0x03D0, 0x03FF
},
{
#ifdef NS_DEBUG
9, "Cyrillic",
#endif
0x0400, 0x04FF
},
{
#ifdef NS_DEBUG
10, "Armenian",
#endif
0x0530, 0x058F
},
{
#ifdef NS_DEBUG
11, "Basic Hebrew",
#endif
0x05D0, 0x05FF
},
{
#ifdef NS_DEBUG
12, "Hebrew Extended",
#endif
0x0590, 0x05CF
},
{
#ifdef NS_DEBUG
13, "Basic Arabic",
#endif
0x0600, 0x0652
},
{
#ifdef NS_DEBUG
14, "Arabic Extended",
#endif
0x0653, 0x06FF
},
{
#ifdef NS_DEBUG
15, "Devanagari",
#endif
0x0900, 0x097F
},
{
#ifdef NS_DEBUG
16, "Bengali",
#endif
0x0980, 0x09FF
},
{
#ifdef NS_DEBUG
17, "Gurmukhi",
#endif
0x0A00, 0x0A7F
},
{
#ifdef NS_DEBUG
18, "Gujarati",
#endif
0x0A80, 0x0AFF
},
{
#ifdef NS_DEBUG
19, "Oriya",
#endif
0x0B00, 0x0B7F
},
{
#ifdef NS_DEBUG
20, "Tamil",
#endif
0x0B80, 0x0BFF
},
{
#ifdef NS_DEBUG
21, "Telugu",
#endif
0x0C00, 0x0C7F
},
{
#ifdef NS_DEBUG
22, "Kannada",
#endif
0x0C80, 0x0CFF
},
{
#ifdef NS_DEBUG
23, "Malayalam",
#endif
0x0D00, 0x0D7F
},
{
#ifdef NS_DEBUG
24, "Thai",
#endif
0x0E00, 0x0E7F
},
{
#ifdef NS_DEBUG
25, "Lao",
#endif
0x0E80, 0x0EFF
},
{
#ifdef NS_DEBUG
26, "Basic Georgian",
#endif
0x10D0, 0x10FF
},
{
#ifdef NS_DEBUG
27, "Georgian Extended",
#endif
0x10A0, 0x10CF
},
{
#ifdef NS_DEBUG
28, "Hangul Jamo",
#endif
0x1100, 0x11FF
},
{
#ifdef NS_DEBUG
29, "Latin Extended Additional",
#endif
0x1E00, 0x1EFF
},
{
#ifdef NS_DEBUG
30, "Greek Extended",
#endif
0x1F00, 0x1FFF
},
{
#ifdef NS_DEBUG
31, "General Punctuation",
#endif
0x2000, 0x206F
},
{
#ifdef NS_DEBUG
32, "Subscripts and Superscripts",
#endif
0x2070, 0x209F
},
{
#ifdef NS_DEBUG
33, "Currency Symbols",
#endif
0x20A0, 0x20CF
},
{
#ifdef NS_DEBUG
34, "Combining Diacritical Marks for Symbols",
#endif
0x20D0, 0x20FF
},
{
#ifdef NS_DEBUG
35, "Letter-like Symbols",
#endif
0x2100, 0x214F
},
{
#ifdef NS_DEBUG
36, "Number Forms",
#endif
0x2150, 0x218F
},
{
#ifdef NS_DEBUG
37, "Arrows",
#endif
0x2190, 0x21FF
},
{
#ifdef NS_DEBUG
38, "Mathematical Operators",
#endif
0x2200, 0x22FF
},
{
#ifdef NS_DEBUG
39, "Miscellaneous Technical",
#endif
0x2300, 0x23FF
},
{
#ifdef NS_DEBUG
40, "Control Pictures",
#endif
0x2400, 0x243F
},
{
#ifdef NS_DEBUG
41, "Optical Character Recognition",
#endif
0x2440, 0x245F
},
{
#ifdef NS_DEBUG
42, "Enclosed Alphanumerics",
#endif
0x2460, 0x24FF
},
{
#ifdef NS_DEBUG
43, "Box Drawing",
#endif
0x2500, 0x257F
},
{
#ifdef NS_DEBUG
44, "Block Elements",
#endif
0x2580, 0x259F
},
{
#ifdef NS_DEBUG
45, "Geometric Shapes",
#endif
0x25A0, 0x25FF
},
{
#ifdef NS_DEBUG
46, "Miscellaneous Symbols",
#endif
0x2600, 0x26FF
},
{
#ifdef NS_DEBUG
47, "Dingbats",
#endif
0x2700, 0x27BF
},
{
#ifdef NS_DEBUG
48, "Chinese, Japanese, and Korean (CJK) Symbols and Punctuation",
#endif
0x3000, 0x303F
},
{
#ifdef NS_DEBUG
49, "Hiragana",
#endif
0x3040, 0x309F
},
{
#ifdef NS_DEBUG
50, "Katakana",
#endif
0x30A0, 0x30FF
},
{
#ifdef NS_DEBUG
51, "Bopomofo",
#endif
0x3100, 0x312F
},
{
#ifdef NS_DEBUG
52, "Hangul Compatibility Jamo",
#endif
0x3130, 0x318F
},
{
#ifdef NS_DEBUG
53, "CJK Miscellaneous",
#endif
0x3190, 0x319F
},
{
#ifdef NS_DEBUG
54, "Enclosed CJK",
#endif
0x3200, 0x32FF
},
{
#ifdef NS_DEBUG
55, "CJK Compatibility",
#endif
0x3300, 0x33FF
},
{
#ifdef NS_DEBUG
56, "Hangul",
#endif
0x3400, 0x3D2D
},
{
#ifdef NS_DEBUG
57, "Reserved for Unicode Subranges",
#endif
0x3D2E, 0x44B7
},
{
#ifdef NS_DEBUG
58, "Reserved for Unicode Subranges",
#endif
0x44B8, 0x4DFF
},
{
#ifdef NS_DEBUG
59, "CJK Unified Ideographs",
#endif
0x4E00, 0x9FFF
},
{
#ifdef NS_DEBUG
60, "Private Use Area",
#endif
0xE000, 0xF8FF
},
{
#ifdef NS_DEBUG
61, "CJK Compatibility Ideographs",
#endif
0xF900, 0xFAFF
},
{
#ifdef NS_DEBUG
62, "Alphabetic Presentation Forms",
#endif
0xFB00, 0xFB4F
},
{
#ifdef NS_DEBUG
63, "Arabic Presentation Forms-A",
#endif
0xFB50, 0xFDFF
},
{
#ifdef NS_DEBUG
64, "Combining Half Marks",
#endif
0xFE20, 0xFE2F
},
{
#ifdef NS_DEBUG
65, "CJK Compatibility Forms",
#endif
0xFE30, 0xFE4F
},
{
#ifdef NS_DEBUG
66, "Small Form Variants",
#endif
0xFE50, 0xFE6F
},
{
#ifdef NS_DEBUG
67, "Arabic Presentation Forms-B",
#endif
0xFE70, 0xFEFE
},
{
#ifdef NS_DEBUG
68, "Halfwidth and Fullwidth Forms",
#endif
0xFF00, 0xFFEF
},
{
#ifdef NS_DEBUG
69, "Specials",
#endif
0xFFF0, 0xFFFD
},
{
#ifdef NS_DEBUG
70-127, "Reserved for Unicode Subranges",
#endif
0x0000, 0x0000
}
};
typedef struct nsGlobalFont
{
nsString* name;
FONTSIGNATURE signature;
PRUint8* map;
} nsGlobalFont;
static nsGlobalFont* gGlobalFonts = nsnull;
static int gGlobalFontsAlloc = 0;
static int gGlobalFontsCount = 0;
nsFontMetricsWin :: nsFontMetricsWin() nsFontMetricsWin :: nsFontMetricsWin()
{ {
NS_INIT_REFCNT(); NS_INIT_REFCNT();
@ -39,6 +491,28 @@ nsFontMetricsWin :: ~nsFontMetricsWin()
mFontHandle = NULL; mFontHandle = NULL;
} }
#ifdef FONT_SWITCHING
if (mFonts) {
delete [] mFonts;
mFonts = nsnull;
}
if (mLoadedFonts) {
nsFontWin* font = mLoadedFonts;
nsFontWin* end = &mLoadedFonts[mLoadedFontsCount];
while (font < end) {
if (font->font) {
::DeleteObject(font->font);
}
font++;
}
PR_Free(mLoadedFonts);
mLoadedFonts = nsnull;
}
#endif /* FONT_SWITCHING */
mDeviceContext = nsnull; mDeviceContext = nsnull;
} }
@ -132,16 +606,199 @@ MapGenericFamilyToFont(const nsString& aGenericFamily,
} }
} }
void
nsFontMetricsWin::FillLogFont(LOGFONT* logFont)
{
// Fill in logFont structure; stolen from awt
logFont->lfWidth = 0;
logFont->lfEscapement = 0;
logFont->lfOrientation = 0;
logFont->lfUnderline =
(mFont->decorations & NS_FONT_DECORATION_UNDERLINE)
? TRUE : FALSE;
logFont->lfStrikeOut =
(mFont->decorations & NS_FONT_DECORATION_LINE_THROUGH)
? TRUE : FALSE;
logFont->lfCharSet = DEFAULT_CHARSET;
logFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont->lfQuality = DEFAULT_QUALITY;
logFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
logFont->lfWeight = ((400 < mFont->weight) ? FW_BOLD : FW_NORMAL); // XXX could be smarter
logFont->lfItalic = (mFont->style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE))
? TRUE : FALSE; // XXX need better oblique support
float app2dev, app2twip, scale;
mDeviceContext->GetAppUnitsToDevUnits(app2dev);
mDeviceContext->GetDevUnitsToTwips(app2twip);
mDeviceContext->GetCanonicalPixelScale(scale);
app2twip *= app2dev * scale;
// this interesting bit of code rounds the font size off to the floor point value
// this is necessary for proper font scaling under windows
PRInt32 sizePoints = NSTwipsToFloorIntPoints(nscoord(mFont->size * app2twip));
float rounded = ((float)NSIntPointsToTwips(sizePoints)) / app2twip;
// round font size off to floor point size to be windows compatible
logFont->lfHeight = - NSToIntRound(rounded * app2dev); // this is proper (windows) rounding
// logFont->lfHeight = - LONG(rounded * app2dev); // this floor rounding is to make ours compatible with Nav 4.0
#ifdef NS_DEBUG
// Make Purify happy
memset(logFont->lfFaceName, 0, sizeof(logFont->lfFaceName));
#endif
}
#ifdef FONT_SWITCHING
static void
FillBitMap(FONTSIGNATURE* aSignature, PRUint8* aMap)
{
DWORD* array = aSignature->fsUsb;
int i = 0;
for (int dword = 0; dword < 4; dword++) {
for (int bit = 0; bit < sizeof(DWORD) * 8; bit++) {
if ((array[dword] >> bit) & 1) {
int end = unicodeRanges[i].end;
for (int c = unicodeRanges[i].begin; c <= end; c++) {
ADD_GLYPH(aMap, c);
}
}
i++;
}
}
}
nsFontWin*
nsFontMetricsWin::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) {
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));
if (newPointer) {
mLoadedFonts = newPointer;
mLoadedFontsAlloc = newSize;
}
else {
return nsnull;
}
}
nsFontWin* font = &mLoadedFonts[mLoadedFontsCount++];
font->font = hfont;
memset(font->map, 0, sizeof(font->map));
FONTSIGNATURE signature;
GetTextCharsetInfo(aDC, &signature, 0);
FillBitMap(&signature, font->map);
::SelectObject(aDC, (HGDIOBJ) oldFont);
return font;
}
return nsnull;
}
static int CALLBACK enumProc(const LOGFONT* logFont, const TEXTMETRIC* metrics,
DWORD fontType, LPARAM closure)
{
// 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) {
int newSize = 2 * (gGlobalFontsAlloc ? gGlobalFontsAlloc : 1);
nsGlobalFont* newPointer = (nsGlobalFont*) PR_Realloc(gGlobalFonts,
newSize * sizeof(nsGlobalFont));
if (newPointer) {
gGlobalFonts = newPointer;
gGlobalFontsAlloc = newSize;
}
else {
return 0;
}
}
nsGlobalFont* font = &gGlobalFonts[gGlobalFontsCount++];
NEWTEXTMETRICEX* metricsEx = (NEWTEXTMETRICEX*) metrics;
font->name = new nsString(logFont->lfFaceName);
font->signature = metricsEx->ntmFontSig;
font->map = nsnull;
return 1;
}
nsFontWin*
nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUnichar c)
{
if (!gGlobalFonts) {
LOGFONT logFont;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfFaceName[0] = 0;
logFont.lfPitchAndFamily = 0;
EnumFontFamiliesEx(aDC, &logFont, enumProc, NULL, 0);
}
for (int i = 0; i < gGlobalFontsCount; i++) {
if (!gGlobalFonts[i].map) {
gGlobalFonts[i].map = (PRUint8*) PR_Calloc(8192, 1);
if (!gGlobalFonts[i].map) {
return nsnull;
}
FillBitMap(&gGlobalFonts[i].signature, gGlobalFonts[i].map);
}
if (FONT_HAS_GLYPH(gGlobalFonts[i].map, c)) {
return LoadFont(aDC, gGlobalFonts[i].name);
}
}
return nsnull;
}
nsFontWin*
nsFontMetricsWin::FindLocalFont(HDC aDC, PRUnichar aChar)
{
while (mFontsIndex < mFontsCount) {
nsFontWin* font = LoadFont(aDC, &mFonts[mFontsIndex++]);
if (font && FONT_HAS_GLYPH(font->map, aChar)) {
return font;
}
}
return nsnull;
}
#endif /* FONT_SWITCHING */
struct FontEnumData { struct FontEnumData {
FontEnumData(nsIDeviceContext* aContext, TCHAR* aFaceName) FontEnumData(nsIDeviceContext* aContext, TCHAR* aFaceName
#ifdef FONT_SWITCHING
, nsFontMetricsWin* aMetrics, HDC aDC
#endif /* FONT_SWITCHING */
)
{ {
mContext = aContext; mContext = aContext;
mFaceName = aFaceName; mFaceName = aFaceName;
#ifdef FONT_SWITCHING
mMetrics = aMetrics;
mDC = aDC;
mFoundASCIIFont = 0;
#endif /* FONT_SWITCHING */
} }
nsIDeviceContext* mContext; nsIDeviceContext* mContext;
TCHAR* mFaceName; TCHAR* mFaceName;
#ifdef FONT_SWITCHING
nsFontMetricsWin* mMetrics;
HDC mDC;
char mFoundASCIIFont;
#endif /* FONT_SWITCHING */
}; };
#ifndef FONT_SWITCHING
static PRBool static PRBool
FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData) FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
{ {
@ -164,55 +821,69 @@ FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
return PR_TRUE; return PR_TRUE;
} }
#else /* FONT_SWITCHING */
static void
FontEnumHelper(FontEnumData* data, nsString* realFace)
{
nsFontMetricsWin* metrics = data->mMetrics;
if (metrics->mFontsCount == metrics->mFontsAlloc) {
int newSize = 2 * (metrics->mFontsAlloc ? metrics->mFontsAlloc : 1);
nsString* newPointer = new nsString[newSize];
if (newPointer) {
for (int i = metrics->mFontsCount - 1; i >= 0; i--) {
newPointer[i].SetString(metrics->mFonts[i].GetUnicode());
}
delete [] metrics->mFonts;
metrics->mFonts = newPointer;
metrics->mFontsAlloc = newSize;
}
else {
return;
}
}
metrics->mFonts[metrics->mFontsCount++].SetString(realFace->GetUnicode());
if (!data->mFoundASCIIFont) {
nsFontWin* font =
metrics->LoadFont(data->mDC, &metrics->mFonts[metrics->mFontsIndex++]);
if (font && FONT_HAS_GLYPH(font->map, 'a')) {
data->mFoundASCIIFont = 1;
realFace->ToCString(data->mFaceName, LF_FACESIZE);
}
}
}
static PRBool
FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
{
FontEnumData* data = (FontEnumData*)aData;
if (aGeneric) {
nsAutoString realFace;
MapGenericFamilyToFont(aFamily, data->mContext, realFace);
FontEnumHelper(data, &realFace);
return PR_TRUE; // don't stop
}
else {
nsAutoString realFace;
PRBool aliased;
data->mContext->GetLocalFontName(aFamily, realFace, aliased);
if (aliased || (NS_OK == data->mContext->CheckFontExistence(realFace))) {
FontEnumHelper(data, &realFace);
return PR_TRUE; // don't stop
}
}
return PR_TRUE;
}
#endif /* FONT_SWITCHING */
void void
nsFontMetricsWin::RealizeFont() nsFontMetricsWin::RealizeFont()
{ {
// Fill in logFont structure; stolen from awt
LOGFONT logFont; LOGFONT logFont;
logFont.lfWidth = 0; FillLogFont(&logFont);
logFont.lfEscapement = 0;
logFont.lfOrientation = 0;
logFont.lfUnderline =
(mFont->decorations & NS_FONT_DECORATION_UNDERLINE)
? TRUE : FALSE;
logFont.lfStrikeOut =
(mFont->decorations & NS_FONT_DECORATION_LINE_THROUGH)
? TRUE : FALSE;
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
logFont.lfWeight = ((400 < mFont->weight) ? FW_BOLD : FW_NORMAL); // XXX could be smarter
logFont.lfItalic = (mFont->style & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE))
? TRUE : FALSE; // XXX need better oblique support
float app2dev, app2twip, scale;
mDeviceContext->GetAppUnitsToDevUnits(app2dev);
mDeviceContext->GetDevUnitsToTwips(app2twip);
mDeviceContext->GetCanonicalPixelScale(scale);
app2twip *= app2dev * scale;
// this interesting bit of code rounds the font size off to the floor point value
// this is necessary for proper font scaling under windows
PRInt32 sizePoints = NSTwipsToFloorIntPoints(nscoord(mFont->size * app2twip));
float rounded = ((float)NSIntPointsToTwips(sizePoints)) / app2twip;
// round font size off to floor point size to be windows compatible
logFont.lfHeight = - NSToIntRound(rounded * app2dev); // this is proper (windows) rounding
// logFont.lfHeight = - LONG(rounded * app2dev); // this floor rounding is to make ours compatible with Nav 4.0
#ifdef NS_DEBUG
// Make Purify happy
memset(logFont.lfFaceName, 0, sizeof(logFont.lfFaceName));
#endif
logFont.lfFaceName[0] = '\0'; logFont.lfFaceName[0] = '\0';
FontEnumData data(mDeviceContext, logFont.lfFaceName);
mFont->EnumerateFamilies(FontEnumCallback, &data);
// Create font handle from font spec
mFontHandle = ::CreateFontIndirect(&logFont);
HWND win = NULL; HWND win = NULL;
HDC dc = NULL; HDC dc = NULL;
@ -225,6 +896,16 @@ nsFontMetricsWin::RealizeFont()
dc = ::GetDC(win); dc = ::GetDC(win);
} }
#ifdef FONT_SWITCHING
FontEnumData data(mDeviceContext, logFont.lfFaceName, this, dc);
#else
FontEnumData data(mDeviceContext, logFont.lfFaceName);
#endif
mFont->EnumerateFamilies(FontEnumCallback, &data);
// Create font handle from font spec
mFontHandle = ::CreateFontIndirect(&logFont);
HFONT oldfont = (HFONT)::SelectObject(dc, (HGDIOBJ) mFontHandle); HFONT oldfont = (HFONT)::SelectObject(dc, (HGDIOBJ) mFontHandle);
// Get font metrics // Get font metrics

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

@ -29,6 +29,27 @@
#include "nsCRT.h" #include "nsCRT.h"
#include "nsDeviceContextWin.h" #include "nsDeviceContextWin.h"
#define FONT_SWITCHING
#ifdef FONT_SWITCHING
#ifdef FONT_HAS_GLYPH
#undef FONT_HAS_GLYPH
#endif
#define FONT_HAS_GLYPH(map, g) (((map)[(g) >> 3] >> ((g) & 7)) & 1)
#ifdef ADD_GLYPH
#undef ADD_GLYPH
#endif
#define ADD_GLYPH(map, g) (map)[(g) >> 3] |= (1 << ((g) & 7))
typedef struct nsFontWin
{
HFONT font;
PRUint8 map[8192]; // XXX save memory by sharing these among fonts -- erik
} nsFontWin;
#endif /* FONT_SWITCHING */
class nsFontMetricsWin : public nsIFontMetrics class nsFontMetricsWin : public nsIFontMetrics
{ {
public: public:
@ -56,7 +77,25 @@ public:
NS_IMETHOD GetFont(const nsFont *&aFont); NS_IMETHOD GetFont(const nsFont *&aFont);
NS_IMETHOD GetFontHandle(nsFontHandle &aHandle); NS_IMETHOD GetFontHandle(nsFontHandle &aHandle);
#ifdef FONT_SWITCHING
nsFontWin* FindGlobalFont(HDC aDC, PRUnichar aChar);
nsFontWin* FindLocalFont(HDC aDC, PRUnichar aChar);
nsFontWin* LoadFont(HDC aDC, nsString* aName);
nsFontWin *mLoadedFonts;
PRUint16 mLoadedFontsAlloc;
PRUint16 mLoadedFontsCount;
nsString *mFonts;
PRUint16 mFontsAlloc;
PRUint16 mFontsCount;
PRUint16 mFontsIndex;
#endif /* FONT_SWITCHING */
protected: protected:
void FillLogFont(LOGFONT* aLogFont);
void RealizeFont(); void RealizeFont();
nsDeviceContextWin *mDeviceContext; nsDeviceContextWin *mDeviceContext;

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

@ -17,6 +17,7 @@
*/ */
#include "nsRenderingContextWin.h" #include "nsRenderingContextWin.h"
#include "nsFontMetricsWin.h"
#include "nsRegionWin.h" #include "nsRegionWin.h"
#include <math.h> #include <math.h>
#include "libimg.h" #include "libimg.h"
@ -1445,6 +1446,8 @@ NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const nsString& aString, nscoord
return GetWidth(aString.GetUnicode(), aString.Length(), aWidth, aFontID); return GetWidth(aString.GetUnicode(), aString.Length(), aWidth, aFontID);
} }
#ifndef FONT_SWITCHING
NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString, NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString,
PRUint32 aLength, PRUint32 aLength,
nscoord &aWidth, nscoord &aWidth,
@ -1467,6 +1470,84 @@ NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
#else /* FONT_SWITCHING */
NS_IMETHODIMP nsRenderingContextWin :: GetWidth(const PRUnichar *aString,
PRUint32 aLength,
nscoord &aWidth,
PRInt32 *aFontID)
{
if (nsnull != mFontMetrics)
{
nsFontMetricsWin* metrics = (nsFontMetricsWin*) mFontMetrics;
HFONT prevFont = nsnull;
SIZE size;
SetupFontAndColor();
LONG width = 0;
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];
while (font < end) {
if (FONT_HAS_GLYPH(font->map, c)) {
currFont = font->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;
}
}
FoundFont:
// XXX avoid this test by duplicating code
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont);
::GetTextExtentPoint32W(mDC, &aString[start], i - start, &size);
width += size.cx;
prevFont = currFont;
start = i;
}
}
else {
prevFont = currFont;
start = i;
}
}
if (prevFont) {
::SelectObject(mDC, prevFont);
::GetTextExtentPoint32W(mDC, &aString[start], i - start, &size);
width += size.cx;
}
aWidth = NSToCoordRound(float(width) * mP2T);
::SelectObject(mDC, mCurrFont);
if (nsnull != aFontID)
*aFontID = 0;
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
#endif /* FONT_SWITCHING */
NS_IMETHODIMP nsRenderingContextWin :: DrawString(const char *aString, PRUint32 aLength, NS_IMETHODIMP nsRenderingContextWin :: DrawString(const char *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nscoord aX, nscoord aY,
const nscoord* aSpacing) const nscoord* aSpacing)
@ -1496,6 +1577,8 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawString(const char *aString, PRUint32
return NS_OK; return NS_OK;
} }
#ifndef FONT_SWITCHING
NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUint32 aLength, NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUint32 aLength,
nscoord aX, nscoord aY, nscoord aX, nscoord aY,
PRInt32 aFontID, PRInt32 aFontID,
@ -1552,6 +1635,122 @@ NS_IMETHODIMP nsRenderingContextWin :: DrawString(const PRUnichar *aString, PRUi
return NS_OK; return NS_OK;
} }
#else /* FONT_SWITCHING */
NS_IMETHODIMP nsRenderingContextWin :: 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);
nsFontMetricsWin* metrics = (nsFontMetricsWin*) mFontMetrics;
HFONT prevFont = nsnull;
SIZE size;
SetupFontAndColor();
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];
while (font < end) {
if (FONT_HAS_GLYPH(font->map, c)) {
currFont = font->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;
}
}
FoundFont:
if (prevFont) {
if (currFont != prevFont) {
::SelectObject(mDC, prevFont);
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);
::ExtTextOutW(mDC, x, y, 0, NULL, str, 1, NULL);
aX += *aSpacing++;
str++;
}
}
else {
::ExtTextOutW(mDC, x, y, 0, NULL, &aString[start], i - start, NULL);
::GetTextExtentPoint32W(mDC, &aString[start], i - start, &size);
x += size.cx;
}
prevFont = currFont;
start = i;
}
}
else {
prevFont = currFont;
start = i;
}
}
if (prevFont) {
::SelectObject(mDC, prevFont);
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);
::ExtTextOutW(mDC, x, y, 0, NULL, str, 1, NULL);
aX += *aSpacing++;
str++;
}
}
else {
::ExtTextOutW(mDC, x, y, 0, NULL, &aString[start], i - start, NULL);
}
}
::SelectObject(mDC, mCurrFont);
return NS_OK;
}
else
return NS_ERROR_FAILURE;
}
#endif /* FONT_SWITCHING */
NS_IMETHODIMP nsRenderingContextWin :: DrawString(const nsString& aString, NS_IMETHODIMP nsRenderingContextWin :: DrawString(const nsString& aString,
nscoord aX, nscoord aY, nscoord aX, nscoord aY,
PRInt32 aFontID, PRInt32 aFontID,