mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 719288 - Fill and stroke SVG text with one Draw call r=roc
This commit is contained in:
parent
358646373b
commit
e20fcb14ba
@ -2794,6 +2794,7 @@ struct NS_STACK_CLASS nsCanvasBidiProcessor : public nsBidiPresUtils::BidiProces
|
||||
0,
|
||||
mTextRun->GetLength(),
|
||||
nsnull,
|
||||
nsnull,
|
||||
nsnull);
|
||||
}
|
||||
|
||||
|
@ -333,7 +333,8 @@ nsFontMetrics::DrawString(const char *aString, PRUint32 aLength,
|
||||
if (mTextRunRTL) {
|
||||
pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
|
||||
}
|
||||
textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength, &provider, nsnull);
|
||||
textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength,
|
||||
&provider, nsnull, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
@ -351,7 +352,8 @@ nsFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
|
||||
if (mTextRunRTL) {
|
||||
pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
|
||||
}
|
||||
textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength, &provider, nsnull);
|
||||
textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength,
|
||||
&provider, nsnull, nsnull);
|
||||
}
|
||||
|
||||
nsBoundingMetrics
|
||||
|
@ -1238,7 +1238,8 @@ struct GlyphBuffer {
|
||||
return &mGlyphBuffer[mNumGlyphs++];
|
||||
}
|
||||
|
||||
void Flush(cairo_t *aCR, gfxFont::DrawMode aDrawMode, bool aReverse,
|
||||
void Flush(cairo_t *aCR, cairo_pattern_t *aStrokePattern,
|
||||
gfxFont::DrawMode aDrawMode, bool aReverse,
|
||||
bool aFinish = false) {
|
||||
// Ensure there's enough room for a glyph to be added to the buffer
|
||||
if (!aFinish && mNumGlyphs < GLYPH_BUFFER_SIZE) {
|
||||
@ -1261,9 +1262,18 @@ struct GlyphBuffer {
|
||||
}
|
||||
|
||||
if (aDrawMode & gfxFont::GLYPH_STROKE) {
|
||||
if (aStrokePattern) {
|
||||
cairo_save(aCR);
|
||||
cairo_set_source(aCR, aStrokePattern);
|
||||
}
|
||||
|
||||
cairo_new_path(aCR);
|
||||
cairo_glyph_path(aCR, mGlyphBuffer, mNumGlyphs);
|
||||
cairo_stroke(aCR);
|
||||
|
||||
if (aStrokePattern) {
|
||||
cairo_restore(aCR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1341,10 +1351,18 @@ gfxFont::CalcXScale(gfxContext *aContext)
|
||||
void
|
||||
gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
gfxContext *aContext, DrawMode aDrawMode, gfxPoint *aPt,
|
||||
Spacing *aSpacing)
|
||||
Spacing *aSpacing, gfxPattern *aStrokePattern)
|
||||
{
|
||||
NS_ASSERTION(aDrawMode <= gfxFont::GLYPH_PATH, "GLYPH_PATH cannot be used with GLYPH_FILL or GLYPH_STROKE");
|
||||
|
||||
// We have to multiply the stroke matrix by the context matrix as cairo
|
||||
// multiplies by the inverse of the context matrix when the pattern is set
|
||||
gfxMatrix strokeMatrix;
|
||||
if (aStrokePattern) {
|
||||
strokeMatrix = aStrokePattern->GetMatrix();
|
||||
aStrokePattern->SetMatrix(aContext->CurrentMatrix().Multiply(strokeMatrix));
|
||||
}
|
||||
|
||||
if (aStart >= aEnd)
|
||||
return;
|
||||
|
||||
@ -1372,6 +1390,10 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
|
||||
cairo_t *cr = aContext->GetCairo();
|
||||
RefPtr<DrawTarget> dt = aContext->GetDrawTarget();
|
||||
cairo_pattern_t *strokePattern = nsnull;
|
||||
if (aStrokePattern) {
|
||||
strokePattern = aStrokePattern->CairoPattern();
|
||||
}
|
||||
|
||||
RefPtr<ScaledFont> scaledFont;
|
||||
|
||||
@ -1410,7 +1432,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
}
|
||||
glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit);
|
||||
glyph->y = ToDeviceUnits(y, devUnitsPerAppUnit);
|
||||
glyphs.Flush(cr, aDrawMode, isRTL);
|
||||
glyphs.Flush(cr, strokePattern, aDrawMode, isRTL);
|
||||
|
||||
// synthetic bolding by multi-striking with 1-pixel offsets
|
||||
// at least once, more if there's room (large font sizes)
|
||||
@ -1426,7 +1448,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
devUnitsPerAppUnit);
|
||||
doubleglyph->y = glyph->y;
|
||||
strikeOffset += synBoldOnePixelOffset;
|
||||
glyphs.Flush(cr, aDrawMode, isRTL);
|
||||
glyphs.Flush(cr, strokePattern, aDrawMode, isRTL);
|
||||
} while (--strikeCount > 0);
|
||||
}
|
||||
} else {
|
||||
@ -1463,7 +1485,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
}
|
||||
glyph->x = ToDeviceUnits(glyphX, devUnitsPerAppUnit);
|
||||
glyph->y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
|
||||
glyphs.Flush(cr, aDrawMode, isRTL);
|
||||
glyphs.Flush(cr, strokePattern, aDrawMode, isRTL);
|
||||
|
||||
if (IsSyntheticBold()) {
|
||||
double strikeOffset = synBoldOnePixelOffset;
|
||||
@ -1478,7 +1500,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
devUnitsPerAppUnit);
|
||||
doubleglyph->y = glyph->y;
|
||||
strikeOffset += synBoldOnePixelOffset;
|
||||
glyphs.Flush(cr, aDrawMode, isRTL);
|
||||
glyphs.Flush(cr, strokePattern, aDrawMode, isRTL);
|
||||
} while (--strikeCount > 0);
|
||||
}
|
||||
}
|
||||
@ -1507,7 +1529,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
}
|
||||
|
||||
// draw any remaining glyphs
|
||||
glyphs.Flush(cr, aDrawMode, isRTL, true);
|
||||
glyphs.Flush(cr, strokePattern, aDrawMode, isRTL, true);
|
||||
|
||||
} else {
|
||||
if (aDrawMode == gfxFont::GLYPH_PATH) {
|
||||
@ -1672,6 +1694,11 @@ gfxFont::Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
dt->SetTransform(oldMat);
|
||||
}
|
||||
|
||||
// Restore matrix for stroke pattern
|
||||
if (aStrokePattern) {
|
||||
aStrokePattern->SetMatrix(strokeMatrix);
|
||||
}
|
||||
|
||||
*aPt = gfxPoint(x, y);
|
||||
}
|
||||
|
||||
@ -4265,6 +4292,7 @@ gfxTextRun::ShrinkToLigatureBoundaries(PRUint32 *aStart, PRUint32 *aEnd)
|
||||
void
|
||||
gfxTextRun::DrawGlyphs(gfxFont *aFont, gfxContext *aContext,
|
||||
gfxFont::DrawMode aDrawMode, gfxPoint *aPt,
|
||||
gfxPattern *aStrokePattern,
|
||||
PRUint32 aStart, PRUint32 aEnd,
|
||||
PropertyProvider *aProvider,
|
||||
PRUint32 aSpacingStart, PRUint32 aSpacingEnd)
|
||||
@ -4273,7 +4301,7 @@ gfxTextRun::DrawGlyphs(gfxFont *aFont, gfxContext *aContext,
|
||||
bool haveSpacing = GetAdjustedSpacingArray(aStart, aEnd, aProvider,
|
||||
aSpacingStart, aSpacingEnd, &spacingBuffer);
|
||||
aFont->Draw(this, aStart, aEnd, aContext, aDrawMode, aPt,
|
||||
haveSpacing ? spacingBuffer.Elements() : nsnull);
|
||||
haveSpacing ? spacingBuffer.Elements() : nsnull, aStrokePattern);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4330,7 +4358,7 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, gfxContext *aCtx,
|
||||
aCtx->Clip();
|
||||
gfxFloat direction = GetDirection();
|
||||
gfxPoint pt(aPt->x - direction*data.mPartAdvance, aPt->y);
|
||||
DrawGlyphs(aFont, aCtx, gfxFont::GLYPH_FILL, &pt, data.mLigatureStart,
|
||||
DrawGlyphs(aFont, aCtx, gfxFont::GLYPH_FILL, &pt, nsnull, data.mLigatureStart,
|
||||
data.mLigatureEnd, aProvider, aStart, aEnd);
|
||||
aCtx->Restore();
|
||||
|
||||
@ -4406,7 +4434,8 @@ struct BufferAlphaColor {
|
||||
void
|
||||
gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, gfxFont::DrawMode aDrawMode,
|
||||
PRUint32 aStart, PRUint32 aLength,
|
||||
PropertyProvider *aProvider, gfxFloat *aAdvanceWidth)
|
||||
PropertyProvider *aProvider, gfxFloat *aAdvanceWidth,
|
||||
gfxPattern *aStrokePattern)
|
||||
{
|
||||
NS_ASSERTION(aStart + aLength <= mCharacterCount, "Substring out of range");
|
||||
NS_ASSERTION(aDrawMode <= gfxFont::GLYPH_PATH, "GLYPH_PATH cannot be used with GLYPH_FILL or GLYPH_STROKE");
|
||||
@ -4457,7 +4486,7 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, gfxFont::DrawMode aDrawMode
|
||||
DrawPartialLigature(font, aContext, start, ligatureRunStart, &pt, aProvider);
|
||||
}
|
||||
|
||||
DrawGlyphs(font, aContext, aDrawMode, &pt, ligatureRunStart,
|
||||
DrawGlyphs(font, aContext, aDrawMode, &pt, aStrokePattern, ligatureRunStart,
|
||||
ligatureRunEnd, aProvider, ligatureRunStart, ligatureRunEnd);
|
||||
|
||||
if (aDrawMode == gfxFont::GLYPH_FILL) {
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "gfxPattern.h"
|
||||
|
||||
typedef struct _cairo_scaled_font cairo_scaled_font_t;
|
||||
|
||||
@ -1323,7 +1324,8 @@ public:
|
||||
*/
|
||||
virtual void Draw(gfxTextRun *aTextRun, PRUint32 aStart, PRUint32 aEnd,
|
||||
gfxContext *aContext, DrawMode aDrawMode, gfxPoint *aBaselineOrigin,
|
||||
Spacing *aSpacing);
|
||||
Spacing *aSpacing, gfxPattern *aStrokePattern);
|
||||
|
||||
/**
|
||||
* Measure a run of characters. See gfxTextRun::Metrics.
|
||||
* @param aTight if false, then return the union of the glyph extents
|
||||
@ -2369,7 +2371,7 @@ public:
|
||||
gfxFont::DrawMode aDrawMode,
|
||||
PRUint32 aStart, PRUint32 aLength,
|
||||
PropertyProvider *aProvider,
|
||||
gfxFloat *aAdvanceWidth);
|
||||
gfxFloat *aAdvanceWidth, gfxPattern *aStrokePattern);
|
||||
|
||||
/**
|
||||
* Computes the ReflowMetrics for a substring.
|
||||
@ -2814,7 +2816,7 @@ private:
|
||||
// **** drawing helper ****
|
||||
void DrawGlyphs(gfxFont *aFont, gfxContext *aContext,
|
||||
gfxFont::DrawMode aDrawMode, gfxPoint *aPt,
|
||||
PRUint32 aStart, PRUint32 aEnd,
|
||||
gfxPattern *aStrokePattern, PRUint32 aStart, PRUint32 aEnd,
|
||||
PropertyProvider *aProvider,
|
||||
PRUint32 aSpacingStart, PRUint32 aSpacingEnd);
|
||||
|
||||
|
@ -5563,7 +5563,7 @@ nsTextFrame::DrawTextRun(gfxContext* const aCtx,
|
||||
bool aDrawSoftHyphen)
|
||||
{
|
||||
mTextRun->Draw(aCtx, aTextBaselinePt, gfxFont::GLYPH_FILL, aOffset, aLength,
|
||||
&aProvider, &aAdvanceWidth);
|
||||
&aProvider, &aAdvanceWidth, nsnull);
|
||||
|
||||
if (aDrawSoftHyphen) {
|
||||
// Don't use ctx as the context, because we need a reference context here,
|
||||
@ -5575,7 +5575,8 @@ nsTextFrame::DrawTextRun(gfxContext* const aCtx,
|
||||
gfxFloat hyphenBaselineX = aTextBaselinePt.x + mTextRun->GetDirection() * aAdvanceWidth -
|
||||
(mTextRun->IsRightToLeft() ? hyphenTextRun->GetAdvanceWidth(0, hyphenTextRun->GetLength(), nsnull) : 0);
|
||||
hyphenTextRun->Draw(aCtx, gfxPoint(hyphenBaselineX, aTextBaselinePt.y),
|
||||
gfxFont::GLYPH_FILL, 0, hyphenTextRun->GetLength(), nsnull, nsnull);
|
||||
gfxFont::GLYPH_FILL, 0, hyphenTextRun->GetLength(),
|
||||
nsnull, nsnull, nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,28 +165,9 @@ SetupFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext,
|
||||
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
|
||||
float aOpacity)
|
||||
{
|
||||
const nsStyleSVGPaint &paint = aStyleContext->GetStyleSVG()->*aFillOrStroke;
|
||||
nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
|
||||
bool isServer = paint.mType == eStyleSVGPaintType_Server;
|
||||
nscolor color = isServer ? paint.mFallbackColor : paint.mPaint.mColor;
|
||||
if (styleIfVisited) {
|
||||
const nsStyleSVGPaint &paintIfVisited =
|
||||
styleIfVisited->GetStyleSVG()->*aFillOrStroke;
|
||||
// To prevent Web content from detecting if a user has visited a URL
|
||||
// (via URL loading triggered by paint servers or performance
|
||||
// differences between paint servers or between a paint server and a
|
||||
// color), we do not allow whether links are visited to change which
|
||||
// paint server is used or switch between paint servers and simple
|
||||
// colors. A :visited style may only override a simple color with
|
||||
// another simple color.
|
||||
if (paintIfVisited.mType == eStyleSVGPaintType_Color &&
|
||||
paint.mType == eStyleSVGPaintType_Color) {
|
||||
nscolor colorIfVisited = paintIfVisited.mPaint.mColor;
|
||||
nscolor colors[2] = { color, colorIfVisited };
|
||||
color = nsStyleContext::CombineVisitedColors(colors,
|
||||
aStyleContext->RelevantLinkVisited());
|
||||
}
|
||||
}
|
||||
nscolor color;
|
||||
nsSVGUtils::GetFallbackOrPaintColor(aContext, aStyleContext, aFillOrStroke,
|
||||
&aOpacity, &color);
|
||||
|
||||
SetupCairoColor(aContext, color, aOpacity);
|
||||
}
|
||||
|
@ -115,9 +115,6 @@ protected:
|
||||
*/
|
||||
virtual PRUint16 GetHitTestFlags();
|
||||
|
||||
private:
|
||||
bool GetStrokeDashData(FallibleTArray<gfxFloat>& dashes, gfxFloat *dashOffset);
|
||||
|
||||
/**
|
||||
* Returns the given 'fill-opacity' or 'stroke-opacity' value multiplied by
|
||||
* the value of the 'opacity' property if it's possible to avoid the expense
|
||||
@ -126,6 +123,9 @@ private:
|
||||
* given 'fill-opacity'/'stroke-opacity' is returned unmodified.
|
||||
*/
|
||||
float MaybeOptimizeOpacity(float aFillOrStrokeOpacity);
|
||||
|
||||
private:
|
||||
bool GetStrokeDashData(FallibleTArray<gfxFloat>& dashes, gfxFloat *dashOffset);
|
||||
};
|
||||
|
||||
#endif // __NS_SVGGEOMETRYFRAME_H__
|
||||
|
@ -53,6 +53,8 @@
|
||||
#include "gfxContext.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsSVGPaintServerFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
@ -354,9 +356,9 @@ nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext,
|
||||
|
||||
if (renderMode == nsSVGRenderState::CLIP_MASK) {
|
||||
gfx->SetColor(gfxRGBA(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
FillCharacters(&iter, gfx);
|
||||
DrawCharacters(&iter, gfx, gfxFont::GLYPH_FILL);
|
||||
} else {
|
||||
AddCharactersToPath(&iter, gfx);
|
||||
DrawCharacters(&iter, gfx, gfxFont::GLYPH_PATH);
|
||||
}
|
||||
|
||||
gfx->SetMatrix(matrix);
|
||||
@ -371,19 +373,13 @@ nsSVGGlyphFrame::PaintSVG(nsSVGRenderState *aContext,
|
||||
CharacterIterator iter(this, true);
|
||||
iter.SetInitialMatrix(gfx);
|
||||
|
||||
if (SetupCairoFill(gfx)) {
|
||||
gfxMatrix matrix = gfx->CurrentMatrix();
|
||||
FillCharacters(&iter, gfx);
|
||||
gfx->SetMatrix(matrix);
|
||||
}
|
||||
nsRefPtr<gfxPattern> strokePattern;
|
||||
DrawMode drawMode = SetupCairoState(gfx, &strokePattern);
|
||||
|
||||
if (SetupCairoStroke(gfx)) {
|
||||
// SetupCairoStroke will clear mTextRun whenever
|
||||
// there is a pattern or gradient on the text
|
||||
iter.Reset();
|
||||
|
||||
StrokeCharacters(&iter, gfx);
|
||||
if (drawMode) {
|
||||
DrawCharacters(&iter, gfx, drawMode, strokePattern);
|
||||
}
|
||||
|
||||
gfx->Restore();
|
||||
|
||||
return NS_OK;
|
||||
@ -545,24 +541,6 @@ nsSVGGlyphFrame::NotifyRedrawUnsuspended()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGGlyphFrame::AddCharactersToPath(CharacterIterator *aIter,
|
||||
gfxContext *aContext)
|
||||
{
|
||||
if (aIter->SetupForDirectTextRunDrawing(aContext)) {
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_PATH, 0,
|
||||
mTextRun->GetLength(), nsnull, nsnull);
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint32 i;
|
||||
while ((i = aIter->NextCluster()) != aIter->InvalidCluster()) {
|
||||
aIter->SetupForDrawing(aContext);
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_PATH, i,
|
||||
aIter->ClusterLength(), nsnull, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGGlyphFrame::AddBoundingBoxesToPath(CharacterIterator *aIter,
|
||||
gfxContext *aContext)
|
||||
@ -586,39 +564,26 @@ nsSVGGlyphFrame::AddBoundingBoxesToPath(CharacterIterator *aIter,
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGGlyphFrame::FillCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext)
|
||||
nsSVGGlyphFrame::DrawCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext,
|
||||
DrawMode aDrawMode,
|
||||
gfxPattern *aStrokePattern)
|
||||
{
|
||||
if (aDrawMode & gfxFont::GLYPH_STROKE) {
|
||||
aIter->SetLineWidthAndDashesForDrawing(aContext);
|
||||
}
|
||||
|
||||
if (aIter->SetupForDirectTextRunDrawing(aContext)) {
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_FILL, 0,
|
||||
mTextRun->GetLength(), nsnull, nsnull);
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), aDrawMode, 0,
|
||||
mTextRun->GetLength(), nsnull, nsnull, aStrokePattern);
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint32 i;
|
||||
while ((i = aIter->NextCluster()) != aIter->InvalidCluster()) {
|
||||
aIter->SetupForDrawing(aContext);
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_FILL, i,
|
||||
aIter->ClusterLength(), nsnull, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSVGGlyphFrame::StrokeCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext)
|
||||
{
|
||||
aIter->SetLineWidthAndDashesForDrawing(aContext);
|
||||
if (aIter->SetupForDirectTextRunDrawing(aContext)) {
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_STROKE, 0,
|
||||
mTextRun->GetLength(), nsnull, nsnull);
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint32 i;
|
||||
while ((i = aIter->NextCluster()) != aIter->InvalidCluster()) {
|
||||
aIter->SetupForDrawing(aContext);
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), gfxFont::GLYPH_STROKE, i,
|
||||
aIter->ClusterLength(), nsnull, nsnull);
|
||||
mTextRun->Draw(aContext, gfxPoint(0, 0), aDrawMode, i,
|
||||
aIter->ClusterLength(), nsnull, nsnull, aStrokePattern);
|
||||
}
|
||||
}
|
||||
|
||||
@ -913,6 +878,46 @@ nsSVGGlyphFrame::GetBaselineOffset(float aMetricsScale)
|
||||
return baselineAppUnits * aMetricsScale;
|
||||
}
|
||||
|
||||
DrawMode
|
||||
nsSVGGlyphFrame::SetupCairoState(gfxContext *context, nsRefPtr<gfxPattern> *strokePattern) {
|
||||
DrawMode toDraw = DrawMode(0);
|
||||
const nsStyleSVG* style = GetStyleSVG();
|
||||
|
||||
if (HasStroke()) {
|
||||
gfxContextMatrixAutoSaveRestore matrixRestore(context);
|
||||
context->IdentityMatrix();
|
||||
|
||||
toDraw = DrawMode(toDraw | gfxFont::GLYPH_STROKE);
|
||||
|
||||
SetupCairoStrokeHitGeometry(context);
|
||||
float opacity = style->mStrokeOpacity;
|
||||
nsSVGPaintServerFrame *ps = GetPaintServer(&style->mStroke,
|
||||
nsSVGEffects::StrokeProperty());
|
||||
|
||||
if (ps) {
|
||||
// Gradient or Pattern: can get pattern directly from frame
|
||||
*strokePattern = ps->GetPaintServerPattern(this, opacity);
|
||||
|
||||
NS_ASSERTION(*strokePattern, "No pattern returned from paint server");
|
||||
} else {
|
||||
nscolor color;
|
||||
nsSVGUtils::GetFallbackOrPaintColor(context, GetStyleContext(),
|
||||
&nsStyleSVG::mStroke, &opacity,
|
||||
&color);
|
||||
*strokePattern = new gfxPattern(gfxRGBA(NS_GET_R(color) / 255.0,
|
||||
NS_GET_G(color) / 255.0,
|
||||
NS_GET_B(color) / 255.0,
|
||||
NS_GET_A(color) / 255.0 * opacity));
|
||||
}
|
||||
}
|
||||
|
||||
if (SetupCairoFill(context)) {
|
||||
toDraw = DrawMode(toDraw | gfxFont::GLYPH_FILL);
|
||||
}
|
||||
|
||||
return toDraw;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Utilities for converting from indices in the uncompressed content
|
||||
|
@ -53,6 +53,8 @@ class nsSVGGlyphFrame;
|
||||
class CharacterIterator;
|
||||
struct CharacterPosition;
|
||||
|
||||
typedef gfxFont::DrawMode DrawMode;
|
||||
|
||||
typedef nsSVGGeometryFrame nsSVGGlyphFrameBase;
|
||||
|
||||
class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
|
||||
@ -236,10 +238,10 @@ protected:
|
||||
gfxContext *aContext);
|
||||
void AddBoundingBoxesToPath(CharacterIterator *aIter,
|
||||
gfxContext *aContext);
|
||||
void FillCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext);
|
||||
void StrokeCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext);
|
||||
void DrawCharacters(CharacterIterator *aIter,
|
||||
gfxContext *aContext,
|
||||
DrawMode aDrawMode,
|
||||
gfxPattern *aStrokePattern = nsnull);
|
||||
|
||||
void NotifyGlyphMetricsChange();
|
||||
void SetupGlobalTransform(gfxContext *aContext);
|
||||
@ -264,6 +266,9 @@ protected:
|
||||
bool mCompressWhitespace;
|
||||
bool mTrimLeadingWhitespace;
|
||||
bool mTrimTrailingWhitespace;
|
||||
|
||||
private:
|
||||
DrawMode SetupCairoState(gfxContext *context, nsRefPtr<gfxPattern> *strokePattern);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1522,3 +1522,32 @@ nsSVGUtils::RootSVGElementHasViewbox(const nsIContent *aRootSVGElem)
|
||||
|
||||
return svgSvgElem->HasValidViewbox();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsSVGUtils::GetFallbackOrPaintColor(gfxContext *aContext, nsStyleContext *aStyleContext,
|
||||
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
|
||||
float *aOpacity, nscolor *color)
|
||||
{
|
||||
const nsStyleSVGPaint &paint = aStyleContext->GetStyleSVG()->*aFillOrStroke;
|
||||
nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
|
||||
bool isServer = paint.mType == eStyleSVGPaintType_Server;
|
||||
*color = isServer ? paint.mFallbackColor : paint.mPaint.mColor;
|
||||
if (styleIfVisited) {
|
||||
const nsStyleSVGPaint &paintIfVisited =
|
||||
styleIfVisited->GetStyleSVG()->*aFillOrStroke;
|
||||
// To prevent Web content from detecting if a user has visited a URL
|
||||
// (via URL loading triggered by paint servers or performance
|
||||
// differences between paint servers or between a paint server and a
|
||||
// color), we do not allow whether links are visited to change which
|
||||
// paint server is used or switch between paint servers and simple
|
||||
// colors. A :visited style may only override a simple color with
|
||||
// another simple color.
|
||||
if (paintIfVisited.mType == eStyleSVGPaintType_Color &&
|
||||
paint.mType == eStyleSVGPaintType_Color) {
|
||||
nscolor colorIfVisited = paintIfVisited.mPaint.mColor;
|
||||
nscolor colors[2] = { *color, colorIfVisited };
|
||||
*color = nsStyleContext::CombineVisitedColors(colors,
|
||||
aStyleContext->RelevantLinkVisited());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsRenderingContext.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxMatrix.h"
|
||||
#include "nsStyleStruct.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsPresContext;
|
||||
@ -586,6 +587,11 @@ public:
|
||||
* builds, it will trigger a false return-value as a safe fallback.)
|
||||
*/
|
||||
static bool RootSVGElementHasViewbox(const nsIContent *aRootSVGElem);
|
||||
|
||||
static void GetFallbackOrPaintColor(gfxContext *aContext,
|
||||
nsStyleContext *aStyleContext,
|
||||
nsStyleSVGPaint nsStyleSVG::*aFillOrStroke,
|
||||
float *aOpacity, nscolor *color);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user