зеркало из https://github.com/mozilla/gecko-dev.git
Bug 889235 - Make text-shadow work on SVG text. r=cam
This commit is contained in:
Родитель
3f90ffabca
Коммит
dc06f6d670
|
@ -2599,7 +2599,7 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
{
|
{
|
||||||
const nsStyleText* textStyle = aFrame->StyleText();
|
const nsStyleText* textStyle = aFrame->StyleText();
|
||||||
if (!textStyle->HasTextShadow(aFrame))
|
if (!textStyle->HasTextShadow())
|
||||||
return aTextAndDecorationsRect;
|
return aTextAndDecorationsRect;
|
||||||
|
|
||||||
nsRect resultRect = aTextAndDecorationsRect;
|
nsRect resultRect = aTextAndDecorationsRect;
|
||||||
|
@ -3814,7 +3814,7 @@ nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame,
|
||||||
void* aCallbackData)
|
void* aCallbackData)
|
||||||
{
|
{
|
||||||
const nsStyleText* textStyle = aFrame->StyleText();
|
const nsStyleText* textStyle = aFrame->StyleText();
|
||||||
if (!textStyle->HasTextShadow(aFrame))
|
if (!textStyle->HasTextShadow())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Text shadow happens with the last value being painted at the back,
|
// Text shadow happens with the last value being painted at the back,
|
||||||
|
|
|
@ -5211,9 +5211,6 @@ static bool GetSelectionTextShadow(nsIFrame* aFrame,
|
||||||
nsTextPaintStyle& aTextPaintStyle,
|
nsTextPaintStyle& aTextPaintStyle,
|
||||||
nsCSSShadowArray** aShadow)
|
nsCSSShadowArray** aShadow)
|
||||||
{
|
{
|
||||||
if (aFrame->IsSVGText()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
case nsISelectionController::SELECTION_NORMAL:
|
case nsISelectionController::SELECTION_NORMAL:
|
||||||
return aTextPaintStyle.GetSelectionShadow(aShadow);
|
return aTextPaintStyle.GetSelectionShadow(aShadow);
|
||||||
|
@ -5511,7 +5508,7 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||||
|
|
||||||
// Determine what shadow, if any, to draw - either from textStyle
|
// Determine what shadow, if any, to draw - either from textStyle
|
||||||
// or from the ::-moz-selection pseudo-class if specified there
|
// or from the ::-moz-selection pseudo-class if specified there
|
||||||
nsCSSShadowArray *shadow = textStyle->GetTextShadow(this);
|
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
|
||||||
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
||||||
|
|
||||||
// Draw shadows, if any
|
// Draw shadows, if any
|
||||||
|
@ -5897,7 +5894,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||||
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
||||||
if (!aCallbacks) {
|
if (!aCallbacks) {
|
||||||
const nsStyleText* textStyle = StyleText();
|
const nsStyleText* textStyle = StyleText();
|
||||||
if (textStyle->HasTextShadow(this)) {
|
if (textStyle->HasTextShadow()) {
|
||||||
// Text shadow happens with the last value being painted at the back,
|
// Text shadow happens with the last value being painted at the back,
|
||||||
// ie. it is painted first.
|
// ie. it is painted first.
|
||||||
gfxTextRun::Metrics shadowMetrics =
|
gfxTextRun::Metrics shadowMetrics =
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="reftest-wait">
|
||||||
|
<text x="30" y="30" fill="green" style="text-shadow: #cc9900 20px 12px 2px">Hello</text>
|
||||||
|
<script>
|
||||||
|
function f() {
|
||||||
|
document.getElementsByTagName("text")[0].style.textShadow = "grey 3px 3px";
|
||||||
|
document.documentElement.removeAttribute("class");
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("MozReftestInvalidate", f, false);
|
||||||
|
</script>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 529 B |
|
@ -1,7 +0,0 @@
|
||||||
<!--
|
|
||||||
Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
-->
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="700" height="200">
|
|
||||||
<text x="100" y="100" style="font: 16px sans-serif">hello <tspan style="text-shadow: 2px 2px 3px #000">there</tspan> everyone</text>
|
|
||||||
</svg>
|
|
До Ширина: | Высота: | Размер: 326 B |
|
@ -127,6 +127,9 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
|
||||||
== textLength-5.svg textLength-5-ref.svg
|
== textLength-5.svg textLength-5-ref.svg
|
||||||
== textLength-6.svg textLength-6-ref.svg
|
== textLength-6.svg textLength-6-ref.svg
|
||||||
|
|
||||||
|
# text-shadow
|
||||||
|
== text-shadow.svg text-shadow-ref.svg
|
||||||
|
|
||||||
# tests for ignoring various properties
|
# tests for ignoring various properties
|
||||||
== ignore-border.svg ignore-prop-ref.svg
|
== ignore-border.svg ignore-prop-ref.svg
|
||||||
== ignore-display.svg ignore-display-ref.svg
|
== ignore-display.svg ignore-display-ref.svg
|
||||||
|
@ -135,7 +138,6 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
|
||||||
== ignore-position.svg ignore-position-ref.svg
|
== ignore-position.svg ignore-position-ref.svg
|
||||||
== ignore-margin.svg ignore-prop-ref.svg
|
== ignore-margin.svg ignore-prop-ref.svg
|
||||||
== ignore-padding.svg ignore-prop-ref.svg
|
== ignore-padding.svg ignore-prop-ref.svg
|
||||||
== ignore-text-shadow.svg ignore-prop-ref.svg
|
|
||||||
== ignore-vertical-align.svg ignore-vertical-align-ref.svg
|
== ignore-vertical-align.svg ignore-vertical-align-ref.svg
|
||||||
== ignore-overflow-scroll.svg ignore-prop-ref.svg
|
== ignore-overflow-scroll.svg ignore-prop-ref.svg
|
||||||
== ignore-text-align.svg ignore-prop-ref.svg
|
== ignore-text-align.svg ignore-prop-ref.svg
|
||||||
|
@ -163,6 +165,7 @@ fuzzy-if(/^Windows\x20NT\x206\.[12]/.test(http.oscpu),4,15) == textLength-3.svg
|
||||||
== dynamic-dominant-baseline.svg dynamic-dominant-baseline-ref.svg
|
== dynamic-dominant-baseline.svg dynamic-dominant-baseline-ref.svg
|
||||||
== dynamic-multiple-x.svg dynamic-multiple-x-ref.svg
|
== dynamic-multiple-x.svg dynamic-multiple-x-ref.svg
|
||||||
fuzzy-if(!d2d,14,2) fuzzy-if(azureQuartz,1,6) == dynamic-non-scaling-stroke.svg dynamic-non-scaling-stroke-ref.svg #Bug 885316
|
fuzzy-if(!d2d,14,2) fuzzy-if(azureQuartz,1,6) == dynamic-non-scaling-stroke.svg dynamic-non-scaling-stroke-ref.svg #Bug 885316
|
||||||
|
== dynamic-text-shadow.svg text-shadow-ref.svg
|
||||||
|
|
||||||
# text and masks
|
# text and masks
|
||||||
HTTP(../..) == mask-applied.svg mask-applied-ref.svg
|
HTTP(../..) == mask-applied.svg mask-applied-ref.svg
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<text x="33" y="33" fill="grey">Hello</text>
|
||||||
|
<text x="30" y="30" fill="green">Hello</text>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 261 B |
|
@ -0,0 +1,7 @@
|
||||||
|
<!--
|
||||||
|
Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
-->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<text x="30" y="30" fill="green" style="text-shadow: grey 3px 3px;">Hello</text>
|
||||||
|
</svg>
|
После Ширина: | Высота: | Размер: 249 B |
|
@ -1431,13 +1431,13 @@ struct nsStyleText {
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are defined in nsStyleStructInlines.h.
|
// These are defined in nsStyleStructInlines.h.
|
||||||
|
inline bool HasTextShadow() const;
|
||||||
|
inline nsCSSShadowArray* GetTextShadow() const;
|
||||||
|
|
||||||
// The aContextFrame argument on each of these is the frame this
|
// The aContextFrame argument on each of these is the frame this
|
||||||
// style struct is for. If the frame is for SVG text, the return
|
// style struct is for. If the frame is for SVG text, the return
|
||||||
// value will be massaged to be something that makes sense for
|
// value will be massaged to be something that makes sense for
|
||||||
// SVG text.
|
// SVG text.
|
||||||
inline bool HasTextShadow(const nsIFrame* aContextFrame) const;
|
|
||||||
inline nsCSSShadowArray* GetTextShadow(const nsIFrame* aContextFrame) const;
|
|
||||||
inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
|
inline bool WhiteSpaceCanWrap(const nsIFrame* aContextFrame) const;
|
||||||
inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
|
inline bool WordCanWrap(const nsIFrame* aContextFrame) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -57,19 +57,14 @@ nsStyleBorder::GetSubImage(uint8_t aIndex) const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsStyleText::HasTextShadow(const nsIFrame* aContextFrame) const
|
nsStyleText::HasTextShadow() const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
|
return mTextShadow;
|
||||||
return mTextShadow && !aContextFrame->IsSVGText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSShadowArray*
|
nsCSSShadowArray*
|
||||||
nsStyleText::GetTextShadow(const nsIFrame* aContextFrame) const
|
nsStyleText::GetTextShadow() const
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aContextFrame->StyleText() == this, "unexpected aContextFrame");
|
|
||||||
if (aContextFrame->IsSVGText()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return mTextShadow;
|
return mTextShadow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -632,8 +632,10 @@ struct TextRenderedRun
|
||||||
eIncludeFill = 1,
|
eIncludeFill = 1,
|
||||||
// Includes the stroke geometry of the text in the returned rectangle.
|
// Includes the stroke geometry of the text in the returned rectangle.
|
||||||
eIncludeStroke = 2,
|
eIncludeStroke = 2,
|
||||||
|
// Includes any text shadow in the returned rectangle.
|
||||||
|
eIncludeTextShadow = 4,
|
||||||
// Don't include any horizontal glyph overflow in the returned rectangle.
|
// Don't include any horizontal glyph overflow in the returned rectangle.
|
||||||
eNoHorizontalOverflow = 4
|
eNoHorizontalOverflow = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -910,11 +912,21 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
||||||
x = metrics.mBoundingBox.x;
|
x = metrics.mBoundingBox.x;
|
||||||
width = metrics.mBoundingBox.width;
|
width = metrics.mBoundingBox.width;
|
||||||
}
|
}
|
||||||
gfxRect fillInAppUnits(x, baseline - above,
|
nsRect fillInAppUnits(x, baseline - above,
|
||||||
width, metrics.mBoundingBox.height + above + below);
|
width, metrics.mBoundingBox.height + above + below);
|
||||||
|
|
||||||
|
// Account for text-shadow.
|
||||||
|
if (aFlags & eIncludeTextShadow) {
|
||||||
|
fillInAppUnits =
|
||||||
|
nsLayoutUtils::GetTextShadowRectsUnion(fillInAppUnits, mFrame);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the app units rectangle to user units.
|
// Convert the app units rectangle to user units.
|
||||||
gfxRect fill = AppUnitsToFloatCSSPixels(fillInAppUnits, aContext);
|
gfxRect fill = AppUnitsToFloatCSSPixels(gfxRect(fillInAppUnits.x,
|
||||||
|
fillInAppUnits.y,
|
||||||
|
fillInAppUnits.width,
|
||||||
|
fillInAppUnits.height),
|
||||||
|
aContext);
|
||||||
|
|
||||||
// Scale the rectangle up due to any mFontSizeScaleFactor. We scale
|
// Scale the rectangle up due to any mFontSizeScaleFactor. We scale
|
||||||
// it around the text's origin.
|
// it around the text's origin.
|
||||||
|
@ -3738,14 +3750,25 @@ SVGTextFrame::ReflowSVG()
|
||||||
TextRenderedRunIterator it(this, TextRenderedRunIterator::eAllFrames);
|
TextRenderedRunIterator it(this, TextRenderedRunIterator::eAllFrames);
|
||||||
for (TextRenderedRun run = it.Current(); run.mFrame; run = it.Next()) {
|
for (TextRenderedRun run = it.Current(); run.mFrame; run = it.Next()) {
|
||||||
uint32_t runFlags = 0;
|
uint32_t runFlags = 0;
|
||||||
|
if (run.mFrame->StyleSVG()->mFill.mType != eStyleSVGPaintType_None) {
|
||||||
|
runFlags |= TextRenderedRun::eIncludeFill |
|
||||||
|
TextRenderedRun::eIncludeTextShadow;
|
||||||
|
}
|
||||||
|
if (nsSVGUtils::HasStroke(run.mFrame)) {
|
||||||
|
runFlags |= TextRenderedRun::eIncludeFill |
|
||||||
|
TextRenderedRun::eIncludeTextShadow;
|
||||||
|
}
|
||||||
|
// Our "visual" overflow rect needs to be valid for building display lists
|
||||||
|
// for hit testing, which means that for certain values of 'pointer-events'
|
||||||
|
// it needs to include the geometry of the fill or stroke even when the fill/
|
||||||
|
// stroke don't actually render (e.g. when stroke="none" or
|
||||||
|
// stroke-opacity="0"). GetGeometryHitTestFlags accounts for 'pointer-events'.
|
||||||
|
// The text-shadow is not part of the hit-test area.
|
||||||
uint16_t hitTestFlags = nsSVGUtils::GetGeometryHitTestFlags(run.mFrame);
|
uint16_t hitTestFlags = nsSVGUtils::GetGeometryHitTestFlags(run.mFrame);
|
||||||
|
if (hitTestFlags & SVG_HIT_TEST_FILL) {
|
||||||
if ((hitTestFlags & SVG_HIT_TEST_FILL) ||
|
|
||||||
run.mFrame->StyleSVG()->mFill.mType != eStyleSVGPaintType_None) {
|
|
||||||
runFlags |= TextRenderedRun::eIncludeFill;
|
runFlags |= TextRenderedRun::eIncludeFill;
|
||||||
}
|
}
|
||||||
if ((hitTestFlags & SVG_HIT_TEST_STROKE) ||
|
if (hitTestFlags & SVG_HIT_TEST_STROKE) {
|
||||||
nsSVGUtils::HasStroke(run.mFrame)) {
|
|
||||||
runFlags |= TextRenderedRun::eIncludeStroke;
|
runFlags |= TextRenderedRun::eIncludeStroke;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче