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 //////////////////////////////////////////////////////////////////////////////
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
,
90 HDC hdc
= rGraphics
->GetHDC();
92 // issue an ReleaseHDC() when leaving the scope
93 const ::comphelper::ScopeGuard
aGuard(
94 boost::bind( &Gdiplus::Graphics::ReleaseHDC
,
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.
106 aVirtualDevice
.SetAntialiasing(ANTIALIASING_DISABLE_TEXT
);
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
);
125 const ::com::sun::star::rendering::FontRequest
& rFontRequest
= rCanvasFont
->getFontRequest();
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
);
137 rFontRequest
.FontDescription
.FontDescription
.Proportion
== rendering::PanoseProportion::MONO_SPACED
138 ? PITCH_FIXED
: PITCH_VARIABLE
);
140 aFont
.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest
.Locale
));
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
);
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
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);
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
] );
227 aVirtualDevice
.DrawTextArray( aEmptyPoint
,
230 (xub_StrLen
)rText
.StartPosition
,
231 (xub_StrLen
)rText
.Length
);
236 aVirtualDevice
.DrawText( aEmptyPoint
,
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
)
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);
260 const ::com::sun::star::rendering::FontRequest
& rFontRequest
= rCanvasFont
->getFontRequest();
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
);
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
);
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 ],
308 return geometry::RealRectangle2D( 0, nAboveBaseline
,
309 aVirtualDevice
.GetTextWidth(
311 ::canvas::tools::numeric_cast
<sal_uInt16
>(rText
.StartPosition
),
312 ::canvas::tools::numeric_cast
<sal_uInt16
>(rText
.Length
) ),