Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(524)

Side by Side Diff: Source/core/rendering/svg/RenderSVGResourceMasker.cpp

Issue 23643003: ImageBuffer-less SVG masking and clipping. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fix the Win build. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details. 12 * Library General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU Library General Public License 14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to 15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA. 17 * Boston, MA 02110-1301, USA.
18 */ 18 */
19 19
20 #include "config.h" 20 #include "config.h"
21 21
22 #include "core/rendering/svg/RenderSVGResourceMasker.h" 22 #include "core/rendering/svg/RenderSVGResourceMasker.h"
23 23
24 #include "core/platform/graphics/FloatRect.h" 24 #include "core/platform/graphics/FloatRect.h"
25 #include "core/platform/graphics/GraphicsContext.h" 25 #include "core/platform/graphics/GraphicsContext.h"
26 #include "core/platform/graphics/GraphicsContextStateSaver.h"
26 #include "core/platform/graphics/ImageBuffer.h" 27 #include "core/platform/graphics/ImageBuffer.h"
27 #include "core/platform/graphics/transforms/AffineTransform.h" 28 #include "core/platform/graphics/transforms/AffineTransform.h"
28 #include "core/rendering/svg/RenderSVGResource.h" 29 #include "core/rendering/svg/RenderSVGResource.h"
29 #include "core/rendering/svg/SVGRenderingContext.h" 30 #include "core/rendering/svg/SVGRenderingContext.h"
30 #include "core/svg/SVGElement.h" 31 #include "core/svg/SVGElement.h"
31 #include "core/svg/SVGMaskElement.h" 32 #include "core/svg/SVGMaskElement.h"
32 #include "core/svg/SVGUnitTypes.h" 33 #include "core/svg/SVGUnitTypes.h"
33 34
34 #include "wtf/UnusedParam.h" 35 #include "wtf/UnusedParam.h"
35 #include "wtf/Vector.h" 36 #include "wtf/Vector.h"
36 37
37 namespace WebCore { 38 namespace WebCore {
38 39
39 RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceTy pe; 40 RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceTy pe;
40 41
41 RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement* node) 42 RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement* node)
42 : RenderSVGResourceContainer(node) 43 : RenderSVGResourceContainer(node)
43 { 44 {
44 } 45 }
45 46
46 RenderSVGResourceMasker::~RenderSVGResourceMasker() 47 RenderSVGResourceMasker::~RenderSVGResourceMasker()
47 { 48 {
48 if (m_masker.isEmpty())
49 return;
50
51 deleteAllValues(m_masker);
52 m_masker.clear();
53 } 49 }
54 50
55 void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation ) 51 void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation )
56 { 52 {
57 m_maskContentBoundaries = FloatRect(); 53 m_maskContentBoundaries = FloatRect();
58 if (!m_masker.isEmpty()) {
59 deleteAllValues(m_masker);
60 m_masker.clear();
61 }
62
63 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation); 54 markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInval idation : ParentOnlyInvalidation);
64 } 55 }
65 56
66 void RenderSVGResourceMasker::removeClientFromCache(RenderObject* client, bool m arkForInvalidation) 57 void RenderSVGResourceMasker::removeClientFromCache(RenderObject* client, bool m arkForInvalidation)
67 { 58 {
68 ASSERT(client); 59 ASSERT(client);
69
70 if (m_masker.contains(client))
71 delete m_masker.take(client);
72
73 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation); 60 markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidati on : ParentOnlyInvalidation);
74 } 61 }
75 62
76 bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode) 63 bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*,
64 GraphicsContext*& context, unsigned short resourceMode)
77 { 65 {
78 ASSERT(object); 66 ASSERT(object);
79 ASSERT(context); 67 ASSERT(context);
68 ASSERT(style());
80 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode); 69 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
81 70 ASSERT_WITH_SECURITY_IMPLICATION(!needsLayout());
82 bool missingMaskerData = !m_masker.contains(object);
83 if (missingMaskerData)
84 m_masker.set(object, new MaskerData);
85
86 MaskerData* maskerData = m_masker.get(object);
87
88 AffineTransform absoluteTransform;
89 SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(obje ct, absoluteTransform);
90 71
91 FloatRect repaintRect = object->repaintRectInLocalCoordinates(); 72 FloatRect repaintRect = object->repaintRectInLocalCoordinates();
73 if (repaintRect.isEmpty() || !node()->hasChildNodes())
74 return false;
92 75
93 if (!maskerData->maskImage && !repaintRect.isEmpty()) { 76 const SVGRenderStyle* svgStyle = style()->svgStyle();
94 SVGMaskElement* maskElement = toSVGMaskElement(node()); 77 ASSERT(svgStyle);
95 if (!maskElement) 78 ColorSpace colorSpace = svgStyle->colorInterpolation() == CI_LINEARRGB
96 return false; 79 ? ColorSpaceLinearRGB
80 : ColorSpaceDeviceRGB;
97 81
98 ASSERT(style()); 82 // Mask layer start.
99 const SVGRenderStyle* svgStyle = style()->svgStyle(); 83 context->beginTransparencyLayer(1, &repaintRect);
100 ASSERT(svgStyle); 84 {
101 ColorSpace colorSpace = svgStyle->colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB; 85 // Draw the mask with color conversion (when needed).
102 if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransfo rm, maskerData->maskImage, Unaccelerated)) 86 GraphicsContextStateSaver maskContentSaver(*context);
103 return false; 87 context->setColorSpaceConversion(ColorSpaceDeviceRGB, colorSpace);
104 88
105 if (!drawContentIntoMaskImage(maskerData, colorSpace, maskElement, objec t)) { 89 drawMaskContent(context, object->objectBoundingBox());
106 maskerData->maskImage.clear();
107 }
108 } 90 }
109 91
110 if (!maskerData->maskImage) 92 // Content layer start.
111 return false; 93 MaskType maskType = svgStyle->maskType() == MT_LUMINANCE ? LuminanceMaskType : AlphaMaskType;
112 94 context->beginMaskedLayer(repaintRect, maskType);
113 SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRe ct, maskerData->maskImage, missingMaskerData);
114 return true;
115 }
116
117 bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, C olorSpace colorSpace, const SVGMaskElement* maskElement, RenderObject* object)
118 {
119 GraphicsContext* maskImageContext = maskerData->maskImage->context();
120 ASSERT(maskImageContext);
121
122 // Eventually adjust the mask image context according to the target objectBo undingBox.
123 AffineTransform maskContentTransformation;
124 if (maskElement->maskContentUnitsCurrentValue() == SVGUnitTypes::SVG_UNIT_TY PE_OBJECTBOUNDINGBOX) {
125 FloatRect objectBoundingBox = object->objectBoundingBox();
126 maskContentTransformation.translate(objectBoundingBox.x(), objectBoundin gBox.y());
127 maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), obj ectBoundingBox.height());
128 maskImageContext->concatCTM(maskContentTransformation);
129 }
130
131 // Draw the content into the ImageBuffer.
132 for (Node* node = maskElement->firstChild(); node; node = node->nextSibling( )) {
133 RenderObject* renderer = node->renderer();
134 if (!node->isSVGElement() || !renderer)
135 continue;
136 if (renderer->needsLayout())
137 return false;
138 RenderStyle* style = renderer->style();
139 if (!style || style->display() == NONE || style->visibility() != VISIBLE )
140 continue;
141 SVGRenderingContext::renderSubtreeToImageBuffer(maskerData->maskImage.ge t(), renderer, maskContentTransformation);
142 }
143
144 maskerData->maskImage->transformColorSpace(ColorSpaceDeviceRGB, colorSpace);
145
146 ASSERT(style());
147 ASSERT(style()->svgStyle());
148 // Create the luminance mask.
149 if (style()->svgStyle()->maskType() == MT_LUMINANCE)
150 maskerData->maskImage->convertToLuminanceMask();
151 95
152 return true; 96 return true;
153 } 97 }
154 98
99 void RenderSVGResourceMasker::postApplyResource(RenderObject*, GraphicsContext*& context,
100 unsigned short resourceMode, const Path*, const RenderSVGShape*)
101 {
102 ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
103
104 // Transfer content layer -> mask layer (SrcIn)
105 context->endLayer();
106 // Transfer mask layer -> bg layer (SrcOver)
107 context->endLayer();
108 }
109
110 void RenderSVGResourceMasker::drawMaskContent(GraphicsContext* context, const Fl oatRect& targetBoundingBox)
111 {
112 ASSERT(context);
113
114 // Adjust the mask image context according to the target objectBoundingBox.
115 AffineTransform maskContentTransformation;
116 if (toSVGMaskElement(node())->maskContentUnitsCurrentValue() == SVGUnitTypes ::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
117 maskContentTransformation.translate(targetBoundingBox.x(), targetBoundin gBox.y());
118 maskContentTransformation.scaleNonUniform(targetBoundingBox.width(), tar getBoundingBox.height());
119 context->concatCTM(maskContentTransformation);
120 }
121
122 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) {
123 RenderObject* renderer = childNode->renderer();
124 if (!childNode->isSVGElement() || !renderer)
125 continue;
126 RenderStyle* style = renderer->style();
127 if (!style || style->display() == NONE || style->visibility() != VISIBLE )
128 continue;
129
130 SVGRenderingContext::renderSubtree(context, renderer, maskContentTransfo rmation);
131 }
132 }
133
155 void RenderSVGResourceMasker::calculateMaskContentRepaintRect() 134 void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
156 { 135 {
157 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) { 136 for (Node* childNode = node()->firstChild(); childNode; childNode = childNod e->nextSibling()) {
158 RenderObject* renderer = childNode->renderer(); 137 RenderObject* renderer = childNode->renderer();
159 if (!childNode->isSVGElement() || !renderer) 138 if (!childNode->isSVGElement() || !renderer)
160 continue; 139 continue;
161 RenderStyle* style = renderer->style(); 140 RenderStyle* style = renderer->style();
162 if (!style || style->display() == NONE || style->visibility() != VISIBLE ) 141 if (!style || style->display() == NONE || style->visibility() != VISIBLE )
163 continue; 142 continue;
164 m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect (renderer->repaintRectInLocalCoordinates())); 143 m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect (renderer->repaintRectInLocalCoordinates()));
(...skipping 21 matching lines...) Expand all
186 transform.translate(objectBoundingBox.x(), objectBoundingBox.y()); 165 transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
187 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h eight()); 166 transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.h eight());
188 maskRect = transform.mapRect(maskRect); 167 maskRect = transform.mapRect(maskRect);
189 } 168 }
190 169
191 maskRect.intersect(maskBoundaries); 170 maskRect.intersect(maskBoundaries);
192 return maskRect; 171 return maskRect;
193 } 172 }
194 173
195 } 174 }
OLDNEW
« no previous file with comments | « Source/core/rendering/svg/RenderSVGResourceMasker.h ('k') | Source/core/rendering/svg/RenderSVGResourcePattern.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698