зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
14f6a376b9
Коммит
de4ecba1c8
|
@ -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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче