xref: /AOO41X/main/canvas/source/vcl/textlayout.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_canvas.hxx"
30*cdf0e10cSrcweir 
31*cdf0e10cSrcweir #include <canvas/debug.hxx>
32*cdf0e10cSrcweir #include <tools/diagnose_ex.h>
33*cdf0e10cSrcweir #include <canvas/canvastools.hxx>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include <com/sun/star/rendering/CompositeOperation.hpp>
36*cdf0e10cSrcweir #include <com/sun/star/rendering/TextDirection.hpp>
37*cdf0e10cSrcweir 
38*cdf0e10cSrcweir #include <vcl/metric.hxx>
39*cdf0e10cSrcweir #include <vcl/virdev.hxx>
40*cdf0e10cSrcweir 
41*cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
42*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
43*cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
44*cdf0e10cSrcweir 
45*cdf0e10cSrcweir #include "impltools.hxx"
46*cdf0e10cSrcweir #include "textlayout.hxx"
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #include <boost/scoped_array.hpp>
49*cdf0e10cSrcweir 
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir using namespace ::com::sun::star;
52*cdf0e10cSrcweir 
53*cdf0e10cSrcweir namespace vclcanvas
54*cdf0e10cSrcweir {
55*cdf0e10cSrcweir     namespace
56*cdf0e10cSrcweir     {
57*cdf0e10cSrcweir         void setupLayoutMode( OutputDevice& rOutDev,
58*cdf0e10cSrcweir                               sal_Int8		nTextDirection )
59*cdf0e10cSrcweir         {
60*cdf0e10cSrcweir             // TODO(P3): avoid if already correctly set
61*cdf0e10cSrcweir             sal_uIntPtr nLayoutMode;
62*cdf0e10cSrcweir             switch( nTextDirection )
63*cdf0e10cSrcweir             {
64*cdf0e10cSrcweir                 default:
65*cdf0e10cSrcweir                     nLayoutMode = 0;
66*cdf0e10cSrcweir                     break;
67*cdf0e10cSrcweir                 case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
68*cdf0e10cSrcweir                     nLayoutMode = TEXT_LAYOUT_BIDI_LTR;
69*cdf0e10cSrcweir                     break;
70*cdf0e10cSrcweir                 case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
71*cdf0e10cSrcweir                     nLayoutMode = TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG;
72*cdf0e10cSrcweir                     break;
73*cdf0e10cSrcweir                 case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
74*cdf0e10cSrcweir                     nLayoutMode = TEXT_LAYOUT_BIDI_RTL;
75*cdf0e10cSrcweir                     break;
76*cdf0e10cSrcweir                 case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
77*cdf0e10cSrcweir                     nLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG;
78*cdf0e10cSrcweir                     break;
79*cdf0e10cSrcweir             }
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir             // set calculated layout mode. Origin is always the left edge,
82*cdf0e10cSrcweir             // as required at the API spec
83*cdf0e10cSrcweir             rOutDev.SetLayoutMode( nLayoutMode | TEXT_LAYOUT_TEXTORIGIN_LEFT );
84*cdf0e10cSrcweir         }
85*cdf0e10cSrcweir     }
86*cdf0e10cSrcweir 
87*cdf0e10cSrcweir     TextLayout::TextLayout( const rendering::StringContext&                  aText,
88*cdf0e10cSrcweir                             sal_Int8                                         nDirection,
89*cdf0e10cSrcweir                             sal_Int64                                        nRandomSeed,
90*cdf0e10cSrcweir                             const CanvasFont::Reference&                     rFont,
91*cdf0e10cSrcweir                             const uno::Reference<rendering::XGraphicDevice>& xDevice,
92*cdf0e10cSrcweir                             const OutDevProviderSharedPtr&                   rOutDev ) :
93*cdf0e10cSrcweir         TextLayout_Base( m_aMutex ),
94*cdf0e10cSrcweir         maText( aText ),
95*cdf0e10cSrcweir         maLogicalAdvancements(),
96*cdf0e10cSrcweir         mpFont( rFont ),
97*cdf0e10cSrcweir         mxDevice( xDevice ),
98*cdf0e10cSrcweir         mpOutDevProvider( rOutDev ),
99*cdf0e10cSrcweir         mnTextDirection( nDirection )
100*cdf0e10cSrcweir     {
101*cdf0e10cSrcweir         (void)nRandomSeed;
102*cdf0e10cSrcweir     }
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir     void SAL_CALL TextLayout::disposing()
105*cdf0e10cSrcweir     {
106*cdf0e10cSrcweir         tools::LocalGuard aGuard;
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir         mpOutDevProvider.reset();
109*cdf0e10cSrcweir         mxDevice.clear();
110*cdf0e10cSrcweir         mpFont.reset();
111*cdf0e10cSrcweir     }
112*cdf0e10cSrcweir 
113*cdf0e10cSrcweir     // XTextLayout
114*cdf0e10cSrcweir     uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes(  ) throw (uno::RuntimeException)
115*cdf0e10cSrcweir     {
116*cdf0e10cSrcweir         tools::LocalGuard aGuard;
117*cdf0e10cSrcweir 
118*cdf0e10cSrcweir         OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
119*cdf0e10cSrcweir         VirtualDevice aVDev( rOutDev );
120*cdf0e10cSrcweir         aVDev.SetFont( mpFont->getVCLFont() );
121*cdf0e10cSrcweir 
122*cdf0e10cSrcweir         setupLayoutMode( aVDev, mnTextDirection );
123*cdf0e10cSrcweir 
124*cdf0e10cSrcweir         const rendering::ViewState aViewState(
125*cdf0e10cSrcweir             geometry::AffineMatrix2D(1,0,0, 0,1,0),
126*cdf0e10cSrcweir             NULL);
127*cdf0e10cSrcweir 
128*cdf0e10cSrcweir         rendering::RenderState aRenderState (
129*cdf0e10cSrcweir             geometry::AffineMatrix2D(1,0,0,0,1,0),
130*cdf0e10cSrcweir             NULL,
131*cdf0e10cSrcweir             uno::Sequence<double>(4),
132*cdf0e10cSrcweir             rendering::CompositeOperation::SOURCE);
133*cdf0e10cSrcweir 
134*cdf0e10cSrcweir         ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
135*cdf0e10cSrcweir         setupTextOffsets(aOffsets.get(), maLogicalAdvancements, aViewState, aRenderState);
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir         uno::Sequence< uno::Reference< rendering::XPolyPolygon2D> > aOutlineSequence;
138*cdf0e10cSrcweir         ::basegfx::B2DPolyPolygonVector aOutlines;
139*cdf0e10cSrcweir         if (aVDev.GetTextOutlines(
140*cdf0e10cSrcweir             aOutlines,
141*cdf0e10cSrcweir             maText.Text,
142*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
143*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
144*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length),
145*cdf0e10cSrcweir             sal_False,
146*cdf0e10cSrcweir             0,
147*cdf0e10cSrcweir             aOffsets.get()))
148*cdf0e10cSrcweir         {
149*cdf0e10cSrcweir             aOutlineSequence.realloc(aOutlines.size());
150*cdf0e10cSrcweir             sal_Int32 nIndex (0);
151*cdf0e10cSrcweir             for (::basegfx::B2DPolyPolygonVector::const_iterator
152*cdf0e10cSrcweir                      iOutline(aOutlines.begin()),
153*cdf0e10cSrcweir                      iEnd(aOutlines.end());
154*cdf0e10cSrcweir                  iOutline!=iEnd;
155*cdf0e10cSrcweir                  ++iOutline)
156*cdf0e10cSrcweir             {
157*cdf0e10cSrcweir                 aOutlineSequence[nIndex++] = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon(
158*cdf0e10cSrcweir                     mxDevice,
159*cdf0e10cSrcweir                     *iOutline);
160*cdf0e10cSrcweir             }
161*cdf0e10cSrcweir         }
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir         return aOutlineSequence;
164*cdf0e10cSrcweir     }
165*cdf0e10cSrcweir 
166*cdf0e10cSrcweir     uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures(  ) throw (uno::RuntimeException)
167*cdf0e10cSrcweir     {
168*cdf0e10cSrcweir         tools::LocalGuard aGuard;
169*cdf0e10cSrcweir 
170*cdf0e10cSrcweir 
171*cdf0e10cSrcweir         OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
172*cdf0e10cSrcweir         VirtualDevice aVDev( rOutDev );
173*cdf0e10cSrcweir         aVDev.SetFont( mpFont->getVCLFont() );
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir         setupLayoutMode( aVDev, mnTextDirection );
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir         const rendering::ViewState aViewState(
178*cdf0e10cSrcweir             geometry::AffineMatrix2D(1,0,0, 0,1,0),
179*cdf0e10cSrcweir             NULL);
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir         rendering::RenderState aRenderState (
182*cdf0e10cSrcweir             geometry::AffineMatrix2D(1,0,0,0,1,0),
183*cdf0e10cSrcweir             NULL,
184*cdf0e10cSrcweir             uno::Sequence<double>(4),
185*cdf0e10cSrcweir             rendering::CompositeOperation::SOURCE);
186*cdf0e10cSrcweir 
187*cdf0e10cSrcweir         ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
188*cdf0e10cSrcweir         setupTextOffsets(aOffsets.get(), maLogicalAdvancements, aViewState, aRenderState);
189*cdf0e10cSrcweir 
190*cdf0e10cSrcweir         MetricVector aMetricVector;
191*cdf0e10cSrcweir         uno::Sequence<geometry::RealRectangle2D> aBoundingBoxes;
192*cdf0e10cSrcweir         if (aVDev.GetGlyphBoundRects(
193*cdf0e10cSrcweir             Point(0,0),
194*cdf0e10cSrcweir             maText.Text,
195*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
196*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length),
197*cdf0e10cSrcweir             ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
198*cdf0e10cSrcweir             aMetricVector))
199*cdf0e10cSrcweir         {
200*cdf0e10cSrcweir             aBoundingBoxes.realloc(aMetricVector.size());
201*cdf0e10cSrcweir             sal_Int32 nIndex (0);
202*cdf0e10cSrcweir             for (MetricVector::const_iterator
203*cdf0e10cSrcweir                      iMetric(aMetricVector.begin()),
204*cdf0e10cSrcweir                      iEnd(aMetricVector.end());
205*cdf0e10cSrcweir                  iMetric!=iEnd;
206*cdf0e10cSrcweir                  ++iMetric)
207*cdf0e10cSrcweir             {
208*cdf0e10cSrcweir                 aBoundingBoxes[nIndex++] = geometry::RealRectangle2D(
209*cdf0e10cSrcweir                     iMetric->getX(),
210*cdf0e10cSrcweir                     iMetric->getY(),
211*cdf0e10cSrcweir                     iMetric->getX() + iMetric->getWidth(),
212*cdf0e10cSrcweir                     iMetric->getY() + iMetric->getHeight());
213*cdf0e10cSrcweir             }
214*cdf0e10cSrcweir         }
215*cdf0e10cSrcweir         return aBoundingBoxes;
216*cdf0e10cSrcweir     }
217*cdf0e10cSrcweir 
218*cdf0e10cSrcweir     uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures(  ) throw (uno::RuntimeException)
219*cdf0e10cSrcweir     {
220*cdf0e10cSrcweir         tools::LocalGuard aGuard;
221*cdf0e10cSrcweir 
222*cdf0e10cSrcweir         // TODO(F1)
223*cdf0e10cSrcweir         return uno::Sequence< geometry::RealRectangle2D >();
224*cdf0e10cSrcweir     }
225*cdf0e10cSrcweir 
226*cdf0e10cSrcweir     uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements(  ) throw (uno::RuntimeException)
227*cdf0e10cSrcweir     {
228*cdf0e10cSrcweir         tools::LocalGuard aGuard;
229*cdf0e10cSrcweir 
230*cdf0e10cSrcweir         return maLogicalAdvancements;
231*cdf0e10cSrcweir     }
232*cdf0e10cSrcweir 
233*cdf0e10cSrcweir     void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
234*cdf0e10cSrcweir     {
235*cdf0e10cSrcweir         tools::LocalGuard aGuard;
236*cdf0e10cSrcweir 
237*cdf0e10cSrcweir         ENSURE_ARG_OR_THROW( aAdvancements.getLength() == maText.Length,
238*cdf0e10cSrcweir                          "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir         maLogicalAdvancements = aAdvancements;
241*cdf0e10cSrcweir     }
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir     geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds(  ) throw (uno::RuntimeException)
244*cdf0e10cSrcweir     {
245*cdf0e10cSrcweir         tools::LocalGuard aGuard;
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir     	if( !mpOutDevProvider )
248*cdf0e10cSrcweir             return geometry::RealRectangle2D();
249*cdf0e10cSrcweir 
250*cdf0e10cSrcweir         OutputDevice& rOutDev = mpOutDevProvider->getOutDev();
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir         VirtualDevice aVDev( rOutDev );
253*cdf0e10cSrcweir         aVDev.SetFont( mpFont->getVCLFont() );
254*cdf0e10cSrcweir 
255*cdf0e10cSrcweir         // need metrics for Y offset, the XCanvas always renders
256*cdf0e10cSrcweir         // relative to baseline
257*cdf0e10cSrcweir         const ::FontMetric& aMetric( aVDev.GetFontMetric() );
258*cdf0e10cSrcweir 
259*cdf0e10cSrcweir         setupLayoutMode( aVDev, mnTextDirection );
260*cdf0e10cSrcweir 
261*cdf0e10cSrcweir         const sal_Int32 nAboveBaseline( /*-aMetric.GetIntLeading()*/ - aMetric.GetAscent() );
262*cdf0e10cSrcweir         const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
263*cdf0e10cSrcweir 
264*cdf0e10cSrcweir         if( maLogicalAdvancements.getLength() )
265*cdf0e10cSrcweir         {
266*cdf0e10cSrcweir             return geometry::RealRectangle2D( 0, nAboveBaseline,
267*cdf0e10cSrcweir                                               maLogicalAdvancements[ maLogicalAdvancements.getLength()-1 ],
268*cdf0e10cSrcweir                                               nBelowBaseline );
269*cdf0e10cSrcweir         }
270*cdf0e10cSrcweir         else
271*cdf0e10cSrcweir         {
272*cdf0e10cSrcweir             return geometry::RealRectangle2D( 0, nAboveBaseline,
273*cdf0e10cSrcweir                                               aVDev.GetTextWidth(
274*cdf0e10cSrcweir                                                   maText.Text,
275*cdf0e10cSrcweir                                                   ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
276*cdf0e10cSrcweir                                                   ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) ),
277*cdf0e10cSrcweir                                               nBelowBaseline );
278*cdf0e10cSrcweir         }
279*cdf0e10cSrcweir     }
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir     double SAL_CALL TextLayout::justify( double nSize ) throw (lang::IllegalArgumentException, uno::RuntimeException)
282*cdf0e10cSrcweir     {
283*cdf0e10cSrcweir         tools::LocalGuard aGuard;
284*cdf0e10cSrcweir 
285*cdf0e10cSrcweir         (void)nSize;
286*cdf0e10cSrcweir 
287*cdf0e10cSrcweir         // TODO(F1)
288*cdf0e10cSrcweir         return 0.0;
289*cdf0e10cSrcweir     }
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir     double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& aNextLayouts,
292*cdf0e10cSrcweir                                                  double                                                           nSize ) throw (lang::IllegalArgumentException, uno::RuntimeException)
293*cdf0e10cSrcweir     {
294*cdf0e10cSrcweir         tools::LocalGuard aGuard;
295*cdf0e10cSrcweir 
296*cdf0e10cSrcweir         (void)aNextLayouts;
297*cdf0e10cSrcweir         (void)nSize;
298*cdf0e10cSrcweir 
299*cdf0e10cSrcweir         // TODO(F1)
300*cdf0e10cSrcweir         return 0.0;
301*cdf0e10cSrcweir     }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir     rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& aHitPoint ) throw (uno::RuntimeException)
304*cdf0e10cSrcweir     {
305*cdf0e10cSrcweir         tools::LocalGuard aGuard;
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir         (void)aHitPoint;
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir         // TODO(F1)
310*cdf0e10cSrcweir         return rendering::TextHit();
311*cdf0e10cSrcweir     }
312*cdf0e10cSrcweir 
313*cdf0e10cSrcweir     rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 nInsertionIndex, sal_Bool bExcludeLigatures ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
314*cdf0e10cSrcweir     {
315*cdf0e10cSrcweir         tools::LocalGuard aGuard;
316*cdf0e10cSrcweir 
317*cdf0e10cSrcweir         (void)nInsertionIndex;
318*cdf0e10cSrcweir         (void)bExcludeLigatures;
319*cdf0e10cSrcweir 
320*cdf0e10cSrcweir         // TODO(F1)
321*cdf0e10cSrcweir         return rendering::Caret();
322*cdf0e10cSrcweir     }
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir     sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 nStartIndex, sal_Int32 nCaretAdvancement, sal_Bool bExcludeLigatures ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
325*cdf0e10cSrcweir     {
326*cdf0e10cSrcweir         tools::LocalGuard aGuard;
327*cdf0e10cSrcweir 
328*cdf0e10cSrcweir         (void)nStartIndex;
329*cdf0e10cSrcweir         (void)nCaretAdvancement;
330*cdf0e10cSrcweir         (void)bExcludeLigatures;
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir         // TODO(F1)
333*cdf0e10cSrcweir         return 0;
334*cdf0e10cSrcweir     }
335*cdf0e10cSrcweir 
336*cdf0e10cSrcweir     uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
337*cdf0e10cSrcweir     {
338*cdf0e10cSrcweir         tools::LocalGuard aGuard;
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir         (void)nStartIndex;
341*cdf0e10cSrcweir         (void)nEndIndex;
342*cdf0e10cSrcweir 
343*cdf0e10cSrcweir         // TODO(F1)
344*cdf0e10cSrcweir         return uno::Reference< rendering::XPolyPolygon2D >();
345*cdf0e10cSrcweir     }
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir     uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
348*cdf0e10cSrcweir     {
349*cdf0e10cSrcweir         tools::LocalGuard aGuard;
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir         (void)nStartIndex;
352*cdf0e10cSrcweir         (void)nEndIndex;
353*cdf0e10cSrcweir 
354*cdf0e10cSrcweir         // TODO(F1)
355*cdf0e10cSrcweir         return uno::Reference< rendering::XPolyPolygon2D >();
356*cdf0e10cSrcweir     }
357*cdf0e10cSrcweir 
358*cdf0e10cSrcweir     double SAL_CALL TextLayout::getBaselineOffset(  ) throw (uno::RuntimeException)
359*cdf0e10cSrcweir     {
360*cdf0e10cSrcweir         tools::LocalGuard aGuard;
361*cdf0e10cSrcweir 
362*cdf0e10cSrcweir         // TODO(F1)
363*cdf0e10cSrcweir         return 0.0;
364*cdf0e10cSrcweir     }
365*cdf0e10cSrcweir 
366*cdf0e10cSrcweir     sal_Int8 SAL_CALL TextLayout::getMainTextDirection(  ) throw (uno::RuntimeException)
367*cdf0e10cSrcweir     {
368*cdf0e10cSrcweir         tools::LocalGuard aGuard;
369*cdf0e10cSrcweir 
370*cdf0e10cSrcweir         return mnTextDirection;
371*cdf0e10cSrcweir     }
372*cdf0e10cSrcweir 
373*cdf0e10cSrcweir     uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont(  ) throw (uno::RuntimeException)
374*cdf0e10cSrcweir     {
375*cdf0e10cSrcweir         tools::LocalGuard aGuard;
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir         return mpFont.getRef();
378*cdf0e10cSrcweir     }
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir     rendering::StringContext SAL_CALL TextLayout::getText(  ) throw (uno::RuntimeException)
381*cdf0e10cSrcweir     {
382*cdf0e10cSrcweir         tools::LocalGuard aGuard;
383*cdf0e10cSrcweir 
384*cdf0e10cSrcweir         return maText;
385*cdf0e10cSrcweir     }
386*cdf0e10cSrcweir 
387*cdf0e10cSrcweir     bool TextLayout::draw( OutputDevice&                 rOutDev,
388*cdf0e10cSrcweir                            const Point&                  rOutpos,
389*cdf0e10cSrcweir                            const rendering::ViewState&   viewState,
390*cdf0e10cSrcweir                            const rendering::RenderState& renderState ) const
391*cdf0e10cSrcweir     {
392*cdf0e10cSrcweir         tools::LocalGuard aGuard;
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir         setupLayoutMode( rOutDev, mnTextDirection );
395*cdf0e10cSrcweir 
396*cdf0e10cSrcweir         if( maLogicalAdvancements.getLength() )
397*cdf0e10cSrcweir         {
398*cdf0e10cSrcweir             // TODO(P2): cache that
399*cdf0e10cSrcweir             ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
400*cdf0e10cSrcweir             setupTextOffsets( aOffsets.get(), maLogicalAdvancements, viewState, renderState );
401*cdf0e10cSrcweir 
402*cdf0e10cSrcweir             // TODO(F3): ensure correct length and termination for DX
403*cdf0e10cSrcweir             // array (last entry _must_ contain the overall width)
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir             rOutDev.DrawTextArray( rOutpos,
406*cdf0e10cSrcweir                                    maText.Text,
407*cdf0e10cSrcweir                                    aOffsets.get(),
408*cdf0e10cSrcweir                                    ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
409*cdf0e10cSrcweir                                    ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
410*cdf0e10cSrcweir         }
411*cdf0e10cSrcweir         else
412*cdf0e10cSrcweir         {
413*cdf0e10cSrcweir             rOutDev.DrawText( rOutpos,
414*cdf0e10cSrcweir                               maText.Text,
415*cdf0e10cSrcweir                               ::canvas::tools::numeric_cast<sal_uInt16>(maText.StartPosition),
416*cdf0e10cSrcweir                               ::canvas::tools::numeric_cast<sal_uInt16>(maText.Length) );
417*cdf0e10cSrcweir         }
418*cdf0e10cSrcweir 
419*cdf0e10cSrcweir         return true;
420*cdf0e10cSrcweir     }
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir     namespace
423*cdf0e10cSrcweir     {
424*cdf0e10cSrcweir         class OffsetTransformer
425*cdf0e10cSrcweir         {
426*cdf0e10cSrcweir         public:
427*cdf0e10cSrcweir             OffsetTransformer( const ::basegfx::B2DHomMatrix& rMat ) :
428*cdf0e10cSrcweir                 maMatrix( rMat )
429*cdf0e10cSrcweir             {
430*cdf0e10cSrcweir             }
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir             sal_Int32 operator()( const double& rOffset )
433*cdf0e10cSrcweir             {
434*cdf0e10cSrcweir                 // This is an optimization of the normal rMat*[x,0]
435*cdf0e10cSrcweir                 // transformation of the advancement vector (in x
436*cdf0e10cSrcweir                 // direction), followed by a length calculation of the
437*cdf0e10cSrcweir                 // resulting vector: advancement' =
438*cdf0e10cSrcweir                 // ||rMat*[x,0]||. Since advancements are vectors, we
439*cdf0e10cSrcweir                 // can ignore translational components, thus if [x,0],
440*cdf0e10cSrcweir                 // it follows that rMat*[x,0]=[x',0] holds. Thus, we
441*cdf0e10cSrcweir                 // just have to calc the transformation of the x
442*cdf0e10cSrcweir                 // component.
443*cdf0e10cSrcweir 
444*cdf0e10cSrcweir                 // TODO(F2): Handle non-horizontal advancements!
445*cdf0e10cSrcweir                 return ::basegfx::fround( hypot(maMatrix.get(0,0)*rOffset,
446*cdf0e10cSrcweir 												maMatrix.get(1,0)*rOffset) );
447*cdf0e10cSrcweir             }
448*cdf0e10cSrcweir 
449*cdf0e10cSrcweir         private:
450*cdf0e10cSrcweir             ::basegfx::B2DHomMatrix maMatrix;
451*cdf0e10cSrcweir         };
452*cdf0e10cSrcweir     }
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir     void TextLayout::setupTextOffsets( sal_Int32*						outputOffsets,
455*cdf0e10cSrcweir                                        const uno::Sequence< double >& 	inputOffsets,
456*cdf0e10cSrcweir                                        const rendering::ViewState& 		viewState,
457*cdf0e10cSrcweir                                        const rendering::RenderState& 	renderState		) const
458*cdf0e10cSrcweir     {
459*cdf0e10cSrcweir         ENSURE_OR_THROW( outputOffsets!=NULL,
460*cdf0e10cSrcweir                           "TextLayout::setupTextOffsets offsets NULL" );
461*cdf0e10cSrcweir 
462*cdf0e10cSrcweir         ::basegfx::B2DHomMatrix aMatrix;
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir         ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
465*cdf0e10cSrcweir                                                      viewState,
466*cdf0e10cSrcweir                                                      renderState);
467*cdf0e10cSrcweir 
468*cdf0e10cSrcweir         // fill integer offsets
469*cdf0e10cSrcweir         ::std::transform( const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray(),
470*cdf0e10cSrcweir                           const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray()+inputOffsets.getLength(),
471*cdf0e10cSrcweir                           outputOffsets,
472*cdf0e10cSrcweir                           OffsetTransformer( aMatrix ) );
473*cdf0e10cSrcweir     }
474*cdf0e10cSrcweir 
475*cdf0e10cSrcweir 
476*cdf0e10cSrcweir #define IMPLEMENTATION_NAME "VCLCanvas::TextLayout"
477*cdf0e10cSrcweir #define SERVICE_NAME "com.sun.star.rendering.TextLayout"
478*cdf0e10cSrcweir 
479*cdf0e10cSrcweir     ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
480*cdf0e10cSrcweir     {
481*cdf0e10cSrcweir         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
482*cdf0e10cSrcweir     }
483*cdf0e10cSrcweir 
484*cdf0e10cSrcweir     sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
485*cdf0e10cSrcweir     {
486*cdf0e10cSrcweir         return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
487*cdf0e10cSrcweir     }
488*cdf0e10cSrcweir 
489*cdf0e10cSrcweir     uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames()  throw( uno::RuntimeException )
490*cdf0e10cSrcweir     {
491*cdf0e10cSrcweir         uno::Sequence< ::rtl::OUString > aRet(1);
492*cdf0e10cSrcweir         aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
493*cdf0e10cSrcweir 
494*cdf0e10cSrcweir         return aRet;
495*cdf0e10cSrcweir     }
496*cdf0e10cSrcweir }
497