--- mozilla/gfx/src/gtk/nsFontMetricsPango.h.pango-underline 2005-05-02 22:48:30.000000000 +0200 +++ mozilla/gfx/src/gtk/nsFontMetricsPango.h 2006-01-05 11:55:19.000000000 +0100 @@ -90,13 +90,23 @@ { aHeight = mMaxHeight; return NS_OK; }; +#ifdef FONT_LEADING_APIS_V2 + NS_IMETHOD GetInternalLeading (nscoord &aLeading) + { aLeading = mInternalLeading; + return NS_OK; }; + + NS_IMETHOD GetExternalLeading (nscoord &aLeading) + { aLeading = mExternalLeading; + return NS_OK; }; +#else NS_IMETHOD GetNormalLineHeight (nscoord &aHeight) - { aHeight = mEmHeight + mLeading; + { aHeight = mEmHeight + mInternalLeading; return NS_OK; }; NS_IMETHOD GetLeading (nscoord &aLeading) - { aLeading = mLeading; + { aLeading = mInternalLeading; return NS_OK; }; +#endif NS_IMETHOD GetEmHeight (nscoord &aHeight) { aHeight = mEmHeight; @@ -252,7 +262,8 @@ nscoord mUnderlineOffset; nscoord mUnderlineSize; nscoord mMaxHeight; - nscoord mLeading; + nscoord mInternalLeading; + nscoord mExternalLeading; nscoord mEmHeight; nscoord mEmAscent; nscoord mEmDescent; --- mozilla/gfx/src/gtk/nsFontMetricsPango.cpp.pango-underline 2006-01-05 11:55:19.000000000 +0100 +++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 2006-01-05 18:23:12.000000000 +0100 @@ -68,6 +68,12 @@ static PRLogModuleInfo *gPangoFontLog; static int gNumInstances; +static PRBool gDoingLineheightFixup = PR_FALSE; +static nsIAtom* gJA = nsnull; +static nsIAtom* gKO = nsnull; +static nsIAtom* gZHCN = nsnull; +static nsIAtom* gZHTW = nsnull; +static nsIAtom* gZHHK = nsnull; // Defines @@ -158,6 +164,10 @@ NS_IMPL_ISUPPORTS1(nsFontMetricsPango, nsIFontMetrics) +#define IsCJKLangGroupAtom(a) ((a) == gJA || (a) == gKO || (a) == gZHCN || \ + (a) == gZHTW || (a) == gZHHK) + + // nsIFontMetrics impl NS_IMETHODIMP @@ -184,6 +194,41 @@ prefService = do_GetService(NS_PREF_CONTRACTID); if (!prefService) return NS_ERROR_FAILURE; + + // if we do not include/compensate external leading in calculating normal + // line height, we don't set gDoingLineheightFixup either to keep old behavior. + // These code should be eliminated in future when we choose to stay with + // one normal lineheight calculation method. + PRInt32 intPref; + if (NS_SUCCEEDED(prefService->GetIntPref( + "browser.display.normal_lineheight_calc_control", &intPref))) + gDoingLineheightFixup = (intPref != 0); + + gJA = NS_NewAtom("ja"); + if (!gJA) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + gKO = NS_NewAtom("ko"); + if (!gKO) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + gZHCN = NS_NewAtom("zh-CN"); + if (!gZHCN) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + gZHTW = NS_NewAtom("zh-TW"); + if (!gZHTW) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } + gZHHK = NS_NewAtom("zh-HK"); + if (!gZHHK) { + FreeGlobals(); + return NS_ERROR_OUT_OF_MEMORY; + } nsXPIDLCString value; const char* langGroup; @@ -301,19 +346,26 @@ val = -MOZ_FT_TRUNC(face->size->metrics.descender); mMaxDescent = NSToIntRound(val * f); - nscoord lineHeight = mMaxAscent + mMaxDescent; + // mMaxHeight (needs ascent and descent) + mMaxHeight = mMaxAscent + mMaxDescent; - // mLeading (needs ascent and descent and EM height) - if (lineHeight > mEmHeight) - mLeading = lineHeight - mEmHeight; - else - mLeading = 0; + // mExternalLeading (needs MaxHeight and base2base dist. (xftFont->height)) + val = MOZ_FT_TRUNC (face->size->metrics.height); + if (NSToIntRound (val * f) > mMaxHeight) { + mExternalLeading = NSToIntRound (val * f) - mMaxHeight; + } + else { + mExternalLeading = 0; + } - // mMaxHeight (needs ascent and descent) - mMaxHeight = lineHeight; + // mInternalLeading (needs ascent, descent and EM height) + if (mMaxHeight > mEmHeight) + mInternalLeading = mMaxHeight - mEmHeight; + else + mInternalLeading = 0; // mEmAscent (needs maxascent, EM height, ascent and descent) - mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight); + mEmAscent = nscoord(mMaxAscent * mEmHeight / mMaxHeight); // mEmDescent (needs EM height and EM ascent mEmDescent = mEmHeight - mEmAscent; @@ -354,29 +406,99 @@ mXHeight = nscoord(((float)mMaxAscent) * 0.56 * f); } - // mUnderlineOffset (offset for underlines) - val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position, - face->size->metrics.y_scale); - if (val) { - mUnderlineOffset = NSToIntRound(val * f); + // mUnderlineSize (thickness of an underline) + float rawUlSize = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness, + face->size->metrics.y_scale); + if (rawUlSize) { + mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(rawUlSize * f))); } else { - mUnderlineOffset = - -NSToIntRound(PR_MAX(1, floor(0.1 * - MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f); + val = MOZ_FT_TRUNC(face->size->metrics.height); + mUnderlineSize = + NSToIntRound(PR_MAX(1, floor(0.05 * val + 0.5)) * f); } - // mUnderlineSize (thickness of an underline) - val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness, - face->size->metrics.y_scale); - if (val) { - mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f))); + // mUnderlineOffset (offset for underlines) + float rawUlOffset = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position, + face->size->metrics.y_scale); + /*if (PR_LOG_TEST(gXftFontLoad, PR_LOG_DEBUG)) { + printf ("raw underline pos=%d, y_scale=%ld, scaled=%f\n", + face->underline_position, long(face->size->metrics.y_scale), rawUlOffset); + }*/ + + nscoord RaiseBaseline = 0; + if (gDoingLineheightFixup && IsCJKLangGroupAtom(mLangGroup.get())) { + nscoord Leading = mInternalLeading + mExternalLeading; + val = MOZ_FT_TRUNC (face->size->metrics.height); + nscoord rawOffset = rawUlOffset ? NSToIntRound(rawUlOffset * f) : + -NSToIntRound(PR_MAX(1, floor(0.1 * val + 0.5)) * f); + nscoord expectOffset = PR_MAX(2 * mUnderlineSize, -rawOffset); + + if (mEmDescent >= (mUnderlineSize + expectOffset)) { + mUnderlineOffset = -expectOffset; + } + else if (mMaxDescent >= (mUnderlineSize + expectOffset)) { + mUnderlineOffset = -expectOffset; + } + else if (mMaxDescent >= 2 * mUnderlineSize + nscoord(f)) { + mUnderlineOffset = -mUnderlineSize - nscoord(f); + } + else if (Leading >= (mUnderlineSize + expectOffset)) { //nead raise baseline + RaiseBaseline = (mUnderlineSize + expectOffset) - mEmDescent; + RaiseBaseline = (RaiseBaseline + nscoord(f) - 1)/nscoord(f); + mUnderlineOffset = -expectOffset; + } + else { + mExternalLeading += (mUnderlineSize + expectOffset) - Leading; + mMaxDescent += (mUnderlineSize + expectOffset) - Leading; + mMaxHeight = mMaxAscent + mMaxDescent; + val = MOZ_FT_TRUNC (face->size->metrics.height); + if (NSToIntRound (val * f) > mMaxHeight) { + mExternalLeading = NSToIntRound (val * f) - mMaxHeight; + } + else { + mExternalLeading = 0; + } + if (mMaxHeight > mEmHeight) + mInternalLeading = mMaxHeight - mEmHeight; + else + mInternalLeading = 0; + mEmAscent = nscoord(mMaxAscent * mEmHeight / mMaxHeight); + mEmDescent = mEmHeight - mEmAscent; + mUnderlineOffset = -expectOffset; + } + if (mEmDescent + mUnderlineOffset >= 2*mUnderlineSize) + mUnderlineOffset -= mUnderlineSize; } else { - mUnderlineSize = - NSToIntRound(PR_MAX(1, - floor(0.05 * MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f); + if (rawUlOffset) { + mUnderlineOffset = NSToIntRound(rawUlOffset * f); + } + else { + val = MOZ_FT_TRUNC (face->size->metrics.height); + mUnderlineOffset = + -NSToIntRound(PR_MAX(1, floor(0.1 * val + 0.5)) * f); + } } + // The underline position specified in CJK fonts works well for + // Latin letters, but doesn't work as well for CJK characters (see + // bug 218032). For CJK characters, the descent position is preferred. + // However, we cannot do the adjustment per character basis + // (that would results in a 'zigzaged' undeline). In addition, + // the underline position specified in non-CJK fonts works well + // for all glyphs in them so that we should leave it alone. + // Therefore, the underline position is adjusted only if the langGroup + // of a font is CJK and enough space available for the adjustment. + + // Baseline need to be raised so that underline will stay + // within boundary. + + if (RaiseBaseline) { + mEmAscent -= RaiseBaseline; + mEmDescent += RaiseBaseline; + mMaxAscent -= RaiseBaseline; + mMaxDescent += RaiseBaseline; + } // mSuperscriptOffset if (os2 && os2->ySuperscriptYOffset) { @@ -1564,6 +1686,11 @@ void FreeGlobals(void) { + NS_IF_RELEASE(gJA); + NS_IF_RELEASE(gKO); + NS_IF_RELEASE(gZHCN); + NS_IF_RELEASE(gZHTW); + NS_IF_RELEASE(gZHHK); } /* static */