--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5125,24 +5125,25 @@ struct EmphasisMarkInfo
UniquePtr<gfxTextRun> textRun;
gfxFloat advance;
gfxFloat baselineOffset;
};
NS_DECLARE_FRAME_PROPERTY_DELETABLE(EmphasisMarkProperty, EmphasisMarkInfo)
UniquePtr<gfxTextRun>
-GenerateTextRunForEmphasisMarks(nsTextFrame* aFrame, nsFontMetrics* aFontMetrics,
- WritingMode aWM, const nsStyleText* aStyleText)
+GenerateTextRunForEmphasisMarks(nsTextFrame* aFrame,
+ nsFontMetrics* aFontMetrics,
+ nsStyleContext* aStyleContext,
+ const nsStyleText* aStyleText)
{
const nsString& emphasisString = aStyleText->mTextEmphasisStyleString;
RefPtr<DrawTarget> dt = CreateReferenceDrawTarget(aFrame);
auto appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
- uint32_t flags = nsLayoutUtils::
- GetTextRunOrientFlagsForStyle(aFrame->StyleContext());
+ uint32_t flags = nsLayoutUtils::GetTextRunOrientFlagsForStyle(aStyleContext);
if (flags == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED) {
// The emphasis marks should always be rendered upright per spec.
flags = gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT;
}
return aFontMetrics->GetThebesFontGroup()->
MakeTextRun<char16_t>(emphasisString.get(), emphasisString.Length(),
dt, appUnitsPerDevUnit, flags, nullptr);
}
@@ -5164,34 +5165,41 @@ nsRect
nsTextFrame::UpdateTextEmphasis(WritingMode aWM, PropertyProvider& aProvider)
{
const nsStyleText* styleText = StyleText();
if (!styleText->HasTextEmphasis()) {
Properties().Delete(EmphasisMarkProperty());
return nsRect();
}
+ nsStyleContext* styleContext = StyleContext();
+ bool isTextCombined = styleContext->IsTextCombined();
+ if (isTextCombined) {
+ styleContext = styleContext->GetParent();
+ }
RefPtr<nsFontMetrics> fm = nsLayoutUtils::
- GetFontMetricsOfEmphasisMarks(StyleContext(), GetFontSizeInflation());
+ GetFontMetricsOfEmphasisMarks(styleContext, GetFontSizeInflation());
EmphasisMarkInfo* info = new EmphasisMarkInfo;
info->textRun =
- GenerateTextRunForEmphasisMarks(this, fm, aWM, styleText);
+ GenerateTextRunForEmphasisMarks(this, fm, styleContext, styleText);
info->advance = info->textRun->GetAdvanceWidth();
// Calculate the baseline offset
LogicalSide side = styleText->TextEmphasisSide(aWM);
- nsFontMetrics* baseFontMetrics = aProvider.GetFontMetrics();
- LogicalSize frameSize = GetLogicalSize();
+ LogicalSize frameSize = GetLogicalSize(aWM);
// The overflow rect is inflated in the inline direction by half
// advance of the emphasis mark on each side, so that even if a mark
// is drawn for a zero-width character, it won't be clipped.
LogicalRect overflowRect(aWM, -info->advance / 2,
- /* BStart to be computed below */0,
+ /* BStart to be computed below */ 0,
frameSize.ISize(aWM) + info->advance,
fm->MaxAscent() + fm->MaxDescent());
+ RefPtr<nsFontMetrics> baseFontMetrics = isTextCombined
+ ? nsLayoutUtils::GetInflatedFontMetricsForFrame(GetParent())
+ : do_AddRef(aProvider.GetFontMetrics());
// When the writing mode is vertical-lr the line is inverted, and thus
// the ascent and descent are swapped.
nscoord absOffset = (side == eLogicalSideBStart) != aWM.IsLineInverted() ?
baseFontMetrics->MaxAscent() + fm->MaxDescent() :
baseFontMetrics->MaxDescent() + fm->MaxAscent();
nscoord startLeading = 0;
nscoord endLeading = 0;
if (nsRubyFrame* ruby = FindRubyAncestor(this)) {
@@ -5200,16 +5208,21 @@ nsTextFrame::UpdateTextEmphasis(WritingM
if (side == eLogicalSideBStart) {
info->baselineOffset = -absOffset - startLeading;
overflowRect.BStart(aWM) = -overflowRect.BSize(aWM) - startLeading;
} else {
MOZ_ASSERT(side == eLogicalSideBEnd);
info->baselineOffset = absOffset + endLeading;
overflowRect.BStart(aWM) = frameSize.BSize(aWM) + endLeading;
}
+ // If text combined, fix the gap between the text frame and its parent.
+ if (isTextCombined) {
+ nscoord gap = (baseFontMetrics->MaxHeight() - frameSize.BSize(aWM)) / 2;
+ overflowRect.BStart(aWM) += gap * (side == eLogicalSideBStart ? -1 : 1);
+ }
Properties().Set(EmphasisMarkProperty(), info);
return overflowRect.GetPhysicalRect(aWM, frameSize.GetPhysicalSize(aWM));
}
void
nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext,
nsIFrame* aBlock,
@@ -6179,40 +6192,58 @@ nsTextFrame::PaintTextWithSelection(
DestroySelectionDetails(details);
return true;
}
void
nsTextFrame::DrawEmphasisMarks(gfxContext* aContext, WritingMode aWM,
const gfxPoint& aTextBaselinePt,
- Range aRange,
+ const gfxPoint& aFramePt, Range aRange,
const nscolor* aDecorationOverrideColor,
PropertyProvider* aProvider)
{
const auto info = Properties().Get(EmphasisMarkProperty());
if (!info) {
return;
}
+ bool isTextCombined = StyleContext()->IsTextCombined();
nscolor color = aDecorationOverrideColor ? *aDecorationOverrideColor :
nsLayoutUtils::GetColor(this, eCSSProperty_text_emphasis_color);
aContext->SetColor(Color::FromABGR(color));
- gfxPoint pt(aTextBaselinePt);
+ gfxPoint pt;
+ if (!isTextCombined) {
+ pt = aTextBaselinePt;
+ } else {
+ MOZ_ASSERT(aWM.IsVertical());
+ pt = aFramePt;
+ if (aWM.IsVerticalRL()) {
+ pt.x += GetSize().width - GetLogicalBaseline(aWM);
+ } else {
+ pt.x += GetLogicalBaseline(aWM);
+ }
+ }
if (!aWM.IsVertical()) {
pt.y += info->baselineOffset;
} else {
if (aWM.IsVerticalRL()) {
pt.x -= info->baselineOffset;
} else {
pt.x += info->baselineOffset;
}
}
- mTextRun->DrawEmphasisMarks(aContext, info->textRun.get(), info->advance,
- pt, aRange, aProvider);
+ if (!isTextCombined) {
+ mTextRun->DrawEmphasisMarks(aContext, info->textRun.get(), info->advance,
+ pt, aRange, aProvider);
+ } else {
+ pt.y += (GetSize().height - info->advance) / 2;
+ info->textRun->Draw(Range(info->textRun.get()), pt,
+ gfxTextRun::DrawParams(aContext));
+ }
}
nscolor
nsTextFrame::GetCaretColorAt(int32_t aOffset)
{
NS_PRECONDITION(aOffset >= 0, "aOffset must be positive");
nscolor result = nsFrame::GetCaretColorAt(aOffset);
@@ -6758,17 +6789,18 @@ nsTextFrame::DrawTextRunAndDecorations(R
}
// CSS 2.1 mandates that text be painted after over/underlines,
// and *then* line-throughs
DrawTextRun(aRange, aTextBaselinePt, aParams);
}
// Emphasis marks
- DrawEmphasisMarks(aParams.context, wm, aTextBaselinePt, aRange,
+ DrawEmphasisMarks(aParams.context, wm,
+ aTextBaselinePt, aParams.framePt, aRange,
aParams.decorationOverrideColor, aParams.provider);
// Line-throughs
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
for (const LineDecoration& dec : Reversed(aDecorations.mStrikes)) {
paintDecorationLine(dec, &Metrics::strikeoutSize,
&Metrics::strikeoutOffset);
}
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -453,17 +453,17 @@ public:
// helper: paint text decorations for text selected by aSelectionType
void PaintTextSelectionDecorations(const PaintTextSelectionParams& aParams,
SelectionDetails* aDetails,
SelectionType aSelectionType);
void DrawEmphasisMarks(gfxContext* aContext,
mozilla::WritingMode aWM,
const gfxPoint& aTextBaselinePt,
- Range aRange,
+ const gfxPoint& aFramePt, Range aRange,
const nscolor* aDecorationOverrideColor,
PropertyProvider* aProvider);
virtual nscolor GetCaretColorAt(int32_t aOffset) override;
int16_t GetSelectionStatus(int16_t* aSelectionFlags);
int32_t GetContentOffset() const { return mContentOffset; }