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 |