merge the formfield patch from ooo-build
[ooovba.git] / drawinglayer / source / primitive2d / textlayoutdevice.cxx
blob6fe64bdd71dd69069a0386ee2cfe932f4740409c
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: textlayoutdevice.cxx,v $
7 * $Revision: 1.10 $
9 * last change: $Author: aw $ $Date: 2008-05-27 14:11:20 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/primitive2d/textlayoutdevice.hxx>
40 #include <vcl/timer.hxx>
41 #include <vcl/virdev.hxx>
42 #include <vcl/font.hxx>
43 #include <vcl/metric.hxx>
44 #include <i18npool/mslangid.hxx>
45 #include <drawinglayer/primitive2d/textprimitive2d.hxx>
46 #include <vcl/svapp.hxx>
48 //////////////////////////////////////////////////////////////////////////////
49 // VDev RevDevice provider
51 namespace
53 class ImpTimedRefDev : public Timer
55 ImpTimedRefDev** mppStaticPointerOnMe;
56 VirtualDevice* mpVirDev;
57 sal_uInt32 mnUseCount;
59 public:
60 ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe);
61 ~ImpTimedRefDev();
62 virtual void Timeout();
64 VirtualDevice& acquireVirtualDevice();
65 void releaseVirtualDevice();
68 ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe)
69 : mppStaticPointerOnMe(ppStaticPointerOnMe),
70 mpVirDev(0L),
71 mnUseCount(0L)
73 SetTimeout(3L * 60L * 1000L); // three minutes
74 Start();
77 ImpTimedRefDev::~ImpTimedRefDev()
79 OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
81 if(mppStaticPointerOnMe && *mppStaticPointerOnMe)
83 *mppStaticPointerOnMe = 0L;
86 if(mpVirDev)
88 delete mpVirDev;
92 void ImpTimedRefDev::Timeout()
94 // for obvious reasons, do not call anything after this
95 delete (this);
98 VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
100 if(!mpVirDev)
102 mpVirDev = new VirtualDevice();
103 mpVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
106 if(!mnUseCount)
108 Stop();
111 mnUseCount++;
113 return *mpVirDev;
116 void ImpTimedRefDev::releaseVirtualDevice()
118 OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
119 mnUseCount--;
121 if(!mnUseCount)
123 Start();
126 } // end of anonymous namespace
128 //////////////////////////////////////////////////////////////////////////////
129 // access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive
131 namespace drawinglayer
133 namespace primitive2d
135 // static pointer here
136 static ImpTimedRefDev* pImpGlobalRefDev = 0L;
138 // static methods here
139 VirtualDevice& acquireGlobalVirtualDevice()
141 if(!pImpGlobalRefDev)
143 pImpGlobalRefDev = new ImpTimedRefDev(&pImpGlobalRefDev);
146 return pImpGlobalRefDev->acquireVirtualDevice();
149 void releaseGlobalVirtualDevice()
151 OSL_ENSURE(pImpGlobalRefDev, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
152 pImpGlobalRefDev->releaseVirtualDevice();
155 TextLayouterDevice::TextLayouterDevice()
156 : mrDevice(acquireGlobalVirtualDevice())
160 TextLayouterDevice::~TextLayouterDevice()
162 releaseGlobalVirtualDevice();
165 void TextLayouterDevice::setFont(const Font& rFont)
167 mrDevice.SetFont( rFont );
170 void TextLayouterDevice::setFontAttributes(
171 const FontAttributes& rFontAttributes,
172 double fFontScaleX,
173 double fFontScaleY,
174 const ::com::sun::star::lang::Locale& rLocale)
176 setFont(getVclFontFromFontAttributes(
177 rFontAttributes,
178 fFontScaleX,
179 fFontScaleY,
180 0.0,
181 rLocale));
184 double TextLayouterDevice::getOverlineOffset() const
186 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
187 double fRet = (rMetric.GetIntLeading() / 2.0) - rMetric.GetAscent();
188 return fRet;
191 double TextLayouterDevice::getUnderlineOffset() const
193 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
194 double fRet = rMetric.GetDescent() / 2.0;
195 return fRet;
198 double TextLayouterDevice::getStrikeoutOffset() const
200 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
201 double fRet = (rMetric.GetAscent() - rMetric.GetIntLeading()) / 3.0;
202 return fRet;
205 double TextLayouterDevice::getOverlineHeight() const
207 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
208 double fRet = rMetric.GetIntLeading() / 2.5;
209 return fRet;
212 double TextLayouterDevice::getUnderlineHeight() const
214 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
215 double fRet = rMetric.GetDescent() / 4.0;
216 return fRet;
219 double TextLayouterDevice::getTextHeight() const
221 return mrDevice.GetTextHeight();
224 double TextLayouterDevice::getTextWidth(
225 const String& rText,
226 xub_StrLen nIndex,
227 xub_StrLen nLength) const
229 return mrDevice.GetTextWidth(rText, nIndex, nLength);
232 bool TextLayouterDevice::getTextOutlines(
233 basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
234 const String& rText,
235 xub_StrLen nIndex,
236 xub_StrLen nLength,
237 const ::std::vector< double >& rDXArray)
239 const sal_uInt32 nDXArrayCount(rDXArray.size());
241 if(nDXArrayCount)
243 OSL_ENSURE(nDXArrayCount == nLength, "DXArray size does not correspond to text portion size (!)");
244 std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount);
246 for(sal_uInt32 a(0); a < nDXArrayCount; a++)
248 aIntegerDXArray[a] = basegfx::fround(rDXArray[a]);
251 return mrDevice.GetTextOutlines(
252 rB2DPolyPolyVector,
253 rText,
254 nIndex,
255 nIndex,
256 nLength,
257 true,
259 &(aIntegerDXArray[0]));
261 else
263 return mrDevice.GetTextOutlines(
264 rB2DPolyPolyVector,
265 rText,
266 nIndex,
267 nIndex,
268 nLength,
269 true,
275 basegfx::B2DRange TextLayouterDevice::getTextBoundRect(
276 const String& rText,
277 xub_StrLen nIndex,
278 xub_StrLen nLength) const
280 if(nLength)
282 Rectangle aRect;
284 mrDevice.GetTextBoundRect(
285 aRect,
286 rText,
287 nIndex,
288 nIndex,
289 nLength);
291 // #i104432#, #i102556# take empty results into account
292 if(!aRect.IsEmpty())
294 return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom());
298 return basegfx::B2DRange();
300 } // end of namespace primitive2d
301 } // end of namespace drawinglayer
303 //////////////////////////////////////////////////////////////////////////////
304 // helper methods for vcl font handling
306 namespace drawinglayer
308 namespace primitive2d
310 Font getVclFontFromFontAttributes(
311 const FontAttributes& rFontAttributes,
312 double fFontScaleX,
313 double fFontScaleY,
314 double fFontRotation,
315 const ::com::sun::star::lang::Locale& rLocale)
317 // detect FontScaling
318 const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
319 const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
320 const bool bFontIsScaled(nHeight != nWidth);
322 #ifdef WIN32
323 // for WIN32 systems, start with creating an unscaled font. If FontScaling
324 // is wanted, that width needs to be adapted using FontMetric again to get a
325 // width of the unscaled font
326 Font aRetval(
327 rFontAttributes.getFamilyName(),
328 rFontAttributes.getStyleName(),
329 Size(0, nHeight));
330 #else
331 // for non-WIN32 systems things are easier since these accept a Font creation
332 // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
333 // FontWidth when no scaling is used to explicitely have that zero when e.g. the
334 // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
335 // set FontWidth; import that in a WIN32 system, and trouble is there)
336 Font aRetval(
337 rFontAttributes.getFamilyName(),
338 rFontAttributes.getStyleName(),
339 Size(bFontIsScaled ? nWidth : 0, nHeight));
340 #endif
341 // define various other FontAttributes
342 aRetval.SetAlign(ALIGN_BASELINE);
343 aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE);
344 aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE);
345 aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.getWeight()));
346 aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
347 aRetval.SetOutline(rFontAttributes.getOutline());
348 aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale));
350 #ifdef WIN32
351 // for WIN32 systems, correct the FontWidth if FontScaling is used
352 if(bFontIsScaled && nHeight > 0)
354 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval));
356 if(aUnscaledFontMetric.GetWidth() > 0)
358 const double fScaleFactor((double)nWidth / (double)nHeight);
359 const sal_uInt32 nScaledWidth(basegfx::fround((double)aUnscaledFontMetric.GetWidth() * fScaleFactor));
360 aRetval.SetWidth(nScaledWidth);
363 #endif
364 // handle FontRotation (if defined)
365 if(!basegfx::fTools::equalZero(fFontRotation))
367 sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI)));
368 aRetval.SetOrientation(aRotate10th % 3600);
371 return aRetval;
374 FontAttributes getFontAttributesFromVclFont(
375 basegfx::B2DVector& o_rSize,
376 const Font& rFont,
377 bool bRTL,
378 bool bBiDiStrong)
380 const FontAttributes aRetval(
381 rFont.GetName(),
382 rFont.GetStyleName(),
383 static_cast<sal_uInt16>(rFont.GetWeight()),
384 RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(),
385 rFont.IsVertical(),
386 ITALIC_NONE != rFont.GetItalic(),
387 rFont.IsOutline(),
388 bRTL,
389 bBiDiStrong);
390 // TODO: eKerning
392 // set FontHeight and init to no FontScaling
393 o_rSize.setY(rFont.GetSize().getHeight() > 0 ? rFont.GetSize().getHeight() : 0);
394 o_rSize.setX(o_rSize.getY());
396 #ifdef WIN32
397 // for WIN32 systems, the FontScaling at the Font is detected by
398 // checking that FontWidth != 0. When FontScaling is used, WIN32
399 // needs to do extra stuff to detect the correct width (since it's
400 // zero and not equal the font height) and it's relationship to
401 // the height
402 if(rFont.GetSize().getWidth() > 0)
404 Font aUnscaledFont(rFont);
405 aUnscaledFont.SetWidth(0);
406 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
408 if(aUnscaledFontMetric.GetWidth() > 0)
410 const double fScaleFactor((double)rFont.GetSize().getWidth() / (double)aUnscaledFontMetric.GetWidth());
411 o_rSize.setX(fScaleFactor * o_rSize.getY());
414 #else
415 // For non-WIN32 systems the detection is the same, but the value
416 // is easier achieved since width == height is interpreted as no
417 // scaling. Ergo, Width == 0 means width == height, and width != 0
418 // means the scaling is in the direct relation of width to height
419 if(rFont.GetSize().getWidth() > 0)
421 o_rSize.setX((double)rFont.GetSize().getWidth());
423 #endif
424 return aRetval;
426 } // end of namespace primitive2d
427 } // end of namespace drawinglayer
429 //////////////////////////////////////////////////////////////////////////////
430 // eof