| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> |
| 3 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 3 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
| 4 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> | 4 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> |
| 5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "RenderSVGText.h" | 31 #include "RenderSVGText.h" |
| 32 #include "SVGRenderSupport.h" | 32 #include "SVGRenderSupport.h" |
| 33 #include "SVGRenderingContext.h" | 33 #include "SVGRenderingContext.h" |
| 34 #include <wtf/UnusedParam.h> | 34 #include <wtf/UnusedParam.h> |
| 35 | 35 |
| 36 namespace WebCore { | 36 namespace WebCore { |
| 37 | 37 |
| 38 RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node) | 38 RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node) |
| 39 : RenderSVGResourceContainer(node) | 39 : RenderSVGResourceContainer(node) |
| 40 , m_shouldCollectGradientAttributes(true) | 40 , m_shouldCollectGradientAttributes(true) |
| 41 #if USE(CG) | |
| 42 , m_savedContext(0) | |
| 43 #endif | |
| 44 { | 41 { |
| 45 } | 42 } |
| 46 | 43 |
| 47 void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidati
on) | 44 void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidati
on) |
| 48 { | 45 { |
| 49 m_gradientMap.clear(); | 46 m_gradientMap.clear(); |
| 50 m_shouldCollectGradientAttributes = true; | 47 m_shouldCollectGradientAttributes = true; |
| 51 markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : Pa
rentOnlyInvalidation); | 48 markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : Pa
rentOnlyInvalidation); |
| 52 } | 49 } |
| 53 | 50 |
| 54 void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool
markForInvalidation) | 51 void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool
markForInvalidation) |
| 55 { | 52 { |
| 56 ASSERT(client); | 53 ASSERT(client); |
| 57 m_gradientMap.remove(client); | 54 m_gradientMap.remove(client); |
| 58 markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation
: ParentOnlyInvalidation); | 55 markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation
: ParentOnlyInvalidation); |
| 59 } | 56 } |
| 60 | 57 |
| 61 #if USE(CG) | |
| 62 static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con
text, | |
| 63 GraphicsContext*& sav
edContext, | |
| 64 OwnPtr<ImageBuffer>&
imageBuffer, | |
| 65 RenderObject* object) | |
| 66 { | |
| 67 RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(obj
ect); | |
| 68 ASSERT(textRootBlock); | |
| 69 | |
| 70 AffineTransform absoluteTransform; | |
| 71 SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(text
RootBlock, absoluteTransform); | |
| 72 | |
| 73 FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates(); | |
| 74 OwnPtr<ImageBuffer> maskImage; | |
| 75 if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform,
maskImage, ColorSpaceDeviceRGB, Unaccelerated)) | |
| 76 return false; | |
| 77 | |
| 78 GraphicsContext* maskImageContext = maskImage->context(); | |
| 79 ASSERT(maskImageContext); | |
| 80 ASSERT(maskImage); | |
| 81 savedContext = context; | |
| 82 context = maskImageContext; | |
| 83 imageBuffer = maskImage.release(); | |
| 84 return true; | |
| 85 } | |
| 86 | |
| 87 static inline AffineTransform clipToTextMask(GraphicsContext* context, | |
| 88 OwnPtr<ImageBuffer>& imageBuffer, | |
| 89 FloatRect& targetRect, | |
| 90 RenderObject* object, | |
| 91 bool boundingBoxMode, | |
| 92 const AffineTransform& gradientTran
sform) | |
| 93 { | |
| 94 RenderObject* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(obj
ect); | |
| 95 ASSERT(textRootBlock); | |
| 96 | |
| 97 AffineTransform absoluteTransform; | |
| 98 SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(text
RootBlock, absoluteTransform); | |
| 99 | |
| 100 targetRect = textRootBlock->repaintRectInLocalCoordinates(); | |
| 101 SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRec
t, imageBuffer, false); | |
| 102 | |
| 103 AffineTransform matrix; | |
| 104 if (boundingBoxMode) { | |
| 105 FloatRect maskBoundingBox = textRootBlock->objectBoundingBox(); | |
| 106 matrix.translate(maskBoundingBox.x(), maskBoundingBox.y()); | |
| 107 matrix.scaleNonUniform(maskBoundingBox.width(), maskBoundingBox.height()
); | |
| 108 } | |
| 109 matrix *= gradientTransform; | |
| 110 return matrix; | |
| 111 } | |
| 112 #endif | |
| 113 | |
| 114 bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
style, GraphicsContext*& context, unsigned short resourceMode) | 58 bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
style, GraphicsContext*& context, unsigned short resourceMode) |
| 115 { | 59 { |
| 116 ASSERT(object); | 60 ASSERT(object); |
| 117 ASSERT(style); | 61 ASSERT(style); |
| 118 ASSERT(context); | 62 ASSERT(context); |
| 119 ASSERT(resourceMode != ApplyToDefaultMode); | 63 ASSERT(resourceMode != ApplyToDefaultMode); |
| 120 | 64 |
| 121 // Be sure to synchronize all SVG properties on the gradientElement _before_
processing any further. | 65 // Be sure to synchronize all SVG properties on the gradientElement _before_
processing any further. |
| 122 // Otherwhise the call to collectGradientAttributes() in createTileImage(),
may cause the SVG DOM property | 66 // Otherwhise the call to collectGradientAttributes() in createTileImage(),
may cause the SVG DOM property |
| 123 // synchronization to kick in, which causes removeAllClientsFromCache() to b
e called, which in turn deletes our | 67 // synchronization to kick in, which causes removeAllClientsFromCache() to b
e called, which in turn deletes our |
| (...skipping 19 matching lines...) Expand all Loading... |
| 143 OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).iter
ator->value; | 87 OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).iter
ator->value; |
| 144 if (!gradientData) | 88 if (!gradientData) |
| 145 gradientData = adoptPtr(new GradientData); | 89 gradientData = adoptPtr(new GradientData); |
| 146 | 90 |
| 147 bool isPaintingText = resourceMode & ApplyToTextMode; | 91 bool isPaintingText = resourceMode & ApplyToTextMode; |
| 148 | 92 |
| 149 // Create gradient object | 93 // Create gradient object |
| 150 if (!gradientData->gradient) { | 94 if (!gradientData->gradient) { |
| 151 buildGradient(gradientData.get()); | 95 buildGradient(gradientData.get()); |
| 152 | 96 |
| 153 // CG platforms will handle the gradient space transform for text after
applying the | 97 // We want the text bounding box applied to the gradient space transform
now, so the gradient shader can use it. |
| 154 // resource, so don't apply it here. For non-CG platforms, we want the t
ext bounding | |
| 155 // box applied to the gradient space transform now, so the gradient shad
er can use it. | |
| 156 #if USE(CG) | |
| 157 if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX &&
!objectBoundingBox.isEmpty() && !isPaintingText) { | |
| 158 #else | |
| 159 if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX &&
!objectBoundingBox.isEmpty()) { | 98 if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX &&
!objectBoundingBox.isEmpty()) { |
| 160 #endif | |
| 161 gradientData->userspaceTransform.translate(objectBoundingBox.x(), ob
jectBoundingBox.y()); | 99 gradientData->userspaceTransform.translate(objectBoundingBox.x(), ob
jectBoundingBox.y()); |
| 162 gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.w
idth(), objectBoundingBox.height()); | 100 gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.w
idth(), objectBoundingBox.height()); |
| 163 } | 101 } |
| 164 | 102 |
| 165 AffineTransform gradientTransform; | 103 AffineTransform gradientTransform; |
| 166 calculateGradientTransform(gradientTransform); | 104 calculateGradientTransform(gradientTransform); |
| 167 | 105 |
| 168 gradientData->userspaceTransform *= gradientTransform; | 106 gradientData->userspaceTransform *= gradientTransform; |
| 169 if (isPaintingText) { | 107 if (isPaintingText) { |
| 170 // Depending on font scaling factor, we may need to rescale the grad
ient here since | 108 // Depending on font scaling factor, we may need to rescale the grad
ient here since |
| 171 // text painting removes the scale factor from the context. | 109 // text painting removes the scale factor from the context. |
| 172 AffineTransform additionalTextTransform; | 110 AffineTransform additionalTextTransform; |
| 173 if (shouldTransformOnTextPainting(object, additionalTextTransform)) | 111 if (shouldTransformOnTextPainting(object, additionalTextTransform)) |
| 174 gradientData->userspaceTransform *= additionalTextTransform; | 112 gradientData->userspaceTransform *= additionalTextTransform; |
| 175 } | 113 } |
| 176 gradientData->gradient->setGradientSpaceTransform(gradientData->userspac
eTransform); | 114 gradientData->gradient->setGradientSpaceTransform(gradientData->userspac
eTransform); |
| 177 } | 115 } |
| 178 | 116 |
| 179 if (!gradientData->gradient) | 117 if (!gradientData->gradient) |
| 180 return false; | 118 return false; |
| 181 | 119 |
| 182 // Draw gradient | 120 // Draw gradient |
| 183 context->save(); | 121 context->save(); |
| 184 | 122 |
| 185 if (isPaintingText) { | 123 if (isPaintingText) |
| 186 #if USE(CG) | |
| 187 if (!createMaskAndSwapContextForTextGradient(context, m_savedContext, m_
imageBuffer, object)) { | |
| 188 context->restore(); | |
| 189 return false; | |
| 190 } | |
| 191 #endif | |
| 192 | |
| 193 context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFil
l : TextModeStroke); | 124 context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFil
l : TextModeStroke); |
| 194 } | |
| 195 | 125 |
| 196 const SVGRenderStyle* svgStyle = style->svgStyle(); | 126 const SVGRenderStyle* svgStyle = style->svgStyle(); |
| 197 ASSERT(svgStyle); | 127 ASSERT(svgStyle); |
| 198 | 128 |
| 199 if (resourceMode & ApplyToFillMode) { | 129 if (resourceMode & ApplyToFillMode) { |
| 200 context->setAlpha(svgStyle->fillOpacity()); | 130 context->setAlpha(svgStyle->fillOpacity()); |
| 201 context->setFillGradient(gradientData->gradient); | 131 context->setFillGradient(gradientData->gradient); |
| 202 context->setFillRule(svgStyle->fillRule()); | 132 context->setFillRule(svgStyle->fillRule()); |
| 203 } else if (resourceMode & ApplyToStrokeMode) { | 133 } else if (resourceMode & ApplyToStrokeMode) { |
| 204 if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) | 134 if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE) |
| 205 gradientData->gradient->setGradientSpaceTransform(transformOnNonScal
ingStroke(object, gradientData->userspaceTransform)); | 135 gradientData->gradient->setGradientSpaceTransform(transformOnNonScal
ingStroke(object, gradientData->userspaceTransform)); |
| 206 context->setAlpha(svgStyle->strokeOpacity()); | 136 context->setAlpha(svgStyle->strokeOpacity()); |
| 207 context->setStrokeGradient(gradientData->gradient); | 137 context->setStrokeGradient(gradientData->gradient); |
| 208 SVGRenderSupport::applyStrokeStyleToContext(context, style, object); | 138 SVGRenderSupport::applyStrokeStyleToContext(context, style, object); |
| 209 } | 139 } |
| 210 | 140 |
| 211 return true; | 141 return true; |
| 212 } | 142 } |
| 213 | 143 |
| 214 void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
Context*& context, unsigned short resourceMode, const Path* path, const RenderSV
GShape* shape) | 144 void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
Context*& context, unsigned short resourceMode, const Path* path, const RenderSV
GShape* shape) |
| 215 { | 145 { |
| 216 ASSERT(context); | 146 ASSERT(context); |
| 217 ASSERT(resourceMode != ApplyToDefaultMode); | 147 ASSERT(resourceMode != ApplyToDefaultMode); |
| 148 UNUSED_PARAM(object); |
| 218 | 149 |
| 219 if (resourceMode & ApplyToTextMode) { | 150 if (resourceMode & ApplyToFillMode) { |
| 220 #if USE(CG) | 151 if (path) |
| 221 // CG requires special handling for gradient on text | 152 context->fillPath(*path); |
| 222 GradientData* gradientData; | 153 else if (shape) |
| 223 if (m_savedContext && (gradientData = m_gradientMap.get(object))) { | 154 shape->fillShape(context); |
| 224 // Restore on-screen drawing context | 155 } |
| 225 context = m_savedContext; | 156 if (resourceMode & ApplyToStrokeMode) { |
| 226 m_savedContext = 0; | 157 if (path) |
| 227 | 158 context->strokePath(*path); |
| 228 AffineTransform gradientTransform; | 159 else if (shape) |
| 229 calculateGradientTransform(gradientTransform); | 160 shape->strokeShape(context); |
| 230 | |
| 231 FloatRect targetRect; | |
| 232 gradientData->gradient->setGradientSpaceTransform(clipToTextMask(con
text, m_imageBuffer, targetRect, object, gradientUnits() == SVGUnitTypes::SVG_UN
IT_TYPE_OBJECTBOUNDINGBOX, gradientTransform)); | |
| 233 context->setFillGradient(gradientData->gradient); | |
| 234 | |
| 235 context->fillRect(targetRect); | |
| 236 m_imageBuffer.clear(); | |
| 237 } | |
| 238 #else | |
| 239 UNUSED_PARAM(object); | |
| 240 #endif | |
| 241 } else { | |
| 242 if (resourceMode & ApplyToFillMode) { | |
| 243 if (path) | |
| 244 context->fillPath(*path); | |
| 245 else if (shape) | |
| 246 shape->fillShape(context); | |
| 247 } | |
| 248 if (resourceMode & ApplyToStrokeMode) { | |
| 249 if (path) | |
| 250 context->strokePath(*path); | |
| 251 else if (shape) | |
| 252 shape->strokeShape(context); | |
| 253 } | |
| 254 } | 161 } |
| 255 | 162 |
| 256 context->restore(); | 163 context->restore(); |
| 257 } | 164 } |
| 258 | 165 |
| 259 void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vecto
r<Gradient::ColorStop>& stops) const | 166 void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vecto
r<Gradient::ColorStop>& stops) const |
| 260 { | 167 { |
| 261 ASSERT(gradientData->gradient); | 168 ASSERT(gradientData->gradient); |
| 262 | 169 |
| 263 const Vector<Gradient::ColorStop>::const_iterator end = stops.end(); | 170 const Vector<Gradient::ColorStop>::const_iterator end = stops.end(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 277 return SpreadMethodRepeat; | 184 return SpreadMethodRepeat; |
| 278 } | 185 } |
| 279 | 186 |
| 280 ASSERT_NOT_REACHED(); | 187 ASSERT_NOT_REACHED(); |
| 281 return SpreadMethodPad; | 188 return SpreadMethodPad; |
| 282 } | 189 } |
| 283 | 190 |
| 284 } | 191 } |
| 285 | 192 |
| 286 #endif | 193 #endif |
| OLD | NEW |