Bug 496989 - Simplify text/glyph interface. r=jwatt

This commit is contained in:
Robert Longson 2009-06-17 22:05:02 +01:00
parent ac050d8a8d
commit df2c2b87cf
4 changed files with 78 additions and 109 deletions

View File

@ -56,20 +56,9 @@ public:
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)=0;
NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval)=0;
enum { BASELINE_ALPHABETIC = 0U };
enum { BASELINE_HANGING = 1U };
enum { BASELINE_IDEOGRAPHC = 2U };
enum { BASELINE_MATHEMATICAL = 3U };
enum { BASELINE_CENTRAL = 4U };
enum { BASELINE_MIDDLE = 5U };
enum { BASELINE_TEXT_BEFORE_EDGE = 6U };
enum { BASELINE_TEXT_AFTER_EDGE = 7U };
NS_IMETHOD_(float) GetBaselineOffset(PRUint16 baselineIdentifier,
PRBool aForceGlobalTransform)=0;
NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform)=0;
NS_IMETHOD_(void) SetGlyphPosition(float x, float y)=0;
NS_IMETHOD_(void) SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform)=0;
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent()=0;
NS_IMETHOD_(PRBool) IsStartOfChunk()=0; // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y)=0;

View File

@ -720,6 +720,65 @@ nsSVGGlyphFrame::GetCharacterPositions(nsTArray<CharacterPosition>* aCharacterPo
return PR_TRUE;
}
float
nsSVGGlyphFrame::GetSubStringAdvance(PRUint32 charnum,
PRUint32 fragmentChars)
{
if (fragmentChars == 0)
return 0.0f;
gfxFloat advance = mTextRun->GetAdvanceWidth(charnum, fragmentChars, nsnull);
return float(advance);
}
gfxFloat
nsSVGGlyphFrame::GetBaselineOffset(PRBool aForceGlobalTransform)
{
float drawScale, metricsScale;
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return 0.0;
gfxTextRun::Metrics metrics =
mTextRun->MeasureText(0, mTextRun->GetLength(),
gfxFont::LOOSE_INK_EXTENTS, nsnull, nsnull);
PRUint16 dominantBaseline;
for (nsIFrame *frame = GetParent(); frame; frame = frame->GetParent()) {
dominantBaseline = frame->GetStyleSVGReset()->mDominantBaseline;
if (dominantBaseline != NS_STYLE_DOMINANT_BASELINE_AUTO ||
frame->GetType() == nsGkAtoms::svgTextFrame) {
break;
}
}
gfxFloat baselineAppUnits;
switch (dominantBaseline) {
case NS_STYLE_DOMINANT_BASELINE_HANGING:
// not really right, but the best we can do with the information provided
// FALLTHROUGH
case NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE:
baselineAppUnits = -metrics.mAscent;
break;
case NS_STYLE_DOMINANT_BASELINE_TEXT_AFTER_EDGE:
case NS_STYLE_DOMINANT_BASELINE_IDEOGRAPHIC:
baselineAppUnits = metrics.mDescent;
break;
case NS_STYLE_DOMINANT_BASELINE_CENTRAL:
case NS_STYLE_DOMINANT_BASELINE_MIDDLE:
baselineAppUnits = -(metrics.mAscent - metrics.mDescent) / 2.0;
break;
case NS_STYLE_DOMINANT_BASELINE_AUTO:
case NS_STYLE_DOMINANT_BASELINE_ALPHABETIC:
return 0.0;
default:
NS_WARNING("We don't know about this type of dominant-baseline");
return 0.0;
}
return baselineAppUnits * metricsScale;
}
//----------------------------------------------------------------------
// Utilities for converting from indices in the uncompressed content
@ -865,9 +924,9 @@ nsSVGGlyphFrame::GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
// nsISVGGlyphFragmentLeaf interface:
NS_IMETHODIMP_(void)
nsSVGGlyphFrame::SetGlyphPosition(float x, float y)
nsSVGGlyphFrame::SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform)
{
mPosition.MoveTo(x, y);
mPosition.MoveTo(x, y - GetBaselineOffset(aForceGlobalTransform));
nsSVGUtils::UpdateGraphic(this);
}
@ -947,42 +1006,6 @@ nsSVGGlyphFrame::GetRotationOfChar(PRUint32 charnum, float *_retval)
return NS_OK;
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetBaselineOffset(PRUint16 baselineIdentifier,
PRBool aForceGlobalTransform)
{
float drawScale, metricsScale;
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return 0.0f;
gfxTextRun::Metrics metrics =
mTextRun->MeasureText(0, mTextRun->GetLength(),
gfxFont::LOOSE_INK_EXTENTS, nsnull, nsnull);
gfxFloat baselineAppUnits;
switch (baselineIdentifier) {
case BASELINE_HANGING:
// not really right, but the best we can do with the information provided
// FALLTHROUGH
case BASELINE_TEXT_BEFORE_EDGE:
baselineAppUnits = -metrics.mAscent;
break;
case BASELINE_TEXT_AFTER_EDGE:
baselineAppUnits = metrics.mDescent;
break;
case BASELINE_CENTRAL:
case BASELINE_MIDDLE:
baselineAppUnits = -(metrics.mAscent - metrics.mDescent) / 2.0f;
break;
case BASELINE_ALPHABETIC:
default:
baselineAppUnits = 0.0;
break;
}
return float(baselineAppUnits)*metricsScale;
}
NS_IMETHODIMP_(float)
nsSVGGlyphFrame::GetAdvance(PRBool aForceGlobalTransform)
{
@ -990,9 +1013,8 @@ nsSVGGlyphFrame::GetAdvance(PRBool aForceGlobalTransform)
if (!EnsureTextRun(&drawScale, &metricsScale, aForceGlobalTransform))
return 0.0f;
gfxFloat advanceAppUnits =
mTextRun->GetAdvanceWidth(0, mTextRun->GetLength(), nsnull);
return float(advanceAppUnits)*metricsScale;
float advanceAppUnits = GetSubStringAdvance(0, mTextRun->GetLength());
return advanceAppUnits * metricsScale;
}
NS_IMETHODIMP_(nsSVGTextPathFrame*)
@ -1130,9 +1152,8 @@ nsSVGGlyphFrame::GetSubStringLength(PRUint32 charnum, PRUint32 fragmentChars)
if (!EnsureTextRun(&drawScale, &metricsScale, PR_FALSE))
return 0.0f;
gfxFloat advanceAppUnits =
mTextRun->GetAdvanceWidth(charnum, fragmentChars, nsnull);
return float(advanceAppUnits)*metricsScale;
float advanceAppUnits = GetSubStringAdvance(charnum, fragmentChars);
return advanceAppUnits * metricsScale;
}
PRInt32

