update dev300-m58
[ooovba.git] / drawinglayer / source / primitive2d / textlayoutdevice.cxx
blobb2fe10d6f97609576bb230ca3148a5807cafeb96
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>
47 //////////////////////////////////////////////////////////////////////////////
48 // VDev RevDevice provider
50 namespace
52 class ImpTimedRefDev : public Timer
54 ImpTimedRefDev** mppStaticPointerOnMe;
55 VirtualDevice* mpVirDev;
56 sal_uInt32 mnUseCount;
58 public:
59 ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe);
60 ~ImpTimedRefDev();
61 virtual void Timeout();
63 VirtualDevice& acquireVirtualDevice();
64 void releaseVirtualDevice();
67 ImpTimedRefDev::ImpTimedRefDev(ImpTimedRefDev** ppStaticPointerOnMe)
68 : mppStaticPointerOnMe(ppStaticPointerOnMe),
69 mpVirDev(0L),
70 mnUseCount(0L)
72 SetTimeout(3L * 60L * 1000L); // three minutes
73 Start();
76 ImpTimedRefDev::~ImpTimedRefDev()
78 OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
80 if(mppStaticPointerOnMe && *mppStaticPointerOnMe)
82 *mppStaticPointerOnMe = 0L;
85 if(mpVirDev)
87 delete mpVirDev;
91 void ImpTimedRefDev::Timeout()
93 // for obvious reasons, do not call anything after this
94 delete (this);
97 VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
99 if(!mpVirDev)
101 mpVirDev = new VirtualDevice();
102 mpVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
105 if(!mnUseCount)
107 Stop();
110 mnUseCount++;
112 return *mpVirDev;
115 void ImpTimedRefDev::releaseVirtualDevice()
117 OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
118 mnUseCount--;
120 if(!mnUseCount)
122 Start();
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();
183 return fRet;
186 double TextLayouterDevice::getUnderlineOffset() const
188 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
189 double fRet = rMetric.GetDescent() / 2.0;
190 return fRet;
193 double TextLayouterDevice::getStrikeoutOffset() const
195 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
196 double fRet = (rMetric.GetAscent() - rMetric.GetIntLeading()) / 3.0;
197 return fRet;
200 #ifdef WIN32
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;
210 #endif
212 double TextLayouterDevice::getOverlineHeight() const
214 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
215 double fRet = rMetric.GetIntLeading() / 2.5;
216 return fRet;
219 double TextLayouterDevice::getUnderlineHeight() const
221 const ::FontMetric& rMetric = mrDevice.GetFontMetric();
222 double fRet = rMetric.GetDescent() / 4.0;
223 return fRet;
226 double TextLayouterDevice::getTextHeight() const
228 return mrDevice.GetTextHeight();
231 double TextLayouterDevice::getTextWidth(
232 const String& rText,
233 xub_StrLen nIndex,
234 xub_StrLen nLength) const
236 return mrDevice.GetTextWidth(rText, nIndex, nLength);
239 bool TextLayouterDevice::getTextOutlines(
240 basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
241 const String& rText,
242 xub_StrLen nIndex,
243 xub_StrLen nLength,
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(
263 rB2DPolyPolyVector,
264 rText,
265 nIndex,
266 nIndex,
267 nLength,
268 true,
270 nDXArraySize ? &(aTransformedDXArray[0]) : 0);
273 basegfx::B2DRange TextLayouterDevice::getTextBoundRect(
274 const String& rText,
275 xub_StrLen nIndex,
276 xub_StrLen nLength) const
278 if(nLength)
280 Rectangle aRect;
282 mrDevice.GetTextBoundRect(
283 aRect,
284 rText,
285 nIndex,
286 nIndex,
287 nLength);
289 // #i102556# take empty results into account
290 if(!aRect.IsEmpty())
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,
325 double fFontScaleX,
326 double fFontScaleY,
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)));
333 Font aRetval(
334 rFontAttributes.getFamilyName(),
335 rFontAttributes.getStyleName(),
336 #ifdef WIN32
337 Size(0, nHeight));
338 #else
339 Size(nWidth, nHeight));
340 #endif
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 // #100424# use higher precision
352 if(!basegfx::fTools::equal(fFontScaleX, fFontScaleY))
354 // #i92757#
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.
369 // previous stuff:
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);
375 #endif
377 if(!basegfx::fTools::equalZero(fFontRotation))
379 sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI)));
380 aRetval.SetOrientation(aRotate10th % 3600);
383 return aRetval;
386 FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong)
388 FontAttributes aRetval(
389 rFont.GetName(),
390 rFont.GetStyleName(),
391 static_cast<sal_uInt16>(rFont.GetWeight()),
392 RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(),
393 rFont.IsVertical(),
394 ITALIC_NONE != rFont.GetItalic(),
395 rFont.IsOutline(),
396 bRTL,
397 bBiDiStrong);
398 // TODO: eKerning
400 const sal_Int32 nWidth(rFont.GetSize().getWidth());
401 const sal_Int32 nHeight(rFont.GetSize().getHeight());
403 rSize.setX(nWidth ? nWidth : nHeight);
404 rSize.setY(nHeight);
406 return aRetval;
408 } // end of namespace primitive2d
409 } // end of namespace drawinglayer
411 //////////////////////////////////////////////////////////////////////////////
412 // eof