1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: textlayoutdevice.cxx,v $
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,
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
53 class ImpTimedRefDev
: public Timer
55 ImpTimedRefDev
** mppStaticPointerOnMe
;
56 VirtualDevice
* mpVirDev
;
57 sal_uInt32 mnUseCount
;
60 ImpTimedRefDev(ImpTimedRefDev
** ppStaticPointerOnMe
);
62 virtual void Timeout();
64 VirtualDevice
& acquireVirtualDevice();
65 void releaseVirtualDevice();
68 ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev
** ppStaticPointerOnMe
)
69 : mppStaticPointerOnMe(ppStaticPointerOnMe
),
73 SetTimeout(3L * 60L * 1000L); // three minutes
77 ImpTimedRefDev::~ImpTimedRefDev()
79 OSL_ENSURE(0L == mnUseCount
, "destruction of a still used ImpTimedRefDev (!)");
81 if(mppStaticPointerOnMe
&& *mppStaticPointerOnMe
)
83 *mppStaticPointerOnMe
= 0L;
92 void ImpTimedRefDev::Timeout()
94 // for obvious reasons, do not call anything after this
98 VirtualDevice
& ImpTimedRefDev::acquireVirtualDevice()
102 mpVirDev
= new VirtualDevice();
103 mpVirDev
->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1
);
116 void ImpTimedRefDev::releaseVirtualDevice()
118 OSL_ENSURE(mnUseCount
, "mismatch call number to releaseVirtualDevice() (!)");
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
,
174 const ::com::sun::star::lang::Locale
& rLocale
)
176 setFont(getVclFontFromFontAttributes(
184 double TextLayouterDevice::getOverlineOffset() const
186 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
187 double fRet
= (rMetric
.GetIntLeading() / 2.0) - rMetric
.GetAscent();
191 double TextLayouterDevice::getUnderlineOffset() const
193 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
194 double fRet
= rMetric
.GetDescent() / 2.0;
198 double TextLayouterDevice::getStrikeoutOffset() const
200 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
201 double fRet
= (rMetric
.GetAscent() - rMetric
.GetIntLeading()) / 3.0;
205 double TextLayouterDevice::getOverlineHeight() const
207 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
208 double fRet
= rMetric
.GetIntLeading() / 2.5;
212 double TextLayouterDevice::getUnderlineHeight() const
214 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
215 double fRet
= rMetric
.GetDescent() / 4.0;
219 double TextLayouterDevice::getTextHeight() const
221 return mrDevice
.GetTextHeight();
224 double TextLayouterDevice::getTextWidth(
227 xub_StrLen nLength
) const
229 return mrDevice
.GetTextWidth(rText
, nIndex
, nLength
);
232 bool TextLayouterDevice::getTextOutlines(
233 basegfx::B2DPolyPolygonVector
& rB2DPolyPolyVector
,
237 const ::std::vector
< double >& rDXArray
)
239 const sal_uInt32
nDXArrayCount(rDXArray
.size());
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(
259 &(aIntegerDXArray
[0]));
263 return mrDevice
.GetTextOutlines(
275 basegfx::B2DRange
TextLayouterDevice::getTextBoundRect(
278 xub_StrLen nLength
) const
284 mrDevice
.GetTextBoundRect(
291 // #i104432#, #i102556# take empty results into account
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
,
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
);
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
327 rFontAttributes
.getFamilyName(),
328 rFontAttributes
.getStyleName(),
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)
337 rFontAttributes
.getFamilyName(),
338 rFontAttributes
.getStyleName(),
339 Size(bFontIsScaled
? nWidth
: 0, nHeight
));
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
));
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
);
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);
374 FontAttributes
getFontAttributesFromVclFont(
375 basegfx::B2DVector
& o_rSize
,
380 const FontAttributes
aRetval(
382 rFont
.GetStyleName(),
383 static_cast<sal_uInt16
>(rFont
.GetWeight()),
384 RTL_TEXTENCODING_SYMBOL
== rFont
.GetCharSet(),
386 ITALIC_NONE
!= rFont
.GetItalic(),
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());
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
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());
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());
426 } // end of namespace primitive2d
427 } // end of namespace drawinglayer
429 //////////////////////////////////////////////////////////////////////////////