--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -368,18 +368,19 @@ nsFontMetrics::DrawString(const char *aS
Range range(0, aLength);
if (mTextRunRTL) {
if (mVertical) {
pt.y += textRun->GetAdvanceWidth(range, &provider);
} else {
pt.x += textRun->GetAdvanceWidth(range, &provider);
}
}
- textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL,
- range, &provider, nullptr, nullptr);
+ gfxTextRun::DrawParams params(aContext->ThebesContext());
+ params.provider = &provider;
+ textRun->Draw(range, pt, params);
}
void
nsFontMetrics::DrawString(const char16_t* aString, uint32_t aLength,
nscoord aX, nscoord aY,
nsRenderingContext *aContext,
DrawTarget* aTextRunConstructionDrawTarget)
{
@@ -395,18 +396,19 @@ nsFontMetrics::DrawString(const char16_t
Range range(0, aLength);
if (mTextRunRTL) {
if (mVertical) {
pt.y += textRun->GetAdvanceWidth(range, &provider);
} else {
pt.x += textRun->GetAdvanceWidth(range, &provider);
}
}
- textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL,
- range, &provider, nullptr, nullptr);
+ gfxTextRun::DrawParams params(aContext->ThebesContext());
+ params.provider = &provider;
+ textRun->Draw(range, pt, params);
}
static nsBoundingMetrics
GetTextBoundingMetrics(nsFontMetrics* aMetrics, const char16_t* aString,
uint32_t aLength, mozilla::gfx::DrawTarget* aDrawTarget,
gfxFont::BoundingBoxType aType)
{
if (aLength == 0)
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -1939,16 +1939,17 @@ gfxFont::DrawGlyphs(gfxShapedText
// This method is mostly parallel to DrawGlyphs.
void
gfxFont::DrawEmphasisMarks(gfxTextRun* aShapedText, gfxPoint* aPt,
uint32_t aOffset, uint32_t aCount,
const EmphasisMarkDrawParams& aParams)
{
gfxFloat& inlineCoord = aParams.isVertical ? aPt->y : aPt->x;
gfxTextRun::Range markRange(aParams.mark);
+ gfxTextRun::DrawParams params(aParams.context);
gfxFloat clusterStart = -std::numeric_limits<gfxFloat>::infinity();
bool shouldDrawEmphasisMark = false;
for (uint32_t i = 0, idx = aOffset; i < aCount; ++i, ++idx) {
if (aParams.spacing) {
inlineCoord += aParams.direction * aParams.spacing[i].mBefore;
}
if (aShapedText->IsClusterStart(idx) ||
@@ -1960,18 +1961,17 @@ gfxFont::DrawEmphasisMarks(gfxTextRun* a
}
inlineCoord += aParams.direction * aShapedText->GetAdvanceForGlyph(idx);
if (shouldDrawEmphasisMark &&
(i + 1 == aCount || aShapedText->IsClusterStart(idx + 1))) {
gfxFloat clusterAdvance = inlineCoord - clusterStart;
// Move the coord backward to get the needed start point.
gfxFloat delta = (clusterAdvance + aParams.advance) / 2;
inlineCoord -= delta;
- aParams.mark->Draw(aParams.context, *aPt, DrawMode::GLYPH_FILL,
- markRange, nullptr, nullptr, nullptr);
+ aParams.mark->Draw(markRange, *aPt, params);
inlineCoord += delta;
shouldDrawEmphasisMark = false;
}
if (aParams.spacing) {
inlineCoord += aParams.direction * aParams.spacing[i].mAfter;
}
}
}
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -559,133 +559,131 @@ struct BufferAlphaColor {
mContext->PopGroupAndBlend();
mContext->Restore();
}
gfxContext *mContext;
};
void
-gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
- Range aRange,
- PropertyProvider *aProvider, gfxFloat *aAdvanceWidth,
- gfxTextContextPaint *aContextPaint,
- gfxTextRunDrawCallbacks *aCallbacks)
+gfxTextRun::Draw(Range aRange, gfxPoint aPt, const DrawParams& aParams)
{
NS_ASSERTION(aRange.end <= GetLength(), "Substring out of range");
- NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH ||
- !(int(aDrawMode) & int(DrawMode::GLYPH_PATH)),
+ NS_ASSERTION(aParams.drawMode == DrawMode::GLYPH_PATH ||
+ !(int(aParams.drawMode) & int(DrawMode::GLYPH_PATH)),
"GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH");
- NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH || !aCallbacks,
+ NS_ASSERTION(aParams.drawMode == DrawMode::GLYPH_PATH || !aParams.callbacks,
"callback must not be specified unless using GLYPH_PATH");
bool skipDrawing = mSkipDrawing;
- if (aDrawMode == DrawMode::GLYPH_FILL) {
+ if (aParams.drawMode == DrawMode::GLYPH_FILL) {
Color currentColor;
- if (aContext->GetDeviceColor(currentColor) && currentColor.a == 0) {
+ if (aParams.context->GetDeviceColor(currentColor) &&
+ currentColor.a == 0) {
skipDrawing = true;
}
}
gfxFloat direction = GetDirection();
if (skipDrawing) {
// We don't need to draw anything;
// but if the caller wants advance width, we need to compute it here
- if (aAdvanceWidth) {
- gfxTextRun::Metrics metrics = MeasureText(aRange,
- gfxFont::LOOSE_INK_EXTENTS,
- aContext->GetDrawTarget(),
- aProvider);
- *aAdvanceWidth = metrics.mAdvanceWidth * direction;
+ if (aParams.advanceWidth) {
+ gfxTextRun::Metrics metrics = MeasureText(
+ aRange, gfxFont::LOOSE_INK_EXTENTS,
+ aParams.context->GetDrawTarget(), aParams.provider);
+ *aParams.advanceWidth = metrics.mAdvanceWidth * direction;
}
// return without drawing
return;
}
// synthetic bolding draws glyphs twice ==> colors with opacity won't draw
// correctly unless first drawn without alpha
- BufferAlphaColor syntheticBoldBuffer(aContext);
+ BufferAlphaColor syntheticBoldBuffer(aParams.context);
Color currentColor;
bool needToRestore = false;
- if (aDrawMode == DrawMode::GLYPH_FILL &&
- HasNonOpaqueNonTransparentColor(aContext, currentColor) &&
+ if (aParams.drawMode == DrawMode::GLYPH_FILL &&
+ HasNonOpaqueNonTransparentColor(aParams.context, currentColor) &&
HasSyntheticBoldOrColor(this, aRange)) {
needToRestore = true;
// measure text, use the bounding box
- gfxTextRun::Metrics metrics = MeasureText(aRange,
- gfxFont::LOOSE_INK_EXTENTS,
- aContext->GetDrawTarget(),
- aProvider);
+ gfxTextRun::Metrics metrics = MeasureText(
+ aRange, gfxFont::LOOSE_INK_EXTENTS,
+ aParams.context->GetDrawTarget(), aParams.provider);
metrics.mBoundingBox.MoveBy(aPt);
syntheticBoldBuffer.PushSolidColor(metrics.mBoundingBox, currentColor,
GetAppUnitsPerDevUnit());
}
// Set up parameters that will be constant across all glyph runs we need
// to draw, regardless of the font used.
TextRunDrawParams params;
- params.context = aContext;
+ params.context = aParams.context;
params.devPerApp = 1.0 / double(GetAppUnitsPerDevUnit());
params.isVerticalRun = IsVertical();
params.isRTL = IsRightToLeft();
params.direction = direction;
- params.drawMode = aDrawMode;
- params.callbacks = aCallbacks;
- params.runContextPaint = aContextPaint;
- params.paintSVGGlyphs = !aCallbacks || aCallbacks->mShouldPaintSVGGlyphs;
- params.dt = aContext->GetDrawTarget();
- params.fontSmoothingBGColor = aContext->GetFontSmoothingBackgroundColor();
+ params.drawMode = aParams.drawMode;
+ params.callbacks = aParams.callbacks;
+ params.runContextPaint = aParams.contextPaint;
+ params.paintSVGGlyphs = !aParams.callbacks ||
+ aParams.callbacks->mShouldPaintSVGGlyphs;
+ params.dt = aParams.context->GetDrawTarget();
+ params.fontSmoothingBGColor =
+ aParams.context->GetFontSmoothingBackgroundColor();
GlyphRunIterator iter(this, aRange);
gfxFloat advance = 0.0;
while (iter.NextRun()) {
gfxFont *font = iter.GetGlyphRun()->mFont;
uint32_t start = iter.GetStringStart();
uint32_t end = iter.GetStringEnd();
Range ligatureRange(start, end);
ShrinkToLigatureBoundaries(&ligatureRange);
- bool drawPartial = aDrawMode == DrawMode::GLYPH_FILL ||
- (aDrawMode == DrawMode::GLYPH_PATH && aCallbacks);
+ bool drawPartial = aParams.drawMode == DrawMode::GLYPH_FILL ||
+ (aParams.drawMode == DrawMode::GLYPH_PATH &&
+ aParams.callbacks);
gfxPoint origPt = aPt;
if (drawPartial) {
DrawPartialLigature(font, Range(start, ligatureRange.start),
- &aPt, aProvider, params,
+ &aPt, aParams.provider, params,
iter.GetGlyphRun()->mOrientation);
}
DrawGlyphs(font, ligatureRange, &aPt,
- aProvider, ligatureRange, params,
+ aParams.provider, ligatureRange, params,
iter.GetGlyphRun()->mOrientation);
if (drawPartial) {
DrawPartialLigature(font, Range(ligatureRange.end, end),
- &aPt, aProvider, params,
+ &aPt, aParams.provider, params,
iter.GetGlyphRun()->mOrientation);
}
if (params.isVerticalRun) {
advance += (aPt.y - origPt.y) * params.direction;
} else {
advance += (aPt.x - origPt.x) * params.direction;
}
}
// composite result when synthetic bolding used
if (needToRestore) {
syntheticBoldBuffer.PopAlpha();
}
- if (aAdvanceWidth) {
- *aAdvanceWidth = advance;
+ if (aParams.advanceWidth) {
+ *aParams.advanceWidth = advance;
}
}
// This method is mostly parallel to Draw().
void
gfxTextRun::DrawEmphasisMarks(gfxContext *aContext, gfxTextRun* aMark,
gfxFloat aMarkAdvance, gfxPoint aPt,
Range aRange, PropertyProvider* aProvider)
--- a/gfx/thebes/gfxTextRun.h
+++ b/gfx/thebes/gfxTextRun.h
@@ -227,42 +227,49 @@ public:
gfxFloat ClusterAdvance(PropertyProvider *aProvider) const;
private:
gfxTextRun *mTextRun;
uint32_t mCurrentChar;
};
+ struct DrawParams
+ {
+ gfxContext* context;
+ DrawMode drawMode = DrawMode::GLYPH_FILL;
+ PropertyProvider* provider = nullptr;
+ // If non-null, the advance width of the substring is set.
+ gfxFloat* advanceWidth = nullptr;
+ gfxTextContextPaint* contextPaint = nullptr;
+ gfxTextRunDrawCallbacks* callbacks = nullptr;
+ explicit DrawParams(gfxContext* aContext) : context(aContext) {}
+ };
+
/**
* Draws a substring. Uses only GetSpacing from aBreakProvider.
* The provided point is the baseline origin on the left of the string
* for LTR, on the right of the string for RTL.
- * @param aAdvanceWidth if non-null, the advance width of the substring
- * is returned here.
*
* Drawing should respect advance widths in the sense that for LTR runs,
- * Draw(ctx, pt, Range(start, middle), dirty, &provider, &advance) followed by
- * Draw(ctx, gfxPoint(pt.x + advance, pt.y), Range(middle, end),
- * dirty, &provider, nullptr) should have the same effect as
- * Draw(ctx, pt, Range(start, end), dirty, &provider, nullptr).
+ * Draw(Range(start, middle), pt, ...) followed by
+ * Draw(Range(middle, end), gfxPoint(pt.x + advance, pt.y), ...)
+ * should have the same effect as
+ * Draw(Range(start, end), pt, ...)
+ *
* For RTL runs the rule is:
- * Draw(ctx, pt, Range(middle, end), dirty, &provider, &advance) followed by
- * Draw(ctx, gfxPoint(pt.x + advance, pt.y), Range(start, middle),
- * dirty, &provider, nullptr) should have the same effect as
- * Draw(ctx, pt, Range(start, end), dirty, &provider, nullptr).
+ * Draw(Range(middle, end), pt, ...) followed by
+ * Draw(Range(start, middle), gfxPoint(pt.x + advance, pt.y), ...)
+ * should have the same effect as
+ * Draw(Range(start, end), pt, ...)
*
* Glyphs should be drawn in logical content order, which can be significant
* if they overlap (perhaps due to negative spacing).
*/
- void Draw(gfxContext *aContext, gfxPoint aPt,
- DrawMode aDrawMode, Range aRange,
- PropertyProvider *aProvider,
- gfxFloat *aAdvanceWidth, gfxTextContextPaint *aContextPaint,
- gfxTextRunDrawCallbacks *aCallbacks = nullptr);
+ void Draw(Range aRange, gfxPoint aPt, const DrawParams& aParams);
/**
* Draws the emphasis marks for this text run. Uses only GetSpacing
* from aProvider. The provided point is the baseline origin of the
* line of emphasis marks.
*/
void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
gfxFloat aMarkAdvance, gfxPoint aPt,
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -247,18 +247,18 @@ nsDisplayTextOverflowMarker::PaintTextTo
pt += aOffsetFromRect;
if (mStyle->mType == NS_STYLE_TEXT_OVERFLOW_ELLIPSIS) {
gfxTextRun* textRun = GetEllipsisTextRun(mFrame);
if (textRun) {
NS_ASSERTION(!textRun->IsRightToLeft(),
"Ellipsis textruns should always be LTR!");
gfxPoint gfxPt(pt.x, pt.y);
- textRun->Draw(aCtx->ThebesContext(), gfxPt, DrawMode::GLYPH_FILL,
- gfxTextRun::Range(textRun), nullptr, nullptr, nullptr);
+ textRun->Draw(gfxTextRun::Range(textRun), gfxPt,
+ gfxTextRun::DrawParams(aCtx->ThebesContext()));
}
} else {
RefPtr<nsFontMetrics> fm;
nsLayoutUtils::GetFontMetricsForFrame(mFrame, getter_AddRefs(fm),
nsLayoutUtils::FontSizeInflationFor(mFrame));
nsLayoutUtils::DrawString(mFrame, *fm, aCtx, mStyle->mString.get(),
mStyle->mString.Length(), pt);
}
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -6581,27 +6581,30 @@ DrawTextRun(gfxTextRun* aTextRun,
const gfxPoint& aTextBaselinePt,
gfxTextRun::Range aRange,
PropertyProvider* aProvider,
nscolor aTextColor,
gfxFloat* aAdvanceWidth,
gfxTextContextPaint* aContextPaint,
nsTextFrame::DrawPathCallbacks* aCallbacks)
{
- DrawMode drawMode = aCallbacks ? DrawMode::GLYPH_PATH :
- DrawMode::GLYPH_FILL;
+ gfxTextRun::DrawParams params(aCtx);
+ params.drawMode = aCallbacks ? DrawMode::GLYPH_PATH
+ : DrawMode::GLYPH_FILL;
+ params.provider = aProvider;
+ params.advanceWidth = aAdvanceWidth;
+ params.contextPaint = aContextPaint;
+ params.callbacks = aCallbacks;
if (aCallbacks) {
aCallbacks->NotifyBeforeText(aTextColor);
- aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aRange,
- aProvider, aAdvanceWidth, aContextPaint, aCallbacks);
+ aTextRun->Draw(aRange, aTextBaselinePt, params);
aCallbacks->NotifyAfterText();
} else {
aCtx->SetColor(Color::FromABGR(aTextColor));
- aTextRun->Draw(aCtx, aTextBaselinePt, drawMode, aRange,
- aProvider, aAdvanceWidth, aContextPaint);
+ aTextRun->Draw(aRange, aTextBaselinePt, params);
}
}
void
nsTextFrame::DrawTextRun(gfxContext* const aCtx,
const gfxPoint& aTextBaselinePt,
Range aRange,
PropertyProvider& aProvider,
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -2141,19 +2141,18 @@ nsMathMLChar::PaintForeground(nsPresCont
switch(mDraw)
{
case DRAW_NORMAL:
case DRAW_VARIANT:
// draw a single glyph (base size or size variant)
// XXXfredw verify if mGlyphs[0] is non-null to workaround bug 973322.
if (mGlyphs[0]) {
- mGlyphs[0]->Draw(thebesContext, gfxPoint(0.0, mUnscaledAscent),
- DrawMode::GLYPH_FILL, Range(mGlyphs[0]),
- nullptr, nullptr, nullptr);
+ mGlyphs[0]->Draw(Range(mGlyphs[0]), gfxPoint(0.0, mUnscaledAscent),
+ gfxTextRun::DrawParams(thebesContext));
}
break;
case DRAW_PARTS: {
// paint by parts
if (NS_STRETCH_DIRECTION_VERTICAL == mDirection)
PaintVertically(aPresContext, thebesContext, r, fgColor);
else if (NS_STRETCH_DIRECTION_HORIZONTAL == mDirection)
PaintHorizontally(aPresContext, thebesContext, r, fgColor);
@@ -2270,16 +2269,18 @@ nsMathMLChar::PaintVertically(nsPresCont
}
nsRect unionRect = aRect;
unionRect.x += mBoundingMetrics.leftBearing;
unionRect.width =
mBoundingMetrics.rightBearing - mBoundingMetrics.leftBearing;
unionRect.Inflate(oneDevPixel, oneDevPixel);
+ gfxTextRun::DrawParams params(aThebesContext);
+
/////////////////////////////////////
// draw top, middle, bottom
for (i = 0; i <= 2; ++i) {
// glue can be null
if (mGlyphs[i]) {
nscoord dy = offset[i];
// Draw a glyph in a clipped area so that we don't have hairy chars
// pending outside
@@ -2298,19 +2299,17 @@ nsMathMLChar::PaintVertically(nsPresCont
}
else { // middle
clipRect.y = start[i];
clipRect.height = end[i] - start[i];
}
}
if (!clipRect.IsEmpty()) {
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
- mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy),
- DrawMode::GLYPH_FILL, Range(mGlyphs[i]),
- nullptr, nullptr, nullptr);
+ mGlyphs[i]->Draw(Range(mGlyphs[i]), gfxPoint(dx, dy), params);
}
}
}
///////////////
// fill the gap between top and middle, and between middle and bottom.
if (!mGlyphs[3]) { // null glue : draw a rule
// figure out the dimensions of the rule to be drawn :
@@ -2366,19 +2365,17 @@ nsMathMLChar::PaintVertically(nsPresCont
// Make sure not to draw outside the character
nscoord dy = std::max(end[i], aRect.y);
nscoord fillEnd = std::min(start[i+1], aRect.YMost());
while (dy < fillEnd) {
clipRect.y = dy;
clipRect.height = std::min(bm.ascent + bm.descent, fillEnd - dy);
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
dy += bm.ascent;
- mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy),
- DrawMode::GLYPH_FILL, Range(mGlyphs[3]),
- nullptr, nullptr, nullptr);
+ mGlyphs[3]->Draw(Range(mGlyphs[3]), gfxPoint(dx, dy), params);
dy += bm.descent;
}
}
}
#ifdef DEBUG
else {
for (i = 0; i < 2; ++i) {
NS_ASSERTION(end[i] >= start[i+1],
@@ -2444,16 +2441,18 @@ nsMathMLChar::PaintHorizontally(nsPresCo
end[i] = (end[i] + start[i+1]) / 2;
start[i+1] = end[i];
}
}
nsRect unionRect = aRect;
unionRect.Inflate(oneDevPixel, oneDevPixel);
+ gfxTextRun::DrawParams params(aThebesContext);
+
///////////////////////////
// draw left, middle, right
for (i = 0; i <= 2; ++i) {
// glue can be null
if (mGlyphs[i]) {
nscoord dx = offset[i];
nsRect clipRect = unionRect;
// Clip at the join to get a solid edge (without overlap or gap), when
@@ -2470,19 +2469,17 @@ nsMathMLChar::PaintHorizontally(nsPresCo
}
else { // middle
clipRect.x = start[i];
clipRect.width = end[i] - start[i];
}
}
if (!clipRect.IsEmpty()) {
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
- mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy),
- DrawMode::GLYPH_FILL, Range(mGlyphs[i]),
- nullptr, nullptr, nullptr);
+ mGlyphs[i]->Draw(Range(mGlyphs[i]), gfxPoint(dx, dy), params);
}
}
}
////////////////
// fill the gap between left and middle, and between middle and right.
if (!mGlyphs[3]) { // null glue : draw a rule
// figure out the dimensions of the rule to be drawn :
@@ -2536,19 +2533,17 @@ nsMathMLChar::PaintHorizontally(nsPresCo
// Make sure not to draw outside the character
nscoord dx = std::max(end[i], aRect.x);
nscoord fillEnd = std::min(start[i+1], aRect.XMost());
while (dx < fillEnd) {
clipRect.x = dx;
clipRect.width = std::min(bm.rightBearing - bm.leftBearing, fillEnd - dx);
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
dx -= bm.leftBearing;
- mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy),
- DrawMode::GLYPH_FILL, Range(mGlyphs[3]),
- nullptr, nullptr, nullptr);
+ mGlyphs[3]->Draw(Range(mGlyphs[3]), gfxPoint(dx, dy), params);
dx += bm.rightBearing;
}
}
}
#ifdef DEBUG
else { // no glue
for (i = 0; i < 2; ++i) {
NS_ASSERTION(end[i] >= start[i+1],