1464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5464702f4SAndrew Rist  * distributed with this work for additional information
6464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10464702f4SAndrew Rist  *
11464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12464702f4SAndrew Rist  *
13464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14464702f4SAndrew Rist  * software distributed under the License is distributed on an
15464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17464702f4SAndrew Rist  * specific language governing permissions and limitations
18464702f4SAndrew Rist  * under the License.
19464702f4SAndrew Rist  *
20464702f4SAndrew Rist  *************************************************************/
21464702f4SAndrew Rist 
22464702f4SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
28cdf0e10cSrcweir #include <vcl/timer.hxx>
29cdf0e10cSrcweir #include <vcl/virdev.hxx>
30cdf0e10cSrcweir #include <vcl/font.hxx>
31cdf0e10cSrcweir #include <vcl/metric.hxx>
32cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
33cdf0e10cSrcweir #include <drawinglayer/primitive2d/textprimitive2d.hxx>
34cdf0e10cSrcweir #include <vcl/svapp.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
37cdf0e10cSrcweir // VDev RevDevice provider
38cdf0e10cSrcweir 
39cdf0e10cSrcweir namespace
40cdf0e10cSrcweir {
41cdf0e10cSrcweir 	class ImpTimedRefDev : public Timer
42cdf0e10cSrcweir 	{
43cdf0e10cSrcweir 		ImpTimedRefDev**					mppStaticPointerOnMe;
44cdf0e10cSrcweir 		VirtualDevice*						mpVirDev;
45cdf0e10cSrcweir 		sal_uInt32							mnUseCount;
46cdf0e10cSrcweir 
47cdf0e10cSrcweir 	public:
48cdf0e10cSrcweir 		ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe);
49cdf0e10cSrcweir 		~ImpTimedRefDev();
50cdf0e10cSrcweir 	    virtual void Timeout();
51cdf0e10cSrcweir 
52cdf0e10cSrcweir 		VirtualDevice& acquireVirtualDevice();
53cdf0e10cSrcweir 		void releaseVirtualDevice();
54cdf0e10cSrcweir 	};
55cdf0e10cSrcweir 
ImpTimedRefDev(ImpTimedRefDev ** ppStaticPointerOnMe)56cdf0e10cSrcweir 	ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe)
57cdf0e10cSrcweir 	:	mppStaticPointerOnMe(ppStaticPointerOnMe),
58cdf0e10cSrcweir 		mpVirDev(0L),
59cdf0e10cSrcweir 		mnUseCount(0L)
60cdf0e10cSrcweir 	{
61cdf0e10cSrcweir 		SetTimeout(3L * 60L * 1000L); // three minutes
62cdf0e10cSrcweir 		Start();
63cdf0e10cSrcweir 	}
64cdf0e10cSrcweir 
~ImpTimedRefDev()65cdf0e10cSrcweir 	ImpTimedRefDev::~ImpTimedRefDev()
66cdf0e10cSrcweir 	{
67cdf0e10cSrcweir 		OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
68cdf0e10cSrcweir 
69cdf0e10cSrcweir 		if(mppStaticPointerOnMe && *mppStaticPointerOnMe)
70cdf0e10cSrcweir 		{
71cdf0e10cSrcweir 			*mppStaticPointerOnMe = 0L;
72cdf0e10cSrcweir 		}
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 		if(mpVirDev)
75cdf0e10cSrcweir 		{
76cdf0e10cSrcweir 			delete mpVirDev;
77cdf0e10cSrcweir 		}
78cdf0e10cSrcweir 	}
79cdf0e10cSrcweir 
Timeout()80cdf0e10cSrcweir 	void ImpTimedRefDev::Timeout()
81cdf0e10cSrcweir 	{
82cdf0e10cSrcweir 		// for obvious reasons, do not call anything after this
83cdf0e10cSrcweir 		delete (this);
84cdf0e10cSrcweir 	}
85cdf0e10cSrcweir 
acquireVirtualDevice()86cdf0e10cSrcweir 	VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
87cdf0e10cSrcweir 	{
88cdf0e10cSrcweir 		if(!mpVirDev)
89cdf0e10cSrcweir 		{
90cdf0e10cSrcweir 			mpVirDev = new VirtualDevice();
91cdf0e10cSrcweir 			mpVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
92cdf0e10cSrcweir 		}
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 		if(!mnUseCount)
95cdf0e10cSrcweir 		{
96cdf0e10cSrcweir 			Stop();
97cdf0e10cSrcweir 		}
98cdf0e10cSrcweir 
99cdf0e10cSrcweir 		mnUseCount++;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 		return *mpVirDev;
102cdf0e10cSrcweir 	}
103cdf0e10cSrcweir 
releaseVirtualDevice()104cdf0e10cSrcweir 	void ImpTimedRefDev::releaseVirtualDevice()
105cdf0e10cSrcweir 	{
106cdf0e10cSrcweir 		OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
107cdf0e10cSrcweir 		mnUseCount--;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 		if(!mnUseCount)
110cdf0e10cSrcweir 		{
111cdf0e10cSrcweir 			Start();
112cdf0e10cSrcweir 		}
113cdf0e10cSrcweir 	}
114cdf0e10cSrcweir } // end of anonymous namespace
115cdf0e10cSrcweir 
116cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
117cdf0e10cSrcweir // access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive
118cdf0e10cSrcweir 
119cdf0e10cSrcweir namespace drawinglayer
120cdf0e10cSrcweir {
121cdf0e10cSrcweir 	namespace primitive2d
122cdf0e10cSrcweir 	{
123cdf0e10cSrcweir 		// static pointer here
124cdf0e10cSrcweir 		static ImpTimedRefDev* pImpGlobalRefDev = 0L;
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 		// static methods here
acquireGlobalVirtualDevice()127cdf0e10cSrcweir 		VirtualDevice& acquireGlobalVirtualDevice()
128cdf0e10cSrcweir 		{
129cdf0e10cSrcweir 			if(!pImpGlobalRefDev)
130cdf0e10cSrcweir 			{
131cdf0e10cSrcweir 				pImpGlobalRefDev = new ImpTimedRefDev(&pImpGlobalRefDev);
132cdf0e10cSrcweir 			}
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 			return pImpGlobalRefDev->acquireVirtualDevice();
135cdf0e10cSrcweir 		}
136cdf0e10cSrcweir 
releaseGlobalVirtualDevice()137cdf0e10cSrcweir 		void releaseGlobalVirtualDevice()
138cdf0e10cSrcweir 		{
139cdf0e10cSrcweir 			OSL_ENSURE(pImpGlobalRefDev, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
140cdf0e10cSrcweir 			pImpGlobalRefDev->releaseVirtualDevice();
141cdf0e10cSrcweir 		}
142cdf0e10cSrcweir 
TextLayouterDevice()143cdf0e10cSrcweir 		TextLayouterDevice::TextLayouterDevice()
144cdf0e10cSrcweir 		:	mrDevice(acquireGlobalVirtualDevice())
145cdf0e10cSrcweir 		{
146cdf0e10cSrcweir 		}
147cdf0e10cSrcweir 
~TextLayouterDevice()148cdf0e10cSrcweir 		TextLayouterDevice::~TextLayouterDevice()
149cdf0e10cSrcweir 		{
150cdf0e10cSrcweir 			releaseGlobalVirtualDevice();
151cdf0e10cSrcweir 		}
152cdf0e10cSrcweir 
setFont(const Font & rFont)153cdf0e10cSrcweir 		void TextLayouterDevice::setFont(const Font& rFont)
154cdf0e10cSrcweir 		{
155cdf0e10cSrcweir 			mrDevice.SetFont( rFont );
156cdf0e10cSrcweir 		}
157cdf0e10cSrcweir 
setFontAttribute(const attribute::FontAttribute & rFontAttribute,double fFontScaleX,double fFontScaleY,const::com::sun::star::lang::Locale & rLocale)158cdf0e10cSrcweir 		void TextLayouterDevice::setFontAttribute(
159cdf0e10cSrcweir             const attribute::FontAttribute& rFontAttribute,
160cdf0e10cSrcweir             double fFontScaleX,
161cdf0e10cSrcweir             double fFontScaleY,
162cdf0e10cSrcweir             const ::com::sun::star::lang::Locale& rLocale)
163cdf0e10cSrcweir 		{
164cdf0e10cSrcweir 			setFont(getVclFontFromFontAttribute(
165cdf0e10cSrcweir                 rFontAttribute,
166cdf0e10cSrcweir                 fFontScaleX,
167cdf0e10cSrcweir                 fFontScaleY,
168cdf0e10cSrcweir                 0.0,
169cdf0e10cSrcweir                 rLocale));
170cdf0e10cSrcweir         }
171cdf0e10cSrcweir 
getOverlineOffset() const172cdf0e10cSrcweir         double TextLayouterDevice::getOverlineOffset() const
173cdf0e10cSrcweir         {
174cdf0e10cSrcweir             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
175cdf0e10cSrcweir             double fRet = (rMetric.GetIntLeading() / 2.0) - rMetric.GetAscent();
176cdf0e10cSrcweir             return fRet;
177cdf0e10cSrcweir         }
178cdf0e10cSrcweir 
getUnderlineOffset() const179cdf0e10cSrcweir 		double TextLayouterDevice::getUnderlineOffset() const
180cdf0e10cSrcweir 		{
181cdf0e10cSrcweir 			const ::FontMetric& rMetric = mrDevice.GetFontMetric();
182cdf0e10cSrcweir 			double fRet = rMetric.GetDescent() / 2.0;
183cdf0e10cSrcweir 			return fRet;
184cdf0e10cSrcweir 		}
185cdf0e10cSrcweir 
getStrikeoutOffset() const186cdf0e10cSrcweir 		double TextLayouterDevice::getStrikeoutOffset() const
187cdf0e10cSrcweir 		{
188cdf0e10cSrcweir 			const ::FontMetric& rMetric = mrDevice.GetFontMetric();
189cdf0e10cSrcweir 			double fRet = (rMetric.GetAscent() - rMetric.GetIntLeading()) / 3.0;
190cdf0e10cSrcweir 			return fRet;
191cdf0e10cSrcweir 		}
192cdf0e10cSrcweir 
getOverlineHeight() const193cdf0e10cSrcweir         double TextLayouterDevice::getOverlineHeight() const
194cdf0e10cSrcweir         {
195cdf0e10cSrcweir             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
196cdf0e10cSrcweir             double fRet = rMetric.GetIntLeading() / 2.5;
197cdf0e10cSrcweir             return fRet;
198cdf0e10cSrcweir         }
199cdf0e10cSrcweir 
getUnderlineHeight() const200cdf0e10cSrcweir 		double TextLayouterDevice::getUnderlineHeight() const
201cdf0e10cSrcweir 		{
202cdf0e10cSrcweir 			const ::FontMetric& rMetric = mrDevice.GetFontMetric();
203cdf0e10cSrcweir 			double fRet = rMetric.GetDescent() / 4.0;
204cdf0e10cSrcweir 			return fRet;
205cdf0e10cSrcweir 		}
206cdf0e10cSrcweir 
getTextHeight() const207cdf0e10cSrcweir 		double TextLayouterDevice::getTextHeight() const
208cdf0e10cSrcweir 		{
209cdf0e10cSrcweir 			return mrDevice.GetTextHeight();
210cdf0e10cSrcweir 		}
211cdf0e10cSrcweir 
getTextWidth(const String & rText,sal_uInt32 nIndex,sal_uInt32 nLength) const212cdf0e10cSrcweir 		double TextLayouterDevice::getTextWidth(
213cdf0e10cSrcweir 			const String& rText,
214cdf0e10cSrcweir 			sal_uInt32 nIndex,
215cdf0e10cSrcweir 			sal_uInt32 nLength) const
216cdf0e10cSrcweir 		{
217cdf0e10cSrcweir 			return mrDevice.GetTextWidth(rText, nIndex, nLength);
218cdf0e10cSrcweir 		}
219cdf0e10cSrcweir 
getTextOutlines(basegfx::B2DPolyPolygonVector & rB2DPolyPolyVector,const String & rText,sal_uInt32 nIndex,sal_uInt32 nLength,const::std::vector<double> & rDXArray) const220cdf0e10cSrcweir 		bool TextLayouterDevice::getTextOutlines(
221cdf0e10cSrcweir 			basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
222cdf0e10cSrcweir 			const String& rText,
223cdf0e10cSrcweir 			sal_uInt32 nIndex,
224cdf0e10cSrcweir 			sal_uInt32 nLength,
225cdf0e10cSrcweir             const ::std::vector< double >& rDXArray) const
226cdf0e10cSrcweir 		{
227cdf0e10cSrcweir             const sal_uInt32 nDXArrayCount(rDXArray.size());
228cdf0e10cSrcweir 			sal_uInt32 nTextLength(nLength);
229cdf0e10cSrcweir 			const sal_uInt32 nStringLength(rText.Len());
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 			if(nTextLength + nIndex > nStringLength)
232cdf0e10cSrcweir 			{
233cdf0e10cSrcweir 				nTextLength = nStringLength - nIndex;
234cdf0e10cSrcweir 			}
235cdf0e10cSrcweir 
236cdf0e10cSrcweir             if(nDXArrayCount)
237cdf0e10cSrcweir             {
238cdf0e10cSrcweir                 OSL_ENSURE(nDXArrayCount == nTextLength, "DXArray size does not correspond to text portion size (!)");
239cdf0e10cSrcweir     		    std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount);
240cdf0e10cSrcweir 
241cdf0e10cSrcweir                 for(sal_uInt32 a(0); a < nDXArrayCount; a++)
242cdf0e10cSrcweir                 {
243cdf0e10cSrcweir                     aIntegerDXArray[a] = basegfx::fround(rDXArray[a]);
244cdf0e10cSrcweir                 }
245cdf0e10cSrcweir 
246cdf0e10cSrcweir                 return mrDevice.GetTextOutlines(
247cdf0e10cSrcweir                     rB2DPolyPolyVector,
248cdf0e10cSrcweir                     rText,
249cdf0e10cSrcweir                     nIndex,
250cdf0e10cSrcweir                     nIndex,
251cdf0e10cSrcweir                     nLength,
252cdf0e10cSrcweir                     true,
253cdf0e10cSrcweir 			        0,
254cdf0e10cSrcweir                     &(aIntegerDXArray[0]));
255cdf0e10cSrcweir             }
256cdf0e10cSrcweir             else
257cdf0e10cSrcweir             {
258cdf0e10cSrcweir                 return mrDevice.GetTextOutlines(
259cdf0e10cSrcweir                     rB2DPolyPolyVector,
260cdf0e10cSrcweir                     rText,
261cdf0e10cSrcweir                     nIndex,
262cdf0e10cSrcweir                     nIndex,
263cdf0e10cSrcweir                     nLength,
264cdf0e10cSrcweir                     true,
265cdf0e10cSrcweir 			        0,
266cdf0e10cSrcweir                     0);
267cdf0e10cSrcweir             }
268cdf0e10cSrcweir 		}
269cdf0e10cSrcweir 
getTextBoundRect(const String & rText,sal_uInt32 nIndex,sal_uInt32 nLength) const270cdf0e10cSrcweir 		basegfx::B2DRange TextLayouterDevice::getTextBoundRect(
271cdf0e10cSrcweir 			const String& rText,
272cdf0e10cSrcweir 			sal_uInt32 nIndex,
273cdf0e10cSrcweir 			sal_uInt32 nLength) const
274cdf0e10cSrcweir 		{
275cdf0e10cSrcweir 			sal_uInt32 nTextLength(nLength);
276cdf0e10cSrcweir 			const sal_uInt32 nStringLength(rText.Len());
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 			if(nTextLength + nIndex > nStringLength)
279cdf0e10cSrcweir 			{
280cdf0e10cSrcweir 				nTextLength = nStringLength - nIndex;
281cdf0e10cSrcweir 			}
282cdf0e10cSrcweir 
283cdf0e10cSrcweir 			if(nTextLength)
284cdf0e10cSrcweir 			{
285cdf0e10cSrcweir 				Rectangle aRect;
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 				mrDevice.GetTextBoundRect(
288cdf0e10cSrcweir                     aRect,
289cdf0e10cSrcweir                     rText,
290cdf0e10cSrcweir                     nIndex,
291cdf0e10cSrcweir                     nIndex,
292cdf0e10cSrcweir                     nLength);
293cdf0e10cSrcweir 
294cdf0e10cSrcweir                 // #i104432#, #i102556# take empty results into account
295cdf0e10cSrcweir                 if(!aRect.IsEmpty())
296cdf0e10cSrcweir                 {
297cdf0e10cSrcweir     				return basegfx::B2DRange(
298cdf0e10cSrcweir 						aRect.Left(), aRect.Top(),
299cdf0e10cSrcweir 						aRect.Right(), aRect.Bottom());
300cdf0e10cSrcweir                 }
301cdf0e10cSrcweir 			}
302cdf0e10cSrcweir 
303cdf0e10cSrcweir             return basegfx::B2DRange();
304cdf0e10cSrcweir 		}
305cdf0e10cSrcweir 
getFontAscent() const306cdf0e10cSrcweir         double TextLayouterDevice::getFontAscent() const
307cdf0e10cSrcweir         {
308cdf0e10cSrcweir             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
309cdf0e10cSrcweir             return rMetric.GetAscent();
310cdf0e10cSrcweir         }
311cdf0e10cSrcweir 
getFontDescent() const312cdf0e10cSrcweir         double TextLayouterDevice::getFontDescent() const
313cdf0e10cSrcweir         {
314cdf0e10cSrcweir             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
315cdf0e10cSrcweir             return rMetric.GetDescent();
316cdf0e10cSrcweir         }
317cdf0e10cSrcweir 
addTextRectActions(const Rectangle & rRectangle,const String & rText,sal_uInt16 nStyle,GDIMetaFile & rGDIMetaFile) const318cdf0e10cSrcweir 		void TextLayouterDevice::addTextRectActions(
319cdf0e10cSrcweir 			const Rectangle& rRectangle,
320cdf0e10cSrcweir 			const String& rText,
321cdf0e10cSrcweir 			sal_uInt16 nStyle,
322cdf0e10cSrcweir 			GDIMetaFile& rGDIMetaFile) const
323cdf0e10cSrcweir 		{
324cdf0e10cSrcweir 			mrDevice.AddTextRectActions(
325cdf0e10cSrcweir 				rRectangle, rText, nStyle, rGDIMetaFile);
326cdf0e10cSrcweir 		}
327cdf0e10cSrcweir 
getTextArray(const String & rText,sal_uInt32 nIndex,sal_uInt32 nLength) const328cdf0e10cSrcweir 		::std::vector< double > TextLayouterDevice::getTextArray(
329cdf0e10cSrcweir 			const String& rText,
330cdf0e10cSrcweir 			sal_uInt32 nIndex,
331cdf0e10cSrcweir 			sal_uInt32 nLength) const
332cdf0e10cSrcweir 		{
333cdf0e10cSrcweir 			::std::vector< double > aRetval;
334cdf0e10cSrcweir 			sal_uInt32 nTextLength(nLength);
335cdf0e10cSrcweir 			const sal_uInt32 nStringLength(rText.Len());
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 			if(nTextLength + nIndex > nStringLength)
338cdf0e10cSrcweir 			{
339cdf0e10cSrcweir 				nTextLength = nStringLength - nIndex;
340cdf0e10cSrcweir 			}
341cdf0e10cSrcweir 
342cdf0e10cSrcweir 			if(nTextLength)
343cdf0e10cSrcweir 			{
344cdf0e10cSrcweir 				aRetval.reserve(nTextLength);
345cc213d65SHerbert Dürr 				::std::vector<sal_Int32> aDXArray( nTextLength);
346cc213d65SHerbert Dürr 				mrDevice.GetTextArray(rText, &aDXArray[0], nIndex, nLength);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir 				for(sal_uInt32 a(0); a < nTextLength; a++)
349cdf0e10cSrcweir 				{
350cc213d65SHerbert Dürr 					aRetval.push_back(aDXArray[a]);
351cdf0e10cSrcweir 				}
352cdf0e10cSrcweir 			}
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 			return aRetval;
355cdf0e10cSrcweir 		}
356cdf0e10cSrcweir 
357cdf0e10cSrcweir 	} // end of namespace primitive2d
358cdf0e10cSrcweir } // end of namespace drawinglayer
359cdf0e10cSrcweir 
360cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
361cdf0e10cSrcweir // helper methods for vcl font handling
362cdf0e10cSrcweir 
363cdf0e10cSrcweir namespace drawinglayer
364cdf0e10cSrcweir {
365cdf0e10cSrcweir 	namespace primitive2d
366cdf0e10cSrcweir 	{
getVclFontFromFontAttribute(const attribute::FontAttribute & rFontAttribute,double fFontScaleX,double fFontScaleY,double fFontRotation,const::com::sun::star::lang::Locale & rLocale)367cdf0e10cSrcweir 		Font getVclFontFromFontAttribute(
368cdf0e10cSrcweir             const attribute::FontAttribute& rFontAttribute,
369cdf0e10cSrcweir             double fFontScaleX,
370cdf0e10cSrcweir             double fFontScaleY,
371cdf0e10cSrcweir             double fFontRotation,
372cdf0e10cSrcweir             const ::com::sun::star::lang::Locale& rLocale)
373cdf0e10cSrcweir 		{
374cdf0e10cSrcweir             // detect FontScaling
375cdf0e10cSrcweir 			const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
376cdf0e10cSrcweir             const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
377cdf0e10cSrcweir             const bool bFontIsScaled(nHeight != nWidth);
378cdf0e10cSrcweir 
379cdf0e10cSrcweir #ifdef WIN32
380cdf0e10cSrcweir             // for WIN32 systems, start with creating an unscaled font. If FontScaling
381cdf0e10cSrcweir             // is wanted, that width needs to be adapted using FontMetric again to get a
382cdf0e10cSrcweir             // width of the unscaled font
383cdf0e10cSrcweir 			Font aRetval(
384cdf0e10cSrcweir 				rFontAttribute.getFamilyName(),
385cdf0e10cSrcweir 				rFontAttribute.getStyleName(),
386cdf0e10cSrcweir 				Size(0, nHeight));
387cdf0e10cSrcweir #else
388cdf0e10cSrcweir             // for non-WIN32 systems things are easier since these accept a Font creation
389cdf0e10cSrcweir             // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
390*6d53c851Smseidel             // FontWidth when no scaling is used to explicitly have that zero when e.g. the
391cdf0e10cSrcweir             // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
392cdf0e10cSrcweir             // set FontWidth; import that in a WIN32 system, and trouble is there)
393cdf0e10cSrcweir 			Font aRetval(
394cdf0e10cSrcweir 				rFontAttribute.getFamilyName(),
395cdf0e10cSrcweir 				rFontAttribute.getStyleName(),
396cdf0e10cSrcweir                 Size(bFontIsScaled ? nWidth : 0, nHeight));
397cdf0e10cSrcweir #endif
398cdf0e10cSrcweir             // define various other FontAttribute
399cdf0e10cSrcweir 			aRetval.SetAlign(ALIGN_BASELINE);
400cdf0e10cSrcweir 			aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE);
401cdf0e10cSrcweir 			aRetval.SetVertical(rFontAttribute.getVertical() ? sal_True : sal_False);
402cdf0e10cSrcweir 			aRetval.SetWeight(static_cast<FontWeight>(rFontAttribute.getWeight()));
403cdf0e10cSrcweir 			aRetval.SetItalic(rFontAttribute.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
404cdf0e10cSrcweir 			aRetval.SetOutline(rFontAttribute.getOutline());
405cdf0e10cSrcweir             aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE);
406cdf0e10cSrcweir             aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale));
407cdf0e10cSrcweir 
408cdf0e10cSrcweir #ifdef WIN32
409cdf0e10cSrcweir             // for WIN32 systems, correct the FontWidth if FontScaling is used
410cdf0e10cSrcweir             if(bFontIsScaled && nHeight > 0)
411cdf0e10cSrcweir             {
412cdf0e10cSrcweir                 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval));
413cdf0e10cSrcweir 
414cdf0e10cSrcweir                 if(aUnscaledFontMetric.GetWidth() > 0)
415cdf0e10cSrcweir                 {
416cdf0e10cSrcweir                     const double fScaleFactor((double)nWidth / (double)nHeight);
417cdf0e10cSrcweir                     const sal_uInt32 nScaledWidth(basegfx::fround((double)aUnscaledFontMetric.GetWidth() * fScaleFactor));
418cdf0e10cSrcweir                     aRetval.SetWidth(nScaledWidth);
419cdf0e10cSrcweir                 }
420cdf0e10cSrcweir             }
421cdf0e10cSrcweir #endif
422cdf0e10cSrcweir             // handle FontRotation (if defined)
423cdf0e10cSrcweir 			if(!basegfx::fTools::equalZero(fFontRotation))
424cdf0e10cSrcweir 			{
425cdf0e10cSrcweir 				sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI)));
426cdf0e10cSrcweir 				aRetval.SetOrientation(aRotate10th % 3600);
427cdf0e10cSrcweir 			}
428cdf0e10cSrcweir 
429cdf0e10cSrcweir 			return aRetval;
430cdf0e10cSrcweir 		}
431cdf0e10cSrcweir 
getFontAttributeFromVclFont(basegfx::B2DVector & o_rSize,const Font & rFont,bool bRTL,bool bBiDiStrong)432cdf0e10cSrcweir         attribute::FontAttribute getFontAttributeFromVclFont(
433cdf0e10cSrcweir             basegfx::B2DVector& o_rSize,
434cdf0e10cSrcweir             const Font& rFont,
435cdf0e10cSrcweir             bool bRTL,
436cdf0e10cSrcweir             bool bBiDiStrong)
437cdf0e10cSrcweir 		{
438cdf0e10cSrcweir             const attribute::FontAttribute aRetval(
439cdf0e10cSrcweir 			    rFont.GetName(),
440cdf0e10cSrcweir 			    rFont.GetStyleName(),
441cdf0e10cSrcweir 			    static_cast<sal_uInt16>(rFont.GetWeight()),
442cdf0e10cSrcweir                 RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(),
443cdf0e10cSrcweir 			    rFont.IsVertical(),
444cdf0e10cSrcweir 			    ITALIC_NONE != rFont.GetItalic(),
445cdf0e10cSrcweir                 PITCH_FIXED == rFont.GetPitch(),
446cdf0e10cSrcweir 			    rFont.IsOutline(),
447cdf0e10cSrcweir                 bRTL,
448cdf0e10cSrcweir                 bBiDiStrong);
449cdf0e10cSrcweir 			// TODO: eKerning
450cdf0e10cSrcweir 
451cdf0e10cSrcweir             // set FontHeight and init to no FontScaling
452cdf0e10cSrcweir             o_rSize.setY(rFont.GetSize().getHeight() > 0 ? rFont.GetSize().getHeight() : 0);
453cdf0e10cSrcweir             o_rSize.setX(o_rSize.getY());
454cdf0e10cSrcweir 
455cdf0e10cSrcweir #ifdef WIN32
456cdf0e10cSrcweir             // for WIN32 systems, the FontScaling at the Font is detected by
457cdf0e10cSrcweir             // checking that FontWidth != 0. When FontScaling is used, WIN32
458cdf0e10cSrcweir             // needs to do extra stuff to detect the correct width (since it's
459cdf0e10cSrcweir             // zero and not equal the font height) and it's relationship to
460cdf0e10cSrcweir             // the height
461cdf0e10cSrcweir             if(rFont.GetSize().getWidth() > 0)
462cdf0e10cSrcweir             {
463cdf0e10cSrcweir                 Font aUnscaledFont(rFont);
464cdf0e10cSrcweir                 aUnscaledFont.SetWidth(0);
465cdf0e10cSrcweir                 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
466cdf0e10cSrcweir 
467cdf0e10cSrcweir                 if(aUnscaledFontMetric.GetWidth() > 0)
468cdf0e10cSrcweir                 {
469cdf0e10cSrcweir                     const double fScaleFactor((double)rFont.GetSize().getWidth() / (double)aUnscaledFontMetric.GetWidth());
470cdf0e10cSrcweir                     o_rSize.setX(fScaleFactor * o_rSize.getY());
471cdf0e10cSrcweir                 }
472cdf0e10cSrcweir             }
473cdf0e10cSrcweir #else
474cdf0e10cSrcweir             // For non-WIN32 systems the detection is the same, but the value
475cdf0e10cSrcweir             // is easier achieved since width == height is interpreted as no
476cdf0e10cSrcweir             // scaling. Ergo, Width == 0 means width == height, and width != 0
477cdf0e10cSrcweir             // means the scaling is in the direct relation of width to height
478cdf0e10cSrcweir             if(rFont.GetSize().getWidth() > 0)
479cdf0e10cSrcweir             {
480cdf0e10cSrcweir                 o_rSize.setX((double)rFont.GetSize().getWidth());
481cdf0e10cSrcweir             }
482cdf0e10cSrcweir #endif
483cdf0e10cSrcweir 			return aRetval;
484cdf0e10cSrcweir 		}
485cdf0e10cSrcweir 	} // end of namespace primitive2d
486cdf0e10cSrcweir } // end of namespace drawinglayer
487cdf0e10cSrcweir 
488cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
489cdf0e10cSrcweir // eof
490