fixing CSS letter-spacing on windows. bug 327184. r=vlad

This commit is contained in:
pavlov%pavlov.net 2006-04-08 00:41:08 +00:00
parent 5903c86738
commit 901035901b
9 changed files with 123 additions and 54 deletions

View File

@ -732,5 +732,4 @@ nsThebesDeviceContext::FindScreen(nsIScreen** outScreen)
#endif
mScreenManager->GetPrimaryScreen(outScreen);
}

View File

@ -286,7 +286,7 @@ nsThebesFontMetrics::GetWidth(const char* aString, PRUint32 aLength, nscoord& aW
textrun->SetRightToLeft(mIsRTL);
aWidth = ROUND_TO_TWIPS(textrun->MeasureString(aContext->Thebes()));
aWidth = ROUND_TO_TWIPS(textrun->Measure(aContext->Thebes()));
return NS_OK;
}
@ -306,7 +306,7 @@ nsThebesFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength,
textrun->SetRightToLeft(mIsRTL);
aWidth = ROUND_TO_TWIPS(textrun->MeasureString(aContext->Thebes()));
aWidth = ROUND_TO_TWIPS(textrun->Measure(aContext->Thebes()));
return NS_OK;
@ -366,7 +366,14 @@ nsThebesFontMetrics::DrawString(const char *aString, PRUint32 aLength,
textrun->SetRightToLeft(mIsRTL);
textrun->DrawString(aContext->Thebes(), gfxPoint(NSToIntRound(aX * app2dev), NSToIntRound(aY * app2dev)));
if (aSpacing) {
nsTArray<gfxFloat> spacing(aLength);
for (PRUint32 i = 0; i < aLength; ++i)
spacing.AppendElement(aSpacing[i] * app2dev);
textrun->SetSpacing(spacing);
}
textrun->Draw(aContext->Thebes(), gfxPoint(NSToIntRound(aX * app2dev), NSToIntRound(aY * app2dev)));
return NS_OK;
}
@ -389,7 +396,14 @@ nsThebesFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
textrun->SetRightToLeft(mIsRTL);
textrun->DrawString(aContext->Thebes(), gfxPoint(NSToIntRound(aX * app2dev), NSToIntRound(aY * app2dev)));
if (aSpacing) {
nsTArray<gfxFloat> spacing(aLength);
for (PRUint32 i = 0; i < aLength; ++i)
spacing.AppendElement(aSpacing[i] * app2dev);
textrun->SetSpacing(spacing);
}
textrun->Draw(aContext->Thebes(), gfxPoint(NSToIntRound(aX * app2dev), NSToIntRound(aY * app2dev)));
return NS_OK;
}

View File

