CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / canvas / source / directx / dx_textlayout_drawhelper.cxx
blob7fd29805e2f705ed68bba7a120b669086d7824f3
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_canvas.hxx"
31 #include <tools/poly.hxx>
33 #include <vcl/metric.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/metric.hxx>
36 #include <vcl/canvastools.hxx>
37 #include <tools/diagnose_ex.h>
39 #include <boost/scoped_array.hpp>
40 #include <boost/bind.hpp>
41 #include <com/sun/star/rendering/FontRequest.hpp>
42 #include <com/sun/star/rendering/PanoseProportion.hpp>
43 #include <com/sun/star/rendering/XCanvasFont.hpp>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/scopeguard.hxx>
46 #include <tools/color.hxx>
47 #include <basegfx/polygon/b2dpolypolygon.hxx>
48 #include <basegfx/tools/canvastools.hxx>
49 #include <canvas/canvastools.hxx>
50 #include <canvas/debug.hxx>
51 #include "dx_impltools.hxx"
52 #include <vcl/sysdata.hxx>
53 #include <i18npool/mslangid.hxx>
54 #include "dx_textlayout_drawhelper.hxx"
55 #include "dx_bitmap.hxx"
56 #include "dx_canvasfont.hxx"
58 class ::com::sun::star::rendering::XCanvasFont;
60 using namespace ::com::sun::star;
63 //////////////////////////////////////////////////////////////////////////////
65 namespace dxcanvas
67 class DXBitmap;
68 TextLayoutDrawHelper::TextLayoutDrawHelper(
69 const uno::Reference< rendering::XGraphicDevice >& xGraphicDevice ) :
70 mxGraphicDevice(xGraphicDevice)
74 TextLayoutDrawHelper::~TextLayoutDrawHelper()
78 void TextLayoutDrawHelper::drawText(
79 const GraphicsSharedPtr& rGraphics,
80 const ::com::sun::star::rendering::ViewState& rViewState,
81 const ::com::sun::star::rendering::RenderState& rRenderState,
82 const ::basegfx::B2ISize& rOutputOffset,
83 const ::com::sun::star::rendering::StringContext& rText,
84 const ::com::sun::star::uno::Sequence< double >& rLogicalAdvancements,
85 const ::com::sun::star::uno::Reference<
86 ::com::sun::star::rendering::XCanvasFont >& rCanvasFont,
87 const ::com::sun::star::geometry::Matrix2D& rFontMatrix,
88 bool bAlphaSurface )
90 HDC hdc = rGraphics->GetHDC();
92 // issue an ReleaseHDC() when leaving the scope
93 const ::comphelper::ScopeGuard aGuard(
94 boost::bind( &Gdiplus::Graphics::ReleaseHDC,
95 rGraphics.get(),
96 hdc ));
98 SystemGraphicsData aSystemGraphicsData;
99 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
100 aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(hdc);
101 VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
103 // disable font antialiasing - GDI does not handle alpha
104 // surfaces properly.
105 if( bAlphaSurface )
106 aVirtualDevice.SetAntialiasing(ANTIALIASING_DISABLE_TEXT);
108 if(rText.Length)
110 sal_Bool test = mxGraphicDevice.is();
111 ENSURE_OR_THROW( test,
112 "TextLayoutDrawHelper::drawText(): Invalid GraphicDevice" );
114 // set text color. Make sure to remove transparence part first.
115 Color aColor( COL_WHITE );
117 if( rRenderState.DeviceColor.getLength() > 2 )
118 aColor = ::vcl::unotools::doubleSequenceToColor(
119 rRenderState.DeviceColor,
120 mxGraphicDevice->getDeviceColorSpace());
121 aColor.SetTransparency(0);
122 aVirtualDevice.SetTextColor(aColor);
124 // create the font
125 const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
126 Font aFont(
127 rFontRequest.FontDescription.FamilyName,
128 rFontRequest.FontDescription.StyleName,
129 Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
131 aFont.SetAlign( ALIGN_BASELINE );
132 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
133 aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? sal_True : sal_False );
134 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
135 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
136 aFont.SetPitch(
137 rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
138 ? PITCH_FIXED : PITCH_VARIABLE);
140 aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
142 // setup font color
143 aFont.SetColor( aColor );
144 aFont.SetFillColor( aColor );
146 // adjust to stretched font
147 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
149 const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
150 const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
151 double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
153 if( !::basegfx::fTools::equalZero( fDividend) )
154 fStretch /= fDividend;
156 const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
158 aFont.SetWidth( nNewWidth );
161 // set font
162 aVirtualDevice.SetFont(aFont);
164 // create world transformation matrix
165 ::basegfx::B2DHomMatrix aWorldTransform;
166 ::canvas::tools::mergeViewAndRenderTransform(aWorldTransform, rViewState, rRenderState);
168 if(!rOutputOffset.equalZero())
170 aWorldTransform.translate(rOutputOffset.getX(), rOutputOffset.getY());
173 // set ViewState clipping
174 if(rViewState.Clip.is())
176 ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rViewState.Clip));
177 ::basegfx::B2DHomMatrix aMatrix;
178 ::basegfx::unotools::homMatrixFromAffineMatrix(aMatrix, rViewState.AffineTransform );
180 if(!rOutputOffset.equalZero())
182 aMatrix.translate(rOutputOffset.getX(), rOutputOffset.getY());
185 aClipPoly.transform(aMatrix);
186 const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
187 aVirtualDevice.IntersectClipRegion(rClipRegion);
190 if(rRenderState.Clip.is())
192 ::basegfx::B2DPolyPolygon aClipPoly(dxcanvas::tools::polyPolygonFromXPolyPolygon2D(rRenderState.Clip));
193 aClipPoly.transform(aWorldTransform);
194 const Region& rClipRegion = Region(PolyPolygon(aClipPoly));
195 aVirtualDevice.IntersectClipRegion(rClipRegion);
198 // set world transform
199 XFORM aXForm;
200 aXForm.eM11 = (FLOAT)aWorldTransform.get(0, 0);
201 aXForm.eM12 = (FLOAT)aWorldTransform.get(1, 0);
202 aXForm.eM21 = (FLOAT)aWorldTransform.get(0, 1);
203 aXForm.eM22 = (FLOAT)aWorldTransform.get(1, 1);
204 aXForm.eDx = (FLOAT)aWorldTransform.get(0, 2);
205 aXForm.eDy = (FLOAT)aWorldTransform.get(1, 2);
207 // TODO(F3): This is NOT supported on 95/98/ME!
208 SetGraphicsMode(hdc, GM_ADVANCED);
209 SetTextAlign(hdc, TA_BASELINE);
210 SetWorldTransform(hdc, &aXForm);
212 // use a empty StartPosition for text rendering
213 const Point aEmptyPoint(0, 0);
215 // create the String
216 const String aText(rText.Text.getStr());
218 if( rLogicalAdvancements.getLength() )
220 // create the DXArray
221 const sal_Int32 nLen( rLogicalAdvancements.getLength() );
222 ::boost::scoped_array<sal_Int32> pDXArray( new sal_Int32[nLen] );
223 for( sal_Int32 i=0; i<nLen; ++i )
224 pDXArray[i] = basegfx::fround( rLogicalAdvancements[i] );
226 // draw the String
227 aVirtualDevice.DrawTextArray( aEmptyPoint,
228 aText,
229 pDXArray.get(),
230 (xub_StrLen)rText.StartPosition,
231 (xub_StrLen)rText.Length );
233 else
235 // draw the String
236 aVirtualDevice.DrawText( aEmptyPoint,
237 aText,
238 (xub_StrLen)rText.StartPosition,
239 (xub_StrLen)rText.Length );
244 geometry::RealRectangle2D TextLayoutDrawHelper::queryTextBounds( const rendering::StringContext& rText,
245 const uno::Sequence< double >& rLogicalAdvancements,
246 const uno::Reference< rendering::XCanvasFont >& rCanvasFont,
247 const geometry::Matrix2D& rFontMatrix )
249 if(!(rText.Length))
250 return geometry::RealRectangle2D();
252 // TODO(F1): Fetching default screen DC here, will yield wrong
253 // metrics when e.g. formatting for a printer!
254 SystemGraphicsData aSystemGraphicsData;
255 aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
256 aSystemGraphicsData.hDC = reinterpret_cast< ::HDC >(GetDC( NULL ));
257 VirtualDevice aVirtualDevice(&aSystemGraphicsData, 0);
259 // create the font
260 const ::com::sun::star::rendering::FontRequest& rFontRequest = rCanvasFont->getFontRequest();
261 Font aFont(
262 rFontRequest.FontDescription.FamilyName,
263 rFontRequest.FontDescription.StyleName,
264 Size( 0, ::basegfx::fround(rFontRequest.CellSize)));
266 aFont.SetAlign( ALIGN_BASELINE );
267 aFont.SetCharSet( (rFontRequest.FontDescription.IsSymbolFont==com::sun::star::util::TriState_YES) ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
268 aFont.SetVertical( (rFontRequest.FontDescription.IsVertical==com::sun::star::util::TriState_YES) ? sal_True : sal_False );
269 aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
270 aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
271 aFont.SetPitch(
272 rFontRequest.FontDescription.FontDescription.Proportion == rendering::PanoseProportion::MONO_SPACED
273 ? PITCH_FIXED : PITCH_VARIABLE);
275 // adjust to stretched font
276 if(!::rtl::math::approxEqual(rFontMatrix.m00, rFontMatrix.m11))
278 const Size aSize = aVirtualDevice.GetFontMetric( aFont ).GetSize();
279 const double fDividend( rFontMatrix.m10 + rFontMatrix.m11 );
280 double fStretch = (rFontMatrix.m00 + rFontMatrix.m01);
282 if( !::basegfx::fTools::equalZero( fDividend) )
283 fStretch /= fDividend;
285 const sal_Int32 nNewWidth = ::basegfx::fround( aSize.Width() * fStretch );
287 aFont.SetWidth( nNewWidth );
290 // set font
291 aVirtualDevice.SetFont(aFont);
293 // need metrics for Y offset, the XCanvas always renders
294 // relative to baseline
295 const ::FontMetric& aMetric( aVirtualDevice.GetFontMetric() );
297 const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
298 const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
300 if( rLogicalAdvancements.getLength() )
302 return geometry::RealRectangle2D( 0, nAboveBaseline,
303 rLogicalAdvancements[ rLogicalAdvancements.getLength()-1 ],
304 nBelowBaseline );
306 else
308 return geometry::RealRectangle2D( 0, nAboveBaseline,
309 aVirtualDevice.GetTextWidth(
310 rText.Text,
311 ::canvas::tools::numeric_cast<sal_uInt16>(rText.StartPosition),
312 ::canvas::tools::numeric_cast<sal_uInt16>(rText.Length) ),
313 nBelowBaseline );
319 // eof