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/transparenceprimitive2d.hxx> 28 #include <basegfx/matrix/b2dhommatrixtools.hxx> 29 #include <drawinglayer/geometry/viewinformation2d.hxx> 30 31 ////////////////////////////////////////////////////////////////////////////// 32 33 namespace svgio 34 { 35 namespace svgreader 36 { 37 SvgClipPathNode::SvgClipPathNode( 38 SvgDocument& rDocument, 39 SvgNode* pParent) 40 : SvgNode(SVGTokenClipPathNode, rDocument, pParent), 41 maSvgStyleAttributes(*this), 42 mpaTransform(0), 43 maClipPathUnits(userSpaceOnUse) 44 { 45 } 46 47 SvgClipPathNode::~SvgClipPathNode() 48 { 49 if(mpaTransform) delete mpaTransform; 50 } 51 52 const SvgStyleAttributes* SvgClipPathNode::getSvgStyleAttributes() const 53 { 54 static rtl::OUString aClassStr(rtl::OUString::createFromAscii("clip-path")); 55 maSvgStyleAttributes.checkForCssStyle(aClassStr); 56 57 return &maSvgStyleAttributes; 58 } 59 60 void SvgClipPathNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 61 { 62 // call parent 63 SvgNode::parseAttribute(rTokenName, aSVGToken, aContent); 64 65 // read style attributes 66 maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent); 67 68 // parse own 69 switch(aSVGToken) 70 { 71 case SVGTokenStyle: 72 { 73 maSvgStyleAttributes.readStyle(aContent); 74 break; 75 } 76 case SVGTokenTransform: 77 { 78 const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this)); 79 80 if(!aMatrix.isIdentity()) 81 { 82 setTransform(&aMatrix); 83 } 84 break; 85 } 86 case SVGTokenClipPathUnits: 87 { 88 if(aContent.getLength()) 89 { 90 if(aContent.match(commonStrings::aStrUserSpaceOnUse, 0)) 91 { 92 setClipPathUnits(userSpaceOnUse); 93 } 94 else if(aContent.match(commonStrings::aStrObjectBoundingBox, 0)) 95 { 96 setClipPathUnits(objectBoundingBox); 97 } 98 } 99 break; 100 } 101 } 102 } 103 104 void SvgClipPathNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DSequence& rTarget, bool bReferenced) const 105 { 106 drawinglayer::primitive2d::Primitive2DSequence aNewTarget; 107 108 // decompose childs 109 SvgNode::decomposeSvgNode(aNewTarget, bReferenced); 110 111 if(aNewTarget.hasElements()) 112 { 113 if(getTransform()) 114 { 115 // create embedding group element with transformation 116 const drawinglayer::primitive2d::Primitive2DReference xRef( 117 new drawinglayer::primitive2d::TransformPrimitive2D( 118 *getTransform(), 119 aNewTarget)); 120 121 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xRef); 122 } 123 else 124 { 125 // append to current target 126 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewTarget); 127 } 128 } 129 } 130 131 void SvgClipPathNode::apply(drawinglayer::primitive2d::Primitive2DSequence& rContent) const 132 { 133 if(rContent.hasElements()) 134 { 135 drawinglayer::primitive2d::Primitive2DSequence aClipTarget; 136 137 // get clipPath definition as primitives 138 decomposeSvgNode(aClipTarget, true); 139 140 if(aClipTarget.hasElements()) 141 { 142 if(objectBoundingBox == getClipPathUnits()) 143 { 144 // clip is object-relative, embed in content transformation 145 const basegfx::B2DRange aContentRange( 146 drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 147 rContent, 148 drawinglayer::geometry::ViewInformation2D())); 149 150 const drawinglayer::primitive2d::Primitive2DReference xTransform( 151 new drawinglayer::primitive2d::TransformPrimitive2D( 152 basegfx::tools::createScaleTranslateB2DHomMatrix( 153 aContentRange.getRange(), 154 aContentRange.getMinimum()), 155 aClipTarget)); 156 157 aClipTarget = drawinglayer::primitive2d::Primitive2DSequence(&xTransform, 1); 158 } 159 160 // redefine target. Use TransparencePrimitive2D with created clip 161 // geometry. Using the automatically set mbIsClipPathContent at 162 // SvgStyleAttributes the clip definition is without fill, stroke, 163 // and strokeWidth and forced to black, thus being 100% opaque 164 const drawinglayer::primitive2d::Primitive2DReference xEmbedTransparence( 165 new drawinglayer::primitive2d::TransparencePrimitive2D( 166 rContent, 167 aClipTarget)); 168 169 rContent = drawinglayer::primitive2d::Primitive2DSequence(&xEmbedTransparence, 1); 170 } 171 else 172 { 173 // An empty clipping path will completely clip away the element that had 174 // the �clip-path� property applied. (Svg spec) 175 rContent.realloc(0); 176 } 177 } 178 } 179 180 } // end of namespace svgreader 181 } // end of namespace svgio 182 183 ////////////////////////////////////////////////////////////////////////////// 184 // eof 185