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 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_drawinglayer.hxx" 26 27 #include <drawinglayer/primitive2d/texteffectprimitive2d.hxx> 28 #include <drawinglayer/geometry/viewinformation2d.hxx> 29 #include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx> 30 #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 31 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> 32 #include <basegfx/matrix/b2dhommatrixtools.hxx> 33 34 ////////////////////////////////////////////////////////////////////////////// 35 36 namespace drawinglayer 37 { 38 namespace primitive2d 39 { 40 static double fDiscreteSize(1.1); 41 create2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const42 Primitive2DSequence TextEffectPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 43 { 44 Primitive2DSequence aRetval; 45 46 // get the distance of one discrete units from target display. Use between 1.0 and sqrt(2) to 47 // have good results on rotated objects, too 48 const basegfx::B2DVector aDistance(rViewInformation.getInverseObjectToViewTransformation() * 49 basegfx::B2DVector(fDiscreteSize, fDiscreteSize)); 50 const basegfx::B2DVector aDiagonalDistance(aDistance * (1.0 / 1.44)); 51 52 switch(getTextEffectStyle2D()) 53 { 54 case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED: 55 case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED: 56 case TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT: 57 case TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT: 58 { 59 // prepare transform of sub-group back to (0,0) and align to X-Axis 60 basegfx::B2DHomMatrix aBackTransform(basegfx::tools::createTranslateB2DHomMatrix( 61 -getRotationCenter().getX(), -getRotationCenter().getY())); 62 aBackTransform.rotate(-getDirection()); 63 64 // prepare transform of sub-group back to it's position and rotation 65 basegfx::B2DHomMatrix aForwardTransform(basegfx::tools::createRotateB2DHomMatrix(getDirection())); 66 aForwardTransform.translate(getRotationCenter().getX(), getRotationCenter().getY()); 67 68 // create transformation for one discrete unit 69 const bool bEmbossed( 70 TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED == getTextEffectStyle2D() 71 || TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D()); 72 const bool bDefaultTextColor( 73 TEXTEFFECTSTYLE2D_RELIEF_EMBOSSED_DEFAULT == getTextEffectStyle2D() 74 || TEXTEFFECTSTYLE2D_RELIEF_ENGRAVED_DEFAULT == getTextEffectStyle2D()); 75 basegfx::B2DHomMatrix aTransform(aBackTransform); 76 aRetval.realloc(2); 77 78 if(bEmbossed) 79 { 80 // to bottom-right 81 aTransform.translate(aDiagonalDistance.getX(), aDiagonalDistance.getY()); 82 } 83 else 84 { 85 // to top-left 86 aTransform.translate(-aDiagonalDistance.getX(), -aDiagonalDistance.getY()); 87 } 88 89 aTransform *= aForwardTransform; 90 91 if(bDefaultTextColor) 92 { 93 // emboss/engrave in black, original forced to white 94 const basegfx::BColorModifierSharedPtr aBColorModifierToGray( 95 new basegfx::BColorModifier_replace( 96 basegfx::BColor(0.0))); 97 const Primitive2DReference xModifiedColor( 98 new ModifiedColorPrimitive2D( 99 getTextContent(), 100 aBColorModifierToGray)); 101 102 aRetval[0] = Primitive2DReference( 103 new TransformPrimitive2D( 104 aTransform, 105 Primitive2DSequence(&xModifiedColor, 1))); 106 107 // add original, too 108 const basegfx::BColorModifierSharedPtr aBColorModifierToWhite( 109 new basegfx::BColorModifier_replace( 110 basegfx::BColor(1.0))); 111 112 aRetval[1] = Primitive2DReference( 113 new ModifiedColorPrimitive2D( 114 getTextContent(), 115 aBColorModifierToWhite)); 116 } 117 else 118 { 119 // emboss/engrave in gray, keep original's color 120 const basegfx::BColorModifierSharedPtr aBColorModifierToGray( 121 new basegfx::BColorModifier_replace( 122 basegfx::BColor(0.75))); // 192 123 const Primitive2DReference xModifiedColor( 124 new ModifiedColorPrimitive2D( 125 getTextContent(), 126 aBColorModifierToGray)); 127 128 aRetval[0] = Primitive2DReference( 129 new TransformPrimitive2D( 130 aTransform, 131 Primitive2DSequence(&xModifiedColor, 1))); 132 133 // add original, too 134 aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getTextContent())); 135 } 136 137 break; 138 } 139 case TEXTEFFECTSTYLE2D_OUTLINE: 140 { 141 // create transform primitives in all directions 142 basegfx::B2DHomMatrix aTransform; 143 aRetval.realloc(9); 144 145 aTransform.set(0, 2, aDistance.getX()); 146 aTransform.set(1, 2, 0.0); 147 aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 148 149 aTransform.set(0, 2, aDiagonalDistance.getX()); 150 aTransform.set(1, 2, aDiagonalDistance.getY()); 151 aRetval[1] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 152 153 aTransform.set(0, 2, 0.0); 154 aTransform.set(1, 2, aDistance.getY()); 155 aRetval[2] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 156 157 aTransform.set(0, 2, -aDiagonalDistance.getX()); 158 aTransform.set(1, 2, aDiagonalDistance.getY()); 159 aRetval[3] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 160 161 aTransform.set(0, 2, -aDistance.getX()); 162 aTransform.set(1, 2, 0.0); 163 aRetval[4] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 164 165 aTransform.set(0, 2, -aDiagonalDistance.getX()); 166 aTransform.set(1, 2, -aDiagonalDistance.getY()); 167 aRetval[5] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 168 169 aTransform.set(0, 2, 0.0); 170 aTransform.set(1, 2, -aDistance.getY()); 171 aRetval[6] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 172 173 aTransform.set(0, 2, aDiagonalDistance.getX()); 174 aTransform.set(1, 2, -aDiagonalDistance.getY()); 175 aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent())); 176 177 // at last, place original over it, but force to white 178 const basegfx::BColorModifierSharedPtr aBColorModifierToWhite( 179 new basegfx::BColorModifier_replace( 180 basegfx::BColor(1.0, 1.0, 1.0))); 181 aRetval[8] = Primitive2DReference( 182 new ModifiedColorPrimitive2D( 183 getTextContent(), 184 aBColorModifierToWhite)); 185 186 break; 187 } 188 } 189 190 return aRetval; 191 } 192 TextEffectPrimitive2D(const Primitive2DSequence & rTextContent,const basegfx::B2DPoint & rRotationCenter,double fDirection,TextEffectStyle2D eTextEffectStyle2D)193 TextEffectPrimitive2D::TextEffectPrimitive2D( 194 const Primitive2DSequence& rTextContent, 195 const basegfx::B2DPoint& rRotationCenter, 196 double fDirection, 197 TextEffectStyle2D eTextEffectStyle2D) 198 : BufferedDecompositionPrimitive2D(), 199 maTextContent(rTextContent), 200 maRotationCenter(rRotationCenter), 201 mfDirection(fDirection), 202 meTextEffectStyle2D(eTextEffectStyle2D) 203 { 204 } 205 operator ==(const BasePrimitive2D & rPrimitive) const206 bool TextEffectPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const 207 { 208 if(BasePrimitive2D::operator==(rPrimitive)) 209 { 210 const TextEffectPrimitive2D& rCompare = (TextEffectPrimitive2D&)rPrimitive; 211 212 return (getTextContent() == rCompare.getTextContent() 213 && getRotationCenter() == rCompare.getRotationCenter() 214 && getDirection() == rCompare.getDirection() 215 && getTextEffectStyle2D() == rCompare.getTextEffectStyle2D()); 216 } 217 218 return false; 219 } 220 getB2DRange(const geometry::ViewInformation2D & rViewInformation) const221 basegfx::B2DRange TextEffectPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const 222 { 223 // get range of content and grow by used fDiscreteSize. That way it is not necessary to ask 224 // the whole decomposition for it's ranges (which may be expensive with outline mode which 225 // then will ask 9 times at nearly the same content. This may even be refined here using the 226 // TextEffectStyle information, e.g. for TEXTEFFECTSTYLE2D_RELIEF the grow needs only to 227 // be in two directions 228 basegfx::B2DRange aRetval(getB2DRangeFromPrimitive2DSequence(getTextContent(), rViewInformation)); 229 aRetval.grow(fDiscreteSize); 230 231 return aRetval; 232 } 233 get2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const234 Primitive2DSequence TextEffectPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const 235 { 236 ::osl::MutexGuard aGuard( m_aMutex ); 237 238 if(getBuffered2DDecomposition().hasElements()) 239 { 240 if(maLastObjectToViewTransformation != rViewInformation.getObjectToViewTransformation()) 241 { 242 // conditions of last local decomposition have changed, delete 243 const_cast< TextEffectPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence()); 244 } 245 } 246 247 if(!getBuffered2DDecomposition().hasElements()) 248 { 249 // remember ViewRange and ViewTransformation 250 const_cast< TextEffectPrimitive2D* >(this)->maLastObjectToViewTransformation = rViewInformation.getObjectToViewTransformation(); 251 } 252 253 // use parent implementation 254 return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation); 255 } 256 257 // provide unique ID 258 ImplPrimitrive2DIDBlock(TextEffectPrimitive2D, PRIMITIVE2D_ID_TEXTEFFECTPRIMITIVE2D) 259 260 } // end of namespace primitive2d 261 } // end of namespace drawinglayer 262 263 ////////////////////////////////////////////////////////////////////////////// 264 // eof 265