Make new textframe build again after units landing and other changes. The gfxSkipChars and gfxPangoTextRun changes only affect the new textframe.

This commit is contained in:
roc+%cs.cmu.edu 2007-02-09 04:20:17 +00:00
Родитель fb4bcd4049
Коммит 052b758c05
4 изменённых файлов: 157 добавлений и 111 удалений

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

@ -246,7 +246,12 @@ public:
* The empty constructor creates an object that is useless until it is assigned. * The empty constructor creates an object that is useless until it is assigned.
*/ */
gfxSkipCharsIterator() : mSkipChars(nsnull) {} gfxSkipCharsIterator() : mSkipChars(nsnull) {}
/**
* Return true if this iterator is properly initialized and usable.
*/
PRBool IsInitialized() { return mSkipChars != nsnull; }
/** /**
* Set the iterator to aOriginalStringOffset in the original string. * Set the iterator to aOriginalStringOffset in the original string.
* This can efficiently move forward or backward from the current position. * This can efficiently move forward or backward from the current position.

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

@ -878,7 +878,7 @@ gfxPangoTextRun::GetAdjustedSpacing(PRUint32 aStart, PRUint32 aEnd,
if (aStart >= aEnd) if (aStart >= aEnd)
return; return;
aProvider->GetSpacing(aStart, aEnd, aSpacing); aProvider->GetSpacing(aStart, aEnd - aStart, aSpacing);
// XXX the following loop could be avoided if we add some kind of // XXX the following loop could be avoided if we add some kind of
// TEXT_HAS_LIGATURES flag // TEXT_HAS_LIGATURES flag

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

@ -354,9 +354,8 @@ public:
virtual nsIFrame* GetLastInFlow() const; virtual nsIFrame* GetLastInFlow() const;
virtual nsIFrame* GetLastContinuation() const; virtual nsIFrame* GetLastContinuation() const;
NS_IMETHOD IsSplittable(nsSplittableType& aIsSplittable) const { virtual nsSplittableType GetSplittableType() const {
aIsSplittable = NS_FRAME_SPLITTABLE; return NS_FRAME_SPLITTABLE;
return NS_OK;
} }
/** /**
@ -447,7 +446,8 @@ public:
const nsRect& aDirtyRect); const nsRect& aDirtyRect);
// helper: paint quirks-mode CSS text decorations // helper: paint quirks-mode CSS text decorations
void PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect, void PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
const gfxPoint& aFramePt, nsTextPaintStyle& aTextStyle); const gfxPoint& aFramePt, nsTextPaintStyle& aTextStyle,
PropertyProvider& aProvider);
// helper: paint text frame when we're impacted by at least one selection. // helper: paint text frame when we're impacted by at least one selection.
// Return PR_FALSE if the text was not painted and we should continue with // Return PR_FALSE if the text was not painted and we should continue with
// the fast path. // the fast path.
@ -869,8 +869,9 @@ ReconstructTextForRun(gfxTextRun* aTextRun, PRBool aRememberText,
{ {
gfxSkipCharsBuilder builder; gfxSkipCharsBuilder builder;
nsAutoTArray<PRUint8,BIG_TEXT_NODE_SIZE> buffer; nsAutoTArray<PRUint8,BIG_TEXT_NODE_SIZE> buffer;
PRBool charSize = (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) ? 1 : 2; PRUint32 charSize = (aTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) ? 1 : 2;
PRInt32 length; PRInt32 length;
void* bufEnd;
nsTextFrame* f; nsTextFrame* f;
if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) { if (aTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) {
@ -879,8 +880,9 @@ ReconstructTextForRun(gfxTextRun* aTextRun, PRBool aRememberText,
length = frag->GetLength() - f->GetContentOffset(); length = frag->GetLength() - f->GetContentOffset();
if (!buffer.AppendElements(length*charSize)) if (!buffer.AppendElements(length*charSize))
return; return;
if (!TransformTextToBuffer(f, length, buffer.Elements(), charSize, &builder, bufEnd = TransformTextToBuffer(f, length, buffer.Elements(), charSize, &builder,
aIncomingWhitespace)) aIncomingWhitespace);
if (!bufEnd)
return; return;
} else { } else {
TextRunUserData* userData = NS_STATIC_CAST(TextRunUserData*, aTextRun->GetUserData()); TextRunUserData* userData = NS_STATIC_CAST(TextRunUserData*, aTextRun->GetUserData());
@ -893,7 +895,7 @@ ReconstructTextForRun(gfxTextRun* aTextRun, PRBool aRememberText,
if (!buffer.AppendElements(length*charSize)) if (!buffer.AppendElements(length*charSize))
return; return;
void* buf = buffer.Elements(); bufEnd = buffer.Elements();
for (i = 0; i < userData->mMappedFlowCount; ++i) { for (i = 0; i < userData->mMappedFlowCount; ++i) {
TextRunMappedFlow* flow = &userData->mMappedFlows[i]; TextRunMappedFlow* flow = &userData->mMappedFlows[i];
if (i > 0) { if (i > 0) {
@ -904,24 +906,28 @@ ReconstructTextForRun(gfxTextRun* aTextRun, PRBool aRememberText,
userData->mMappedFlows[i - 1].mStartFrame->GetStyleContext(), userData->mMappedFlows[i - 1].mStartFrame->GetStyleContext(),
"Frames in flow should have same style contexts"); "Frames in flow should have same style contexts");
} }
buf = TransformTextToBuffer(flow->mStartFrame, flow->mContentLength, buf, bufEnd = TransformTextToBuffer(flow->mStartFrame, flow->mContentLength, bufEnd,
charSize, &builder, aIncomingWhitespace); charSize, &builder, aIncomingWhitespace);
if (!buf) if (!bufEnd)
return; return;
} }
f = userData->mMappedFlows[0].mStartFrame; f = userData->mMappedFlows[0].mStartFrame;
} }
PRUint32 transformedLength = NS_STATIC_CAST(PRUint8*, bufEnd) - buffer.Elements();
if (charSize == 2) {
transformedLength >>= 1;
}
if (aRememberText) { if (aRememberText) {
if (charSize == 2) { if (charSize == 2) {
aTextRun->RememberText(NS_REINTERPRET_CAST(PRUnichar*, buffer.Elements()), length); aTextRun->RememberText(NS_REINTERPRET_CAST(PRUnichar*, buffer.Elements()), transformedLength);
} else { } else {
aTextRun->RememberText(buffer.Elements(), length); aTextRun->RememberText(buffer.Elements(), transformedLength);
} }
} }
if (aSetupBreaks) { if (aSetupBreaks) {
aSetupBreaks->SetupBreakSinksForTextRun(aTextRun, buffer.Elements(), length, aSetupBreaks->SetupBreakSinksForTextRun(aTextRun, buffer.Elements(), transformedLength,
charSize == 2, PR_TRUE); charSize == 2, PR_TRUE);
} }
} }
@ -1115,6 +1121,55 @@ BuildTextRunsScanner::GetNextBreakBeforeFrame(PRUint32* aIndex)
return NS_STATIC_CAST(nsTextFrame*, mLineBreakBeforeFrames.ElementAt(index)); return NS_STATIC_CAST(nsTextFrame*, mLineBreakBeforeFrames.ElementAt(index));
} }
static PRUint32
GetSpacingFlags(const nsStyleCoord& aStyleCoord)
{
nscoord spacing = StyleToCoord(aStyleCoord);
if (!spacing)
return 0;
if (spacing > 0)
return gfxTextRunFactory::TEXT_ENABLE_SPACING;
return gfxTextRunFactory::TEXT_ENABLE_SPACING |
gfxTextRunFactory::TEXT_ENABLE_NEGATIVE_SPACING;
}
static gfxFontGroup*
GetFontGroupForFrame(nsIFrame* aFrame)
{
nsIDeviceContext* devContext = aFrame->GetPresContext()->DeviceContext();
const nsStyleFont* fontStyle = aFrame->GetStyleFont();
const nsStyleVisibility* visibilityStyle = aFrame->GetStyleVisibility();
nsCOMPtr<nsIFontMetrics> metrics;
devContext->GetMetricsFor(fontStyle->mFont, visibilityStyle->mLangGroup,
*getter_AddRefs(metrics));
if (!metrics)
return nsnull;
nsIFontMetrics* metricsRaw = metrics;
nsIThebesFontMetrics* fm = NS_STATIC_CAST(nsIThebesFontMetrics*, metricsRaw);
return fm->GetThebesFontGroup();
}
static gfxTextRun*
GetSpecialString(gfxFontGroup* aFontGroup, gfxFontGroup::SpecialString aSpecial,
gfxTextRun* aTextRun)
{
if (!aFontGroup)
return nsnull;
return aFontGroup->GetSpecialStringTextRun(aSpecial, aTextRun);
}
static gfxFont::Metrics
GetFontMetrics(gfxFontGroup* aFontGroup)
{
if (!aFontGroup)
return gfxFont::Metrics();
gfxFont* font = aFontGroup->GetFontAt(0);
if (!font)
return gfxFont::Metrics();
return font->GetMetrics();
}
void void
BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
{ {
@ -1170,24 +1225,12 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) { if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) {
anyTextTransformStyle = PR_TRUE; anyTextTransformStyle = PR_TRUE;
} }
nscoord letterSpacing = StyleToCoord(textStyle->mLetterSpacing); textFlags |= GetSpacingFlags(textStyle->mLetterSpacing);
if (letterSpacing) { textFlags |= GetSpacingFlags(textStyle->mWordSpacing);
textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
if (letterSpacing < 0) {
textFlags |= gfxTextRunFactory::TEXT_ENABLE_NEGATIVE_SPACING;
}
}
PRBool compressWhitespace = !textStyle->WhiteSpaceIsSignificant(); PRBool compressWhitespace = !textStyle->WhiteSpaceIsSignificant();
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == textStyle->mTextAlign && compressWhitespace) { if (NS_STYLE_TEXT_ALIGN_JUSTIFY == textStyle->mTextAlign && compressWhitespace) {
textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING; textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
} }
nscoord wordSpacing = StyleToCoord(textStyle->mWordSpacing);
if (wordSpacing) {
textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
if (wordSpacing < 0) {
textFlags |= gfxTextRunFactory::TEXT_ENABLE_NEGATIVE_SPACING;
}
}
const nsStyleFont* fontStyle = f->GetStyleFont(); const nsStyleFont* fontStyle = f->GetStyleFont();
if (NS_STYLE_FONT_VARIANT_SMALL_CAPS == fontStyle->mFont.variant) { if (NS_STYLE_FONT_VARIANT_SMALL_CAPS == fontStyle->mFont.variant) {
anySmallcapsStyle = PR_TRUE; anySmallcapsStyle = PR_TRUE;
@ -1302,20 +1345,12 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
} }
// Now build the textrun // Now build the textrun
nsCOMPtr<nsIFontMetrics> metrics;
nsTextFrame* firstFrame = mMappedFlows[0].mStartFrame; nsTextFrame* firstFrame = mMappedFlows[0].mStartFrame;
nsIDeviceContext* devContext = firstFrame->GetPresContext()->DeviceContext(); gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame);
const nsStyleFont* fontStyle = firstFrame->GetStyleFont(); if (!fontGroup) {
const nsStyleVisibility* visibilityStyle = firstFrame->GetStyleVisibility();
devContext->GetMetricsFor(fontStyle->mFont, visibilityStyle->mLangGroup,
*getter_AddRefs(metrics));
if (!metrics) {
DestroyUserData(userData); DestroyUserData(userData);
return; return;
} }
nsIFontMetrics* metricsRaw = metrics;
nsIThebesFontMetrics* fm = NS_STATIC_CAST(nsIThebesFontMetrics*, metricsRaw);
gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
// Setup factory chain // Setup factory chain
gfxTextRunFactory* factory = fontGroup; gfxTextRunFactory* factory = fontGroup;
@ -1379,9 +1414,9 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
} }
gfxTextRunFactory::Parameters params = gfxTextRunFactory::Parameters params =
{ mContext, finalUserData, visibilityStyle->mLangGroup, &skipChars, { mContext, finalUserData, firstFrame->GetStyleVisibility()->mLangGroup, &skipChars,
textBreakPoints.Elements(), nextBreakIndex, textBreakPoints.Elements(), nextBreakIndex,
devContext->DevUnitsToAppUnits(), textFlags }; firstFrame->GetPresContext()->AppUnitsPerDevPixel(), textFlags };
gfxTextRun* textRun; gfxTextRun* textRun;
if (mDoubleByteText) { if (mDoubleByteText) {
@ -1535,6 +1570,7 @@ nsTextFrame::EnsureTextRun(nsIRenderingContext* aRC, nsBlockFrame* aBlock,
// Find the flow that contains us // Find the flow that contains us
PRInt32 direction; PRInt32 direction;
PRInt32 startAt = userData->mLastFlowIndex; PRInt32 startAt = userData->mLastFlowIndex;
// Search first forward and then backward from the current position
for (direction = 1; direction >= -1; direction -= 2) { for (direction = 1; direction >= -1; direction -= 2) {
PRInt32 i; PRInt32 i;
for (i = startAt; 0 <= i && i < userData->mMappedFlowCount; i += direction) { for (i = startAt; 0 <= i && i < userData->mMappedFlowCount; i += direction) {
@ -1692,13 +1728,14 @@ public:
PropertyProvider(gfxTextRun* aTextRun, const nsStyleText* aTextStyle, PropertyProvider(gfxTextRun* aTextRun, const nsStyleText* aTextStyle,
const nsTextFragment* aFrag, nsTextFrame* aFrame, const nsTextFragment* aFrag, nsTextFrame* aFrame,
const gfxSkipCharsIterator& aStart, PRInt32 aLength) const gfxSkipCharsIterator& aStart, PRInt32 aLength)
: mTextRun(aTextRun), mTextStyle(aTextStyle), mFrag(aFrag), : mTextRun(aTextRun), mFontGroup(nsnull), mTextStyle(aTextStyle), mFrag(aFrag),
mFrame(aFrame), mStart(aStart), mLength(aLength), mFrame(aFrame), mStart(aStart), mLength(aLength),
mWordSpacing(StyleToCoord(mTextStyle->mWordSpacing)), mWordSpacing(StyleToCoord(mTextStyle->mWordSpacing)),
mLetterSpacing(StyleToCoord(mTextStyle->mLetterSpacing)), mLetterSpacing(StyleToCoord(mTextStyle->mLetterSpacing)),
mJustificationSpacing(0), mJustificationSpacing(0),
mHyphenWidth(-1) mHyphenWidth(-1)
{ {
NS_ASSERTION(mStart.IsInitialized(), "Start not initialized?");
} }
/** /**
@ -1707,7 +1744,7 @@ public:
* *must* be called before this!!! * *must* be called before this!!!
*/ */
PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart) PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart)
: mTextRun(aFrame->GetTextRun()), mTextStyle(aFrame->GetStyleText()), : mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull), mTextStyle(aFrame->GetStyleText()),
mFrag(aFrame->GetContent()->GetText()), mFrag(aFrame->GetContent()->GetText()),
mFrame(aFrame), mStart(aStart), mLength(aFrame->GetContentLength()), mFrame(aFrame), mStart(aStart), mLength(aFrame->GetContentLength()),
mWordSpacing(StyleToCoord(mTextStyle->mWordSpacing)), mWordSpacing(StyleToCoord(mTextStyle->mWordSpacing)),
@ -1751,6 +1788,13 @@ public:
PRUint32 GetOriginalLength() { return mLength; } PRUint32 GetOriginalLength() { return mLength; }
const nsTextFragment* GetFragment() { return mFrag; } const nsTextFragment* GetFragment() { return mFrag; }
gfxFontGroup* GetFontGroup() {
if (!mFontGroup) {
mFontGroup = GetFontGroupForFrame(mFrame);
}
return mFontGroup;
}
protected: protected:
void SetupJustificationSpacing(); void SetupJustificationSpacing();
@ -1758,6 +1802,7 @@ protected:
PRUint8* ComputeTabSpaceCount(PRUint32 aOffset, PRUint32 aLength); PRUint8* ComputeTabSpaceCount(PRUint32 aOffset, PRUint32 aLength);
gfxTextRun* mTextRun; gfxTextRun* mTextRun;
gfxFontGroup* mFontGroup;
const nsStyleText* mTextStyle; const nsStyleText* mTextStyle;
const nsTextFragment* mFrag; const nsTextFragment* mFrag;
nsTextFrame* mFrame; nsTextFrame* mFrame;
@ -1972,8 +2017,12 @@ PropertyProvider::GetSpacing(PRUint32 aStart, PRUint32 aLength,
// for tabs, and how many. // for tabs, and how many.
// ComputeTabSpaceCount takes transformed string offsets. // ComputeTabSpaceCount takes transformed string offsets.
PRUint8* tabSpaceList = ComputeTabSpaceCount(aStart, aLength); PRUint8* tabSpaceList = ComputeTabSpaceCount(aStart, aLength);
gfxFloat spaceWidth = mTextRun->GetAdvanceWidthSpecialString(gfxTextRun::STRING_SPACE) + gfxTextRun* spaceTextRun =
mLetterSpacing + mWordSpacing; GetSpecialString(GetFontGroup(), gfxFontGroup::STRING_SPACE, mTextRun);
gfxFloat spaceWidth = mLetterSpacing + mWordSpacing;
if (spaceTextRun) {
spaceWidth += spaceTextRun->GetAdvanceWidth(0, spaceTextRun->GetLength(), nsnull);
}
for (index = 0; index < aLength; ++index) { for (index = 0; index < aLength; ++index) {
PRInt32 tabSpaces = tabSpaceList[index]; PRInt32 tabSpaces = tabSpaceList[index];
aSpacing[index].mAfter += spaceWidth*tabSpaces; aSpacing[index].mAfter += spaceWidth*tabSpaces;
@ -2035,7 +2084,12 @@ gfxFloat
PropertyProvider::GetHyphenWidth() PropertyProvider::GetHyphenWidth()
{ {
if (mHyphenWidth < 0) { if (mHyphenWidth < 0) {
mHyphenWidth = mTextRun->GetAdvanceWidthSpecialString(gfxTextRun::STRING_HYPHEN) + mLetterSpacing; gfxTextRun* hyphenTextRun =
GetSpecialString(GetFontGroup(), gfxFontGroup::STRING_HYPHEN, mTextRun);
mHyphenWidth = mLetterSpacing;
if (hyphenTextRun) {
mHyphenWidth += hyphenTextRun->GetAdvanceWidth(0, hyphenTextRun->GetLength(), nsnull);
}
} }
return mHyphenWidth; return mHyphenWidth;
} }
@ -2124,7 +2178,7 @@ PropertyProvider::SetupJustificationSpacing()
PRInt32 justifiableCharacters = PRInt32 justifiableCharacters =
ComputeJustifiableCharacters(mStart.GetOriginalOffset(), ComputeJustifiableCharacters(mStart.GetOriginalOffset(),
end.GetOriginalOffset()); end.GetOriginalOffset() - mStart.GetOriginalOffset());
if (justifiableCharacters == 0) { if (justifiableCharacters == 0) {
// Nothing to do, nothing is justifiable and we shouldn't have any // Nothing to do, nothing is justifiable and we shouldn't have any
// justification space assigned // justification space assigned
@ -3176,7 +3230,7 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext,
{ {
gfxRect r = aRect.Intersect(aDirtyRect); gfxRect r = aRect.Intersect(aDirtyRect);
// For now, we need to put this in pixel coordinates // For now, we need to put this in pixel coordinates
float t2p = 1.0/aPresContext->ScaledPixelsToTwips(); float t2p = 1.0/aPresContext->AppUnitsPerDevPixel();
aCtx->NewPath(); aCtx->NewPath();
// pixel-snap // pixel-snap
aCtx->Rectangle(gfxRect(r.X()*t2p, r.Y()*t2p, r.Width()*t2p, r.Height()*t2p), PR_TRUE); aCtx->Rectangle(gfxRect(r.X()*t2p, r.Y()*t2p, r.Width()*t2p, r.Height()*t2p), PR_TRUE);
@ -3187,7 +3241,8 @@ FillClippedRect(gfxContext* aCtx, nsPresContext* aPresContext,
void void
nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect, nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
const gfxPoint& aFramePt, const gfxPoint& aFramePt,
nsTextPaintStyle& aTextPaintStyle) nsTextPaintStyle& aTextPaintStyle,
PropertyProvider& aProvider)
{ {
// Quirks mode text decoration are rendered by children; see bug 1777 // Quirks mode text decoration are rendered by children; see bug 1777
// In non-quirks mode, nsHTMLContainer::Paint and nsBlockFrame::Paint // In non-quirks mode, nsHTMLContainer::Paint and nsBlockFrame::Paint
@ -3248,24 +3303,25 @@ nsTextFrame::PaintTextDecorations(gfxContext* aCtx, const gfxRect& aDirtyRect,
if (!decorations) if (!decorations)
return; return;
gfxFont::Metrics fontMetrics = mTextRun->GetDecorationMetrics(); gfxFont::Metrics fontMetrics = GetFontMetrics(aProvider.GetFontGroup());
gfxFloat pix2app = mTextRun->GetAppUnitsPerDevUnit();
if (decorations & NS_FONT_DECORATION_OVERLINE) { if (decorations & NS_FONT_DECORATION_OVERLINE) {
FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), overColor, aDirtyRect, FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), overColor, aDirtyRect,
gfxRect(aFramePt.x, aFramePt.y, gfxRect(aFramePt.x, aFramePt.y,
GetRect().width, fontMetrics.underlineSize)); GetRect().width, fontMetrics.underlineSize*pix2app));
} }
if (decorations & NS_FONT_DECORATION_UNDERLINE) { if (decorations & NS_FONT_DECORATION_UNDERLINE) {
FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), underColor, aDirtyRect, FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), underColor, aDirtyRect,
gfxRect(aFramePt.x, gfxRect(aFramePt.x,
aFramePt.y + mAscent - fontMetrics.underlineOffset, aFramePt.y + mAscent - fontMetrics.underlineOffset,
GetRect().width, fontMetrics.underlineSize)); GetRect().width, fontMetrics.underlineSize*pix2app));
} }
if (decorations & NS_FONT_DECORATION_LINE_THROUGH) { if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), strikeColor, aDirtyRect, FillClippedRect(aCtx, aTextPaintStyle.GetPresContext(), strikeColor, aDirtyRect,
gfxRect(aFramePt.x, gfxRect(aFramePt.x,
aFramePt.y + mAscent - fontMetrics.strikeoutOffset, aFramePt.y + mAscent - fontMetrics.strikeoutOffset,
GetRect().width, fontMetrics.strikeoutSize)); GetRect().width, fontMetrics.strikeoutSize*pix2app));
} }
} }
@ -3281,13 +3337,14 @@ static void DrawIMEUnderline(gfxContext* aContext, PRInt32 aIndex,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth,
const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics)
{ {
float p2t = aTextPaintStyle.GetPresContext()->AppUnitsPerDevPixel();
nscolor color; nscolor color;
float relativeSize; float relativeSize;
if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize)) if (!aTextPaintStyle.GetIMEUnderline(aIndex, &color, &relativeSize))
return; return;
gfxFloat y = aBaselinePt.y - aFontMetrics.underlineOffset; gfxFloat y = aBaselinePt.y - aFontMetrics.underlineOffset*p2t;
gfxFloat size = aFontMetrics.underlineSize; gfxFloat size = aFontMetrics.underlineSize*p2t;
FillClippedRect(aContext, aTextPaintStyle.GetPresContext(), FillClippedRect(aContext, aTextPaintStyle.GetPresContext(),
color, aDirtyRect, color, aDirtyRect,
gfxRect(aBaselinePt.x + size, y, gfxRect(aBaselinePt.x + size, y,
@ -3302,12 +3359,12 @@ static void DrawSelectionDecorations(gfxContext* aContext, SelectionType aType,
nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth, nsTextPaintStyle& aTextPaintStyle, const gfxPoint& aBaselinePt, gfxFloat aWidth,
const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics) const gfxRect& aDirtyRect, const gfxFont::Metrics& aFontMetrics)
{ {
float p2t = aTextPaintStyle.GetPresContext()->ScaledPixelsToTwips(); float p2t = aTextPaintStyle.GetPresContext()->AppUnitsPerDevPixel();
float t2p = 1/p2t; float t2p = 1/p2t;
switch (aType) { switch (aType) {
case nsISelectionController::SELECTION_SPELLCHECK: { case nsISelectionController::SELECTION_SPELLCHECK: {
gfxFloat y = (aBaselinePt.y - aFontMetrics.underlineOffset)*t2p; gfxFloat y = aBaselinePt.y*t2p - aFontMetrics.underlineOffset;
aContext->SetDash(gfxContext::gfxLineDotted); aContext->SetDash(gfxContext::gfxLineDotted);
aContext->SetColor(gfxRGBA(1.0, 0.0, 0.0)); aContext->SetColor(gfxRGBA(1.0, 0.0, 0.0));
aContext->SetLineWidth(1.0); aContext->SetLineWidth(1.0);
@ -3566,8 +3623,12 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
if (hyphenWidth) { if (hyphenWidth) {
// Draw the hyphen // Draw the hyphen
gfxFloat hyphenBaselineX = aFramePt.x + xOffset + mTextRun->GetDirection()*advance; gfxFloat hyphenBaselineX = aFramePt.x + xOffset + mTextRun->GetDirection()*advance;
mTextRun->DrawSpecialString(aCtx, gfxPoint(hyphenBaselineX, aTextBaselinePt.y), gfxTextRun* hyphenTextRun =
gfxTextRun::STRING_HYPHEN); GetSpecialString(aProvider.GetFontGroup(), gfxFontGroup::STRING_HYPHEN, mTextRun);
if (hyphenTextRun) {
hyphenTextRun->Draw(aCtx, gfxPoint(hyphenBaselineX, aTextBaselinePt.y),
0, hyphenTextRun->GetLength(), &aDirtyRect, nsnull, nsnull);
}
advance += hyphenWidth; advance += hyphenWidth;
} }
iterator.UpdateWithAdvance(advance); iterator.UpdateWithAdvance(advance);
@ -3607,7 +3668,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx,
sdptr = sdptr->mNext; sdptr = sdptr->mNext;
} }
gfxFont::Metrics decorationMetrics = mTextRun->GetDecorationMetrics(); gfxFont::Metrics decorationMetrics = GetFontMetrics(aProvider.GetFontGroup());
SelectionIterator iterator(selectedChars, contentOffset, contentLength, SelectionIterator iterator(selectedChars, contentOffset, contentLength,
aProvider, mTextRun); aProvider, mTextRun);
@ -3640,7 +3701,7 @@ nsTextFrame::PaintTextWithSelection(gfxContext* aCtx,
SelectionType allTypes; SelectionType allTypes;
PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect, PaintTextWithSelectionColors(aCtx, aFramePt, aTextBaselinePt, aDirtyRect,
aProvider, aTextPaintStyle, details, &allTypes); aProvider, aTextPaintStyle, details, &allTypes);
PaintTextDecorations(aCtx, aDirtyRect, aFramePt, aTextPaintStyle); PaintTextDecorations(aCtx, aDirtyRect, aFramePt, aTextPaintStyle, aProvider);
PRInt32 i; PRInt32 i;
// Iterate through just the selection types that paint decorations and // Iterate through just the selection types that paint decorations and
// paint decorations for any that actually occur in this frame. Paint // paint decorations for any that actually occur in this frame. Paint
@ -3714,10 +3775,14 @@ nsTextFrame::PaintText(nsIRenderingContext* aRenderingContext, nsPoint aPt,
&dirtyRect, &provider, needAdvanceWidth); &dirtyRect, &provider, needAdvanceWidth);
if (GetStateBits() & TEXT_HYPHEN_BREAK) { if (GetStateBits() & TEXT_HYPHEN_BREAK) {
gfxFloat hyphenBaselineX = textBaselinePt.x + mTextRun->GetDirection()*advanceWidth; gfxFloat hyphenBaselineX = textBaselinePt.x + mTextRun->GetDirection()*advanceWidth;
mTextRun->DrawSpecialString(ctx, gfxPoint(hyphenBaselineX, textBaselinePt.y), gfxTextRun* hyphenTextRun =
gfxTextRun::STRING_HYPHEN); GetSpecialString(provider.GetFontGroup(), gfxFontGroup::STRING_HYPHEN, mTextRun);
if (hyphenTextRun) {
hyphenTextRun->Draw(ctx, gfxPoint(hyphenBaselineX, textBaselinePt.y),
0, hyphenTextRun->GetLength(), &dirtyRect, nsnull, nsnull);
}
} }
PaintTextDecorations(ctx, dirtyRect, framePt, textPaintStyle); PaintTextDecorations(ctx, dirtyRect, framePt, textPaintStyle, provider);
} }
PRInt16 PRInt16
@ -4248,13 +4313,19 @@ FindFirstLetterRange(const nsTextFragment* aFrag,
} }
static void static void
AddCharToMetrics(gfxFloat aWidth, gfxTextRun::SpecialString aSpecial, gfxTextRun* aTextRun, AddCharToMetrics(gfxFloat aWidth, PropertyProvider* aProvider,
gfxFontGroup::SpecialString aSpecial, gfxTextRun* aTextRun,
gfxTextRun::Metrics* aMetrics, PRBool aTightBoundingBox) gfxTextRun::Metrics* aMetrics, PRBool aTightBoundingBox)
{ {
gfxRect charRect; gfxRect charRect;
if (aTightBoundingBox) { if (aTightBoundingBox) {
gfxTextRun::Metrics charMetrics = gfxTextRun* specialTextRun =
aTextRun->MeasureTextSpecialString(aSpecial, PR_TRUE); GetSpecialString(aProvider->GetFontGroup(), aSpecial, aTextRun);
gfxTextRun::Metrics charMetrics;
if (specialTextRun) {
charMetrics =
specialTextRun->MeasureText(0, specialTextRun->GetLength(), PR_TRUE, nsnull);
}
charRect = charMetrics.mBoundingBox; charRect = charMetrics.mBoundingBox;
} else { } else {
// assume char does not overflow font metrics!!! // assume char does not overflow font metrics!!!
@ -4317,7 +4388,8 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
PropertyProvider provider(this, iter); PropertyProvider provider(this, iter);
RunCharFlags flags(start, length, mTextRun); RunCharFlags flags(start, length, mTextRun);
nscoord maxAdvance = NSToCoordCeil(mTextRun->GetDecorationMetrics().maxAdvance); nscoord maxAdvance = NSToCoordCeil(
GetFontMetrics(provider.GetFontGroup()).maxAdvance*mTextRun->GetAppUnitsPerDevUnit());
PRBool leadingWord = PR_TRUE; PRBool leadingWord = PR_TRUE;
if (flags.GetFlags(0) & gfxTextRun::LINE_BREAK_BEFORE) { if (flags.GetFlags(0) & gfxTextRun::LINE_BREAK_BEFORE) {
@ -4360,10 +4432,11 @@ nsTextFrame::AddInlineMinWidthForFlow(nsIRenderingContext *aRenderingContext,
if (!GetStyleText()->WhiteSpaceIsSignificant()) { if (!GetStyleText()->WhiteSpaceIsSignificant()) {
// Measure whitespace which would be trimmed if this were the end of the line // Measure whitespace which would be trimmed if this were the end of the line
PRUint32 wordLength = PRUint32 wordEnd = wordStart +
GetLengthOfTrimmedText(provider.GetFragment(), wordStart, flowEndInTextRun, &iter); GetLengthOfTrimmedText(provider.GetFragment(), wordStart, flowEndInTextRun, &iter);
aData->trailingWhitespace += gfxFloat width = mTextRun->GetAdvanceWidth(wordEnd,
NSToCoordCeil(mTextRun->GetAdvanceWidth(wordStart + wordLength, flowEndInTextRun, &provider)); flowEndInTextRun - wordEnd, &provider);
aData->trailingWhitespace += NSToCoordCeil(width);
} }
} }
@ -4606,10 +4679,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
iter.SetOriginalOffset(offset); iter.SetOriginalOffset(offset);
PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length); PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length);
// Flush spacing cache to remove any justification/tabbing/letter/word spacing
// because those might have changed since the last reflow
PRUint32 transformedOffset = provider.GetStart().GetSkippedOffset(); PRUint32 transformedOffset = provider.GetStart().GetSkippedOffset();
mTextRun->FlushSpacingCache(transformedOffset);
// The metrics for the text go in here // The metrics for the text go in here
gfxTextRun::Metrics textMetrics; gfxTextRun::Metrics textMetrics;
@ -4716,7 +4786,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
} }
if (usedHyphenation) { if (usedHyphenation) {
// Fix up metrics to include hyphen // Fix up metrics to include hyphen
AddCharToMetrics(provider.GetHyphenWidth(), gfxTextRun::STRING_HYPHEN, AddCharToMetrics(provider.GetHyphenWidth(), &provider, gfxFontGroup::STRING_HYPHEN,
mTextRun, &textMetrics, needTightBoundingBox); mTextRun, &textMetrics, needTightBoundingBox);
AddStateBits(TEXT_HYPHEN_BREAK); AddStateBits(TEXT_HYPHEN_BREAK);
} }
@ -4732,7 +4802,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
end.SetOriginalOffset(offset + charsFit); end.SetOriginalOffset(offset + charsFit);
gfxFloat width = mTextRun->GetAdvanceWidth(currentEnd, gfxFloat width = mTextRun->GetAdvanceWidth(currentEnd,
end.GetSkippedOffset() - currentEnd, &provider); end.GetSkippedOffset() - currentEnd, &provider);
AddCharToMetrics(width, gfxTextRun::STRING_SPACE, mTextRun, &textMetrics, AddCharToMetrics(width, &provider, gfxFontGroup::STRING_SPACE, mTextRun, &textMetrics,
needTightBoundingBox); needTightBoundingBox);
suckedUpWhitespace = PR_TRUE; suckedUpWhitespace = PR_TRUE;
} }
@ -4849,7 +4919,6 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
"Justifiable characters combined???"); "Justifiable characters combined???");
lineLayout.SetTextJustificationWeights(numJustifiableCharacters, lineLayout.SetTextJustificationWeights(numJustifiableCharacters,
textMetrics.mClusterCount - numJustifiableCharacters); textMetrics.mClusterCount - numJustifiableCharacters);
mTextRun->FlushSpacingCache(provider.GetStart().GetSkippedOffset());
} }
if (layoutDependentTextRun) { if (layoutDependentTextRun) {

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

@ -80,16 +80,7 @@ class WrapperTextRun : public gfxTextRun {
public: public:
WrapperTextRun(gfxTextRun* aInner, gfxTextRunFactory::Parameters* aParams) WrapperTextRun(gfxTextRun* aInner, gfxTextRunFactory::Parameters* aParams)
// WrapperTextRuns always take Unicode // WrapperTextRuns always take Unicode
: gfxTextRun(aParams, PR_FALSE), mInner(aInner) {} : gfxTextRun(aParams), mInner(aInner) {}
virtual void DrawSpecialString(gfxContext *aContext, gfxPoint aPt, SpecialString aString)
{ mInner->DrawSpecialString(aContext, aPt, aString); }
virtual gfxFloat GetAdvanceWidthSpecialString(SpecialString aString)
{ return mInner->GetAdvanceWidthSpecialString(aString); }
virtual Metrics MeasureTextSpecialString(SpecialString aString, PRBool aTightBoundingBox)
{ return mInner->MeasureTextSpecialString(aString, aTightBoundingBox); }
virtual gfxFont::Metrics GetDecorationMetrics()
{ return mInner->GetDecorationMetrics(); }
protected: protected:
nsAutoPtr<gfxTextRun> mInner; nsAutoPtr<gfxTextRun> mInner;
@ -191,11 +182,6 @@ public:
TranslateSubstring(&aStart, &aLength); TranslateSubstring(&aStart, &aLength);
return mInner->GetAdvanceWidth(aStart, aLength, &wrapper); return mInner->GetAdvanceWidth(aStart, aLength, &wrapper);
} }
virtual void FlushSpacingCache(PRUint32 aStart)
{
TranslateOffset(&aStart);
mInner->FlushSpacingCache(aStart);
}
// Tricky forwarding where output conversion is required // Tricky forwarding where output conversion is required
virtual void GetCharFlags(PRUint32 aStart, PRUint32 aLength, PRUint8* aFlags); virtual void GetCharFlags(PRUint32 aStart, PRUint32 aLength, PRUint8* aFlags);
@ -491,7 +477,6 @@ public:
gfxFloat* aAdvanceWidthDelta); gfxFloat* aAdvanceWidthDelta);
virtual gfxFloat GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength, virtual gfxFloat GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
PropertyProvider* aBreakProvider); PropertyProvider* aBreakProvider);
virtual void FlushSpacingCache(PRUint32 aStart);
virtual void GetCharFlags(PRUint32 aStart, PRUint32 aLength, PRUint8* aFlags); virtual void GetCharFlags(PRUint32 aStart, PRUint32 aLength, PRUint8* aFlags);
virtual PRUint32 BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength, virtual PRUint32 BreakAndMeasureText(PRUint32 aStart, PRUint32 aMaxLength,
PRBool aLineBreakBefore, gfxFloat aWidth, PRBool aLineBreakBefore, gfxFloat aWidth,
@ -818,19 +803,6 @@ nsMultiTextRun::GetAdvanceWidth(PRUint32 aStart, PRUint32 aLength,
return result; return result;
} }
void
nsMultiTextRun::FlushSpacingCache(PRUint32 aStart)
{
PRUint32 index = FindChildIndexContaining(aStart);
ChildRun* child = &mRuns[index];
child->mChild->FlushSpacingCache(aStart - child->mOffset);
while (index + 1 < mRuns.Length()) {
++index;
child = &mRuns[index];
child->mChild->FlushSpacingCache(0);
}
}
// ============================== // ==============================
// Now define factories that use the above textruns // Now define factories that use the above textruns
// ============================== // ==============================
@ -842,7 +814,7 @@ GetParametersForInner(const gfxTextRunFactory::Parameters& aParams,
gfxTextRunFactory::Parameters params = gfxTextRunFactory::Parameters params =
{ aParams.mContext, nsnull, aParams.mLangGroup, aDummy, { aParams.mContext, nsnull, aParams.mLangGroup, aDummy,
aParams.mInitialBreaks, aParams.mInitialBreakCount, aParams.mInitialBreaks, aParams.mInitialBreakCount,
aParams.mPixelsToUnits, aParams.mFlags }; aParams.mAppUnitsPerDevUnit, aParams.mFlags };
return params; return params;
} }
@ -947,7 +919,7 @@ public:
: nsMultiTextRun(aBaseTextRun, aParams), mString(aString, aLength), : nsMultiTextRun(aBaseTextRun, aParams), mString(aString, aLength),
mFactory(aFactory), mRefContext(aParams->mContext), mFactory(aFactory), mRefContext(aParams->mContext),
mLangGroup(aParams->mLangGroup), mLangGroup(aParams->mLangGroup),
mPixelsToUnits(aParams->mPixelsToUnits), mAppUnitsPerDevUnit(aParams->mAppUnitsPerDevUnit),
mFlags(aParams->mFlags) mFlags(aParams->mFlags)
{ {
PRUint32 i; PRUint32 i;
@ -978,7 +950,7 @@ private:
nsTArray<PRUint32> mLineBreaks; nsTArray<PRUint32> mLineBreaks;
nsTArray<PRPackedBool> mLineBreakOpportunities; nsTArray<PRPackedBool> mLineBreakOpportunities;
nsTArray<nsRefPtr<nsStyleContext> > mStyles; nsTArray<nsRefPtr<nsStyleContext> > mStyles;
gfxFloat mPixelsToUnits; gfxFloat mAppUnitsPerDevUnit;
PRUint32 mFlags; PRUint32 mFlags;
}; };
@ -1056,7 +1028,7 @@ nsCaseTransformingTextRun::Build()
gfxSkipChars dummy; gfxSkipChars dummy;
gfxTextRunFactory::Parameters innerParams = gfxTextRunFactory::Parameters innerParams =
{ mRefContext, nsnull, mLangGroup, &dummy, mLineBreaks.Elements(), { mRefContext, nsnull, mLangGroup, &dummy, mLineBreaks.Elements(),
mLineBreaks.Length(), mPixelsToUnits, mLineBreaks.Length(), PRUint32(mAppUnitsPerDevUnit),
mFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT }; mFlags | gfxTextRunFactory::TEXT_IS_PERSISTENT };
if (mFactory->GetInnerTransformingTextRunFactory()) { if (mFactory->GetInnerTransformingTextRunFactory()) {