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