[GFX] GetBoundingMetrics() added in nsIRenderingContext and associated changes elsewhere (patform-specific) to support its implementation. Fixes for existing bugs discovered while doing the implementation. Details for gtk: Shyjan Mahamud mahamud@cs.cmu.edu's changes to enable the symbol font on Linux, as well as the fix for the CSS font-family bug, and the computation of the bounding metrics. review: Erik, rbs.

This commit is contained in:
rbs%maths.uq.edu.au 1999-11-11 04:16:54 +00:00
Родитель 907d400e00
Коммит 3d4258be6a
4 изменённых файлов: 298 добавлений и 8 удалений

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

@ -812,6 +812,12 @@ static PLHashTable* gFamilyNames = nsnull;
static nsFontFamilyName gFamilyNameTable[] =
{
#ifdef MOZ_MATHML
{ "cmex", "cmex10" },
{ "cmsy", "cmsy10" },
{ "-moz-math-text", "times" },
{ "-moz-math-symbol", "symbol" },
#endif
{ "arial", "helvetica" },
{ "courier new", "courier" },
{ "times new roman", "times" },
@ -859,7 +865,13 @@ static nsFontPropertyName gStretchNames[] =
};
static PLHashTable* gCharSets = nsnull;
#ifdef MOZ_MATHML
static PLHashTable* gSpecialCharSets = nsnull;
#endif
#ifdef MOZ_MATHML
static nsFontCharSetInfo Special = { nsnull };
#endif
static nsFontCharSetInfo Ignore = { nsnull };
static gint
@ -1028,6 +1040,14 @@ static nsFontCharSetInfo X11Johab =
static nsFontCharSetInfo ISO106461 =
{ nsnull, ISO10646Convert, 1 };
#ifdef MOZ_MATHML
static nsFontCharSetInfo AdobeSymbol =
{ "Adobe-Symbol-Encoding", SingleByteConvert, 0 };
static nsFontCharSetInfo CMCMEX =
{ "x-cm-cmex", SingleByteConvert, 0 };
static nsFontCharSetInfo CMCMSY =
{ "x-cm-cmsy", SingleByteConvert, 0 };
#endif
/*
* Normally, the charset of an X font can be determined simply by looking at
@ -1059,7 +1079,9 @@ static nsFontCharSetMap gCharSetMap[] =
{
{ "-ascii", &Ignore },
{ "-ibm pc", &Ignore },
{ "adobe-fontspecific", &Ignore },
#ifdef MOZ_MATHML
{ "adobe-fontspecific", &Special },
#endif
{ "cns11643.1986-1", &CNS116431 },
{ "cns11643.1986-2", &CNS116432 },
{ "cns11643.1992-1", &CNS116431 },
@ -1140,6 +1162,17 @@ static nsFontCharSetMap gCharSetMap[] =
{ nsnull, nsnull }
};
#ifdef MOZ_MATHML
static nsFontCharSetMap gSpecialCharSetMap[] =
{
{ "symbol-adobe-fontspecific", &AdobeSymbol },
{ "cmex10-adobe-fontspecific", &CMCMEX },
{ "cmsy10-adobe-fontspecific", &CMCMSY },
{ nsnull, nsnull }
};
#endif
#undef DEBUG_DUMP_TREE
#ifdef DEBUG_DUMP_TREE
@ -1317,8 +1350,8 @@ PickASizeAndLoad(nsFontSearch* aSearch, nsFontStretch* aStretch,
nsFontCharSet* aCharSet)
{
nsFontGTK* s = nsnull;
nsFontGTK* begin;
nsFontGTK* end;
nsFontGTK* begin = nsnull;
nsFontGTK* end = nsnull;
nsFontMetricsGTK* m = aSearch->mMetrics;
int desiredSize = m->mPixelSize;
int scalable = 0;
@ -1465,6 +1498,58 @@ PickASizeAndLoad(nsFontSearch* aSearch, nsFontStretch* aStretch,
}
}
#ifdef MOZ_MATHML
// CSS font-family bug fix
// CSS font-family order is not respected without the following fix.
// The idea is to ensure that even though the character being searched
// for may not have a glyph in the current font, we need to load it anyway
// if it was one of the fonts requested in the CSS font-family property.
// Otherwise, the FindFont ('a') hack in ::Init () can disrupt the order.
// The font has been requested if (m->mFontsIndex <= m->mFontsCount) is true.
// previously we tested for !IS_REPRESENTABLE only for those cases
// where aCharSet->mInfo->mCharSet was not set since otherwise
// it was caught in SearchCharSet ().
// but now if the font requested is in CSS font-family we have disabled
// the test in SearchCharSet () and so need to test it here.
// in effect we have to test for !IS_REPRESENTABLE always now.
PRBool fontHasGlyph = IS_REPRESENTABLE(s->mMap, aSearch->mChar);
// if fontHasGlyph definitely load.
// else if font was requested in css font-family property list,
// also definitely load to repect the order in the list.
if (fontHasGlyph || (m->mFontsIndex <= m->mFontsCount)) {
if (m->mLoadedFontsCount == m->mLoadedFontsAlloc) {
int newSize;
if (m->mLoadedFontsAlloc) {
newSize = (2 * m->mLoadedFontsAlloc);
}
else {
newSize = 1;
}
nsFontGTK** newPointer = (nsFontGTK**)
PR_Realloc(m->mLoadedFonts, newSize * sizeof(nsFontGTK*));
if (newPointer) {
m->mLoadedFonts = newPointer;
m->mLoadedFontsAlloc = newSize;
}
else {
return;
}
}
m->mLoadedFonts[m->mLoadedFontsCount++] = s;
}
// need to update mFontsIndex to function correctly next time around
if (m->mFontsIndex == m->mFontsCount) {
(m->mFontsIndex)++;
}
// finally, indicate that search for the char
// has succeeded if fontHasGlyph
if (fontHasGlyph) {
aSearch->mFont = s;
}
#else /* MOZ_MATHML */
if (!aCharSet->mInfo->mCharSet) {
if (!IS_REPRESENTABLE(s->mMap, aSearch->mChar)) {
return;
@ -1491,11 +1576,14 @@ PickASizeAndLoad(nsFontSearch* aSearch, nsFontStretch* aStretch,
}
m->mLoadedFonts[m->mLoadedFontsCount++] = s;
aSearch->mFont = s;
#endif /* !MOZ_MATHML */
#ifdef REALLY_NOISY_FONTS
nsFontGTK* result = s;
for (s = begin; s < end; s++) {
printf("%d/%d ", s->mSize, s->mActualSize);
if ((begin != nsnull) && (end != nsnull)) {
for (s = begin; s < end; s++) {
printf("%d/%d ", s->mSize, s->mActualSize);
}
}
printf("%s[%s]: desired %d chose %d\n", aSearch->mFont->mName,
aSearch->mFont->mCharSetInfo->mCharSet,
@ -1786,6 +1874,7 @@ SearchCharSet(PLHashEntry* he, PRIntn i, void* arg)
nsFontCharSetInfo* charSetInfo = charSet->mInfo;
PRUint32* map = charSetInfo->mMap;
nsFontSearch* search = (nsFontSearch*) arg;
nsFontMetricsGTK* m = search->mMetrics;
PRUnichar c = search->mChar;
#ifdef REALLY_NOISY_FONTS
printf("%s: searching for character c=0x%x (%d) '%c' in %s\n",
@ -1800,12 +1889,25 @@ SearchCharSet(PLHashEntry* he, PRIntn i, void* arg)
charSetInfo->mMap = map;
SetUpFontCharSetInfo(charSetInfo);
}
if (!IS_REPRESENTABLE(map, c)) {
#ifdef MOZ_MATHML
// CSS font-family bug fix
// Check if font has been requested from CSS font-family,
// if so ignore IS_REPRESENTABLE. It gets tested again
// in PickASizeAndLoad (), see comments there.
// if font has'nt been requested, we do a redundant test here for speed.
if (m->mFontsIndex >= m->mFontsCount) {
if (!IS_REPRESENTABLE(map, c)) {
#ifdef REALLY_NOISY_FONTS
printf(" ==> character not representable, trying next character set\n");
printf(" ==> character not representable, trying next character set\n");
#endif
return HT_ENUMERATE_NEXT;
return HT_ENUMERATE_NEXT;
}
}
#else /* MOZ_MATHML */
if (!IS_REPRESENTABLE(map, c)) {
return HT_ENUMERATE_NEXT;
}
#endif /* !MOZ_MATHML */
}
TryCharSet(search, charSet);
@ -1923,6 +2025,15 @@ GetFontNames(char* aPattern)
}
nsFontCharSetInfo* charSetInfo =
(nsFontCharSetInfo*) PL_HashTableLookup(gCharSets, charSetName);
#ifdef MOZ_MATHML
// indirection for font specific charset encoding
if (charSetInfo == &Special) {
char *familyCharSetName = PR_smprintf ("%s-%s", familyName, charSetName);
charSetInfo = (nsFontCharSetInfo*) PL_HashTableLookup
(gSpecialCharSets, familyCharSetName);
PR_smprintf_free (familyCharSetName);
}
#endif
if (!charSetInfo) {
#ifdef NOISY_FONTS
printf("cannot find charset %s\n", charSetName);
@ -2136,6 +2247,17 @@ nsFontMetricsGTK::FindFont(PRUnichar aChar)
PL_HashTableAdd(gCharSets, charSetMap->mName, (void*) charSetMap->mInfo);
charSetMap++;
}
#ifdef MOZ_MATHML
gSpecialCharSets = PL_NewHashTable
(0, PL_HashString, PL_CompareStrings, NULL, NULL, NULL);
nsFontCharSetMap* specialCharSetMap = gSpecialCharSetMap;
while (specialCharSetMap->mName) {
PL_HashTableAdd (gSpecialCharSets,
specialCharSetMap->mName,
(void*) specialCharSetMap->mInfo);
specialCharSetMap++;
}
#endif
}
nsFontSearch search = { this, aChar, nsnull };
@ -2197,6 +2319,40 @@ nsFontMetricsGTK::FindFont(PRUnichar aChar)
return nsnull;
}
#ifdef MOZ_MATHML
// bounding metrics for a string
// remember returned values are not in app units
nsresult
nsFontMetricsGTK::GetBoundingMetrics (nsFontGTK* aFont,
const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics)
{
aBoundingMetrics.Clear();
if (0 < aLength) {
XChar2b buf[512]; // XXX watch buffer length !!!
gint len = aFont->mCharSetInfo->Convert(aFont->mCharSetInfo, aString, aLength,
(char*) buf, sizeof(buf));
gdk_text_extents (aFont->mFont, (char*) buf, len,
&aBoundingMetrics.leftBearing,
&aBoundingMetrics.rightBearing,
&aBoundingMetrics.width,
&aBoundingMetrics.ascent,
&aBoundingMetrics.descent);
// get italic correction
XFontStruct *fontInfo = (XFontStruct *) GDK_FONT_XFONT (aFont->mFont);
unsigned long pr = 0;
if (::XGetFontProperty(fontInfo, XA_ITALIC_ANGLE, &pr)) {
aBoundingMetrics.subItalicCorrection = (gint) pr;
aBoundingMetrics.supItalicCorrection = (gint) pr;
}
}
return NS_OK;
}
#endif
gint
nsFontMetricsGTK::GetWidth(nsFontGTK* aFont, const PRUnichar* aString,
PRUint32 aLength)

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

@ -111,6 +111,16 @@ public:
nsFontGTK* FindFont(PRUnichar aChar);
static gint GetWidth(nsFontGTK* aFont, const PRUnichar* aString,
PRUint32 aLength);
#ifdef MOZ_MATHML
// bounding metrics for a string
// remember returned values are not in app units
// - to emulate GetWidth () above
static nsresult
GetBoundingMetrics(nsFontGTK* aFont,
const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics);
#endif
static void DrawString(nsDrawingSurfaceGTK* aSurface, nsFontGTK* aFont,
nscoord aX, nscoord aY, const PRUnichar* aString,
PRUint32 aLength);

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

@ -1602,6 +1602,113 @@ NS_IMETHODIMP nsRenderingContextGTK::RetrieveCurrentNativeGraphicData(PRUint32 *
return NS_OK;
}
#ifdef MOZ_MATHML
#ifdef FONT_SWITCHING
NS_IMETHODIMP
nsRenderingContextGTK::GetBoundingMetrics(const char* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics)
{
aBoundingMetrics.Clear();
if (0 < aLength) {
g_return_val_if_fail(aString != NULL, NS_ERROR_FAILURE);
gdk_text_extents (mCurrentFont, aString, aLength,
&aBoundingMetrics.leftBearing,
&aBoundingMetrics.rightBearing,
&aBoundingMetrics.width,
&aBoundingMetrics.ascent,
&aBoundingMetrics.descent);
aBoundingMetrics.leftBearing = NSToCoordRound(aBoundingMetrics.leftBearing * mP2T);
aBoundingMetrics.rightBearing = NSToCoordRound(aBoundingMetrics.rightBearing * mP2T);
aBoundingMetrics.width = NSToCoordRound(aBoundingMetrics.width * mP2T);
aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * mP2T);
aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * mP2T);
}
return NS_OK;
}
NS_IMETHODIMP
nsRenderingContextGTK::GetBoundingMetrics(const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics,
PRInt32* aFontID)
{
aBoundingMetrics.Clear();
if (0 < aLength) {
g_return_val_if_fail(aString != NULL, NS_ERROR_FAILURE);
nsFontMetricsGTK* metrics = (nsFontMetricsGTK*) mFontMetrics;
nsFontGTK* prevFont = nsnull;
nsBoundingMetrics rawbm;
PRBool firstTime = PR_TRUE;
PRUint32 start = 0;
PRUint32 i;
for (i = 0; i < aLength; i++) {
PRUnichar c = aString[i];
nsFontGTK* currFont = nsnull;
nsFontGTK** font = metrics->mLoadedFonts;
nsFontGTK** end = &metrics->mLoadedFonts[metrics->mLoadedFontsCount];
while (font < end) {
if (IS_REPRESENTABLE((*font)->mMap, c)) {
currFont = *font;
goto FoundFont; // for speed -- avoid "if" statement
}
font++;
}
currFont = metrics->FindFont(c);
FoundFont:
// XXX avoid this test by duplicating code -- erik
if (prevFont) {
if (currFont != prevFont) {
nsFontMetricsGTK::GetBoundingMetrics(prevFont,
(const PRUnichar*) &aString[start],
i - start, rawbm);
if (firstTime) {
firstTime = PR_FALSE;
aBoundingMetrics = rawbm;
}
else {
aBoundingMetrics += rawbm;
}
prevFont = currFont;
start = i;
}
}
else {
prevFont = currFont;
start = i;
}
}
if (prevFont) {
nsFontMetricsGTK::GetBoundingMetrics(prevFont,
(const PRUnichar*) &aString[start],
i - start, rawbm);
if (firstTime) {
aBoundingMetrics = rawbm;
}
else {
aBoundingMetrics += rawbm;
}
}
// convert to app units
aBoundingMetrics.leftBearing = NSToCoordRound(aBoundingMetrics.leftBearing * mP2T);
aBoundingMetrics.rightBearing = NSToCoordRound(aBoundingMetrics.rightBearing * mP2T);
aBoundingMetrics.width = NSToCoordRound(aBoundingMetrics.width * mP2T);
aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * mP2T);
aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * mP2T);
}
if (nsnull != aFontID)
*aFontID = 0;
return NS_OK;
}
#endif /* FONT_SWITCHING */
#endif /* MOZ_MATHML */
NS_IMETHODIMP nsRenderingContextGTK::ConditionRect( nscoord &x, nscoord &y, nscoord &w, nscoord &h )
{
if ( y < -32766 ) {

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

@ -158,6 +158,23 @@ public:
const nsRect &aDestBounds, PRUint32 aCopyFlags);
NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd);
#ifdef MOZ_MATHML
/**
* Returns metrics (in app units) of an 8-bit character string
*/
NS_IMETHOD GetBoundingMetrics(const char* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics);
/**
* Returns metrics (in app units) of a Unicode character string
*/
NS_IMETHOD GetBoundingMetrics(const PRUnichar* aString,
PRUint32 aLength,
nsBoundingMetrics& aBoundingMetrics,
PRInt32* aFontID = nsnull);
#endif /* MOZ_MATHML */
//locals
NS_IMETHOD CommonInit();