Add 'wide'(16bit) non-Unicode truetype font support. Use 'nsAutoArray' for
temporary buffer allocation/deallocation. b=177877, r=shanjian, sr=rbs git-svn-id: svn://10.0.0.236/trunk@135348 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
7e8165e23c
commit
df0ceb7a68
@ -78,3 +78,13 @@ encoding.math5monobold.ttf = x-mathematica5
|
||||
|
||||
# MathType Extra
|
||||
encoding.mtextra.ttf = x-mtextra
|
||||
|
||||
# Korean Jamo TTFs
|
||||
# The suffix '.wide' has to be added to encoding names to identify
|
||||
# these fonts as 'wide' non-Unicode fonts.
|
||||
encoding.newgulim.ttf = x-hykoreanjamo-1.wide
|
||||
encoding.gulimoldhanguljamo.ttf = x-hykoreanjamo-0.wide
|
||||
# For the Korean locale, Korean family names have to be
|
||||
# listed in UTF-8.
|
||||
encoding.새굴림.ttf = x-hykoreanjamo-1.wide
|
||||
encoding.굴림옛한글자모.ttf = x-hykoreanjamo-0.wide
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
@ -140,8 +142,6 @@ PRUint16* nsFontMetricsWin::gEmptyCCMap = nsnull;
|
||||
#define NS_MAX_FONT_WEIGHT 900
|
||||
#define NS_MIN_FONT_WEIGHT 100
|
||||
|
||||
#undef CHAR_BUFFER_SIZE
|
||||
#define CHAR_BUFFER_SIZE 1024
|
||||
|
||||
static nsIPersistentProperties* gFontEncodingProperties = nsnull;
|
||||
static nsICharsetConverterManager2* gCharsetManager = nsnull;
|
||||
@ -572,38 +572,43 @@ nsFontMetricsWin::FillLogFont(LOGFONT* logFont, PRInt32 aWeight,
|
||||
|
||||
|
||||
#define AUTO_FONTDATA_BUFFER_SIZE 16384 /* 16K */
|
||||
#undef CHAR_BUFFER_SIZE
|
||||
#define CHAR_BUFFER_SIZE 1024
|
||||
|
||||
class nsAutoFontDataBuffer {
|
||||
// template for helper classes for temporary buffer allocation
|
||||
template<class T, PRInt32 sz> class nsAutoArray {
|
||||
public:
|
||||
nsAutoFontDataBuffer();
|
||||
~nsAutoFontDataBuffer();
|
||||
nsAutoArray();
|
||||
~nsAutoArray();
|
||||
|
||||
PRUint8* GetArray(PRInt32 aMinLength = 0);
|
||||
T* GetArray(PRInt32 aMinLength = 0);
|
||||
|
||||
private:
|
||||
PRUint8* mArray;
|
||||
PRUint8 mAutoArray[AUTO_FONTDATA_BUFFER_SIZE];
|
||||
T* mArray;
|
||||
T mAutoArray[sz];
|
||||
PRInt32 mCount;
|
||||
};
|
||||
|
||||
nsAutoFontDataBuffer::nsAutoFontDataBuffer()
|
||||
template<class T, PRInt32 sz>
|
||||
nsAutoArray<T, sz>::nsAutoArray()
|
||||
: mArray(mAutoArray),
|
||||
mCount(AUTO_FONTDATA_BUFFER_SIZE)
|
||||
mCount(sz)
|
||||
{
|
||||
}
|
||||
|
||||
nsAutoFontDataBuffer::~nsAutoFontDataBuffer()
|
||||
template<class T, PRInt32 sz>
|
||||
nsAutoArray<T, sz>::~nsAutoArray()
|
||||
{
|
||||
if (mArray && (mArray != mAutoArray)) {
|
||||
delete [] mArray;
|
||||
}
|
||||
}
|
||||
|
||||
PRUint8*
|
||||
nsAutoFontDataBuffer::GetArray(PRInt32 aMinCount)
|
||||
template<class T, PRInt32 sz> T*
|
||||
nsAutoArray<T, sz>::GetArray(PRInt32 aMinCount)
|
||||
{
|
||||
if (aMinCount > mCount) {
|
||||
PRUint8* newArray = new PRUint8[aMinCount];
|
||||
T* newArray = new T[aMinCount];
|
||||
if (!newArray) {
|
||||
return nsnull;
|
||||
}
|
||||
@ -616,6 +621,10 @@ nsAutoFontDataBuffer::GetArray(PRInt32 aMinCount)
|
||||
return mArray;
|
||||
}
|
||||
|
||||
typedef nsAutoArray<PRUint8, AUTO_FONTDATA_BUFFER_SIZE> nsAutoFontDataBuffer;
|
||||
typedef nsAutoArray<char, CHAR_BUFFER_SIZE> nsAutoCharBuffer;
|
||||
typedef nsAutoArray<PRUint16, CHAR_BUFFER_SIZE> nsAutoChar16Buffer;
|
||||
|
||||
static PRUint16
|
||||
GetGlyphIndex(PRUint16 segCount, PRUint16* endCode, PRUint16* startCode,
|
||||
PRUint16* idRangeOffset, PRUint16* idDelta, PRUint8* end, PRUint16 aChar)
|
||||
@ -1151,7 +1160,21 @@ GetEncoding(const char* aFontName, nsString& aValue)
|
||||
(!strcmp(aFontName, mspgothic )) )
|
||||
return NS_ERROR_NOT_AVAILABLE; // error mean do not get a special encoding
|
||||
|
||||
nsCAutoString name(NS_LITERAL_CSTRING("encoding.") + nsDependentCString(aFontName) + NS_LITERAL_CSTRING(".ttf"));
|
||||
// XXX We need this kludge to deal with aFontName in CP949 when the locale
|
||||
// is Korean until we figure out a way to get facename in US-ASCII
|
||||
// regardless of the current locale. We have no control over what
|
||||
// EnumFontFamiliesEx() does.
|
||||
nsCAutoString name;
|
||||
if ( ::GetACP() != 949)
|
||||
name.Assign(NS_LITERAL_CSTRING("encoding.") + nsDependentCString(aFontName) + NS_LITERAL_CSTRING(".ttf"));
|
||||
else {
|
||||
PRUnichar fname[LF_FACESIZE];
|
||||
fname[0] = 0;
|
||||
MultiByteToWideChar(CP_ACP, 0, aFontName,
|
||||
strlen(aFontName) + 1, fname, sizeof(fname)/sizeof(fname[0]));
|
||||
name.Assign(NS_LITERAL_CSTRING("encoding.") + NS_ConvertUCS2toUTF8(fname) + NS_LITERAL_CSTRING(".ttf"));
|
||||
}
|
||||
|
||||
name.StripWhitespace();
|
||||
ToLowerCase(name);
|
||||
|
||||
@ -1188,13 +1211,25 @@ GetDefaultConverterForTTFSymbolEncoding(nsIUnicodeEncoder** aConverter)
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetConverter(const char* aFontName, nsIUnicodeEncoder** aConverter)
|
||||
GetConverter(const char* aFontName, nsIUnicodeEncoder** aConverter, PRBool* aIsWide = nsnull)
|
||||
{
|
||||
*aConverter = nsnull;
|
||||
|
||||
nsAutoString value;
|
||||
nsresult rv = GetEncoding(aFontName, value);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// The encoding name of a wide NonUnicode font in fontEncoding.properties
|
||||
// has '.wide' suffix which has to be removed to get the converter
|
||||
// for the encoding.
|
||||
if (Substring(value, value.Length() - 5, 5) == (NS_LITERAL_STRING(".wide"))) {
|
||||
value.Truncate(value.Length()-5);
|
||||
if (aIsWide)
|
||||
*aIsWide = PR_TRUE;
|
||||
}
|
||||
else
|
||||
if (aIsWide)
|
||||
*aIsWide = PR_FALSE;
|
||||
|
||||
return GetConverterCommon(value, aConverter);
|
||||
}
|
||||
|
||||
@ -1216,6 +1251,36 @@ GetCCMapThroughConverter(const char* aFontName)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
ConvertUnicodeToGlyph(const PRUnichar* aSrc, PRInt32 aSrcLength,
|
||||
PRInt32& aDestLength, nsIUnicodeEncoder* aConverter,
|
||||
PRBool aIsWide, nsAutoCharBuffer& aResult)
|
||||
{
|
||||
if (aIsWide &&
|
||||
NS_FAILED(aConverter->GetMaxLength(aSrc, aSrcLength, &aDestLength))) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
char* str = aResult.GetArray(aDestLength);
|
||||
if (!str) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
aConverter->Convert(aSrc, &aSrcLength, str, &aDestLength);
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
// Convert BE UCS2 to LE UCS2 for 'wide' fonts
|
||||
if (aIsWide) {
|
||||
char* pstr = str;
|
||||
while (pstr < str + aDestLength) {
|
||||
PRUint8 tmp = pstr[0];
|
||||
pstr[0] = pstr[1];
|
||||
pstr[1] = tmp;
|
||||
pstr += 2; // swap every two bytes
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsFontInfo : public PLHashEntry
|
||||
{
|
||||
public:
|
||||
@ -1645,17 +1710,16 @@ nsFontMetricsWin::GetCCMAP(HDC aDC, const char* aShortName, eFontType* aFontType
|
||||
// variable, and this is the first call, the function will cache
|
||||
// the CMAP in the gFontMaps hash table, and returns its location, hence
|
||||
// the caller can re-use the cached value in subsequent calls.
|
||||
static PRUint16*
|
||||
GetGlyphIndices(HDC aDC,
|
||||
nsCharacterMap** aCMAP,
|
||||
const PRUnichar* aString,
|
||||
PRUint32 aLength,
|
||||
PRUint16* aBuffer,
|
||||
PRUint32 aBufferLength)
|
||||
static nsresult
|
||||
GetGlyphIndices(HDC aDC,
|
||||
nsCharacterMap** aCMAP,
|
||||
const PRUnichar* aString,
|
||||
PRUint32 aLength,
|
||||
nsAutoChar16Buffer& aResult)
|
||||
{
|
||||
NS_ASSERTION(aString && aBuffer, "null arg");
|
||||
if (!aString || !aBuffer)
|
||||
return nsnull;
|
||||
NS_ASSERTION(aString, "null arg");
|
||||
if (!aString)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoFontDataBuffer buffer;
|
||||
PRUint8* buf = nsnull;
|
||||
@ -1674,15 +1738,15 @@ GetGlyphIndices(HDC aDC,
|
||||
|
||||
len = GetFontData(aDC, CMAP, 0, nsnull, 0);
|
||||
if ((len == GDI_ERROR) || (!len)) {
|
||||
return nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
buf = buffer.GetArray(len);
|
||||
if (!buf) {
|
||||
return nsnull;
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
DWORD newLen = GetFontData(aDC, CMAP, 0, buf, len);
|
||||
if (newLen != len) {
|
||||
return nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
PRUint8* p = buf + sizeof(PRUint16); // skip version, move to numberOfSubtables
|
||||
PRUint16 n = GET_SHORT(p);
|
||||
@ -1702,12 +1766,12 @@ GetGlyphIndices(HDC aDC,
|
||||
}
|
||||
if (i == n) {
|
||||
NS_WARNING("nsFontMetricsWin::GetGlyphIndices() called for a non-unicode font!");
|
||||
return nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
p = buf + offset;
|
||||
PRUint16 format = GET_SHORT(p);
|
||||
if (format != eTTFormat4SegmentMappingToDeltaValues) {
|
||||
return nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
PRUint8* end = buf + len;
|
||||
|
||||
@ -1772,11 +1836,9 @@ GetGlyphIndices(HDC aDC,
|
||||
PRUint16* idDelta = startCode + segCount;
|
||||
PRUint16* idRangeOffset = idDelta + segCount;
|
||||
|
||||
// if output buffer too small, allocate a bigger array -- the caller should free
|
||||
PRUint16* result = aBuffer;
|
||||
if (aLength > aBufferLength) {
|
||||
result = new PRUint16[aLength];
|
||||
if (!result) return nsnull;
|
||||
PRUint16* result = aResult.GetArray(aLength);
|
||||
if (!result) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
result[i] = GetGlyphIndex(segCount, endCode, startCode,
|
||||
@ -1784,9 +1846,9 @@ GetGlyphIndices(HDC aDC,
|
||||
aString[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
return nsnull;
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@ -1884,7 +1946,9 @@ nsGlyphAgent::GetGlyphMetrics(HDC aDC,
|
||||
// http://support.microsoft.com/support/kb/articles/Q241/3/58.ASP)
|
||||
// we will use glyph indices as a work around.
|
||||
if (0 == aGlyphIndex) { // caller doesn't know the glyph index, so find it
|
||||
GetGlyphIndices(aDC, nsnull, &aChar, 1, &aGlyphIndex, 1);
|
||||
nsAutoChar16Buffer buf;
|
||||
if (NS_SUCCEEDED(GetGlyphIndices(aDC, nsnull, &aChar, 1, buf)))
|
||||
aGlyphIndex = *(buf.GetArray());
|
||||
}
|
||||
if (0 < aGlyphIndex) {
|
||||
return GetGlyphOutlineA(aDC, aGlyphIndex, GGO_METRICS | GGO_GLYPH_INDEX, aGlyphMetrics, 0, nsnull, &mMat);
|
||||
@ -1898,6 +1962,53 @@ nsGlyphAgent::GetGlyphMetrics(HDC aDC,
|
||||
// the global glyph agent that we will be using
|
||||
nsGlyphAgent gGlyphAgent;
|
||||
|
||||
#ifdef MOZ_MATHML
|
||||
|
||||
// the common part of GetBoundingMetrics used by nsFontWinUnicode
|
||||
// and 'wide' nsFontWinNonUnicode.
|
||||
inline static nsresult
|
||||
GetBoundingMetricsCommon(HDC aDC, const PRUnichar* aString, PRUint32 aLength,
|
||||
nsBoundingMetrics& aBoundingMetrics, PRUnichar* aGlyphStr)
|
||||
{
|
||||
// measure the string
|
||||
nscoord descent;
|
||||
GLYPHMETRICS gm;
|
||||
DWORD len = gGlyphAgent.GetGlyphMetrics(aDC, aString[0], aGlyphStr[0], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
descent = -(nscoord(gm.gmptGlyphOrigin.y) - nscoord(gm.gmBlackBoxY));
|
||||
aBoundingMetrics.leftBearing = gm.gmptGlyphOrigin.x;
|
||||
aBoundingMetrics.rightBearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
|
||||
aBoundingMetrics.ascent = gm.gmptGlyphOrigin.y;
|
||||
aBoundingMetrics.descent = descent;
|
||||
aBoundingMetrics.width = gm.gmCellIncX;
|
||||
|
||||
if (1 < aLength) {
|
||||
// loop over each glyph to get the ascent and descent
|
||||
for (PRUint32 i = 1; i < aLength; ++i) {
|
||||
len = gGlyphAgent.GetGlyphMetrics(aDC, aString[i], aGlyphStr[i], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
descent = -(nscoord(gm.gmptGlyphOrigin.y) - nscoord(gm.gmBlackBoxY));
|
||||
if (aBoundingMetrics.ascent < gm.gmptGlyphOrigin.y)
|
||||
aBoundingMetrics.ascent = gm.gmptGlyphOrigin.y;
|
||||
if (aBoundingMetrics.descent < descent)
|
||||
aBoundingMetrics.descent = descent;
|
||||
}
|
||||
// get the final rightBearing and width. Possible kerning is taken into account.
|
||||
SIZE size;
|
||||
::GetTextExtentPointW(aDC, aString, aLength, &size);
|
||||
aBoundingMetrics.width = size.cx;
|
||||
aBoundingMetrics.rightBearing = size.cx - gm.gmCellIncX + gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Subclass for common unicode fonts (e.g, Times New Roman, Arial, etc.).
|
||||
// Offers the fastest rendering because no mapping table is needed (here,
|
||||
@ -1929,16 +2040,21 @@ private:
|
||||
PRBool mUnderlinedOrStrikeOut;
|
||||
};
|
||||
|
||||
// Subclass for non-unicode fonts that need a mapping table and uses
|
||||
// 'A'nsi functions (ExtTextOutA, GetTextExtentPoint32A) after
|
||||
// converting unicode code points to font's encoding indices. (A slight
|
||||
// overhead arises from this conversion.)
|
||||
// Subclass for non-unicode fonts that need a mapping table. 'Narrow'
|
||||
// ones use 'A'nsi functions (ExtTextOutA, GetTextExtentPoint32A) after
|
||||
// converting unicode code points to font's encoding indices while
|
||||
// 'wide' ones use 'W' functions (ExtTextOutW, GetTextExtentPoint32W).
|
||||
// (A slight overhead arises from this conversion.)
|
||||
// NOTE: This subclass also handles some fonts that claim to be
|
||||
// unicode, but need a converter.
|
||||
// unicode, but need a converter. Converter used for 'wide' fonts
|
||||
// among them is assumed to return the result in UCS2(BE) corresponding
|
||||
// to pseudo-Unicode code points used as 'glyph indices'(different from
|
||||
// genuine internal glyph indices used by a font) of non-Unicode
|
||||
// fonts claiming to be Unicode fonts.
|
||||
class nsFontWinNonUnicode : public nsFontWin
|
||||
{
|
||||
public:
|
||||
nsFontWinNonUnicode(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap, nsIUnicodeEncoder* aConverter);
|
||||
nsFontWinNonUnicode(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap, nsIUnicodeEncoder* aConverter, PRBool aIsWide = PR_FALSE);
|
||||
virtual ~nsFontWinNonUnicode();
|
||||
|
||||
virtual PRInt32 GetWidth(HDC aDC, const PRUnichar* aString, PRUint32 aLength);
|
||||
@ -1957,6 +2073,7 @@ public:
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIUnicodeEncoder> mConverter;
|
||||
PRBool mIsWide;
|
||||
};
|
||||
|
||||
void
|
||||
@ -2096,8 +2213,9 @@ nsFontMetricsWin::LoadFont(HDC aDC, nsString* aName)
|
||||
}
|
||||
else if (eFontType_NonUnicode == fontType) {
|
||||
nsCOMPtr<nsIUnicodeEncoder> converter;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter))))
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, ccmap, converter);
|
||||
PRBool isWide;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter), &isWide)))
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, ccmap, converter, isWide);
|
||||
else if (mFont.familyNameQuirks)
|
||||
if (NS_SUCCEEDED(GetDefaultConverterForTTFSymbolEncoding(getter_AddRefs(converter))))
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, ccmap, converter);
|
||||
@ -2132,8 +2250,9 @@ nsFontMetricsWin::LoadGlobalFont(HDC aDC, nsGlobalFont* aGlobalFont)
|
||||
}
|
||||
else if (eFontType_NonUnicode == aGlobalFont->fonttype) {
|
||||
nsCOMPtr<nsIUnicodeEncoder> converter;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter)))) {
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, aGlobalFont->ccmap, converter);
|
||||
PRBool isWide;
|
||||
if (NS_SUCCEEDED(GetConverter(logFont.lfFaceName, getter_AddRefs(converter), &isWide))) {
|
||||
font = new nsFontWinNonUnicode(&logFont, hfont, aGlobalFont->ccmap, converter, isWide);
|
||||
}
|
||||
}
|
||||
if (font) {
|
||||
@ -3774,8 +3893,7 @@ nsFontWinUnicode::GetBoundingMetrics(HDC aDC,
|
||||
nsBoundingMetrics& aBoundingMetrics)
|
||||
{
|
||||
aBoundingMetrics.Clear();
|
||||
PRUint16 str[CHAR_BUFFER_SIZE];
|
||||
PRUint16* pstr = (PRUint16*)&str;
|
||||
nsAutoChar16Buffer buffer;
|
||||
|
||||
// at this stage, the glyph agent should have already been initialized
|
||||
// given that it was used to compute the x-height in RealizeFont()
|
||||
@ -3783,59 +3901,13 @@ nsFontWinUnicode::GetBoundingMetrics(HDC aDC,
|
||||
if (gGlyphAgent.GetState() != eGlyphAgent_UNICODE) {
|
||||
// we are on a platform that doesn't implement GetGlyphOutlineW()
|
||||
// we need to use glyph indices
|
||||
pstr = GetGlyphIndices(aDC, &mCMAP, aString, aLength, str, CHAR_BUFFER_SIZE);
|
||||
if (!pstr) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult rv = GetGlyphIndices(aDC, &mCMAP, aString, aLength, buffer);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// measure the string
|
||||
nscoord descent;
|
||||
GLYPHMETRICS gm;
|
||||
DWORD len = gGlyphAgent.GetGlyphMetrics(aDC, aString[0], pstr[0], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
descent = -(nscoord(gm.gmptGlyphOrigin.y) - nscoord(gm.gmBlackBoxY));
|
||||
aBoundingMetrics.leftBearing = gm.gmptGlyphOrigin.x;
|
||||
aBoundingMetrics.rightBearing = gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
|
||||
aBoundingMetrics.ascent = gm.gmptGlyphOrigin.y;
|
||||
aBoundingMetrics.descent = descent;
|
||||
aBoundingMetrics.width = gm.gmCellIncX;
|
||||
|
||||
if (1 < aLength) {
|
||||
// loop over each glyph to get the ascent and descent
|
||||
for (PRUint32 i = 1; i < aLength; ++i) {
|
||||
len = gGlyphAgent.GetGlyphMetrics(aDC, aString[i], pstr[i], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
descent = -(nscoord(gm.gmptGlyphOrigin.y) - nscoord(gm.gmBlackBoxY));
|
||||
if (aBoundingMetrics.ascent < gm.gmptGlyphOrigin.y)
|
||||
aBoundingMetrics.ascent = gm.gmptGlyphOrigin.y;
|
||||
if (aBoundingMetrics.descent < descent)
|
||||
aBoundingMetrics.descent = descent;
|
||||
}
|
||||
// get the final rightBearing and width. Possible kerning is taken into account.
|
||||
SIZE size;
|
||||
::GetTextExtentPointW(aDC, aString, aLength, &size);
|
||||
aBoundingMetrics.width = size.cx;
|
||||
aBoundingMetrics.rightBearing = size.cx - gm.gmCellIncX + gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
|
||||
}
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return GetBoundingMetricsCommon(aDC, aString, aLength, aBoundingMetrics, buffer.GetArray());
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
@ -3849,9 +3921,10 @@ nsFontWinUnicode::DumpFontInfo()
|
||||
#endif
|
||||
|
||||
nsFontWinNonUnicode::nsFontWinNonUnicode(LOGFONT* aLogFont, HFONT aFont,
|
||||
PRUint16* aCCMap, nsIUnicodeEncoder* aConverter) : nsFontWin(aLogFont, aFont, aCCMap)
|
||||
PRUint16* aCCMap, nsIUnicodeEncoder* aConverter, PRBool aIsWide) : nsFontWin(aLogFont, aFont, aCCMap)
|
||||
{
|
||||
mConverter = aConverter;
|
||||
mIsWide = aIsWide;
|
||||
}
|
||||
|
||||
nsFontWinNonUnicode::~nsFontWinNonUnicode()
|
||||
@ -3862,22 +3935,19 @@ PRInt32
|
||||
nsFontWinNonUnicode::GetWidth(HDC aDC, const PRUnichar* aString,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
char str[CHAR_BUFFER_SIZE];
|
||||
char* pstr = str;
|
||||
if (aLength > CHAR_BUFFER_SIZE) {
|
||||
pstr = new char[aLength];
|
||||
if (!pstr) return 0;
|
||||
}
|
||||
nsAutoCharBuffer buffer;
|
||||
|
||||
PRInt32 srcLength = aLength, destLength = aLength;
|
||||
mConverter->Convert(aString, &srcLength, pstr, &destLength);
|
||||
PRInt32 destLength = aLength;
|
||||
if (NS_FAILED(ConvertUnicodeToGlyph(aString, aLength, destLength,
|
||||
mConverter, mIsWide, buffer))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SIZE size;
|
||||
::GetTextExtentPoint32A(aDC, pstr, aLength, &size);
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
if (!mIsWide)
|
||||
::GetTextExtentPoint32A(aDC, buffer.GetArray(), destLength, &size);
|
||||
else
|
||||
::GetTextExtentPoint32W(aDC, (PRUnichar*) buffer.GetArray(), destLength / 2, &size);
|
||||
|
||||
return size.cx;
|
||||
}
|
||||
@ -3886,21 +3956,18 @@ void
|
||||
nsFontWinNonUnicode::DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
|
||||
const PRUnichar* aString, PRUint32 aLength)
|
||||
{
|
||||
char str[CHAR_BUFFER_SIZE];
|
||||
char* pstr = str;
|
||||
if (aLength > CHAR_BUFFER_SIZE) {
|
||||
pstr = new char[aLength];
|
||||
if (!pstr) return;
|
||||
nsAutoCharBuffer buffer;
|
||||
PRInt32 destLength = aLength;
|
||||
|
||||
if (NS_FAILED(ConvertUnicodeToGlyph(aString, aLength, destLength,
|
||||
mConverter, mIsWide, buffer))) {
|
||||
return;
|
||||
}
|
||||
|
||||
PRInt32 srcLength = aLength, destLength = aLength;
|
||||
mConverter->Convert(aString, &srcLength, pstr, &destLength);
|
||||
|
||||
::ExtTextOutA(aDC, aX, aY, 0, NULL, pstr, aLength, NULL);
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
if (!mIsWide)
|
||||
::ExtTextOutA(aDC, aX, aY, 0, NULL, buffer.GetArray(), aLength, NULL);
|
||||
else
|
||||
::ExtTextOutW(aDC, aX, aY, 0, NULL, (PRUnichar*) buffer.GetArray(), destLength / 2, NULL);
|
||||
}
|
||||
|
||||
#ifdef MOZ_MATHML
|
||||
@ -3911,24 +3978,42 @@ nsFontWinNonUnicode::GetBoundingMetrics(HDC aDC,
|
||||
nsBoundingMetrics& aBoundingMetrics)
|
||||
{
|
||||
aBoundingMetrics.Clear();
|
||||
char str[CHAR_BUFFER_SIZE];
|
||||
char* pstr = str;
|
||||
if (aLength > CHAR_BUFFER_SIZE) {
|
||||
pstr = new char[aLength];
|
||||
if (!pstr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
nsAutoCharBuffer buffer;
|
||||
PRInt32 destLength = aLength;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRInt32 srcLength = aLength, destLength = aLength;
|
||||
mConverter->Convert(aString, &srcLength, pstr, &destLength);
|
||||
rv = ConvertUnicodeToGlyph(aString, aLength, destLength, mConverter,
|
||||
mIsWide, buffer);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (mIsWide) {
|
||||
nsAutoChar16Buffer buf;
|
||||
// at this stage, the glyph agent should have already been initialized
|
||||
// given that it was used to compute the x-height in RealizeFont()
|
||||
NS_ASSERTION(gGlyphAgent.GetState() != eGlyphAgent_UNKNOWN, "Glyph agent is not yet initialized");
|
||||
if (gGlyphAgent.GetState() != eGlyphAgent_UNICODE) {
|
||||
// we are on a platform that doesn't implement GetGlyphOutlineW()
|
||||
// we need to use glyph indices
|
||||
rv = GetGlyphIndices(aDC, &mCMAP, (PRUint16*) buffer.GetArray(), destLength / 2, buf);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// buffer.mBuffer is now a pseudo-Unicode string so that we can use
|
||||
// GetBoundingMetricsCommon() also used by nsFontWinUnicode.
|
||||
return GetBoundingMetricsCommon(aDC, (PRUint16*) buffer.GetArray(),
|
||||
destLength / 2, aBoundingMetrics, buf.GetArray());
|
||||
|
||||
}
|
||||
|
||||
// measure the string
|
||||
nscoord descent;
|
||||
GLYPHMETRICS gm;
|
||||
char* pstr = buffer.GetArray();
|
||||
DWORD len = gGlyphAgent.GetGlyphMetrics(aDC, PRUint8(pstr[0]), &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -3945,9 +4030,6 @@ nsFontWinNonUnicode::GetBoundingMetrics(HDC aDC,
|
||||
for (PRUint32 i = 1; i < aLength; ++i) {
|
||||
len = gGlyphAgent.GetGlyphMetrics(aDC, PRUint8(pstr[i]), &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
@ -3964,10 +4046,6 @@ nsFontWinNonUnicode::GetBoundingMetrics(HDC aDC,
|
||||
aBoundingMetrics.rightBearing = size.cx - gm.gmCellIncX + gm.gmBlackBoxX;
|
||||
}
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3979,7 +4057,7 @@ nsFontWinNonUnicode::DumpFontInfo()
|
||||
printf("FontType: nsFontWinNonUnicode\n");
|
||||
}
|
||||
#endif // NS_DEBUG
|
||||
#endif
|
||||
#endif // MOZ_MATHML
|
||||
|
||||
nsFontWinSubstitute::nsFontWinSubstitute(LOGFONT* aLogFont, HFONT aFont,
|
||||
PRUint16* aCCMap, PRBool aDisplayUnicode) : nsFontWin(aLogFont, aFont, aCCMap)
|
||||
@ -3992,13 +4070,12 @@ nsFontWinSubstitute::~nsFontWinSubstitute()
|
||||
{
|
||||
}
|
||||
|
||||
static PRUnichar*
|
||||
SubstituteChars(PRBool aDisplayUnicode,
|
||||
const PRUnichar* aString,
|
||||
PRUint32 aLength,
|
||||
PRUnichar* aBuffer,
|
||||
PRUint32 aBufferLength,
|
||||
PRUint32* aCount)
|
||||
static nsresult
|
||||
SubstituteChars(PRBool aDisplayUnicode,
|
||||
const PRUnichar* aString,
|
||||
PRUint32 aLength,
|
||||
nsAutoChar16Buffer& aResult,
|
||||
PRUint32* aCount)
|
||||
{
|
||||
if (!gFontSubstituteConverter) {
|
||||
nsComponentManager::
|
||||
@ -4023,20 +4100,17 @@ SubstituteChars(PRBool aDisplayUnicode,
|
||||
}
|
||||
|
||||
// do the transliteration if we have a converter
|
||||
PRUnichar* result = aBuffer;
|
||||
PRUnichar* result;
|
||||
if (gFontSubstituteConverter) {
|
||||
char* conv = nsnull;
|
||||
nsAutoString tmp(aString, aLength); // we need to pass a null-terminated string
|
||||
gFontSubstituteConverter->Convert(tmp.get(), &conv);
|
||||
if (conv) {
|
||||
*aCount = strlen(conv);
|
||||
if (*aCount > aBufferLength) {
|
||||
// allocate a bigger array that the caller should free
|
||||
result = new PRUnichar[*aCount];
|
||||
if (!result) {
|
||||
nsMemory::Free(conv);
|
||||
return nsnull;
|
||||
}
|
||||
result = aResult.GetArray(*aCount);
|
||||
if (!result) {
|
||||
nsMemory::Free(conv);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
PRUnichar* u = result;
|
||||
char* c = conv;
|
||||
@ -4044,38 +4118,30 @@ SubstituteChars(PRBool aDisplayUnicode,
|
||||
*u = *c;
|
||||
}
|
||||
nsMemory::Free(conv);
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// we reach here if we couldn't transliterate, so fallback to question marks
|
||||
if (aLength > aBufferLength) {
|
||||
// allocate a bigger array that the caller should free
|
||||
result = new PRUnichar[aLength];
|
||||
if (!result) return nsnull;
|
||||
}
|
||||
result = aResult.GetArray(aLength);
|
||||
if (!result) return NS_ERROR_OUT_OF_MEMORY;
|
||||
for (PRUint32 i = 0; i < aLength; i++) {
|
||||
result[i] = NS_REPLACEMENT_CHAR;
|
||||
}
|
||||
*aCount = aLength;
|
||||
return result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsFontWinSubstitute::GetWidth(HDC aDC, const PRUnichar* aString,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
PRUnichar str[CHAR_BUFFER_SIZE];
|
||||
PRUnichar* pstr = SubstituteChars(mDisplayUnicode,
|
||||
aString, aLength, str, CHAR_BUFFER_SIZE, &aLength);
|
||||
if (!pstr || !aLength) return 0;
|
||||
nsAutoChar16Buffer buffer;
|
||||
nsresult rv = SubstituteChars(PR_FALSE, aString, aLength, buffer, &aLength);
|
||||
if (NS_FAILED(rv) || !aLength) return 0;
|
||||
|
||||
SIZE size;
|
||||
::GetTextExtentPoint32W(aDC, pstr, aLength, &size);
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
::GetTextExtentPoint32W(aDC, buffer.GetArray(), aLength, &size);
|
||||
|
||||
return size.cx;
|
||||
}
|
||||
@ -4084,16 +4150,11 @@ void
|
||||
nsFontWinSubstitute::DrawString(HDC aDC, PRInt32 aX, PRInt32 aY,
|
||||
const PRUnichar* aString, PRUint32 aLength)
|
||||
{
|
||||
PRUnichar str[CHAR_BUFFER_SIZE];
|
||||
PRUnichar* pstr = SubstituteChars(mDisplayUnicode,
|
||||
aString, aLength, str, CHAR_BUFFER_SIZE, &aLength);
|
||||
if (!pstr || !aLength) return;
|
||||
nsAutoChar16Buffer buffer;
|
||||
nsresult rv = SubstituteChars(PR_FALSE, aString, aLength, buffer, &aLength);
|
||||
if (NS_FAILED(rv) || !aLength) return;
|
||||
|
||||
::ExtTextOutW(aDC, aX, aY, 0, NULL, pstr, aLength, NULL);
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
::ExtTextOutW(aDC, aX, aY, 0, NULL, buffer.GetArray(), aLength, NULL);
|
||||
}
|
||||
|
||||
#ifdef MOZ_MATHML
|
||||
@ -4104,13 +4165,13 @@ nsFontWinSubstitute::GetBoundingMetrics(HDC aDC,
|
||||
nsBoundingMetrics& aBoundingMetrics)
|
||||
{
|
||||
aBoundingMetrics.Clear();
|
||||
PRUnichar str[CHAR_BUFFER_SIZE];
|
||||
PRUnichar* pstr = SubstituteChars(mDisplayUnicode,
|
||||
aString, aLength, str, CHAR_BUFFER_SIZE, &aLength);
|
||||
if (!pstr) return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsAutoChar16Buffer buffer;
|
||||
nsresult rv = SubstituteChars(mDisplayUnicode, aString, aLength, buffer, &aLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!aLength) return NS_OK;
|
||||
PRUint16 s[CHAR_BUFFER_SIZE];
|
||||
PRUint16* ps = (PRUint16*)&s;
|
||||
nsAutoChar16Buffer buf;
|
||||
|
||||
// at this stage, the glyph agent should have already been initialized
|
||||
// given that it was used to compute the x-height in RealizeFont()
|
||||
@ -4118,26 +4179,20 @@ nsFontWinSubstitute::GetBoundingMetrics(HDC aDC,
|
||||
if (gGlyphAgent.GetState() != eGlyphAgent_UNICODE) {
|
||||
// we are on a platform that doesn't implement GetGlyphOutlineW()
|
||||
// we better get all glyph indices in one swoop
|
||||
ps = GetGlyphIndices(aDC, &mCMAP, pstr, aLength, s, CHAR_BUFFER_SIZE);
|
||||
if (!ps) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
rv = GetGlyphIndices(aDC, &mCMAP, buffer.GetArray(), aLength, buf);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
PRUnichar* pstr = buffer.GetArray();
|
||||
PRUnichar* ps = buf.GetArray();
|
||||
|
||||
// measure the string
|
||||
nscoord descent;
|
||||
GLYPHMETRICS gm;
|
||||
DWORD len = gGlyphAgent.GetGlyphMetrics(aDC, pstr[0], ps[0], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
if (ps != s) {
|
||||
delete[] ps;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -4154,12 +4209,6 @@ nsFontWinSubstitute::GetBoundingMetrics(HDC aDC,
|
||||
for (PRUint32 i = 1; i < aLength; ++i) {
|
||||
len = gGlyphAgent.GetGlyphMetrics(aDC, pstr[i], ps[i], &gm);
|
||||
if (GDI_ERROR == len) {
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
if (ps != s) {
|
||||
delete[] ps;
|
||||
}
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
// flip sign of descent for cross-platform compatibility
|
||||
@ -4177,13 +4226,6 @@ nsFontWinSubstitute::GetBoundingMetrics(HDC aDC,
|
||||
aBoundingMetrics.rightBearing = size.cx - gm.gmCellIncX + gm.gmptGlyphOrigin.x + gm.gmBlackBoxX;
|
||||
}
|
||||
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
if (ps != s) {
|
||||
delete[] ps;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -4523,10 +4565,9 @@ void
|
||||
nsFontSubsetSubstitute::Convert(const PRUnichar* aString, PRUint32 aLength,
|
||||
char** aResult, int* aResultLength)
|
||||
{
|
||||
PRUnichar str[CHAR_BUFFER_SIZE];
|
||||
PRUnichar* pstr = SubstituteChars(PR_FALSE,
|
||||
aString, aLength, str, CHAR_BUFFER_SIZE, &aLength);
|
||||
if (!pstr) {
|
||||
nsAutoChar16Buffer buffer;
|
||||
nsresult rv = SubstituteChars(PR_FALSE, aString, aLength, buffer, &aLength);
|
||||
if (NS_FAILED(rv)) {
|
||||
// this is the out-of-memory error case
|
||||
*aResult = nsnull;
|
||||
*aResultLength = 0;
|
||||
@ -4538,10 +4579,7 @@ nsFontSubsetSubstitute::Convert(const PRUnichar* aString, PRUint32 aLength,
|
||||
*aResultLength = 0;
|
||||
return;
|
||||
}
|
||||
nsFontSubset::Convert(pstr, aLength, aResult, aResultLength);
|
||||
if (pstr != str) {
|
||||
delete[] pstr;
|
||||
}
|
||||
nsFontSubset::Convert(buffer.GetArray(), aLength, aResult, aResultLength);
|
||||
}
|
||||
|
||||
nsFontWinA::nsFontWinA(LOGFONT* aLogFont, HFONT aFont, PRUint16* aCCMap)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user