merge the formfield patch from ooo-build
[ooovba.git] / canvas / source / cairo / cairo_textlayout.cxx
blobc33175ceeac31ab110a4a2550f322401a8e56c16
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: cairo_textlayout.cxx,v $
10 * $Revision: 1.7 $
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 <math.h>
36 #include <canvas/debug.hxx>
37 #include <canvas/verbosetrace.hxx>
38 #include <tools/diagnose_ex.h>
40 #include <vcl/metric.hxx>
41 #include <vcl/virdev.hxx>
43 #ifdef WNT
44 #include <tools/prewin.h>
45 #include <windows.h>
46 #include <tools/postwin.h>
47 #ifdef max
48 #undef max
49 #endif
50 #ifdef min
51 #undef min
52 #endif
53 #endif
54 #include <vcl/sysdata.hxx>
56 #include <basegfx/matrix/b2dhommatrix.hxx>
57 #include <basegfx/numeric/ftools.hxx>
59 #include <boost/scoped_array.hpp>
61 #include "cairo_textlayout.hxx"
62 #include "cairo_spritecanvas.hxx"
64 #ifdef CAIRO_HAS_QUARTZ_SURFACE
65 # include "cairo_quartz_cairo.hxx"
66 #elif defined CAIRO_HAS_WIN32_SURFACE
67 # include "cairo_win32_cairo.hxx"
68 # include <cairo-win32.h>
69 #elif defined CAIRO_HAS_XLIB_SURFACE
70 # include "cairo_xlib_cairo.hxx"
71 # include <cairo-ft.h>
72 #else
73 # error Native API needed.
74 #endif
76 using namespace ::cairo;
77 using namespace ::com::sun::star;
79 namespace cairocanvas
81 namespace
83 void setupLayoutMode( OutputDevice& rOutDev,
84 sal_Int8 nTextDirection )
86 // TODO(P3): avoid if already correctly set
87 ULONG nLayoutMode;
88 switch( nTextDirection )
90 default:
91 nLayoutMode = 0;
92 break;
93 case rendering::TextDirection::WEAK_LEFT_TO_RIGHT:
94 nLayoutMode = TEXT_LAYOUT_BIDI_LTR;
95 break;
96 case rendering::TextDirection::STRONG_LEFT_TO_RIGHT:
97 nLayoutMode = TEXT_LAYOUT_BIDI_LTR | TEXT_LAYOUT_BIDI_STRONG;
98 break;
99 case rendering::TextDirection::WEAK_RIGHT_TO_LEFT:
100 nLayoutMode = TEXT_LAYOUT_BIDI_RTL;
101 break;
102 case rendering::TextDirection::STRONG_RIGHT_TO_LEFT:
103 nLayoutMode = TEXT_LAYOUT_BIDI_RTL | TEXT_LAYOUT_BIDI_STRONG;
104 break;
107 // set calculated layout mode. Origin is always the left edge,
108 // as required at the API spec
109 rOutDev.SetLayoutMode( nLayoutMode | TEXT_LAYOUT_TEXTORIGIN_LEFT );
113 TextLayout::TextLayout( const rendering::StringContext& aText,
114 sal_Int8 nDirection,
115 sal_Int64 /*nRandomSeed*/,
116 const CanvasFont::Reference& rFont,
117 const SurfaceProviderRef& rRefDevice ) :
118 TextLayout_Base( m_aMutex ),
119 maText( aText ),
120 maLogicalAdvancements(),
121 mpFont( rFont ),
122 mpRefDevice( rRefDevice ),
123 mnTextDirection( nDirection )
127 TextLayout::~TextLayout()
131 void SAL_CALL TextLayout::disposing()
133 ::osl::MutexGuard aGuard( m_aMutex );
135 mpFont.reset();
136 mpRefDevice.clear();
139 // XTextLayout
140 uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > > SAL_CALL TextLayout::queryTextShapes( ) throw (uno::RuntimeException)
142 ::osl::MutexGuard aGuard( m_aMutex );
144 // TODO
145 return uno::Sequence< uno::Reference< rendering::XPolyPolygon2D > >();
148 uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryInkMeasures( ) throw (uno::RuntimeException)
150 ::osl::MutexGuard aGuard( m_aMutex );
152 // TODO
153 return uno::Sequence< geometry::RealRectangle2D >();
156 uno::Sequence< geometry::RealRectangle2D > SAL_CALL TextLayout::queryMeasures( ) throw (uno::RuntimeException)
158 ::osl::MutexGuard aGuard( m_aMutex );
160 // TODO
161 return uno::Sequence< geometry::RealRectangle2D >();
164 uno::Sequence< double > SAL_CALL TextLayout::queryLogicalAdvancements( ) throw (uno::RuntimeException)
166 ::osl::MutexGuard aGuard( m_aMutex );
168 return maLogicalAdvancements;
171 void SAL_CALL TextLayout::applyLogicalAdvancements( const uno::Sequence< double >& aAdvancements ) throw (lang::IllegalArgumentException, uno::RuntimeException)
173 ::osl::MutexGuard aGuard( m_aMutex );
175 if( aAdvancements.getLength() != maText.Length )
177 OSL_TRACE( "TextLayout::applyLogicalAdvancements(): mismatching number of advancements" );
178 throw lang::IllegalArgumentException();
181 maLogicalAdvancements = aAdvancements;
184 geometry::RealRectangle2D SAL_CALL TextLayout::queryTextBounds( ) throw (uno::RuntimeException)
186 ::osl::MutexGuard aGuard( m_aMutex );
188 OutputDevice* pOutDev = mpRefDevice->getOutputDevice();
189 if( !pOutDev )
190 return geometry::RealRectangle2D();
192 VirtualDevice aVDev( *pOutDev );
193 aVDev.SetFont( mpFont->getVCLFont() );
195 // need metrics for Y offset, the XCanvas always renders
196 // relative to baseline
197 const ::FontMetric& aMetric( aVDev.GetFontMetric() );
199 setupLayoutMode( aVDev, mnTextDirection );
201 const sal_Int32 nAboveBaseline( -aMetric.GetIntLeading() - aMetric.GetAscent() );
202 const sal_Int32 nBelowBaseline( aMetric.GetDescent() );
204 if( maLogicalAdvancements.getLength() )
206 return geometry::RealRectangle2D( 0, nAboveBaseline,
207 maLogicalAdvancements[ maLogicalAdvancements.getLength()-1 ],
208 nBelowBaseline );
210 else
212 return geometry::RealRectangle2D( 0, nAboveBaseline,
213 aVDev.GetTextWidth(
214 maText.Text,
215 ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
216 ::canvas::tools::numeric_cast<USHORT>(maText.Length) ),
217 nBelowBaseline );
221 double SAL_CALL TextLayout::justify( double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
223 ::osl::MutexGuard aGuard( m_aMutex );
225 // TODO
226 return 0.0;
229 double SAL_CALL TextLayout::combinedJustify( const uno::Sequence< uno::Reference< rendering::XTextLayout > >& /*aNextLayouts*/,
230 double /*nSize*/ ) throw (lang::IllegalArgumentException, uno::RuntimeException)
232 ::osl::MutexGuard aGuard( m_aMutex );
234 // TODO
235 return 0.0;
238 rendering::TextHit SAL_CALL TextLayout::getTextHit( const geometry::RealPoint2D& /*aHitPoint*/ ) throw (uno::RuntimeException)
240 ::osl::MutexGuard aGuard( m_aMutex );
242 // TODO
243 return rendering::TextHit();
246 rendering::Caret SAL_CALL TextLayout::getCaret( sal_Int32 /*nInsertionIndex*/,
247 sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
249 ::osl::MutexGuard aGuard( m_aMutex );
251 // TODO
252 return rendering::Caret();
255 sal_Int32 SAL_CALL TextLayout::getNextInsertionIndex( sal_Int32 /*nStartIndex*/,
256 sal_Int32 /*nCaretAdvancement*/,
257 sal_Bool /*bExcludeLigatures*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
259 ::osl::MutexGuard aGuard( m_aMutex );
261 // TODO
262 return 0;
265 uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryVisualHighlighting( sal_Int32 /*nStartIndex*/,
266 sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
268 ::osl::MutexGuard aGuard( m_aMutex );
270 // TODO
271 return uno::Reference< rendering::XPolyPolygon2D >();
274 uno::Reference< rendering::XPolyPolygon2D > SAL_CALL TextLayout::queryLogicalHighlighting( sal_Int32 /*nStartIndex*/,
275 sal_Int32 /*nEndIndex*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
277 ::osl::MutexGuard aGuard( m_aMutex );
279 // TODO
280 return uno::Reference< rendering::XPolyPolygon2D >();
283 double SAL_CALL TextLayout::getBaselineOffset( ) throw (uno::RuntimeException)
285 ::osl::MutexGuard aGuard( m_aMutex );
287 // TODO
288 return 0.0;
291 sal_Int8 SAL_CALL TextLayout::getMainTextDirection( ) throw (uno::RuntimeException)
293 ::osl::MutexGuard aGuard( m_aMutex );
295 return mnTextDirection;
298 uno::Reference< rendering::XCanvasFont > SAL_CALL TextLayout::getFont( ) throw (uno::RuntimeException)
300 ::osl::MutexGuard aGuard( m_aMutex );
302 return mpFont.getRef();
305 rendering::StringContext SAL_CALL TextLayout::getText( ) throw (uno::RuntimeException)
307 ::osl::MutexGuard aGuard( m_aMutex );
309 return maText;
312 void TextLayout::useFont( Cairo* pCairo )
314 rendering::FontRequest aFontRequest = mpFont->getFontRequest();
315 rendering::FontInfo aFontInfo = aFontRequest.FontDescription;
317 cairo_select_font_face( pCairo, ::rtl::OUStringToOString( aFontInfo.FamilyName, RTL_TEXTENCODING_UTF8 ), CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL );
318 cairo_set_font_size( pCairo, aFontRequest.CellSize );
321 /** TextLayout:draw
323 * This function uses the "toy" api of the cairo library
326 bool TextLayout::draw( Cairo* pCairo )
328 ::osl::MutexGuard aGuard( m_aMutex );
330 ::rtl::OUString aSubText = maText.Text.copy( maText.StartPosition, maText.Length );
331 ::rtl::OString aUTF8String = ::rtl::OUStringToOString( aSubText, RTL_TEXTENCODING_UTF8 );
333 cairo_save( pCairo );
334 /* move to 0, 0 as cairo_show_text advances current point and current point is not restored by cairo_restore.
335 before we were depending on unmodified current point which I believed was preserved by save/restore */
336 cairo_move_to( pCairo, 0, 0 );
337 useFont( pCairo );
338 cairo_show_text( pCairo, aUTF8String );
339 cairo_restore( pCairo );
341 return true;
346 * TextLayout::isCairoRenderable
348 * Features currenly not supported by Cairo (VCL rendering is used as fallback):
349 * - vertical glyphs
351 * @return true, if text/font can be rendered with cairo
353 bool TextLayout::isCairoRenderable(SystemFontData aSysFontData) const
355 #if defined UNX && !defined QUARTZ
356 // is font usable?
357 if (!aSysFontData.nFontId) return false;
358 #endif
360 // vertical glyph rendering is not supported in cairo for now
361 if (aSysFontData.bVerticalCharacterType) {
362 OSL_TRACE(":cairocanvas::TextLayout::isCairoRenderable(): ***************** VERTICAL CHARACTER STYLE!!! ****************");
363 return false;
366 return true;
371 * TextLayout::draw
373 * Cairo-based text rendering. Draw text directly on the cairo surface with cairo fonts.
374 * Avoid using VCL VirtualDevices for that, bypassing VCL DrawText functions, when possible
376 * Note: some text effects are not rendered due to lacking generic canvas or cairo canvas
377 * implementation. See issues 92657, 92658, 92659, 92660, 97529
379 * @return true, if successful
381 bool TextLayout::draw( SurfaceSharedPtr& pSurface,
382 OutputDevice& rOutDev,
383 const Point& rOutpos,
384 const rendering::ViewState& viewState,
385 const rendering::RenderState& renderState ) const
387 ::osl::MutexGuard aGuard( m_aMutex );
388 SystemTextLayoutData aSysLayoutData;
389 #if (defined CAIRO_HAS_WIN32_SURFACE) && (OSL_DEBUG_LEVEL > 1)
390 LOGFONTW logfont;
391 #endif
392 setupLayoutMode( rOutDev, mnTextDirection );
394 // TODO(P2): cache that
395 ::boost::scoped_array< sal_Int32 > aOffsets(new sal_Int32[maLogicalAdvancements.getLength()]);
397 if( maLogicalAdvancements.getLength() )
399 setupTextOffsets( aOffsets.get(), maLogicalAdvancements, viewState, renderState );
401 // TODO(F3): ensure correct length and termination for DX
402 // array (last entry _must_ contain the overall width)
405 aSysLayoutData = rOutDev.GetSysTextLayoutData(rOutpos, maText.Text,
406 ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
407 ::canvas::tools::numeric_cast<USHORT>(maText.Length),
408 maLogicalAdvancements.getLength() ? aOffsets.get() : NULL);
410 // The ::GetSysTextLayoutData(), i.e. layouting of text to glyphs can change the font being used.
411 // The fallback checks need to be done after final font is known.
412 if (!isCairoRenderable(aSysLayoutData.aSysFontData)) // VCL FALLBACKS
414 OSL_TRACE(":cairocanvas::TextLayout::draw(S,O,p,v,r): VCL FALLBACK %s%s%s%s - %s",
415 maLogicalAdvancements.getLength() ? "ADV " : "",
416 aSysLayoutData.aSysFontData.bAntialias ? "AA " : "",
417 aSysLayoutData.aSysFontData.bFakeBold ? "FB " : "",
418 aSysLayoutData.aSysFontData.bFakeItalic ? "FI " : "",
419 ::rtl::OUStringToOString( maText.Text.copy( maText.StartPosition, maText.Length ),
420 RTL_TEXTENCODING_UTF8 ).getStr());
422 if (maLogicalAdvancements.getLength()) // VCL FALLBACK - with glyph advances
424 rOutDev.DrawTextArray( rOutpos, maText.Text, aOffsets.get(),
425 ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
426 ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
427 return true;
429 else // VCL FALLBACK - without advances
431 rOutDev.DrawText( rOutpos, maText.Text,
432 ::canvas::tools::numeric_cast<USHORT>(maText.StartPosition),
433 ::canvas::tools::numeric_cast<USHORT>(maText.Length) );
434 return true;
438 if (aSysLayoutData.rGlyphData.empty()) return false; //??? false?
441 * Setup platform independent glyph vector into cairo-based glyphs vector.
444 // setup glyphs
445 std::vector<cairo_glyph_t> cairo_glyphs;
446 cairo_glyphs.reserve( 256 );
448 for( int nStart = 0; nStart < (int) aSysLayoutData.rGlyphData.size(); nStart++ )
450 cairo_glyph_t aGlyph;
451 SystemGlyphData systemGlyph = aSysLayoutData.rGlyphData.at(nStart);
452 aGlyph.index = systemGlyph.index;
453 #ifdef CAIRO_HAS_WIN32_SURFACE
454 // Cairo requires standard glyph indexes (ETO_GLYPH_INDEX), while vcl/win/* uses ucs4 chars.
455 // Convert to standard indexes
456 aGlyph.index = cairo::ucs4toindex((unsigned int) aGlyph.index, aSysLayoutData.aSysFontData.hFont);
457 #endif
458 aGlyph.x = systemGlyph.x;
459 aGlyph.y = systemGlyph.y;
460 cairo_glyphs.push_back(aGlyph);
463 if (cairo_glyphs.empty()) return true; //true or false??
466 * Setup font
467 **/
468 cairo_font_face_t* font_face = NULL;
470 #ifdef CAIRO_HAS_QUARTZ_SURFACE
471 // TODO: use cairo_quartz_font_face_create_for_cgfont(cgFont)
472 // when CGFont (Mac OS X 10.5 API) is provided by the AQUA VCL backend.
473 font_face = cairo_quartz_font_face_create_for_atsu_font_id((ATSUFontID) aSysLayoutData.aSysFontData.aATSUFontID);
475 #elif defined CAIRO_HAS_WIN32_SURFACE
476 #if (OSL_DEBUG_LEVEL > 1)
477 GetObjectW( aSysLayoutData.aSysFontData.hFont, sizeof(logfont), &logfont );
478 #endif
479 // Note: cairo library uses logfont fallbacks when lfEscapement, lfOrientation and lfWidth are not zero.
480 // VCL always has non-zero value for lfWidth
481 font_face = cairo_win32_font_face_create_for_hfont(aSysLayoutData.aSysFontData.hFont);
483 #elif defined CAIRO_HAS_XLIB_SURFACE
484 font_face = cairo_ft_font_face_create_for_ft_face((FT_Face)aSysLayoutData.aSysFontData.nFontId,
485 aSysLayoutData.aSysFontData.nFontFlags);
486 #else
487 # error Native API needed.
488 #endif
490 CairoSharedPtr pSCairo = pSurface->getCairo();
492 cairo_set_font_face( pSCairo.get(), font_face);
494 // create default font options. cairo_get_font_options() does not retrieve the surface defaults,
495 // only what has been set before with cairo_set_font_options()
496 cairo_font_options_t* options = cairo_font_options_create();
497 if (aSysLayoutData.aSysFontData.bAntialias) {
498 // CAIRO_ANTIALIAS_GRAY provides more similar result to VCL Canvas,
499 // so we're not using CAIRO_ANTIALIAS_SUBPIXEL
500 cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
502 cairo_set_font_options( pSCairo.get(), options);
504 // Font color
505 Color mTextColor = rOutDev.GetTextColor();
506 cairo_set_source_rgb(pSCairo.get(),
507 mTextColor.GetRed()/255.0,
508 mTextColor.GetGreen()/255.0,
509 mTextColor.GetBlue()/255.0);
511 // Font rotation and scaling
512 cairo_matrix_t m;
513 Font aFont = rOutDev.GetFont();
514 FontMetric aMetric( rOutDev.GetFontMetric(aFont) );
515 long nWidth = 0;
517 // width calculation is deep magic and platform/font dependant.
518 // width == 0 means no scaling, and usually width == height means the same.
519 // Other values mean horizontal scaling (narrow or stretching)
520 // see issue #101566
522 //proper scale calculation across platforms
523 if (aFont.GetWidth() == 0) {
524 nWidth = aFont.GetHeight();
525 } else {
526 // any scaling needs to be relative to the platform-dependent definition
527 // of width of the font
528 nWidth = aFont.GetHeight() * aFont.GetWidth() / aMetric.GetWidth();
531 cairo_matrix_init_identity(&m);
533 if (aSysLayoutData.orientation) cairo_matrix_rotate(&m, (3600 - aSysLayoutData.orientation) * M_PI / 1800.0);
535 cairo_matrix_scale(&m, nWidth, aFont.GetHeight());
537 //faux italics
538 if (aSysLayoutData.aSysFontData.bFakeItalic) m.xy = -m.xx * 0x6000L / 0x10000L;
540 cairo_set_font_matrix(pSCairo.get(), &m);
542 OSL_TRACE("\r\n:cairocanvas::TextLayout::draw(S,O,p,v,r): Size:(%d,%d), W:%d->%d, Pos (%d,%d), G(%d,%d,%d) %s%s%s%s || Name:%s - %s",
543 aFont.GetWidth(),
544 aFont.GetHeight(),
545 aMetric.GetWidth(),
546 nWidth,
547 (int) rOutpos.X(),
548 (int) rOutpos.Y(),
549 cairo_glyphs[0].index, cairo_glyphs[1].index, cairo_glyphs[2].index,
550 maLogicalAdvancements.getLength() ? "ADV " : "",
551 aSysLayoutData.aSysFontData.bAntialias ? "AA " : "",
552 aSysLayoutData.aSysFontData.bFakeBold ? "FB " : "",
553 aSysLayoutData.aSysFontData.bFakeItalic ? "FI " : "",
554 #if (defined CAIRO_HAS_WIN32_SURFACE) && (OSL_DEBUG_LEVEL > 1)
555 ::rtl::OUStringToOString( reinterpret_cast<const sal_Unicode*> (logfont.lfFaceName), RTL_TEXTENCODING_UTF8 ).getStr(),
556 #else
557 ::rtl::OUStringToOString( aFont.GetName(), RTL_TEXTENCODING_UTF8 ).getStr(),
558 #endif
559 ::rtl::OUStringToOString( maText.Text.copy( maText.StartPosition, maText.Length ),
560 RTL_TEXTENCODING_UTF8 ).getStr()
563 cairo_show_glyphs(pSCairo.get(), &cairo_glyphs[0], cairo_glyphs.size());
565 //faux bold
566 if (aSysLayoutData.aSysFontData.bFakeBold) {
567 double bold_dx = 0.5 * sqrt( 0.7 * aFont.GetHeight() );
568 int total_steps = 2 * ((int) (bold_dx + 0.5));
570 // loop to draw the text for every half pixel of displacement
571 for (int nSteps = 0; nSteps < total_steps; nSteps++) {
572 for(int nGlyphIdx = 0; nGlyphIdx < (int) cairo_glyphs.size(); nGlyphIdx++) {
573 cairo_glyphs[nGlyphIdx].x += bold_dx * nSteps / total_steps;
575 cairo_show_glyphs(pSCairo.get(), &cairo_glyphs[0], cairo_glyphs.size());
577 OSL_TRACE(":cairocanvas::TextLayout::draw(S,O,p,v,r): FAKEBOLD - dx:%d", (int) bold_dx);
580 cairo_restore( pSCairo.get() );
581 cairo_font_face_destroy(font_face);
582 return true;
586 namespace
588 class OffsetTransformer
590 public:
591 OffsetTransformer( const ::basegfx::B2DHomMatrix& rMat ) :
592 maMatrix( rMat )
596 sal_Int32 operator()( const double& rOffset )
598 // This is an optimization of the normal rMat*[x,0]
599 // transformation of the advancement vector (in x
600 // direction), followed by a length calculation of the
601 // resulting vector: advancement' =
602 // ||rMat*[x,0]||. Since advancements are vectors, we
603 // can ignore translational components, thus if [x,0],
604 // it follows that rMat*[x,0]=[x',0] holds. Thus, we
605 // just have to calc the transformation of the x
606 // component.
608 // TODO(F2): Handle non-horizontal advancements!
609 return ::basegfx::fround( hypot(maMatrix.get(0,0)*rOffset,
610 maMatrix.get(1,0)*rOffset) );
613 private:
614 ::basegfx::B2DHomMatrix maMatrix;
618 void TextLayout::setupTextOffsets( sal_Int32* outputOffsets,
619 const uno::Sequence< double >& inputOffsets,
620 const rendering::ViewState& viewState,
621 const rendering::RenderState& renderState ) const
623 ENSURE_OR_THROW( outputOffsets!=NULL,
624 "TextLayout::setupTextOffsets offsets NULL" );
626 ::basegfx::B2DHomMatrix aMatrix;
628 ::canvas::tools::mergeViewAndRenderTransform(aMatrix,
629 viewState,
630 renderState);
632 // fill integer offsets
633 ::std::transform( const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray(),
634 const_cast< uno::Sequence< double >& >(inputOffsets).getConstArray()+inputOffsets.getLength(),
635 outputOffsets,
636 OffsetTransformer( aMatrix ) );
639 #define SERVICE_NAME "com.sun.star.rendering.TextLayout"
640 #define IMPLEMENTATION_NAME "CairoCanvas::TextLayout"
642 ::rtl::OUString SAL_CALL TextLayout::getImplementationName() throw( uno::RuntimeException )
644 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
647 sal_Bool SAL_CALL TextLayout::supportsService( const ::rtl::OUString& ServiceName ) throw( uno::RuntimeException )
649 return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) );
652 uno::Sequence< ::rtl::OUString > SAL_CALL TextLayout::getSupportedServiceNames() throw( uno::RuntimeException )
654 uno::Sequence< ::rtl::OUString > aRet(1);
655 aRet[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) );
657 return aRet;