View File

@ -143,19 +143,13 @@ public:
NS_IMETHOD GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval);
NS_IMETHOD GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval);
NS_IMETHOD GetRotationOfChar(PRUint32 charnum, float *_retval);
/**
* @param aForceGlobalTransform controls whether to use the
* global transform even when NS_STATE_NONDISPLAY_CHILD
*/
NS_IMETHOD_(float) GetBaselineOffset(PRUint16 baselineIdentifier,
PRBool aForceGlobalTransform);
/**
* @param aForceGlobalTransform controls whether to use the
* global transform even when NS_STATE_NONDISPLAY_CHILD
*/
NS_IMETHOD_(float) GetAdvance(PRBool aForceGlobalTransform);
NS_IMETHOD_(void) SetGlyphPosition(float x, float y);
NS_IMETHOD_(void) SetGlyphPosition(float x, float y, PRBool aForceGlobalTransform);
NS_IMETHOD_(nsSVGTextPathFrame*) FindTextPathParent();
NS_IMETHOD_(PRBool) IsStartOfChunk(); // == is new absolutely positioned chunk.
NS_IMETHOD_(void) GetAdjustedPosition(/* inout */ float &x, /* inout */ float &y);
@ -216,6 +210,8 @@ protected:
void SetupGlobalTransform(gfxContext *aContext);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background);
float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars);
gfxFloat GetBaselineOffset(PRBool aForceGlobalTransform);
const nsTextFragment* GetFragment() const
{
return !(GetStateBits() & NS_STATE_SVG_PRINTING) ?

View File

@ -290,8 +290,7 @@ nsSVGTextFrame::NotifyGlyphMetricsChange()
}
static void
GetSingleValue(nsISVGGlyphFragmentLeaf *fragment,
nsIDOMSVGLengthList *list, float *val)
GetSingleValue(nsIDOMSVGLengthList *list, float *val)
{
if (!list)
return;
@ -322,40 +321,6 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
mPositioningDirty = PR_FALSE;
// we'll align every fragment in this chunk on the dominant-baseline:
// XXX should actually inspect 'alignment-baseline' for each fragment
PRUint8 baseline;
switch(GetStyleSVGReset()->mDominantBaseline) {
case NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_TEXT_BEFORE_EDGE;
break;
case NS_STYLE_DOMINANT_BASELINE_TEXT_AFTER_EDGE:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_TEXT_AFTER_EDGE;
break;
case NS_STYLE_DOMINANT_BASELINE_MIDDLE:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_MIDDLE;
break;
case NS_STYLE_DOMINANT_BASELINE_CENTRAL:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_CENTRAL;
break;
case NS_STYLE_DOMINANT_BASELINE_MATHEMATICAL:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_MATHEMATICAL;
break;
case NS_STYLE_DOMINANT_BASELINE_IDEOGRAPHIC:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_IDEOGRAPHC;
break;
case NS_STYLE_DOMINANT_BASELINE_HANGING:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_HANGING;
break;
case NS_STYLE_DOMINANT_BASELINE_AUTO:
case NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT:
case NS_STYLE_DOMINANT_BASELINE_ALPHABETIC:
default:
baseline = nsISVGGlyphFragmentLeaf::BASELINE_ALPHABETIC;
break;
}
nsISVGGlyphFragmentLeaf *fragment, *firstFragment;
firstFragment = node->GetFirstGlyphFragment();
@ -367,22 +332,22 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
{
nsCOMPtr<nsIDOMSVGLengthList> list = GetX();
GetSingleValue(firstFragment, list, &x);
GetSingleValue(list, &x);
}
{
nsCOMPtr<nsIDOMSVGLengthList> list = GetY();
GetSingleValue(firstFragment, list, &y);
GetSingleValue(list, &y);
}
// loop over chunks
while (firstFragment) {
{
nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetX();
GetSingleValue(firstFragment, list, &x);
GetSingleValue(list, &x);
}
{
nsCOMPtr<nsIDOMSVGLengthList> list = firstFragment->GetY();
GetSingleValue(firstFragment, list, &y);
GetSingleValue(list, &y);
}
// check for startOffset on textPath
@ -407,7 +372,7 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
while (fragment) {
float dx = 0.0f;
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx();
GetSingleValue(fragment, list, &dx);
GetSingleValue(list, &dx);
chunkLength += dx + fragment->GetAdvance(aForceGlobalTransform);
fragment = fragment->GetNextGlyphFragment();
if (fragment && fragment->IsAbsolutelyPositioned())
@ -428,16 +393,14 @@ nsSVGTextFrame::UpdateGlyphPositioning(PRBool aForceGlobalTransform)
float dx = 0.0f, dy = 0.0f;
{
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDx();
GetSingleValue(fragment, list, &dx);
GetSingleValue(list, &dx);
}
{
nsCOMPtr<nsIDOMSVGLengthList> list = fragment->GetDy();
GetSingleValue(fragment, list, &dy);
GetSingleValue(list, &dy);
}
float baseline_offset =
fragment->GetBaselineOffset(baseline, aForceGlobalTransform);
fragment->SetGlyphPosition(x + dx, y + dy - baseline_offset);
fragment->SetGlyphPosition(x + dx, y + dy, aForceGlobalTransform);
x += dx + fragment->GetAdvance(aForceGlobalTransform);
y += dy;