зеркало из https://github.com/mozilla/pjs.git
[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:
Родитель
907d400e00
Коммит
3d4258be6a
|
@ -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,12 +1576,15 @@ PickASizeAndLoad(nsFontSearch* aSearch, nsFontStretch* aStretch,
|
|||
}
|
||||
m->mLoadedFonts[m->mLoadedFontsCount++] = s;
|
||||
aSearch->mFont = s;
|
||||
#endif /* !MOZ_MATHML */
|
||||
|
||||
#ifdef REALLY_NOISY_FONTS
|
||||
nsFontGTK* result = s;
|
||||
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,
|
||||
desiredSize, result->mActualSize);
|
||||
|
@ -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,6 +1889,13 @@ SearchCharSet(PLHashEntry* he, PRIntn i, void* arg)
|
|||
charSetInfo->mMap = map;
|
||||
SetUpFontCharSetInfo(charSetInfo);
|
||||
}
|
||||
#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");
|
||||
|
@ -1807,6 +1903,12 @@ SearchCharSet(PLHashEntry* he, PRIntn i, void* arg)
|
|||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
}
|
||||
#else /* MOZ_MATHML */
|
||||
if (!IS_REPRESENTABLE(map, c)) {
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
#endif /* !MOZ_MATHML */
|
||||
}
|
||||
|
||||
TryCharSet(search, charSet);
|
||||
if (search->mFont) {
|
||||
|
@ -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();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче