mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Get rid of background-clip:text and PaintBehaviorForceBlackText.
http://blog.ericzhang.com/punch-through-text-masks-with-css-and-html5/
shows that you can achieve the similar effects using canvas. This
doesn't need to be built into the core engine. It's OK for this
to require more than a line of CSS to achieve.
Unfortunately, the test included this this patch doesn't actually
show that I didn't break anything because background-image
is broken. I got the test from
47e0d126e8%5E%21/#F4
R=eseidel@chromium.org
Review URL: https://codereview.chromium.org/756183004
This commit is contained in:
parent
405dedb984
commit
2c71f77297
@ -348,9 +348,6 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(EFillBox e)
|
||||
case ContentFillBox:
|
||||
m_value.valueID = CSSValueContentBox;
|
||||
break;
|
||||
case TextFillBox:
|
||||
m_value.valueID = CSSValueText;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,8 +364,6 @@ template<> inline CSSPrimitiveValue::operator EFillBox() const
|
||||
case CSSValueContent:
|
||||
case CSSValueContentBox:
|
||||
return ContentFillBox;
|
||||
case CSSValueText:
|
||||
return TextFillBox;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, La
|
||||
paintSelection(context, boxOrigin, style, font);
|
||||
|
||||
// Select the correct color for painting the text.
|
||||
Color foreground = paintInfo.forceBlackText() ? Color::black : renderer().selectionForegroundColor();
|
||||
Color foreground = renderer().selectionForegroundColor();
|
||||
if (foreground != styleTextColor)
|
||||
context->setFillColor(foreground);
|
||||
}
|
||||
|
||||
@ -309,13 +309,6 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
|
||||
return -1;
|
||||
}
|
||||
|
||||
static Color textColorForWhiteBackground(Color textColor)
|
||||
{
|
||||
int distanceFromWhite = differenceSquared(textColor, Color::white);
|
||||
// semi-arbitrarily chose 65025 (255^2) value here after a few tests;
|
||||
return distanceFromWhite > 65025 ? textColor : textColor.dark();
|
||||
}
|
||||
|
||||
bool InlineTextBox::isLineBreak() const
|
||||
{
|
||||
return renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n';
|
||||
@ -366,44 +359,24 @@ struct TextPaintingStyle {
|
||||
bool operator!=(const TextPaintingStyle& other) { return !(*this == other); }
|
||||
};
|
||||
|
||||
TextPaintingStyle textPaintingStyle(RenderText& renderer, RenderStyle* style, bool forceBlackText)
|
||||
TextPaintingStyle textPaintingStyle(RenderText& renderer, RenderStyle* style)
|
||||
{
|
||||
TextPaintingStyle textStyle;
|
||||
|
||||
if (forceBlackText) {
|
||||
textStyle.fillColor = Color::black;
|
||||
textStyle.strokeColor = Color::black;
|
||||
textStyle.emphasisMarkColor = Color::black;
|
||||
textStyle.strokeWidth = style->textStrokeWidth();
|
||||
textStyle.shadow = 0;
|
||||
} else {
|
||||
textStyle.fillColor = renderer.resolveColor(style, CSSPropertyWebkitTextFillColor);
|
||||
textStyle.strokeColor = renderer.resolveColor(style, CSSPropertyWebkitTextStrokeColor);
|
||||
textStyle.emphasisMarkColor = renderer.resolveColor(style, CSSPropertyWebkitTextEmphasisColor);
|
||||
textStyle.strokeWidth = style->textStrokeWidth();
|
||||
textStyle.shadow = style->textShadow();
|
||||
|
||||
// Adjust text color when printing with a white background.
|
||||
bool forceBackgroundToWhite = false;
|
||||
if (forceBackgroundToWhite) {
|
||||
textStyle.fillColor = textColorForWhiteBackground(textStyle.fillColor);
|
||||
textStyle.strokeColor = textColorForWhiteBackground(textStyle.strokeColor);
|
||||
textStyle.emphasisMarkColor = textColorForWhiteBackground(textStyle.emphasisMarkColor);
|
||||
}
|
||||
}
|
||||
|
||||
textStyle.fillColor = renderer.resolveColor(style, CSSPropertyWebkitTextFillColor);
|
||||
textStyle.strokeColor = renderer.resolveColor(style, CSSPropertyWebkitTextStrokeColor);
|
||||
textStyle.emphasisMarkColor = renderer.resolveColor(style, CSSPropertyWebkitTextEmphasisColor);
|
||||
textStyle.strokeWidth = style->textStrokeWidth();
|
||||
textStyle.shadow = style->textShadow();
|
||||
return textStyle;
|
||||
}
|
||||
|
||||
TextPaintingStyle selectionPaintingStyle(RenderText& renderer, bool haveSelection, bool forceBlackText, const TextPaintingStyle& textStyle)
|
||||
TextPaintingStyle selectionPaintingStyle(RenderText& renderer, bool haveSelection, const TextPaintingStyle& textStyle)
|
||||
{
|
||||
TextPaintingStyle selectionStyle = textStyle;
|
||||
|
||||
if (haveSelection) {
|
||||
if (!forceBlackText) {
|
||||
selectionStyle.fillColor = renderer.selectionForegroundColor();
|
||||
selectionStyle.emphasisMarkColor = renderer.selectionEmphasisMarkColor();
|
||||
}
|
||||
selectionStyle.fillColor = renderer.selectionForegroundColor();
|
||||
selectionStyle.emphasisMarkColor = renderer.selectionEmphasisMarkColor();
|
||||
}
|
||||
|
||||
return selectionStyle;
|
||||
@ -564,8 +537,8 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
|
||||
bool useCustomUnderlines = containsComposition && renderer().frame()->inputMethodController().compositionUsesCustomUnderlines();
|
||||
|
||||
// Determine text colors.
|
||||
TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse, paintInfo.forceBlackText());
|
||||
TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSelection, paintInfo.forceBlackText(), textStyle);
|
||||
TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse);
|
||||
TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSelection, textStyle);
|
||||
bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
|
||||
bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != selectionStyle;
|
||||
|
||||
|
||||
@ -76,8 +76,6 @@ struct PaintInfo {
|
||||
return !paintingRoot || paintingRoot == renderer;
|
||||
}
|
||||
|
||||
bool forceBlackText() const { return paintBehavior & PaintBehaviorForceBlackText; }
|
||||
|
||||
void applyTransform(const AffineTransform& localToAncestorTransform, bool identityStatusUnknown = true)
|
||||
{
|
||||
if (identityStatusUnknown && localToAncestorTransform.isIdentity())
|
||||
|
||||
@ -51,9 +51,9 @@ enum PaintPhase {
|
||||
PaintPhaseClippingMask,
|
||||
};
|
||||
|
||||
// FIXME(sky): Remove this enum now that it's unused.
|
||||
enum PaintBehaviorFlags {
|
||||
PaintBehaviorNormal = 0,
|
||||
PaintBehaviorForceBlackText = 1 << 0,
|
||||
};
|
||||
|
||||
typedef unsigned PaintBehavior;
|
||||
|
||||
@ -480,20 +480,6 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
|
||||
|
||||
break;
|
||||
}
|
||||
case TextFillBox: {
|
||||
// First figure out how big the mask has to be. It should be no bigger than what we need
|
||||
// to actually render, so we should intersect the dirty rect with the border box of the background.
|
||||
maskRect = pixelSnappedIntRect(rect);
|
||||
maskRect.intersect(paintInfo.rect);
|
||||
|
||||
// We draw the background into a separate layer, to be later masked with yet another layer
|
||||
// holding the text content.
|
||||
backgroundClipStateSaver.save();
|
||||
context->clip(maskRect);
|
||||
context->beginTransparencyLayer(1);
|
||||
|
||||
break;
|
||||
}
|
||||
case BorderFillBox:
|
||||
break;
|
||||
default:
|
||||
@ -544,30 +530,6 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
|
||||
context->setImageInterpolationQuality(previousInterpolationQuality);
|
||||
}
|
||||
}
|
||||
|
||||
if (bgLayer.clip() == TextFillBox) {
|
||||
// Create the text mask layer.
|
||||
context->setCompositeOperation(CompositeDestinationIn);
|
||||
context->beginTransparencyLayer(1);
|
||||
|
||||
// FIXME: Workaround for https://code.google.com/p/skia/issues/detail?id=1291.
|
||||
context->clearRect(maskRect);
|
||||
|
||||
// Now draw the text into the mask. We do this by painting using a special paint phase that signals to
|
||||
// InlineTextBoxes that they should just add their contents to the clip.
|
||||
PaintInfo info(context, maskRect, PaintPhaseTextClip, PaintBehaviorForceBlackText, 0);
|
||||
context->setCompositeOperation(CompositeSourceOver);
|
||||
if (box) {
|
||||
RootInlineBox& root = box->root();
|
||||
box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), root.lineTop(), root.lineBottom());
|
||||
} else {
|
||||
LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset() : LayoutSize();
|
||||
paint(info, scrolledPaintRect.location() - localOffset);
|
||||
}
|
||||
|
||||
context->endLayer();
|
||||
context->endLayer();
|
||||
}
|
||||
}
|
||||
|
||||
static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio)
|
||||
|
||||
@ -1109,8 +1109,6 @@ void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPainti
|
||||
if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot))
|
||||
paintingRootForRenderer = localPaintingInfo.paintingRoot;
|
||||
|
||||
ASSERT(!(localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText));
|
||||
|
||||
// FIXME(sky): Get rid of PaintBehavior argument now that it's always Normal.
|
||||
PaintBehavior paintBehavior = PaintBehaviorNormal;
|
||||
|
||||
|
||||
@ -241,9 +241,6 @@ static inline bool rendererObscuresBackground(RenderBox* rootBox)
|
||||
|| style->hasTransform())
|
||||
return false;
|
||||
|
||||
if (rootBox->style()->backgroundClip() == TextFillBox)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -312,9 +312,7 @@ static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
|
||||
return BorderFillBox;
|
||||
if (clipA == PaddingFillBox || clipB == PaddingFillBox)
|
||||
return PaddingFillBox;
|
||||
if (clipA == ContentFillBox || clipB == ContentFillBox)
|
||||
return ContentFillBox;
|
||||
return TextFillBox;
|
||||
return ContentFillBox;
|
||||
}
|
||||
|
||||
void FillLayer::computeClipMax() const
|
||||
|
||||
@ -95,7 +95,7 @@ enum EFillAttachment {
|
||||
};
|
||||
|
||||
enum EFillBox {
|
||||
BorderFillBox, PaddingFillBox, ContentFillBox, TextFillBox
|
||||
BorderFillBox, PaddingFillBox, ContentFillBox
|
||||
};
|
||||
|
||||
enum EFillRepeat {
|
||||
|
||||
@ -167,14 +167,6 @@ bool Color::parseHexColor(const String& name, RGBA32& rgb)
|
||||
return parseHexColor(name.characters16(), name.length(), rgb);
|
||||
}
|
||||
|
||||
int differenceSquared(const Color& c1, const Color& c2)
|
||||
{
|
||||
int dR = c1.red() - c2.red();
|
||||
int dG = c1.green() - c2.green();
|
||||
int dB = c1.blue() - c2.blue();
|
||||
return dR * dR + dG * dG + dB * dB;
|
||||
}
|
||||
|
||||
bool Color::setFromString(const String& name)
|
||||
{
|
||||
if (name[0] != '#')
|
||||
|
||||
@ -45,8 +45,6 @@ PLATFORM_EXPORT RGBA32 makeRGBA32FromFloats(float r, float g, float b, float a);
|
||||
PLATFORM_EXPORT RGBA32 makeRGBAFromHSLA(double h, double s, double l, double a);
|
||||
PLATFORM_EXPORT RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a);
|
||||
|
||||
PLATFORM_EXPORT int differenceSquared(const Color&, const Color&);
|
||||
|
||||
inline int redChannel(RGBA32 color) { return (color >> 16) & 0xFF; }
|
||||
inline int greenChannel(RGBA32 color) { return (color >> 8) & 0xFF; }
|
||||
inline int blueChannel(RGBA32 color) { return color & 0xFF; }
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
layer at (0,0) size 800x600
|
||||
RenderView {#document} at (0,0) size 800x600
|
||||
layer at (0,0) size 800x238
|
||||
RenderBlock {sky} at (0,0) size 800x238
|
||||
RenderBlock (anonymous) at (0,0) size 800x38
|
||||
RenderText {#text} at (0,0) size 778x38
|
||||
text run at (0,0) width 778: "Test passes if the image below shows nested green, blue and yellow squares with a dotted black"
|
||||
text run at (0,19) width 59: "border."
|
||||
RenderBlock {div} at (0,38) size 200x200 [border: (25px dotted #000000)]
|
||||
|
||||
17
tests/clipping/background-opaque-clipped-gradients.sky
Normal file
17
tests/clipping/background-opaque-clipped-gradients.sky
Normal file
@ -0,0 +1,17 @@
|
||||
<sky>
|
||||
<import src="../resources/dump-as-render-tree.sky" />
|
||||
<style>
|
||||
div {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
padding: 25px;
|
||||
border: 25px dotted;
|
||||
/* TODO(ojan): background-image appears to be broken. */
|
||||
background-image: linear-gradient(top, yellow, yellow), linear-gradient(top, blue, blue), -linear-gradient(top, green, green);
|
||||
background-clip: content-box, padding-box, border-box;
|
||||
}
|
||||
</style>
|
||||
<!-- TODO(ojan): Make this a reftest once we support them. -->
|
||||
Test passes if the image below shows nested green, blue and yellow squares with a dotted black border.
|
||||
<div></div>
|
||||
</sky>
|
||||
Loading…
x
Reference in New Issue
Block a user