Fixes for 39811, 36417 -- bad text layout on Mac, due to bad space width measurement. Also fixed justified text drawing. r=brade, a=beppe

This commit is contained in:
sfraser%netscape.com 2000-05-26 22:03:33 +00:00
Родитель 14f6a376b9
Коммит de4ecba1c8
4 изменённых файлов: 145 добавлений и 177 удалений

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

@ -24,6 +24,8 @@
#ifndef CarbonHelpers_h__
#define CarbonHelpers_h__
#include <ConditionalMacros.h>
#if (UNIVERSAL_INTERFACES_VERSION >= 0x0330)
#include <ControlDefinitions.h>
#else

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

@ -20,9 +20,6 @@
* Contributor(s):
*/
#include <Fonts.h> // for FetchFontInfo
#include <LowMem.h> // 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;
}

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

@ -27,6 +27,21 @@
#include "nsCarbonHelpers.h"
#endif // CarbonHelpers_h__
#include <LowMem.h>
/** ------------------------------------------------------------
* 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;

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

@ -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;j<drawLen;j++)
currentX += spacing[i++];
}
if (spacing != buffer)
delete[] spacing;
}
else {
res = NS_ERROR_OUT_OF_MEMORY;
goto end_of_func;
}
} else {
short thisFont, nextFont;
thisFont=fontmap->GetFontID(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)
{