@ -103,8 +103,11 @@ public:
gfxAtsuiTextRun(const nsAString& aString, gfxAtsuiFontGroup *aFontGroup);
~gfxAtsuiTextRun();
virtual void DrawString(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat MeasureString(gfxContext *aContext);
virtual void Draw(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat Measure(gfxContext *aContext);
virtual void SetSpacing(const nsTArray<gfxFloat>& spacingArray);
virtual const nsTArray<gfxFloat> *const GetSpacing() const;
private:
nsString mString;

View File

@ -202,12 +202,14 @@ class NS_EXPORT gfxTextRun {
THEBES_DECL_REFCOUNTING_ABSTRACT
public:
virtual void DrawString(gfxContext *aContext,
gfxPoint pt) = 0;
virtual void Draw(gfxContext *aContext, gfxPoint pt) = 0;
// returns length in pixels
virtual gfxFloat MeasureString(gfxContext *aContext) = 0;
virtual gfxFloat Measure(gfxContext *aContext) = 0;
virtual void SetSpacing(const nsTArray<gfxFloat> &spacing) = 0;
virtual const nsTArray<gfxFloat> *const GetSpacing() const = 0;
// defaults to FALSE
virtual void SetRightToLeft(PRBool aIsRTL) { mIsRTL = aIsRTL; }
virtual PRBool IsRightToLeft() const { return mIsRTL; }

View File

@ -95,8 +95,11 @@ public:
gfxPangoTextRun(const nsAString& aString, gfxPangoFontGroup *aFontGroup);
~gfxPangoTextRun();
virtual void DrawString(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat MeasureString(gfxContext *aContext);
virtual void Draw(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat Measure(gfxContext *aContext);
virtual void SetSpacing(const nsTArray<gfxFloat>& spacingArray);
virtual const nsTArray<gfxFloat> *const GetSpacing() const;
private:
nsString mString;

View File

@ -136,23 +136,22 @@ public:
gfxWindowsTextRun(const nsACString& aString, gfxWindowsFontGroup *aFontGroup);
~gfxWindowsTextRun();
virtual void DrawString(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat MeasureString(gfxContext *aContext);
virtual void Draw(gfxContext *aContext, gfxPoint pt);
virtual gfxFloat Measure(gfxContext *aContext);
virtual void SetSpacing(const nsTArray<gfxFloat>& spacingArray);
virtual const nsTArray<gfxFloat> *const GetSpacing() const;
private:
gfxWindowsFont *FindFallbackFont(HDC aDC,
const PRUnichar *aString, PRUint32 aLength,
gfxWindowsFont *aFont);
PRInt32 MeasureOrDrawFast(gfxContext *aContext,
PRBool aDraw,
PRInt32 aX, PRInt32 aY,
const PRInt32 *aSpacing);
PRInt32 MeasureOrDrawUniscribe(gfxContext *aContext, PRBool aDraw,
PRInt32 aX, PRInt32 aY,
const PRInt32 *aSpacing);
PRInt32 MeasureOrDrawFast(gfxContext *aContext, PRBool aDraw, gfxPoint pt);
PRInt32 MeasureOrDrawUniscribe(gfxContext *aContext, PRBool aDraw, gfxPoint pt);
gfxWindowsFontGroup *mGroup;
nsTArray<gfxFloat> mSpacing;
// These should probably be in a union
const nsAString& mString;

View File

@ -366,7 +366,7 @@ gfxAtsuiTextRun::~gfxAtsuiTextRun()
}
void
gfxAtsuiTextRun::DrawString(gfxContext *aContext, gfxPoint pt)
gfxAtsuiTextRun::Draw(gfxContext *aContext, gfxPoint pt)
{
cairo_t *cr = aContext->GetCairo();
nsRefPtr<gfxAtsuiFont> atsuiFont = mGroup->GetFontAt(0);
@ -415,7 +415,7 @@ gfxAtsuiTextRun::DrawString(gfxContext *aContext, gfxPoint pt)
}
gfxFloat
gfxAtsuiTextRun::MeasureString(gfxContext *aContext)
gfxAtsuiTextRun::Measure(gfxContext *aContext)
{
OSStatus status;
ATSTrapezoid trap;
@ -438,3 +438,16 @@ gfxAtsuiTextRun::MeasureString(gfxContext *aContext)
//fprintf (stderr, "measured: %f\n", f);
return f;
}
void
gfxAtsuiTextRun::SetSpacing(const nsTArray<gfxFloat> &spacingArray)
{
// XXX implement me!
}
const nsTArray<gfxFloat> *const
gfxAtsuiTextRun::GetSpacing() const
{
return nsnull;
}

View File

@ -654,7 +654,7 @@ gfxPangoTextRun::EnsurePangoLayout(gfxContext *aContext)
}
void
gfxPangoTextRun::DrawString (gfxContext *aContext, gfxPoint pt)
gfxPangoTextRun::Draw(gfxContext *aContext, gfxPoint pt)
{
gfxMatrix mat = aContext->CurrentMatrix();
@ -677,7 +677,7 @@ gfxPangoTextRun::DrawString (gfxContext *aContext, gfxPoint pt)
EnsurePangoLayout(aContext);
#if 0
MeasureString(aContext);
Measure(aContext);
if (mWidth != -1) {
aContext->Save();
aContext->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
@ -710,7 +710,7 @@ gfxPangoTextRun::DrawString (gfxContext *aContext, gfxPoint pt)
}
gfxFloat
gfxPangoTextRun::MeasureString (gfxContext *aContext)
gfxPangoTextRun::Measure(gfxContext *aContext)
{
if (mWidth == -1) {
EnsurePangoLayout(aContext);
@ -720,6 +720,17 @@ gfxPangoTextRun::MeasureString (gfxContext *aContext)
return mWidth/FLOAT_PANGO_SCALE;
}
void
gfxPangoTextRun::SetSpacing(const nsTArray<gfxFloat> &spacingArray)
{
// XXX implement me!
}
const nsTArray<gfxFloat> *const
gfxPangoTextRun::GetSpacing() const
{
return nsnull;
}
/**
** language group helpers

View File

@ -413,19 +413,19 @@ gfxWindowsTextRun::~gfxWindowsTextRun()
}
void
gfxWindowsTextRun::DrawString(gfxContext *aContext, gfxPoint pt)
gfxWindowsTextRun::Draw(gfxContext *aContext, gfxPoint pt)
{
PRInt32 ret = MeasureOrDrawFast(aContext, PR_TRUE, pt.x, pt.y, nsnull);
PRInt32 ret = MeasureOrDrawFast(aContext, PR_TRUE, pt);
if (ret != -1) {
return;
}
MeasureOrDrawUniscribe(aContext, PR_TRUE, pt.x, pt.y, nsnull);
MeasureOrDrawUniscribe(aContext, PR_TRUE, pt);
}
//#define TIME_MEASURE 1
gfxFloat
gfxWindowsTextRun::MeasureString(gfxContext *aContext)
gfxWindowsTextRun::Measure(gfxContext *aContext)
{
#ifdef TIME_MEASURE
if (mIsASCII) {
@ -436,24 +436,36 @@ gfxWindowsTextRun::MeasureString(gfxContext *aContext)
printf("%s\n", foo.get());
QueryPerformanceCounter(&start);
ret = MeasureOrDrawAscii(aContext, PR_FALSE, 0, 0, nsnull);
ret = MeasureOrDrawAscii(aContext, PR_FALSE, gfxPoint(0,0));
QueryPerformanceCounter(&end);
printf("ascii: %d\n", end.QuadPart - start.QuadPart);
QueryPerformanceCounter(&start);
ret = MeasureOrDrawUniscribe(aContext, PR_FALSE, 0, 0, nsnull);
ret = MeasureOrDrawUniscribe(aContext, PR_FALSE, gfxPoint(0,0));
QueryPerformanceCounter(&end);
printf("utf16: %d\n\n", end.QuadPart - start.QuadPart);
return ret;
}
#else
PRInt32 ret = MeasureOrDrawFast(aContext, PR_FALSE, 0, 0, nsnull);
PRInt32 ret = MeasureOrDrawFast(aContext, PR_FALSE, gfxPoint(0,0));
if (ret != -1) {
return ret;
}
#endif
return MeasureOrDrawUniscribe(aContext, PR_FALSE, 0, 0, nsnull);
return MeasureOrDrawUniscribe(aContext, PR_FALSE, gfxPoint(0,0));
}
void
gfxWindowsTextRun::SetSpacing(const nsTArray<gfxFloat>& spacingArray)
{
mSpacing = spacingArray;
}
const nsTArray<gfxFloat> *const
gfxWindowsTextRun::GetSpacing() const
{
return &mSpacing;
}
gfxWindowsFont *
@ -490,8 +502,7 @@ gfxWindowsTextRun::FindFallbackFont(HDC aDC, const PRUnichar *aString, PRUint32
PRInt32
gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
PRBool aDraw,
PRInt32 aX, PRInt32 aY,
const PRInt32 *aSpacing)
gfxPoint pt)
{
PRInt32 length = 0;
@ -597,9 +608,14 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
double offset = 0;
for (PRInt32 k = 0; k < numGlyphs; k++) {
cglyphs[k].index = glyphs[k];
cglyphs[k].x = aX + offset;
cglyphs[k].y = aY;
offset += NSToCoordRound(dxBuf[k] * cairoToPixels);
cglyphs[k].x = pt.x + offset;
cglyphs[k].y = pt.y;
if (!mSpacing.IsEmpty()) {
offset += mSpacing[k];
} else {
offset += dxBuf[k] * cairoToPixels;
}
}
SetWorldTransform(aDC, &savedxform);
@ -628,8 +644,7 @@ gfxWindowsTextRun::MeasureOrDrawFast(gfxContext *aContext,
PRInt32
gfxWindowsTextRun::MeasureOrDrawUniscribe(gfxContext *aContext,
PRBool aDraw,
PRInt32 aX, PRInt32 aY,
const PRInt32 *aSpacing)
gfxPoint pt)
{
nsRefPtr<gfxASurface> surf = aContext->CurrentSurface();
HDC aDC = GetDCFromSurface(surf);
@ -839,8 +854,9 @@ TRY_AGAIN_JUST_PLACE:
if (!aDraw) {
length += NSToCoordRound((abc.abcA + abc.abcB + abc.abcC) * cairoToPixels);
} else {
PRInt32 *spacing = 0;
PRInt32 *spacing = nsnull;
PRInt32 justTotal = 0;
#if 0
if (aSpacing) {
PRUint32 j;
/* need to correct for layout/gfx spacing mismatch */
@ -885,18 +901,22 @@ TRY_AGAIN_JUST_PLACE:
#endif
}
}
#endif
cairo_glyph_t *cglyphs = (cairo_glyph_t*)malloc(numGlyphs*sizeof(cairo_glyph_t));
PRInt32 offset = 0;
gfxFloat offset = 0;
PRInt32 m = items[i].iCharPos;
for (PRInt32 k = 0; k < numGlyphs; k++) {
cglyphs[k].index = glyphs[k];
cglyphs[k].x = aX + offset + NSToCoordRound(offsets[k].du * cairoToPixels);
cglyphs[k].y = aY + NSToCoordRound(offsets[k].dv * cairoToPixels);
offset += NSToCoordRound(advance[k] * cairoToPixels);
cglyphs[k].x = pt.x + offset + (offsets[k].du * cairoToPixels);
cglyphs[k].y = pt.y + (offsets[k].dv * cairoToPixels);
/* XXX this needs some testing */
if (aSpacing)
offset += spacing[k] * cairoToPixels;
if (!mSpacing.IsEmpty()) {
// XXX We need to convert char index to cluster index.
// But we cannot do it until nsTextFrame is refactored.
offset += mSpacing[m++];
} else {
offset += advance[k] * cairoToPixels;
}
}
#if 0
/* Draw using ScriptTextOut() */
@ -914,7 +934,7 @@ TRY_AGAIN_JUST_PLACE:
xform.eDy = dm[5];
SetWorldTransform (aDC, &xform);
ScriptTextOut(aDC, currentFont->ScriptCache(), aX, aY, 0, NULL, &items->a,
ScriptTextOut(aDC, currentFont->ScriptCache(), pt.x, pt.y, 0, NULL, &items->a,
NULL, 0, glyphs, numGlyphs,
advance, NULL, offsets);
@ -944,8 +964,13 @@ TRY_AGAIN_JUST_PLACE:
#endif
free(cglyphs);
aX += NSToCoordRound((abc.abcA + abc.abcB + abc.abcC + justTotal) * cairoToPixels);
free(spacing);
pt.x += offset;
//NSToCoordRound((abc.abcA + abc.abcB + abc.abcC + justTotal) * cairoToPixels);
#if 0
if (spacing)
free(spacing);
#endif
}
free(offsets);
free(advance);