From de4ecba1c8943051411d25472491b635b4305054 Mon Sep 17 00:00:00 2001 From: "sfraser%netscape.com" Date: Fri, 26 May 2000 22:03:33 +0000 Subject: [PATCH] Fixes for 39811, 36417 -- bad text layout on Mac, due to bad space width measurement. Also fixed justified text drawing. r=brade, a=beppe --- gfx/src/mac/nsCarbonHelpers.h | 2 + gfx/src/mac/nsFontMetricsMac.cpp | 105 +++----------- gfx/src/mac/nsGfxUtils.h | 47 ++++-- gfx/src/mac/nsUnicodeRenderingToolkit.cpp | 168 +++++++++++----------- 4 files changed, 145 insertions(+), 177 deletions(-) diff --git a/gfx/src/mac/nsCarbonHelpers.h b/gfx/src/mac/nsCarbonHelpers.h index b7603e99f5ba..3afb8afe86ea 100644 --- a/gfx/src/mac/nsCarbonHelpers.h +++ b/gfx/src/mac/nsCarbonHelpers.h @@ -24,6 +24,8 @@ #ifndef CarbonHelpers_h__ #define CarbonHelpers_h__ +#include + #if (UNIVERSAL_INTERFACES_VERSION >= 0x0330) #include #else diff --git a/gfx/src/mac/nsFontMetricsMac.cpp b/gfx/src/mac/nsFontMetricsMac.cpp index 25ae2040396c..62c50645e5a9 100644 --- a/gfx/src/mac/nsFontMetricsMac.cpp +++ b/gfx/src/mac/nsFontMetricsMac.cpp @@ -20,9 +20,6 @@ * Contributor(s): */ -#include // for FetchFontInfo -#include // forgive me father - #include "nsCarbonHelpers.h" #include "nsFontMetricsMac.h" @@ -57,51 +54,7 @@ nsFontMetricsMac :: ~nsFontMetricsMac() NS_IMPL_ISUPPORTS(nsFontMetricsMac, kIFontMetricsIID); -//------------------------------------------------------------------------ -// FetchFontInfo moved from the FontManager lib to InterfaceLib between -// Mac OS 8.5 and 8.6. The build expects it to be in InterfaceLib, so -// when running on 8.5, we have to go grovel for it manually. -//------------------------------------------------------------------------ -typedef pascal OSErr (*FetchFontInfoProc)(SInt16, SInt16, SInt16, FontInfo *); - -static OSErr MyFetchFontInfo(SInt16 fontID, SInt16 fontSize, SInt16 fontStyle, FontInfo* fInfo) -{ - static Boolean sTriedToGetSymbol = false; - static FetchFontInfoProc sFetchFontInfoCall = FetchFontInfo; - - if (!sFetchFontInfoCall && !sTriedToGetSymbol) // this happens on 8.5 - { - CFragConnectionID connectionID; - Str255 errName; - - OSErr err = ::GetSharedLibrary("\pFontManager", kCompiledCFragArch, kReferenceCFrag, &connectionID, nsnull, errName); - if (err == noErr && connectionID) - { - err = ::FindSymbol(connectionID, "\pFetchFontInfo", (Ptr *)&sFetchFontInfoCall, nsnull); - if (err != noErr) - sFetchFontInfoCall = nsnull; - } - - ::CloseConnection(&connectionID); - sTriedToGetSymbol = true; - } - - if (sFetchFontInfoCall) - return (*sFetchFontInfoCall)(fontID, fontSize, fontStyle, fInfo); - - // evil hack - { - StPortSetter portSetter(::LMGetWMgrPort()); - StTextStyleSetter styleSetter(fontID, fontSize, fontStyle); - GetFontInfo(fInfo); - } - - return cfragNoSymbolErr; -} - - - -NS_IMETHODIMP nsFontMetricsMac :: Init(const nsFont& aFont, nsIAtom* aLangGroup, nsIDeviceContext* aCX) +NS_IMETHODIMP nsFontMetricsMac::Init(const nsFont& aFont, nsIAtom* aLangGroup, nsIDeviceContext* aCX) { NS_ASSERTION(!(nsnull == aCX), "attempt to init fontmetrics with null device context"); @@ -113,18 +66,12 @@ NS_IMETHODIMP nsFontMetricsMac :: Init(const nsFont& aFont, nsIAtom* aLangGroup, TextStyle theStyle; nsFontMetricsMac::GetNativeTextStyle(*this, *mContext, theStyle); + StTextStyleSetter styleSetter(theStyle); + FontInfo fInfo; - // FetchFontInfo gets the font info without having to touch a grafport. It's 8.5 only -#if !TARGET_CARBON - OSErr error = MyFetchFontInfo(mFontNum, theStyle.tsSize, theStyle.tsFace, &fInfo); - NS_ASSERTION(error == noErr, "Error in FetchFontInfo"); -#else - // pinkerton - hack because this routine isn't yet in carbon. - fInfo.ascent = theStyle.tsSize; - fInfo.descent = 3; - fInfo.widMax = 12; - fInfo.leading = 3; -#endif + GetFontInfo(&fInfo); + + FetchFontInfo(theStyle.tsFont, theStyle.tsSize, theStyle.tsFace, &fInfo); float dev2app; mContext->GetDevUnitsToAppUnits(dev2app); @@ -138,35 +85,29 @@ NS_IMETHODIMP nsFontMetricsMac :: Init(const nsFont& aFont, nsIAtom* aLangGroup, mMaxAscent = mEmAscent; mMaxDescent = mEmDescent; - GrafPtr thePort; - ::GetPort(&thePort); - NS_ASSERTION(thePort != nil, "GrafPort is nil in nsFontMetricsMac::Init"); - if (thePort == nil) - { - mMaxAdvance = 0; - mSpaceWidth = 0; - return NS_ERROR_FAILURE; - } - - StTextStyleSetter styleSetter(theStyle); - mMaxAdvance = NSToCoordRound(float(::CharWidth('M')) * dev2app); // don't use fInfo.widMax here mSpaceWidth = NSToCoordRound(float(::CharWidth(' ')) * dev2app); return NS_OK; } -nsUnicodeFontMappingMac* nsFontMetricsMac :: GetUnicodeFontMapping() +nsUnicodeFontMappingMac* nsFontMetricsMac::GetUnicodeFontMapping() { - // we should pass the documentCharset from the nsIDocument level and - // the lang attribute from the tag level to here. - // XXX hard code to some value till peterl pass them down. - nsAutoString lang; - nsAutoString langGroup; langGroup.AssignWithConversion("ja"); - if(mLangGroup) - mLangGroup->ToString(langGroup); - if(! mFontMapping) - mFontMapping = nsUnicodeFontMappingMac::GetCachedInstance(mFont, mContext,langGroup, lang); + if (!mFontMapping) + { + // we should pass the documentCharset from the nsIDocument level and + // the lang attribute from the tag level to here. + // XXX hard code to some value till peterl pass them down. + nsAutoString langGroup; + if (mLangGroup) + mLangGroup->ToString(langGroup); + else + langGroup.AssignWithConversion("ja"); + + nsString lang; + mFontMapping = nsUnicodeFontMappingMac::GetCachedInstance(mFont, mContext, langGroup, lang); + } + return mFontMapping; } @@ -244,7 +185,7 @@ void nsFontMetricsMac::RealizeFont() NS_IMETHODIMP -nsFontMetricsMac :: Destroy() +nsFontMetricsMac::Destroy() { return NS_OK; } diff --git a/gfx/src/mac/nsGfxUtils.h b/gfx/src/mac/nsGfxUtils.h index 1728f5715961..49c96aa2fa3f 100644 --- a/gfx/src/mac/nsGfxUtils.h +++ b/gfx/src/mac/nsGfxUtils.h @@ -27,6 +27,21 @@ #include "nsCarbonHelpers.h" #endif // CarbonHelpers_h__ +#include + + +/** ------------------------------------------------------------ + * Used to assert that we're not clobbering a bad port + */ +inline PRBool CurrentPortIsWMPort() +{ + GrafPtr curPort; + ::GetPort(&curPort); + + return (curPort == ::LMGetWMgrPort()); +} + + //------------------------------------------------------------------------ // utility port setting class //------------------------------------------------------------------------ @@ -52,7 +67,6 @@ protected: GrafPtr mOldPort; }; - //------------------------------------------------------------------------ // utility text state save/restore class //------------------------------------------------------------------------ @@ -62,21 +76,12 @@ class StTextStyleSetter public: StTextStyleSetter(SInt16 fontID, SInt16 fontSize, SInt16 fontFace) { - GrafPtr curPort; - ::GetPort(&curPort); - - mFontID = ::GetPortTextFont(curPort); - mFontSize = ::GetPortTextSize(curPort); - mFontSize = ::GetPortTextFace(curPort); - - ::TextFont(fontID); - ::TextSize(fontSize); - ::TextFace(fontFace); + SetPortFontStyle(fontID, fontSize, fontFace); } StTextStyleSetter(TextStyle& theStyle) { - StTextStyleSetter(theStyle.tsFont, theStyle.tsSize, theStyle.tsFace); + SetPortFontStyle(theStyle.tsFont, theStyle.tsSize, theStyle.tsFace); } ~StTextStyleSetter() @@ -86,6 +91,24 @@ public: ::TextFace(mFontFace); } +protected: + + void SetPortFontStyle(SInt16 fontID, SInt16 fontSize, SInt16 fontFace) + { + GrafPtr curPort; + ::GetPort(&curPort); + + NS_ASSERTION(!CurrentPortIsWMPort(), "Setting window manager port font"); + + mFontID = ::GetPortTextFont(curPort); + mFontSize = ::GetPortTextSize(curPort); + mFontFace = ::GetPortTextFace(curPort); + + ::TextFont(fontID); + ::TextSize(fontSize); + ::TextFace(fontFace); + } + protected: SInt16 mFontID; SInt16 mFontSize; diff --git a/gfx/src/mac/nsUnicodeRenderingToolkit.cpp b/gfx/src/mac/nsUnicodeRenderingToolkit.cpp index 6ea889dec022..5cad777b79db 100644 --- a/gfx/src/mac/nsUnicodeRenderingToolkit.cpp +++ b/gfx/src/mac/nsUnicodeRenderingToolkit.cpp @@ -955,7 +955,7 @@ nsresult nsUnicodeRenderingToolkit :: DrawTextSegment( bufLen, &processBytes, &outLen, (LogicalAddress)buf); - // no mater if failed or not, as long as it convert some text, we process it. + // no matter if failed or not, as long as it convert some text, we process it. if(outLen > 0) { DrawScriptText(buf, outLen, x, y, thisWidth); @@ -1076,99 +1076,101 @@ NS_IMETHODIMP nsUnicodeRenderingToolkit :: GetWidth(const PRUnichar *aString, PR } #define IS_FORMAT_CONTROL_CHARS(c) ((0x2000==((c)&0xFFF0))||(0x2028==((c)&0xFFF8))) -#define IS_CONTEXTUAL_CHARS(c) ((0x0600<=(c))&&((c)<0x1000)) -#define IS_COMBINING_CHARS(c) ((0x0300<=(c))&&((c)<0x0370)) +#define IS_CONTEXTUAL_CHARS(c) ((0x0600<=(c))&&((c)<0x1000)) +#define IS_COMBINING_CHARS(c) ((0x0300<=(c))&&((c)<0x0370)) //------------------------------------------------------------------------ NS_IMETHODIMP nsUnicodeRenderingToolkit :: DrawString(const PRUnichar *aString, PRUint32 aLength, nscoord aX, nscoord aY, PRInt32 aFontID, const nscoord* aSpacing) { - nsresult res = NS_OK; - nsFontMetricsMac *metrics = (nsFontMetricsMac*) mGS->mFontMetrics; - nsUnicodeFontMappingMac* fontmap = metrics->GetUnicodeFontMapping(); - - PRInt32 x = aX; - PRInt32 y = aY; + nsresult res = NS_OK; + nsFontMetricsMac *metrics = (nsFontMetricsMac*) mGS->mFontMetrics; + nsUnicodeFontMappingMac* fontmap = metrics->GetUnicodeFontMapping(); + + PRInt32 x = aX; + + // offset to baseline + nscoord ascent = 0; + mGS->mFontMetrics->GetMaxAscent(ascent); // ascent is twips + + PRInt32 transformedY = aY + ascent; + mGS->mTMatrix.TransformCoord(&x, &transformedY); + + PRUint32 i; + PRInt32 currentX = aX; + PRUint32 thisWidth = 0; + const short *scriptFallbackFonts = fontmap->GetScriptFallbackFonts(); - nscoord ascent = 0; - mGS->mFontMetrics->GetMaxAscent(ascent); - y += ascent; + if (aSpacing) + { + for (i = 0; i < aLength; ) + { + PRUint32 drawLen; + short curFontNum = fontmap->GetFontID(aString[i]); - mGS->mTMatrix.TransformCoord(&x,&y); + for (drawLen = 1; (i + drawLen) < aLength; drawLen++) + { + PRUnichar uc = aString[i+drawLen]; + if(! (IS_CONTEXTUAL_CHARS(uc) || + IS_FORMAT_CONTROL_CHARS(uc) || + IS_COMBINING_CHARS(uc)) ) { + break; + } + } - PRUint32 i; - PRInt32 currentX = x; - PRUint32 thisWidth = 0; - const short *scriptFallbackFonts = fontmap->GetScriptFallbackFonts(); - - if(aSpacing) { - int buffer[STACK_TREASHOLD]; - int* spacing = (aLength <= STACK_TREASHOLD ? buffer : new int[aLength]); - if (spacing) - { - mGS->mTMatrix.ScaleXCoords(aSpacing, aLength, spacing); - for(i =0; i < aLength; ) - { - PRUint32 j,drawLen; - short curFontNum = fontmap->GetFontID(aString[i]); - for(drawLen = 1; ((i+drawLen) < aLength);drawLen++) { - PRUnichar uc = aString[i+drawLen]; - if(! ( IS_CONTEXTUAL_CHARS(uc) || - IS_FORMAT_CONTROL_CHARS(uc) || - IS_COMBINING_CHARS(uc)) ) { - break; - } - } - res = DrawTextSegment(aString+i, drawLen, curFontNum, scriptFallbackFonts, currentX, y, thisWidth); - if(NS_FAILED(res)) { - if (spacing != buffer) - delete[] spacing; - goto end_of_func; - } - for(j=0;jGetFontID(aString[0]);; - PRUint32 start; - for(i =1, start=0; i < aLength; i++) - { - PRUnichar uch = aString[i]; - if(! IS_FORMAT_CONTROL_CHARS(uch)) - { - nextFont = fontmap->GetFontID(uch); - if(thisFont != nextFont) - { // start new font run... - - res = DrawTextSegment(aString+start, i-start, thisFont, scriptFallbackFonts, - currentX, y, thisWidth); - if(NS_FAILED(res)) - goto end_of_func; - currentX += thisWidth; - start = i; - thisFont = nextFont; - } - } - } - - res = DrawTextSegment(aString+start, aLength-start, thisFont, - scriptFallbackFonts, currentX, y, thisWidth); - if(NS_FAILED(res)) - goto end_of_func; + PRInt32 transformedX = currentX, ignoreY = 0; + mGS->mTMatrix.TransformCoord(&transformedX, &ignoreY); + res = DrawTextSegment(aString+i, drawLen, curFontNum, scriptFallbackFonts, transformedX, transformedY, thisWidth); + if (NS_FAILED(res)) + return res; + + for (PRUint32 j = 0; j < drawLen; j++) + currentX += aSpacing[i + j]; + + i += drawLen; } - -end_of_func: + } + else // no spacing array + { + short thisFont, nextFont; + thisFont = fontmap->GetFontID(aString[0]); + PRUint32 start; - return res; + for (i = 1, start = 0; i < aLength; i++) + { + PRUnichar uch = aString[i]; + if(! IS_FORMAT_CONTROL_CHARS(uch)) + { + nextFont = fontmap->GetFontID(uch); + if (thisFont != nextFont) + { // start new font run... + + + PRInt32 transformedX = currentX, ignoreY = 0; + mGS->mTMatrix.TransformCoord(&transformedX, &ignoreY); + + res = DrawTextSegment(aString + start, i - start, thisFont, scriptFallbackFonts, transformedX, transformedY, thisWidth); + if (NS_FAILED(res)) + return res; + + currentX += thisWidth; + start = i; + thisFont = nextFont; + } + } + } + + PRInt32 transformedX = currentX, ignoreY = 0; + mGS->mTMatrix.TransformCoord(&transformedX, &ignoreY); + res = DrawTextSegment(aString+start, aLength-start, thisFont, scriptFallbackFonts, transformedX, transformedY, thisWidth); + if (NS_FAILED(res)) + return res; + } + + return NS_OK; } + + //------------------------------------------------------------------------ NS_IMETHODIMP nsUnicodeRenderingToolkit :: PrepareToDraw(float aP2T, nsIDeviceContext* aContext, nsGraphicState* aGS, GrafPtr aPort) {