1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_svgio.hxx" 24 25 #include <svgio/svgreader/svgclippathnode.hxx> 26 #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 27 #include <drawinglayer/primitive2d/maskprimitive2d.hxx> 28 #include <basegfx/matrix/b2dhommatrixtools.hxx> 29 #include <drawinglayer/geometry/viewinformation2d.hxx> 30 #include <drawinglayer/processor2d/contourextractor2d.hxx> 31 #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 32 33 ////////////////////////////////////////////////////////////////////////////// 34 35 namespace svgio 36 { 37 namespace svgreader 38 { 39 SvgClipPathNode::SvgClipPathNode( 40 SvgDocument& rDocument, 41 SvgNode* pParent) 42 : SvgNode(SVGTokenClipPathNode, rDocument, pParent), 43 maSvgStyleAttributes(*this), 44 mpaTransform(0), 45 maClipPathUnits(userSpaceOnUse) 46 { 47 } 48 49 SvgClipPathNode::~SvgClipPathNode() 50 { 51 if(mpaTransform) delete mpaTransform; 52 } 53 54 const SvgStyleAttributes* SvgClipPathNode::getSvgStyleAttributes() const 55 { 56 return &maSvgStyleAttributes; 57 } 58 59 void SvgClipPathNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 60 { 61 // call parent 62 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 63 64 // read style attributes 65 maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); 66 67 // parse own 68 switch(aSVGToken) 69 { 70 case SVGTokenStyle: 71 { 72 maSvgStyleAttributes.readStyle(aContent); 73 break; 74 } 75 case SVGTokenTransform: 76 { 77 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); 78 79 if(!aMatrix.isIdentity()) 80 { 81 setTransform(&aMatrix); 82 } 83 break; 84 } 85 case SVGTokenClipPathUnits: 86 { 87 if(aContent.getLength()) 88 { 89 if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) 90 { 91 setClipPathUnits(userSpaceOnUse); 92 } 93 else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) 94 { 95 setClipPathUnits(objectBoundingBox); 96 } 97 } 98 break; 99 } 100 default: 101 { 102 break; 103 } 104 } 105 } 106 107 void SvgClipPathNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 108 { 109 drawinglayer::primitive2d::Primitive2DSequence aNewTarget; 110 111 // decompose childs 112 SvgNode::decomposeSvgNode(aNewTarget, bReferenced); 113 114 if(aNewTarget.hasElements()) 115 { 116 if(getTransform()) 117 { 118 // create embedding group element with transformation 119 const drawinglayer::primitive2d::Primitive2DReference xRef( 120 new drawinglayer::primitive2d::TransformPrimitive2D( 121 *getTransform(), 122 aNewTarget)); 123 124 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); 125 } 126 else 127 { 128 // append to current target 129 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); 130 } 131 } 132 } 133 134 void SvgClipPathNode::apply(drawinglayer::primitive2d::Primitive2DSequence& rContent) const 135 { 136 if(rContent.hasElements()) 137 { 138 const drawinglayer::geometry::ViewInformation2D aViewInformation2D; 139 drawinglayer::primitive2d::Primitive2DSequence aClipTarget; 140 basegfx::B2DPolyPolygon aClipPolyPolygon; 141 142 // get clipPath definition as primitives 143 decomposeSvgNode(aClipTarget, true); 144 145 if(aClipTarget.hasElements()) 146 { 147 // extract filled plygons as base for a mask PolyPolygon 148 drawinglayer::processor2d::ContourExtractor2D aExtractor(aViewInformation2D, true); 149 150 aExtractor.process(aClipTarget); 151 152 const basegfx::B2DPolyPolygonVector& rResult(aExtractor.getExtractedContour()); 153 const sal_uInt32 nSize(rResult.size()); 154 155 if(nSize > 1) 156 { 157 // merge to single clipPolyPolygon 158 aClipPolyPolygon = basegfx::tools::mergeToSinglePolyPolygon(rResult); 159 } 160 else 161 { 162 aClipPolyPolygon = rResult[0]; 163 } 164 } 165 166 if(aClipPolyPolygon.count()) 167 { 168 if(objectBoundingBox == getClipPathUnits()) 169 { 170 // clip is object-relative, transform using content transformation 171 const basegfx::B2DRange aContentRange( 172 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 173 rContent, 174 aViewInformation2D)); 175 176 aClipPolyPolygon.transform( 177 basegfx::tools::createScaleTranslateB2DHomMatrix( 178 aContentRange.getRange(), 179 aContentRange.getMinimum())); 180 } 181 182 // redefine target. Use MaskPrimitive2D with created clip 183 // geometry. Using the automatically set mbIsClipPathContent at 184 // SvgStyleAttributes the clip definition is without fill, stroke, 185 // and strokeWidth and forced to black 186 const drawinglayer::primitive2d::Primitive2DReference xEmbedTransparence( 187 new drawinglayer::primitive2d::MaskPrimitive2D( 188 aClipPolyPolygon, 189 rContent)); 190 191 rContent = drawinglayer::primitive2d::Primitive2DSequence(&xEmbedTransparence, 1); 192 } 193 else 194 { 195 // An empty clipping path will completely clip away the element that had 196 // the �clip-path� property applied. (Svg spec) 197 rContent.realloc(0); 198 } 199 } 200 } 201 202 } // end of namespace svgreader 203 } // end of namespace svgio 204 205 ////////////////////////////////////////////////////////////////////////////// 206 // eof 207