Commit 01f2c572 authored by hyatt@apple.com's avatar hyatt@apple.com
Browse files

2008-04-12 David Hyatt <hyatt@apple.com>

        Add gradient support to border-image (even though it's mostly just weird).

        Reviewed by Dan

        Added fast/gradients/border-image-gradient.html
              fast/gradients/border-image-gradient-sides-and-corners.html

        * css/CSSBorderImageValue.h:
        (WebCore::CSSBorderImageValue::imageValue):
        * css/CSSStyleSelector.cpp:
        (WebCore::CSSStyleSelector::applyProperty):
        * platform/graphics/GeneratedImage.cpp:
        (WebCore::GeneratedImage::draw):
        * rendering/InlineFlowBox.cpp:
        (WebCore::InlineFlowBox::paintBoxDecorations):
        * rendering/RenderBox.cpp:
        (WebCore::RenderBox::imageChanged):
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::mustRepaintBackgroundOrBorder):
        (WebCore::RenderObject::paintBorderImage):
        (WebCore::RenderObject::paintBorder):
        (WebCore::RenderObject::updateBackgroundImages):
        (WebCore::RenderObject::arenaDelete):
        * rendering/RenderStyle.cpp:
        (WebCore::StyleCachedImage::isLoaded):
        * rendering/RenderStyle.h:
        (WebCore::StyleImage::isLoaded):
        (WebCore::BorderImage::image):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31837 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent cb9466c8
2008-04-12 David Hyatt <hyatt@apple.com>
Add gradient support to border-image (even though it's mostly just weird).
Reviewed by Dan
Added fast/gradients/border-image-gradient.html
fast/gradients/border-image-gradient-sides-and-corners.html
* css/CSSBorderImageValue.h:
(WebCore::CSSBorderImageValue::imageValue):
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::applyProperty):
* platform/graphics/GeneratedImage.cpp:
(WebCore::GeneratedImage::draw):
* rendering/InlineFlowBox.cpp:
(WebCore::InlineFlowBox::paintBoxDecorations):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::imageChanged):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::mustRepaintBackgroundOrBorder):
(WebCore::RenderObject::paintBorderImage):
(WebCore::RenderObject::paintBorder):
(WebCore::RenderObject::updateBackgroundImages):
(WebCore::RenderObject::arenaDelete):
* rendering/RenderStyle.cpp:
(WebCore::StyleCachedImage::isLoaded):
* rendering/RenderStyle.h:
(WebCore::StyleImage::isLoaded):
(WebCore::BorderImage::image):
2008-04-11 Dan Bernstein <mitz@apple.com>
 
