fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / drawinglayer / source / primitive2d / textprimitive2d.cxx
blob16f60f585fa08805509f46e247567022252d78cd
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
21 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
22 #include <basegfx/polygon/b2dpolypolygon.hxx>
23 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
24 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
25 #include <drawinglayer/primitive2d/texteffectprimitive2d.hxx>
26 #include <basegfx/matrix/b2dhommatrixtools.hxx>
28 //////////////////////////////////////////////////////////////////////////////
30 using namespace com::sun::star;
32 //////////////////////////////////////////////////////////////////////////////
34 namespace
36 // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted
37 // scale from a text transformation. A copy is modified so that it contains only positive
38 // scalings and XY-equal scalings to allow to get a non-X-scaled Vcl-Font for TextLayouter.
39 // rScale is adapted accordingly to contain the corrected scale which would need to be
40 // applied to e.g. outlines received from TextLayouter under usage of fontScale. This
41 // includes Y-Scale, X-Scale-correction and mirrorings.
42 basegfx::B2DVector getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale)
44 // copy input value
45 basegfx::B2DVector aFontScale(rScale);
47 // correct FontHeight settings
48 if(basegfx::fTools::equalZero(aFontScale.getY()))
50 // no font height; choose one and adapt scale to get back to original scaling
51 static double fDefaultFontScale(100.0);
52 rScale.setY(1.0 / fDefaultFontScale);
53 aFontScale.setY(fDefaultFontScale);
55 else if(basegfx::fTools::less(aFontScale.getY(), 0.0))
57 // negative font height; invert and adapt scale to get back to original scaling
58 aFontScale.setY(-aFontScale.getY());
59 rScale.setY(-1.0);
61 else
63 // positive font height; adapt scale; scaling will be part of the polygons
64 rScale.setY(1.0);
67 // correct FontWidth settings
68 if(basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY()))
70 // no FontScale, adapt scale
71 rScale.setX(1.0);
73 else
75 // If FontScale is used, force to no FontScale to get a non-scaled VCL font.
76 // Adapt scaling in X accordingly.
77 rScale.setX(aFontScale.getX() / aFontScale.getY());
78 aFontScale.setX(aFontScale.getY());
81 return aFontScale;
83 } // end of anonymous namespace
85 //////////////////////////////////////////////////////////////////////////////
87 namespace drawinglayer
89 namespace primitive2d
91 void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const
93 if(getTextLength())
95 // decompose object transformation to single values
96 basegfx::B2DVector aScale, aTranslate;
97 double fRotate, fShearX;
99 // if decomposition returns false, create no geometry since e.g. scaling may
100 // be zero
101 if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX))
103 // handle special case: If scale is negative in (x,y) (3rd quadrant), it can
104 // be expressed as rotation by PI
105 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
107 aScale = basegfx::absolute(aScale);
108 fRotate += F_PI;
111 // for the TextLayouterDevice, it is necessary to have a scaling representing
112 // the font size. Since we want to extract polygons here, it is okay to
113 // work just with scaling and to ignore shear, rotation and translation,
114 // all that can be applied to the polygons later
115 const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
117 // prepare textlayoutdevice
118 TextLayouterDevice aTextLayouter;
119 aTextLayouter.setFontAttribute(
120 getFontAttribute(),
121 aFontScale.getX(),
122 aFontScale.getY(),
123 getLocale());
125 // When getting outlines from stretched text (aScale.getX() != 1.0) it
126 // is necessary to inverse-scale the DXArray (if used) to not get the
127 // outlines already aligned to given, but wrong DXArray
128 if(getDXArray().size() && !basegfx::fTools::equal(aScale.getX(), 1.0))
130 ::std::vector< double > aScaledDXArray = getDXArray();
131 const double fDXArrayScale(1.0 / aScale.getX());
133 for(sal_uInt32 a(0); a < aScaledDXArray.size(); a++)
135 aScaledDXArray[a] *= fDXArrayScale;
138 // get the text outlines
139 aTextLayouter.getTextOutlines(
140 rTarget,
141 getText(),
142 getTextPosition(),
143 getTextLength(),
144 aScaledDXArray);
146 else
148 // get the text outlines
149 aTextLayouter.getTextOutlines(
150 rTarget,
151 getText(),
152 getTextPosition(),
153 getTextLength(),
154 getDXArray());
157 // create primitives for the outlines
158 const sal_uInt32 nCount(rTarget.size());
160 if(nCount)
162 // prepare object transformation for polygons
163 rTransformation = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
164 aScale, fShearX, fRotate, aTranslate);
170 Primitive2DSequence TextSimplePortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
172 Primitive2DSequence aRetval;
174 if(getTextLength())
176 basegfx::B2DPolyPolygonVector aB2DPolyPolyVector;
177 basegfx::B2DHomMatrix aPolygonTransform;
179 // get text outlines and their object transformation
180 getTextOutlinesAndTransformation(aB2DPolyPolyVector, aPolygonTransform);
182 // create primitives for the outlines
183 const sal_uInt32 nCount(aB2DPolyPolyVector.size());
185 if(nCount)
187 // alloc space for the primitives
188 aRetval.realloc(nCount);
190 // color-filled polypolygons
191 for(sal_uInt32 a(0L); a < nCount; a++)
193 // prepare polypolygon
194 basegfx::B2DPolyPolygon& rPolyPolygon = aB2DPolyPolyVector[a];
195 rPolyPolygon.transform(aPolygonTransform);
196 aRetval[a] = new PolyPolygonColorPrimitive2D(rPolyPolygon, getFontColor());
199 if(getFontAttribute().getOutline())
201 // decompose polygon transformation to single values
202 basegfx::B2DVector aScale, aTranslate;
203 double fRotate, fShearX;
204 aPolygonTransform.decompose(aScale, aTranslate, fRotate, fShearX);
206 // create outline text effect with current content and replace
207 Primitive2DReference aNewTextEffect(new TextEffectPrimitive2D(
208 aRetval,
209 aTranslate,
210 fRotate,
211 TEXTEFFECTSTYLE2D_OUTLINE));
213 aRetval = Primitive2DSequence(&aNewTextEffect, 1);
218 return aRetval;
221 TextSimplePortionPrimitive2D::TextSimplePortionPrimitive2D(
222 const basegfx::B2DHomMatrix& rNewTransform,
223 const String& rText,
224 xub_StrLen aTextPosition,
225 xub_StrLen aTextLength,
226 const ::std::vector< double >& rDXArray,
227 const attribute::FontAttribute& rFontAttribute,
228 const ::com::sun::star::lang::Locale& rLocale,
229 const basegfx::BColor& rFontColor,
230 bool bFilled,
231 long nWidthToFill)
232 : BufferedDecompositionPrimitive2D(),
233 maTextTransform(rNewTransform),
234 maText(rText),
235 maTextPosition(aTextPosition),
236 maTextLength(aTextLength),
237 maDXArray(rDXArray),
238 maFontAttribute(rFontAttribute),
239 maLocale(rLocale),
240 maFontColor(rFontColor),
241 maB2DRange(),
242 mbFilled(bFilled),
243 mnWidthToFill(nWidthToFill)
245 #if OSL_DEBUG_LEVEL > 0
246 const xub_StrLen aStringLength(getText().Len());
247 OSL_ENSURE(aStringLength >= getTextPosition() && aStringLength >= getTextPosition() + getTextLength(),
248 "TextSimplePortionPrimitive2D with text out of range (!)");
249 #endif
252 bool LocalesAreEqual(const ::com::sun::star::lang::Locale& rA, const ::com::sun::star::lang::Locale& rB)
254 return (rA.Language == rB.Language
255 && rA.Country == rB.Country
256 && rA.Variant == rB.Variant);
259 bool TextSimplePortionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
261 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
263 const TextSimplePortionPrimitive2D& rCompare = (TextSimplePortionPrimitive2D&)rPrimitive;
265 return (getTextTransform() == rCompare.getTextTransform()
266 && getText() == rCompare.getText()
267 && getTextPosition() == rCompare.getTextPosition()
268 && getTextLength() == rCompare.getTextLength()
269 && getDXArray() == rCompare.getDXArray()
270 && getFontAttribute() == rCompare.getFontAttribute()
271 && LocalesAreEqual(getLocale(), rCompare.getLocale())
272 && getFontColor() == rCompare.getFontColor()
273 && mbFilled == rCompare.mbFilled
274 && mnWidthToFill == rCompare.mnWidthToFill);
277 return false;
280 basegfx::B2DRange TextSimplePortionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
282 if(maB2DRange.isEmpty() && getTextLength())
284 // get TextBoundRect as base size
285 // decompose object transformation to single values
286 basegfx::B2DVector aScale, aTranslate;
287 double fRotate, fShearX;
289 if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX))
291 // for the TextLayouterDevice, it is necessary to have a scaling representing
292 // the font size. Since we want to extract polygons here, it is okay to
293 // work just with scaling and to ignore shear, rotation and translation,
294 // all that can be applied to the polygons later
295 const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale));
297 // prepare textlayoutdevice
298 TextLayouterDevice aTextLayouter;
299 aTextLayouter.setFontAttribute(
300 getFontAttribute(),
301 aFontScale.getX(),
302 aFontScale.getY(),
303 getLocale());
305 // get basic text range
306 basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()));
308 // #i104432#, #i102556# take empty results into account
309 if(!aNewRange.isEmpty())
311 // prepare object transformation for range
312 const basegfx::B2DHomMatrix aRangeTransformation(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
313 aScale, fShearX, fRotate, aTranslate));
315 // apply range transformation to it
316 aNewRange.transform(aRangeTransformation);
318 // assign to buffered value
319 const_cast< TextSimplePortionPrimitive2D* >(this)->maB2DRange = aNewRange;
324 return maB2DRange;
327 // provide unique ID
328 ImplPrimitive2DIDBlock(TextSimplePortionPrimitive2D, PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D)
330 } // end of namespace primitive2d
331 } // end of namespace drawinglayer
333 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */