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>
47 //////////////////////////////////////////////////////////////////////////////
48 // VDev RevDevice provider
52 class ImpTimedRefDev
: public Timer
54 ImpTimedRefDev
** mppStaticPointerOnMe
;
55 VirtualDevice
* mpVirDev
;
56 sal_uInt32 mnUseCount
;
59 ImpTimedRefDev(ImpTimedRefDev
** ppStaticPointerOnMe
);
61 virtual void Timeout();
63 VirtualDevice
& acquireVirtualDevice();
64 void releaseVirtualDevice();
67 ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev
** ppStaticPointerOnMe
)
68 : mppStaticPointerOnMe(ppStaticPointerOnMe
),
72 SetTimeout(3L * 60L * 1000L); // three minutes
76 ImpTimedRefDev::~ImpTimedRefDev()
78 OSL_ENSURE(0L == mnUseCount
, "destruction of a still used ImpTimedRefDev (!)");
80 if(mppStaticPointerOnMe
&& *mppStaticPointerOnMe
)
82 *mppStaticPointerOnMe
= 0L;
91 void ImpTimedRefDev::Timeout()
93 // for obvious reasons, do not call anything after this
97 VirtualDevice
& ImpTimedRefDev::acquireVirtualDevice()
101 mpVirDev
= new VirtualDevice();
102 mpVirDev
->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1
);
115 void ImpTimedRefDev::releaseVirtualDevice()
117 OSL_ENSURE(mnUseCount
, "mismatch call number to releaseVirtualDevice() (!)");
125 } // end of anonymous namespace
127 //////////////////////////////////////////////////////////////////////////////
128 // access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive
130 namespace drawinglayer
132 namespace primitive2d
134 // static pointer here
135 static ImpTimedRefDev
* pImpGlobalRefDev
= 0L;
137 // static methods here
138 VirtualDevice
& acquireGlobalVirtualDevice()
140 if(!pImpGlobalRefDev
)
142 pImpGlobalRefDev
= new ImpTimedRefDev(&pImpGlobalRefDev
);
145 return pImpGlobalRefDev
->acquireVirtualDevice();
148 void releaseGlobalVirtualDevice()
150 OSL_ENSURE(pImpGlobalRefDev
, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
151 pImpGlobalRefDev
->releaseVirtualDevice();
154 TextLayouterDevice::TextLayouterDevice()
155 : mrDevice(acquireGlobalVirtualDevice())
159 TextLayouterDevice::~TextLayouterDevice()
161 releaseGlobalVirtualDevice();
164 void TextLayouterDevice::setFont(const Font
& rFont
)
166 mrDevice
.SetFont( rFont
);
169 void TextLayouterDevice::setFontAttributes(const FontAttributes
& rFontAttributes
, const basegfx::B2DHomMatrix
& rTransform
, const ::com::sun::star::lang::Locale
& rLocale
)
171 setFont(getVclFontFromFontAttributes(rFontAttributes
, rTransform
, rLocale
, mrDevice
));
174 void TextLayouterDevice::setFontAttributes(const FontAttributes
& rFontAttributes
, double fFontScaleX
, double fFontScaleY
, const ::com::sun::star::lang::Locale
& rLocale
)
176 setFont(getVclFontFromFontAttributes(rFontAttributes
, fFontScaleX
, fFontScaleY
, 0.0, rLocale
, mrDevice
));
179 double TextLayouterDevice::getOverlineOffset() const
181 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
182 double fRet
= (rMetric
.GetIntLeading() / 2.0) - rMetric
.GetAscent();
186 double TextLayouterDevice::getUnderlineOffset() const
188 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
189 double fRet
= rMetric
.GetDescent() / 2.0;
193 double TextLayouterDevice::getStrikeoutOffset() const
195 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
196 double fRet
= (rMetric
.GetAscent() - rMetric
.GetIntLeading()) / 3.0;
201 double TextLayouterDevice::getCurrentFontRelation() const
203 const Font
aFont(mrDevice
.GetFont());
204 const FontMetric
aFontMetric(mrDevice
.GetFontMetric(aFont
));
205 const double fWidth(aFontMetric
.GetWidth());
206 const double fHeight(aFont
.GetHeight());
208 return basegfx::fTools::equalZero(fWidth
) ? 1.0 : fHeight
/ fWidth
;
212 double TextLayouterDevice::getOverlineHeight() const
214 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
215 double fRet
= rMetric
.GetIntLeading() / 2.5;
219 double TextLayouterDevice::getUnderlineHeight() const
221 const ::FontMetric
& rMetric
= mrDevice
.GetFontMetric();
222 double fRet
= rMetric
.GetDescent() / 4.0;
226 double TextLayouterDevice::getTextHeight() const
228 return mrDevice
.GetTextHeight();
231 double TextLayouterDevice::getTextWidth(
234 xub_StrLen nLength
) const
236 return mrDevice
.GetTextWidth(rText
, nIndex
, nLength
);
239 bool TextLayouterDevice::getTextOutlines(
240 basegfx::B2DPolyPolygonVector
& rB2DPolyPolyVector
,
244 // #i89784# added suppirt for DXArray for justified text
245 const ::std::vector
< double >& rDXArray
,
246 double fFontScaleWidth
)
248 std::vector
< sal_Int32
> aTransformedDXArray
;
249 const sal_uInt32
nDXArraySize(rDXArray
.size());
251 if(nDXArraySize
&& basegfx::fTools::more(fFontScaleWidth
, 0.0))
253 OSL_ENSURE(nDXArraySize
== nLength
, "DXArray size does not correspond to text portion size (!)");
254 aTransformedDXArray
.reserve(nDXArraySize
);
256 for(std::vector
< double >::const_iterator
aStart(rDXArray
.begin()); aStart
!= rDXArray
.end(); aStart
++)
258 aTransformedDXArray
.push_back(basegfx::fround((*aStart
) * fFontScaleWidth
));
262 return mrDevice
.GetTextOutlines(
270 nDXArraySize
? &(aTransformedDXArray
[0]) : 0);
273 basegfx::B2DRange
TextLayouterDevice::getTextBoundRect(
276 xub_StrLen nLength
) const
282 mrDevice
.GetTextBoundRect(
289 // #i102556# take empty results into account
292 return basegfx::B2DRange(aRect
.Left(), aRect
.Top(), aRect
.Right(), aRect
.Bottom());
296 return basegfx::B2DRange();
298 } // end of namespace primitive2d
299 } // end of namespace drawinglayer
301 //////////////////////////////////////////////////////////////////////////////
302 // helper methods for vcl font handling
304 namespace drawinglayer
306 namespace primitive2d
308 Font
getVclFontFromFontAttributes(
309 const FontAttributes
& rFontAttributes
,
310 const basegfx::B2DHomMatrix
& rTransform
,
311 const ::com::sun::star::lang::Locale
& rLocale
,
312 const OutputDevice
& rOutDev
)
314 // decompose matrix to have position and size of text
315 basegfx::B2DVector aScale
, aTranslate
;
316 double fRotate
, fShearX
;
318 rTransform
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
320 return getVclFontFromFontAttributes(rFontAttributes
, aScale
.getX(), aScale
.getY(), fRotate
, rLocale
, rOutDev
);
323 Font
getVclFontFromFontAttributes(
324 const FontAttributes
& rFontAttributes
,
327 double fFontRotation
,
328 const ::com::sun::star::lang::Locale
& rLocale
,
329 const OutputDevice
& /*rOutDev*/)
331 sal_uInt32
nWidth(basegfx::fround(fabs(fFontScaleX
)));
332 sal_uInt32
nHeight(basegfx::fround(fabs(fFontScaleY
)));
334 rFontAttributes
.getFamilyName(),
335 rFontAttributes
.getStyleName(),
339 Size(nWidth
, nHeight
));
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 // #100424# use higher precision
352 if(!basegfx::fTools::equal(fFontScaleX
, fFontScaleY
))
355 // Removed the relative calculation with GetFontMetric() usage again. On
356 // the one hand it was wrong (integer division always created zero), OTOH
357 // calculating a scale factor from current to target width and then using
358 // it to actually scale the current width does nothing but set the target
359 // value directly. Maybe more is needed here with WIN version of font
360 // width/height handling, but currently, this works the simple way.
362 // As can be seen, when this can stay the simple way, the OutputDevice
363 // can be removed from the whole getVclFontFromFontAttributes implementations
364 // again and make it more VCL-independent.
366 // Adapted nWidth usage to nWidth-1 to be completely compatible with
367 // non-primitive version.
370 // const FontMetric aFontMetric(rOutDev.GetFontMetric(aRetval));
371 // const double fCurrentWidth(aFontMetric.GetWidth());
372 // aRetval.SetWidth(basegfx::fround(fCurrentWidth * ((double)nWidth/(double)nHeight)));
373 aRetval
.SetWidth(nWidth
? nWidth
- 1 : 0);
377 if(!basegfx::fTools::equalZero(fFontRotation
))
379 sal_Int16
aRotate10th((sal_Int16
)(fFontRotation
* (-1800.0/F_PI
)));
380 aRetval
.SetOrientation(aRotate10th
% 3600);
386 FontAttributes
getFontAttributesFromVclFont(basegfx::B2DVector
& rSize
, const Font
& rFont
, bool bRTL
, bool bBiDiStrong
)
388 FontAttributes
aRetval(
390 rFont
.GetStyleName(),
391 static_cast<sal_uInt16
>(rFont
.GetWeight()),
392 RTL_TEXTENCODING_SYMBOL
== rFont
.GetCharSet(),
394 ITALIC_NONE
!= rFont
.GetItalic(),
400 const sal_Int32
nWidth(rFont
.GetSize().getWidth());
401 const sal_Int32
nHeight(rFont
.GetSize().getHeight());
403 rSize
.setX(nWidth
? nWidth
: nHeight
);
408 } // end of namespace primitive2d
409 } // end of namespace drawinglayer
411 //////////////////////////////////////////////////////////////////////////////