Reviewed by Dave Hyatt.
......@@ -23,8 +23,7 @@
#ifndef CSSBorderImageValue_h
#define CSSBorderImageValue_h
#include "CSSImageGeneratorValue.h"
#include "CSSImageValue.h"
#include "CSSValue.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
......@@ -40,9 +39,8 @@ public:
virtual String cssText() const;
CSSImageValue* imageValue() const { return m_image->isImageValue() ? static_cast<CSSImageValue*>(m_image.get()) : 0; }
CSSImageGeneratorValue* generatorValue() const { return m_image->isImageGeneratorValue() ? static_cast<CSSImageGeneratorValue*>(m_image.get()) : 0; }
CSSValue* imageValue() const { return m_image.get(); }
public:
// The border image.
RefPtr<CSSValue> m_image;
......
......@@ -3817,11 +3817,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
// Set the image (this kicks off the load).
if (borderImage->imageValue())
image.m_image = borderImage->imageValue()->image(m_element->document()->docLoader());
else
return; // FIXME: Add gradient support.
image.m_image = createStyleImage(borderImage->imageValue());
// Set up a length box to represent our image slices.
LengthBox& l = image.m_slices;
Rect* r = borderImage->m_imageSliceRect.get();
......
......@@ -36,16 +36,13 @@ namespace WebCore {
void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
{
// Generated images should never be scaled, since it was the front end's responsibility to update our size to the correct
// resolution.
ASSERT(dstRect.size() == srcRect.size());
ASSERT(srcRect.x() + srcRect.width() == m_size.width());
ASSERT(srcRect.y() + srcRect.height() == m_size.height());
context->save();
context->setCompositeOperation(compositeOp);
context->clip(dstRect);
context->translate(dstRect.x() - srcRect.x(), dstRect.y() - srcRect.y());
context->translate(dstRect.x(), dstRect.y());
if (dstRect.size() != srcRect.size())
context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
context->translate(-srcRect.x(), -srcRect.y());
context->fillRect(FloatRect(FloatPoint(), m_size), *m_generator.get());
context->restore();
}
......
......@@ -732,7 +732,7 @@ void InlineFlowBox::paintBoxDecorations(RenderObject::PaintInfo& paintInfo, int
// :first-line cannot be used to put borders on a line. Always paint borders with our
// non-first-line style.
if (parent() && object()->style()->hasBorder()) {
CachedImage* borderImage = object()->style()->borderImage().image();
StyleImage* borderImage = object()->style()->borderImage().image();
bool hasBorderImage = borderImage && borderImage->canRender(styleToUse->effectiveZoom());
if (hasBorderImage && !borderImage->isLoaded())
return; // Don't paint anything while we wait for the image to load.
......
......@@ -480,7 +480,7 @@ void RenderBox::imageChanged(CachedImage* image)
if (!image || !image->canRender(style()->effectiveZoom()) || !parent() || !view())
return;
if (isInlineFlow() || style()->borderImage().image() == image) {
if (isInlineFlow() || style()->borderImage().image()->data() == image) {
repaint();
return;
}
......
......@@ -851,7 +851,7 @@ bool RenderObject::mustRepaintBackgroundOrBorder() const
// Background is ok. Let's check border.
if (style()->hasBorder()) {
// Border images are not ok.
CachedImage* borderImage = style()->borderImage().image();
StyleImage* borderImage = style()->borderImage().image();
bool shouldPaintBorderImage = borderImage && borderImage->canRender(style()->effectiveZoom());
// If the image hasn't loaded, we're still using the normal border style.
......@@ -1148,7 +1148,7 @@ void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1,
bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
{
CachedImage* borderImage = style->borderImage().image();
StyleImage* borderImage = style->borderImage().image();
if (!borderImage->isLoaded())
return true; // Never paint a border image incrementally, but don't paint the fallback borders either.
......@@ -1162,14 +1162,17 @@ bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, in
clipped = true;
}
// FIXME: border-image is broken with full page zooming when tiling has to happen, since the tiling function
// doesn't have any understanding of the zoom that is in effect on the tile.
borderImage->setImageContainerSize(IntSize(w, h));
int imageWidth = borderImage->image()->width();
int imageHeight = borderImage->image()->height();
IntSize imageSize = borderImage->imageSize(1.0f);
int imageWidth = imageSize.width();
int imageHeight = imageSize.height();
int topSlice = min(imageHeight, style->borderImage().m_slices.top.calcValue(borderImage->image()->height()));
int bottomSlice = min(imageHeight, style->borderImage().m_slices.bottom.calcValue(borderImage->image()->height()));
int leftSlice = min(imageWidth, style->borderImage().m_slices.left.calcValue(borderImage->image()->width()));
int rightSlice = min(imageWidth, style->borderImage().m_slices.right.calcValue(borderImage->image()->width()));
int topSlice = min(imageHeight, style->borderImage().m_slices.top.calcValue(imageHeight));
int bottomSlice = min(imageHeight, style->borderImage().m_slices.bottom.calcValue(imageHeight));
int leftSlice = min(imageWidth, style->borderImage().m_slices.left.calcValue(imageWidth));
int rightSlice = min(imageWidth, style->borderImage().m_slices.right.calcValue(imageWidth));
EBorderImageRule hRule = style->borderImage().horizontalRule();
EBorderImageRule vRule = style->borderImage().verticalRule();
......@@ -1181,24 +1184,27 @@ bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, in
bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - style->borderLeftWidth() - style->borderRightWidth()) > 0 &&
(imageHeight - topSlice - bottomSlice) > 0 && (h - style->borderTopWidth() - style->borderBottomWidth()) > 0;
Image* image = borderImage->image(this, imageSize);
if (drawLeft) {
// Paint the top and bottom left corners.
// The top left corner rect is (tx, ty, leftWidth, topWidth)
// The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
if (drawTop)
graphicsContext->drawImage(borderImage->image(), IntRect(tx, ty, style->borderLeftWidth(), style->borderTopWidth()),
graphicsContext->drawImage(image, IntRect(tx, ty, style->borderLeftWidth(), style->borderTopWidth()),
IntRect(0, 0, leftSlice, topSlice));
// The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
// The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
if (drawBottom)
graphicsContext->drawImage(borderImage->image(), IntRect(tx, ty + h - style->borderBottomWidth(), style->borderLeftWidth(), style->borderBottomWidth()),
graphicsContext->drawImage(image, IntRect(tx, ty + h - style->borderBottomWidth(), style->borderLeftWidth(), style->borderBottomWidth()),
IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice));
// Paint the left edge.
// Have to scale and tile into the border rect.
graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx, ty + style->borderTopWidth(), style->borderLeftWidth(),
graphicsContext->drawTiledImage(image, IntRect(tx, ty + style->borderTopWidth(), style->borderLeftWidth(),
h - style->borderTopWidth() - style->borderBottomWidth()),
IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice),
Image::StretchTile, (Image::TileRule)vRule);
......@@ -1209,17 +1215,17 @@ bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, in
// The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
// The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
if (drawTop)
graphicsContext->drawImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty, style->borderRightWidth(), style->borderTopWidth()),
graphicsContext->drawImage(image, IntRect(tx + w - style->borderRightWidth(), ty, style->borderRightWidth(), style->borderTopWidth()),
IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice));
// The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
// The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, botomSlice)
if (drawBottom)
graphicsContext->drawImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty + h - style->borderBottomWidth(), style->borderRightWidth(), style->borderBottomWidth()),
graphicsContext->drawImage(image, IntRect(tx + w - style->borderRightWidth(), ty + h - style->borderBottomWidth(), style->borderRightWidth(), style->borderBottomWidth()),
IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice));
// Paint the right edge.
graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty + style->borderTopWidth(), style->borderRightWidth(),
graphicsContext->drawTiledImage(image, IntRect(tx + w - style->borderRightWidth(), ty + style->borderTopWidth(), style->borderRightWidth(),
h - style->borderTopWidth() - style->borderBottomWidth()),
IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice),
Image::StretchTile, (Image::TileRule)vRule);
......@@ -1227,20 +1233,20 @@ bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, in
// Paint the top edge.
if (drawTop)
graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty, w - style->borderLeftWidth() - style->borderRightWidth(), style->borderTopWidth()),
graphicsContext->drawTiledImage(image, IntRect(tx + style->borderLeftWidth(), ty, w - style->borderLeftWidth() - style->borderRightWidth(), style->borderTopWidth()),
IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice),
(Image::TileRule)hRule, Image::StretchTile);
// Paint the bottom edge.
if (drawBottom)
graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty + h - style->borderBottomWidth(),
graphicsContext->drawTiledImage(image, IntRect(tx + style->borderLeftWidth(), ty + h - style->borderBottomWidth(),
w - style->borderLeftWidth() - style->borderRightWidth(), style->borderBottomWidth()),
IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice),
(Image::TileRule)hRule, Image::StretchTile);
// Paint the middle.
if (drawMiddle)
graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty + style->borderTopWidth(), w - style->borderLeftWidth() - style->borderRightWidth(),
graphicsContext->drawTiledImage(image, IntRect(tx + style->borderLeftWidth(), ty + style->borderTopWidth(), w - style->borderLeftWidth() - style->borderRightWidth(),
h - style->borderTopWidth() - style->borderBottomWidth()),
IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice),
(Image::TileRule)hRule, (Image::TileRule)vRule);
......@@ -1255,7 +1261,7 @@ bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, in
void RenderObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
const RenderStyle* style, bool begin, bool end)
{
CachedImage* borderImage = style->borderImage().image();
StyleImage* borderImage = style->borderImage().image();
bool shouldPaintBackgroundImage = borderImage && borderImage->canRender(style->effectiveZoom());
if (shouldPaintBackgroundImage)
shouldPaintBackgroundImage = paintBorderImage(graphicsContext, tx, ty, w, h, style);
......@@ -2283,8 +2289,8 @@ void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
currNew->backgroundImage()->addClient(this);
}
CachedImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
CachedImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
StyleImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
StyleImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
if (oldBorderImage != newBorderImage) {
if (oldBorderImage)
oldBorderImage->removeClient(this);
......@@ -2483,7 +2489,7 @@ void RenderObject::arenaDelete(RenderArena* arena, void* base)
backgroundImage->removeClient(this);
}
if (CachedImage* borderImage = m_style->borderImage().image())
if (StyleImage* borderImage = m_style->borderImage().image())
borderImage->removeClient(this);
m_style->deref(arena);
......
......@@ -122,6 +122,11 @@ bool StyleCachedImage::canRender(float multiplier) const
return m_image->canRender(multiplier);
}
bool StyleCachedImage::isLoaded() const
{
return m_image->isLoaded();
}
IntSize StyleCachedImage::imageSize(float multiplier) const
{
return m_image->imageSize(multiplier);
......
......@@ -31,7 +31,7 @@
*
* The order of the values in the enums have to agree with the order specified
* in CSSValueKeywords.in, otherwise some optimizations in the parser will fail,
* and produce invaliud results.
* and produce invalid results.
*/
#include "AffineTransform.h"
......@@ -147,6 +147,7 @@ public:
virtual PassRefPtr<CSSValue> cssValue() = 0;
virtual bool canRender(float multiplier) const { return true; }
virtual bool isLoaded() const { return true; }
virtual IntSize imageSize(float multiplier) const = 0;
virtual void setImageContainerSize(const IntSize&) = 0;
virtual void addClient(RenderObject*) = 0;
......@@ -171,6 +172,7 @@ public:
virtual PassRefPtr<CSSValue> cssValue();
virtual bool canRender(float multiplier) const;
virtual bool isLoaded() const;
virtual IntSize imageSize(float multiplier) const;
virtual void setImageContainerSize(const IntSize&);
virtual void addClient(RenderObject*);
......@@ -302,7 +304,7 @@ enum EBorderImageRule {
class BorderImage {
public:
BorderImage() :m_image(0), m_horizontalRule(BI_STRETCH), m_verticalRule(BI_STRETCH) {}
BorderImage(CachedImage* image, LengthBox slices, EBorderImageRule h, EBorderImageRule v)
BorderImage(StyleImage* image, LengthBox slices, EBorderImageRule h, EBorderImageRule v)
:m_image(image), m_slices(slices), m_horizontalRule(h), m_verticalRule(v) {}
bool operator==(const BorderImage& o) const
......@@ -312,12 +314,12 @@ public:
}
bool hasImage() const { return m_image != 0; }
CachedImage* image() const { return m_image; }
StyleImage* image() const { return m_image.get(); }
EBorderImageRule horizontalRule() const { return static_cast<EBorderImageRule>(m_horizontalRule); }
EBorderImageRule verticalRule() const { return static_cast<EBorderImageRule>(m_verticalRule); }
CachedImage* m_image;
RefPtr<StyleImage> m_image;
LengthBox m_slices;
unsigned m_horizontalRule : 2; // EBorderImageRule
unsigned m_verticalRule : 2; // EBorderImageRule
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment