merge the formfield patch from ooo-build
[ooovba.git] / canvas / source / directx / dx_textlayout_drawhelper.cxx
blobf9451b516754fb9147e000f18c0d7c1ba8184a3e
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: dx_textlayout_drawhelper.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_canvas.hxx"
34 #include <tools/poly.hxx>
36 #include <vcl/metric.hxx>
37 #include <vcl/virdev.hxx>
38 #include <vcl/metric.hxx>
39 #include <vcl/canvastools.hxx>
40 #include <tools/diagnose_ex.h>
42 #include <boost/scoped_array.hpp>
43 #include <boost/bind.hpp>
44 #include <com/sun/star/rendering/FontRequest.hpp>
45 #include <com/sun/star/rendering/XCanvasFont.hpp>
46 #include <comphelper/sequence.hxx>
47 #include <comphelper/scopeguard.hxx>
48 #include <tools/color.hxx>
49 #include <basegfx/polygon/b2dpolypolygon.hxx>
50 #include <basegfx/tools/canvastools.hxx>
51 #include <canvas/canvastools.hxx>
52 #include <canvas/debug.hxx>
53 #include "dx_impltools.hxx"
54 #include <vcl/sysdata.hxx>
55 #include <i18npool/mslangid.hxx>
56 #include "dx_textlayout_drawhelper.hxx"
57 #include "dx_bitmap.hxx"
58 #include "dx_canvasfont.hxx"
60 class ::com::sun::star::rendering::XCanvasFont;
62 using namespace ::com::sun::star;
65 //////////////////////////////////////////////////////////////////////////////
67 namespace dxcanvas
69 class DXBitmap;
70 TextLayoutDrawHelper::TextLayoutDrawHelper(
71 const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice ) :
72 mxGraphicDevice(xGraphicDevice)
76 TextLayoutDrawHelper::~TextLayoutDrawHelper()
80 void TextLayoutDrawHelper::drawText(
81 const GraphicsSharedPtr& rGraphics,
82 const ::com::sun::star::rendering::ViewState& rViewState,
83 const ::com::sun::star::rendering::RenderState& rRenderState,
84 const ::basegfx::B2ISize& rOutputOffset,
85 const ::com::sun::star::rendering::StringContext& rText,
86 const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
87 const ::com::sun::star::uno::Reference<
88 ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
89 const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
90 bool bAlphaSurface )
92 HDC hdc = rGraphics->GetHDC();
94 // issue an ReleaseHDC() when leaving the scope
95 const ::comphelper::ScopeGuard aGuard(
96 boost::bind( &Gdiplus::Graphics::ReleaseHDC,
97 rGraphics.get(),
98 hdc ));
100 SystemGraphicsData aSystemGraphicsData;
101 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
102 aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(hdc);
103 VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
105 // disable font antialiasing - GDI does not handle alpha
106 // surfaces properly.
107 if( bAlphaSurface )
108 aVirtualDevice.SetAntialiasing(ANTIALIASING_DISABLE_TEXT);
110 if(rText.Length)
112 sal_Bool test = mxGraphicDevice.is();
113 ENSURE_OR_THROW( test,
114 "TextLayoutDrawHelper::drawText(): Invalid GraphicDevice" );
116 // set text color. Make sure to remove transparence part first.
117 Color aColor( COL_WHITE );
119 if( rRenderState.DeviceColor.getLength() > 2 )
120 aColor = ::vcl::unotools::doubleSequenceToColor(
121 rRenderState.DeviceColor,
122 mxGraphicDevice->getDeviceColorSpace());
123 aColor.SetTransparency(0);
124 aVirtualDevice.SetTextColor(aColor);
126 // create the font
127 const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
128 Font aFont(
129 rFontRequest.FontDescription.FamilyName,
130 rFontRequest.FontDescription.StyleName,
131 Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
133 aFont.SetAlign( ALIGN_BASELINE );
134 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
135 aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
136 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
137 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
139 aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
141 // setup font color
142 aFont.SetColor( aColor );
143 aFont.SetFillColor( aColor );
145 // adjust to stretched font
146 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
148 const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
149 const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
150 double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
152 if( !::basegfx::fTools::equalZero( fDividend) )
153 fStretch /= fDividend;
155 const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
157 aFont.SetWidth( nNewWidth );
160 // set font
161 aVirtualDevice.SetFont(aFont);
163 // create world transformation matrix
164 ::basegfx::B2DHomMatrix aWorldTransform;
165 ::canvas::tools::mergeViewAndRenderTransform(aWorldTransform, rViewState, rRenderState);
167 if(!rOutputOffset.equalZero())
169 aWorldTransform.translate(rOutputOffset.getX(), rOutputOffset.getY());
172 // set ViewState clipping
173 if(rViewState.Clip.is())
175 ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rViewState.Clip));
176 ::basegfx::B2DHomMatrix aMatrix;
177 ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, rViewState.AffineTransform );
179 if(!rOutputOffset.equalZero())
181 aMatrix.translate(rOutputOffset.getX(), rOutputOffset.getY());
184 aClipPoly.transform(aMatrix);
185 const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
186 aVirtualDevice.IntersectClipRegion(rClipRegion);
189 if(rRenderState.Clip.is())
191 ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rRenderState.Clip));
192 aClipPoly.transform(aWorldTransform);
193 const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
194 aVirtualDevice.IntersectClipRegion(rClipRegion);
197 // set world transform
198 XFORM aXForm;
199 aXForm.eM11 = (FLOAT)aWorldTransform.get(0, 0);
200 aXForm.eM12 = (FLOAT)aWorldTransform.get(1, 0);
201 aXForm.eM21 = (FLOAT)aWorldTransform.get(0, 1);
202 aXForm.eM22 = (FLOAT)aWorldTransform.get(1, 1);
203 aXForm.eDx = (FLOAT)aWorldTransform.get(0, 2);
204 aXForm.eDy = (FLOAT)aWorldTransform.get(1, 2);
206 // TODO(F3): This is NOT supported on 95/98/ME!
207 SetGraphicsMode(hdc, GM_ADVANCED);
208 SetTextAlign(hdc, TA_BASELINE);
209 SetWorldTransform(hdc, &aXForm);
211 // use a empty StartPosition for text rendering
212 const Point aEmptyPoint(0, 0);
214 // create the String
215 const String aText(rText.Text.getStr());
217 if( rLogicalAdvancements.getLength() )
219 // create the DXArray
220 const sal_Int32 nLen( rLogicalAdvancements.getLength() );
221 ::boost::scoped_array<sal_Int32> pDXArray( new sal_Int32[nLen] );
222 for( sal_Int32 i=0; i<nLen; ++i )
223 pDXArray[i] = basegfx::fround( rLogicalAdvancements[i] );
225 // draw the String
226 aVirtualDevice.DrawTextArray( aEmptyPoint,
227 aText,
228 pDXArray.get(),
229 (xub_StrLen)rText.StartPosition,
230 (xub_StrLen)rText.Length );
232 else
234 // draw the String
235 aVirtualDevice.DrawText( aEmptyPoint,
236 aText,
237 (xub_StrLen)rText.StartPosition,
238 (xub_StrLen)rText.Length );
243 geometry::RealRectangle2D TextLayoutDrawHelper::queryTextBounds( const rendering::StringContext& rText,
244 const uno::Sequence< double >& rLogicalAdvancements,
245 const uno::Reference< rendering::XCanvasFont >& rCanvasFont,
246 const geometry::Matrix2D& rFontMatrix )
248 if(!(rText.Length))
249 return geometry::RealRectangle2D();
251 // TODO(F1): Fetching default screen DC here, will yield wrong
252 // metrics when e.g. formatting for a printer!
253 SystemGraphicsData aSystemGraphicsData;
254 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
255 aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(GetDC( NULL ));
256 VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
258 // create the font
259 const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
260 Font aFont(
261 rFontRequest.FontDescription.FamilyName,
262 rFontRequest.FontDescription.StyleName,
263 Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
265 aFont.SetAlign( ALIGN_BASELINE );
266 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
267 aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? TRUE : FALSE );
268 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
269 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
271 // adjust to stretched font
272 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
274 const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
275 const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
276 double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
278 if( !::basegfx::fTools::equalZero( fDividend) )
279 fStretch /= fDividend;
281 const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
283 aFont.SetWidth( nNewWidth );
286 // set font
287 aVirtualDevice.SetFont(aFont);
289 // need metrics for Y offset, the XCanvas always renders
290 // relative to baseline
291 const ::FontMetric& aMetric( aVirtualDevice.GetFontMetric() );
293 const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
294 const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
296 if( rLogicalAdvancements.getLength() )
298 return geometry::RealRectangle2D( 0, nAboveBaseline,
299 rLogicalAdvancements[ rLogicalAdvancements.getLength()-1 ],
300 nBelowBaseline );
302 else
304 return geometry::RealRectangle2D( 0, nAboveBaseline,
305 aVirtualDevice.GetTextWidth(
306 rText.Text,
307 ::canvas::tools::numeric_cast<USHORT>(rText.StartPosition),
308 ::canvas::tools::numeric_cast<USHORT>(rText.Length) ),
309 nBelowBaseline );
315 // eof