00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025
00026 #if ENABLE(SVG)
00027 #include "SVGMaskElement.h"
00028
00029 #include "CSSStyleSelector.h"
00030 #include "GraphicsContext.h"
00031 #include "ImageBuffer.h"
00032 #include "RenderSVGContainer.h"
00033 #include "SVGLength.h"
00034 #include "SVGNames.h"
00035 #include "SVGRenderSupport.h"
00036 #include "SVGUnitTypes.h"
00037 #include <math.h>
00038 #include <wtf/MathExtras.h>
00039 #include <wtf/OwnPtr.h>
00040
00041 using namespace std;
00042
00043 namespace WebCore {
00044
00045 SVGMaskElement::SVGMaskElement(const QualifiedName& tagName, Document* doc)
00046 : SVGStyledLocatableElement(tagName, doc)
00047 , SVGURIReference()
00048 , SVGTests()
00049 , SVGLangSpace()
00050 , SVGExternalResourcesRequired()
00051 , m_maskUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
00052 , m_maskContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
00053 , m_x(this, LengthModeWidth)
00054 , m_y(this, LengthModeHeight)
00055 , m_width(this, LengthModeWidth)
00056 , m_height(this, LengthModeHeight)
00057 {
00058
00059 setXBaseValue(SVGLength(this, LengthModeWidth, "-10%"));
00060 setYBaseValue(SVGLength(this, LengthModeHeight, "-10%"));
00061
00062
00063 setWidthBaseValue(SVGLength(this, LengthModeWidth, "120%"));
00064 setHeightBaseValue(SVGLength(this, LengthModeHeight, "120%"));
00065 }
00066
00067 SVGMaskElement::~SVGMaskElement()
00068 {
00069 }
00070
00071 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, int, Enumeration, enumeration, MaskUnits, maskUnits, SVGNames::maskUnitsAttr, m_maskUnits)
00072 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, int, Enumeration, enumeration, MaskContentUnits, maskContentUnits, SVGNames::maskContentUnitsAttr, m_maskContentUnits)
00073 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
00074 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
00075 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
00076 ANIMATED_PROPERTY_DEFINITIONS(SVGMaskElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
00077
00078 void SVGMaskElement::parseMappedAttribute(MappedAttribute* attr)
00079 {
00080 if (attr->name() == SVGNames::maskUnitsAttr) {
00081 if (attr->value() == "userSpaceOnUse")
00082 setMaskUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
00083 else if (attr->value() == "objectBoundingBox")
00084 setMaskUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
00085 } else if (attr->name() == SVGNames::maskContentUnitsAttr) {
00086 if (attr->value() == "userSpaceOnUse")
00087 setMaskContentUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE);
00088 else if (attr->value() == "objectBoundingBox")
00089 setMaskContentUnitsBaseValue(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
00090 } else if (attr->name() == SVGNames::xAttr)
00091 setXBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00092 else if (attr->name() == SVGNames::yAttr)
00093 setYBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00094 else if (attr->name() == SVGNames::widthAttr)
00095 setWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
00096 else if (attr->name() == SVGNames::heightAttr)
00097 setHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
00098 else {
00099 if (SVGURIReference::parseMappedAttribute(attr))
00100 return;
00101 if (SVGTests::parseMappedAttribute(attr))
00102 return;
00103 if (SVGLangSpace::parseMappedAttribute(attr))
00104 return;
00105 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
00106 return;
00107 SVGStyledElement::parseMappedAttribute(attr);
00108 }
00109 }
00110
00111 void SVGMaskElement::svgAttributeChanged(const QualifiedName& attrName)
00112 {
00113 SVGStyledElement::svgAttributeChanged(attrName);
00114
00115 if (!m_masker)
00116 return;
00117
00118 if (attrName == SVGNames::maskUnitsAttr || attrName == SVGNames::maskContentUnitsAttr ||
00119 attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
00120 attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||
00121 SVGURIReference::isKnownAttribute(attrName) ||
00122 SVGTests::isKnownAttribute(attrName) ||
00123 SVGLangSpace::isKnownAttribute(attrName) ||
00124 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
00125 SVGStyledElement::isKnownAttribute(attrName))
00126 m_masker->invalidate();
00127 }
00128
00129 void SVGMaskElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
00130 {
00131 SVGStyledElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
00132
00133 if (!m_masker)
00134 return;
00135
00136 m_masker->invalidate();
00137 }
00138
00139 auto_ptr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const
00140 {
00141
00142 float xValue;
00143 float yValue;
00144 float widthValue;
00145 float heightValue;
00146
00147 if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
00148 xValue = x().valueAsPercentage() * targetRect.width();
00149 yValue = y().valueAsPercentage() * targetRect.height();
00150 widthValue = width().valueAsPercentage() * targetRect.width();
00151 heightValue = height().valueAsPercentage() * targetRect.height();
00152 } else {
00153 xValue = x().value();
00154 yValue = y().value();
00155 widthValue = width().value();
00156 heightValue = height().value();
00157 }
00158
00159 IntSize imageSize(lroundf(widthValue), lroundf(heightValue));
00160 clampImageBufferSizeToViewport(document()->renderer(), imageSize);
00161
00162 if (imageSize.width() < static_cast<int>(widthValue))
00163 widthValue = imageSize.width();
00164
00165 if (imageSize.height() < static_cast<int>(heightValue))
00166 heightValue = imageSize.height();
00167
00168 auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, false);
00169 if (!maskImage.get())
00170 return maskImage;
00171
00172 maskDestRect = FloatRect(xValue, yValue, widthValue, heightValue);
00173 if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
00174 maskDestRect.move(targetRect.x(), targetRect.y());
00175
00176 GraphicsContext* maskImageContext = maskImage->context();
00177 ASSERT(maskImageContext);
00178
00179 maskImageContext->save();
00180 maskImageContext->translate(-xValue, -yValue);
00181
00182 if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
00183 maskImageContext->save();
00184 maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height()));
00185 }
00186
00187
00188 for (Node* n = firstChild(); n; n = n->nextSibling()) {
00189 SVGElement* elem = 0;
00190 if (n->isSVGElement())
00191 elem = static_cast<SVGElement*>(n);
00192 if (!elem || !elem->isStyled())
00193 continue;
00194
00195 SVGStyledElement* e = static_cast<SVGStyledElement*>(elem);
00196 RenderObject* item = e->renderer();
00197 if (!item)
00198 continue;
00199
00200 renderSubtreeToImage(maskImage.get(), item);
00201 }
00202
00203 if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
00204 maskImageContext->restore();
00205
00206 maskImageContext->restore();
00207 return maskImage;
00208 }
00209
00210 RenderObject* SVGMaskElement::createRenderer(RenderArena* arena, RenderStyle*)
00211 {
00212 RenderSVGContainer* maskContainer = new (arena) RenderSVGContainer(this);
00213 maskContainer->setDrawsContents(false);
00214 return maskContainer;
00215 }
00216
00217 SVGResource* SVGMaskElement::canvasResource()
00218 {
00219 if (!m_masker)
00220 m_masker = SVGResourceMasker::create(this);
00221 return m_masker.get();
00222 }
00223
00224 }
00225
00226 #endif // ENABLE(SVG)