xref: /trunk/main/vcl/source/gdi/salgdilayout.cxx (revision 5f27b83c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_vcl.hxx"
26 
27 #include <tools/ref.hxx>
28 #include <tools/debug.hxx>
29 #include <tools/poly.hxx>
30 
31 #include <vcl/svapp.hxx>
32 #include <vcl/region.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/window.hxx>
35 #include <vcl/metaact.hxx>
36 #include <vcl/gdimtf.hxx>
37 #include <vcl/print.hxx>
38 #include <vcl/outdev.hxx>
39 #include <vcl/unowrap.hxx>
40 
41 #include <window.h>
42 #include <outdev.h>
43 #include <sallayout.hxx>
44 #include <salgdi.hxx>
45 #include <salframe.hxx>
46 #include <salvd.hxx>
47 #include <salprn.hxx>
48 #include <svdata.hxx>
49 #include <outdata.hxx>
50 
51 
52 #include "basegfx/polygon/b2dpolygon.hxx"
53 
54 // ----------------------------------------------------------------------------
55 // The only common SalFrame method
56 // ----------------------------------------------------------------------------
57 
58 SalFrameGeometry SalFrame::GetGeometry()
59 {
60     // mirror frame coordinates at parent
61     SalFrame *pParent = GetParent();
62     if( pParent && Application::GetSettings().GetLayoutRTL() )
63     {
64         SalFrameGeometry aGeom = maGeometry;
65         int parent_x = aGeom.nX - pParent->maGeometry.nX;
66         aGeom.nX = pParent->maGeometry.nX + pParent->maGeometry.nWidth - maGeometry.nWidth - parent_x;
67         return aGeom;
68     }
69     else
70         return maGeometry;
71 }
72 
73 // ----------------------------------------------------------------------------
74 
75 SalGraphics::SalGraphics()
76 :   m_nLayout( 0 ),
77     m_bAntiAliasB2DDraw(false)
78 {
79     // read global RTL settings
80     if( Application::GetSettings().GetLayoutRTL() )
81 	    m_nLayout = SAL_LAYOUT_BIDI_RTL;
82 }
83 
84 SalGraphics::~SalGraphics()
85 {
86 }
87 
88 // ----------------------------------------------------------------------------
89 
90 bool SalGraphics::drawAlphaBitmap( const SalTwoRect&,
91     const SalBitmap&, const SalBitmap& )
92 {
93     return false;
94 }
95 
96 // ----------------------------------------------------------------------------
97 
98 bool SalGraphics::drawTransformedBitmap(
99     const basegfx::B2DPoint& rNull,
100     const basegfx::B2DPoint& rX,
101     const basegfx::B2DPoint& rY,
102     const SalBitmap& rSourceBitmap,
103     const SalBitmap* pAlphaBitmap)
104 {
105     // here direct support for transformed bitmaps can be impemented
106     return false;
107 }
108 
109 // ----------------------------------------------------------------------------
110 
111 void SalGraphics::mirror( long& x, const OutputDevice *pOutDev, bool bBack ) const
112 {
113 	long w;
114     if( pOutDev && pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
115         w = pOutDev->GetOutputWidthPixel();
116     else
117         w = GetGraphicsWidth();
118 
119 	if( w )
120     {
121         if( pOutDev && pOutDev->ImplIsAntiparallel() )
122         {
123             OutputDevice *pOutDevRef = (OutputDevice*) pOutDev;
124             // mirror this window back
125             if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
126             {
127                 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
128                 if( bBack )
129                     x = x - devX + pOutDevRef->GetOutOffXPixel();
130                 else
131                     x = devX + (x - pOutDevRef->GetOutOffXPixel());
132             }
133             else
134             {
135                 long devX = pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
136                 if( bBack )
137                     x = x - pOutDevRef->GetOutputWidthPixel() + devX - pOutDevRef->GetOutOffXPixel() + 1;
138                 else
139                     x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - 1;
140             }
141         }
142         else if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
143 		    x = w-1-x;
144     }
145 }
146 
147 void SalGraphics::mirror( long& x, long& nWidth, const OutputDevice *pOutDev, bool bBack ) const
148 {
149 	long w;
150     if( pOutDev && pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
151         w = pOutDev->GetOutputWidthPixel();
152     else
153         w = GetGraphicsWidth();
154 
155 	if( w )
156     {
157         if( pOutDev && pOutDev->ImplIsAntiparallel() )
158         {
159             OutputDevice *pOutDevRef = (OutputDevice*) pOutDev;
160             // mirror this window back
161             if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
162             {
163                 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
164                 if( bBack )
165                     x = x - devX + pOutDevRef->GetOutOffXPixel();
166                 else
167                     x = devX + (x - pOutDevRef->GetOutOffXPixel());
168             }
169             else
170             {
171                 long devX = pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
172                 if( bBack )
173                     x = x - pOutDevRef->GetOutputWidthPixel() + devX - pOutDevRef->GetOutOffXPixel() + nWidth;
174                 else
175                     x = pOutDevRef->GetOutputWidthPixel() - (x - devX) + pOutDevRef->GetOutOffXPixel() - nWidth;
176             }
177         }
178         else if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
179 		    x = w-nWidth-x;
180 
181     }
182 }
183 
184 sal_Bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoint *pPtAry2, const OutputDevice *pOutDev, bool bBack ) const
185 {
186 	long w;
187     if( pOutDev && pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
188         w = pOutDev->GetOutputWidthPixel();
189     else
190         w = GetGraphicsWidth();
191 
192 	if( w )
193 	{
194 		sal_uInt32 i, j;
195 
196         if( pOutDev && pOutDev->ImplIsAntiparallel() )
197         {
198             OutputDevice *pOutDevRef = (OutputDevice*) pOutDev;
199             // mirror this window back
200             if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
201             {
202                 long devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
203                 if( bBack )
204                 {
205                     for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
206                     {
207                         //long x = w-1-pPtAry[i].mnX;
208                         //pPtAry2[j].mnX = devX + ( pOutDevRef->mnOutWidth - 1 - (x - devX) );
209                         pPtAry2[j].mnX = pOutDevRef->GetOutOffXPixel() + (pPtAry[i].mnX - devX);
210                         pPtAry2[j].mnY = pPtAry[i].mnY;
211                     }
212                 }
213                 else
214                 {
215                     for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
216                     {
217                         //long x = w-1-pPtAry[i].mnX;
218                         //pPtAry2[j].mnX = devX + ( pOutDevRef->mnOutWidth - 1 - (x - devX) );
219                         pPtAry2[j].mnX = devX + (pPtAry[i].mnX - pOutDevRef->GetOutOffXPixel());
220                         pPtAry2[j].mnY = pPtAry[i].mnY;
221                     }
222                 }
223             }
224             else
225             {
226                 long devX = pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
227                 if( bBack )
228                 {
229                     for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
230                     {
231                         //long x = w-1-pPtAry[i].mnX;
232                         //pPtAry2[j].mnX = devX + ( pOutDevRef->mnOutWidth - 1 - (x - devX) );
233                         pPtAry2[j].mnX = pPtAry[i].mnX - pOutDevRef->GetOutputWidthPixel() + devX - pOutDevRef->GetOutOffXPixel() + 1;
234                         pPtAry2[j].mnY = pPtAry[i].mnY;
235                     }
236                 }
237                 else
238                 {
239                     for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
240                     {
241                         //long x = w-1-pPtAry[i].mnX;
242                         //pPtAry2[j].mnX = devX + ( pOutDevRef->mnOutWidth - 1 - (x - devX) );
243                         pPtAry2[j].mnX = pOutDevRef->GetOutputWidthPixel() - (pPtAry[i].mnX - devX) + pOutDevRef->GetOutOffXPixel() - 1;
244                         pPtAry2[j].mnY = pPtAry[i].mnY;
245                     }
246                 }
247             }
248         }
249         else if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
250         {
251 		    for( i=0, j=nPoints-1; i<nPoints; i++,j-- )
252 		    {
253 			    pPtAry2[j].mnX = w-1-pPtAry[i].mnX;
254 			    pPtAry2[j].mnY = pPtAry[i].mnY;
255 		    }
256         }
257 		return sal_True;
258 	}
259 	else
260 		return sal_False;
261 }
262 
263 void SalGraphics::mirror( Region& rRgn, const OutputDevice *pOutDev, bool bBack ) const
264 {
265     if( rRgn.HasPolyPolygonOrB2DPolyPolygon() )
266     {
267         const basegfx::B2DPolyPolygon aPolyPoly(mirror(rRgn.GetAsB2DPolyPolygon(), pOutDev, bBack));
268 
269         rRgn = Region(aPolyPoly);
270     }
271     else
272     {
273         RectangleVector aRectangles;
274         rRgn.GetRegionRectangles(aRectangles);
275         rRgn.SetEmpty();
276 
277         for(RectangleVector::iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++)
278         {
279             mirror(*aRectIter, pOutDev, bBack);
280             rRgn.Union(*aRectIter);
281         }
282 
283         //ImplRegionInfo		aInfo;
284         //bool				bRegionRect;
285         //Region              aMirroredRegion;
286         //long nX, nY, nWidth, nHeight;
287         //
288         //bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
289         //while ( bRegionRect )
290         //{
291         //    Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
292         //    mirror( aRect, pOutDev, bBack );
293         //    aMirroredRegion.Union( aRect );
294         //    bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
295         //}
296         //rRgn = aMirroredRegion;
297     }
298 }
299 
300 void SalGraphics::mirror( Rectangle& rRect, const OutputDevice *pOutDev, bool bBack ) const
301 {
302     long nWidth = rRect.GetWidth();
303     long x      = rRect.Left();
304     long x_org = x;
305 
306     mirror( x, nWidth, pOutDev, bBack );
307     rRect.Move( x - x_org, 0 );
308 }
309 
310 basegfx::B2DPoint SalGraphics::mirror( const basegfx::B2DPoint& i_rPoint, const OutputDevice *i_pOutDev, bool i_bBack ) const
311 {
312 	long w;
313     if( i_pOutDev && i_pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
314         w = i_pOutDev->GetOutputWidthPixel();
315     else
316         w = GetGraphicsWidth();
317 
318     DBG_ASSERT( w, "missing graphics width" );
319 
320     basegfx::B2DPoint aRet( i_rPoint );
321 	if( w )
322     {
323         if( i_pOutDev && !i_pOutDev->IsRTLEnabled() )
324         {
325             OutputDevice *pOutDevRef = (OutputDevice*)i_pOutDev;
326             // mirror this window back
327             double devX = w-pOutDevRef->GetOutputWidthPixel()-pOutDevRef->GetOutOffXPixel();   // re-mirrored mnOutOffX
328             if( i_bBack )
329                 aRet.setX( i_rPoint.getX() - devX + pOutDevRef->GetOutOffXPixel() );
330             else
331                 aRet.setX( devX + (i_rPoint.getX() - pOutDevRef->GetOutOffXPixel()) );
332         }
333         else
334 		    aRet.setX( w-1-i_rPoint.getX() );
335     }
336     return aRet;
337 }
338 
339 basegfx::B2DPolygon SalGraphics::mirror( const basegfx::B2DPolygon& i_rPoly, const OutputDevice *i_pOutDev, bool i_bBack ) const
340 {
341 	long w;
342     if( i_pOutDev && i_pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
343         w = i_pOutDev->GetOutputWidthPixel();
344     else
345         w = GetGraphicsWidth();
346 
347     DBG_ASSERT( w, "missing graphics width" );
348 
349     basegfx::B2DPolygon aRet;
350 	if( w )
351     {
352         sal_Int32 nPoints = i_rPoly.count();
353         for( sal_Int32 i = 0; i < nPoints; i++ )
354         {
355             aRet.append( mirror( i_rPoly.getB2DPoint( i ), i_pOutDev, i_bBack ) );
356             if( i_rPoly.isPrevControlPointUsed( i ) )
357                 aRet.setPrevControlPoint( i, mirror( i_rPoly.getPrevControlPoint( i ), i_pOutDev, i_bBack ) );
358             if( i_rPoly.isNextControlPointUsed( i ) )
359                 aRet.setNextControlPoint( i, mirror( i_rPoly.getNextControlPoint( i ), i_pOutDev, i_bBack ) );
360         }
361         aRet.setClosed( i_rPoly.isClosed() );
362         aRet.flip();
363     }
364     else
365         aRet = i_rPoly;
366     return aRet;
367 }
368 
369 basegfx::B2DPolyPolygon SalGraphics::mirror( const basegfx::B2DPolyPolygon& i_rPoly, const OutputDevice *i_pOutDev, bool i_bBack ) const
370 {
371 	long w;
372     if( i_pOutDev && i_pOutDev->GetOutDevType() == OUTDEV_VIRDEV )
373         w = i_pOutDev->GetOutputWidthPixel();
374     else
375         w = GetGraphicsWidth();
376 
377     DBG_ASSERT( w, "missing graphics width" );
378 
379     basegfx::B2DPolyPolygon aRet;
380 	if( w )
381     {
382         sal_Int32 nPoly = i_rPoly.count();
383         for( sal_Int32 i = 0; i < nPoly; i++ )
384             aRet.append( mirror( i_rPoly.getB2DPolygon( i ), i_pOutDev, i_bBack ) );
385         aRet.setClosed( i_rPoly.isClosed() );
386         aRet.flip();
387     }
388     else
389         aRet = i_rPoly;
390     return aRet;
391 }
392 
393 // ----------------------------------------------------------------------------
394 
395 bool SalGraphics::SetClipRegion( const Region& i_rClip, const OutputDevice *pOutDev )
396 {
397 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
398 	{
399 	    Region aMirror( i_rClip );
400 		mirror( aMirror, pOutDev );
401 		return setClipRegion( aMirror );
402 	}
403 	return setClipRegion( i_rClip );
404 }
405 
406 void	SalGraphics::DrawPixel( long nX, long nY, const OutputDevice *pOutDev )
407 {
408 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
409 		mirror( nX, pOutDev );
410 	drawPixel( nX, nY );
411 }
412 void	SalGraphics::DrawPixel( long nX, long nY, SalColor nSalColor, const OutputDevice *pOutDev )
413 {
414 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
415 		mirror( nX, pOutDev );
416 	drawPixel( nX, nY, nSalColor );
417 }
418 void	SalGraphics::DrawLine( long nX1, long nY1, long nX2, long nY2, const OutputDevice *pOutDev )
419 {
420 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
421 	{
422 		mirror( nX1, pOutDev );
423 		mirror( nX2, pOutDev );
424 	}
425 	drawLine( nX1, nY1, nX2, nY2 );
426 }
427 void	SalGraphics::DrawRect( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
428 {
429 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
430 		mirror( nX, nWidth, pOutDev );
431 	drawRect( nX, nY, nWidth, nHeight );
432 }
433 bool SalGraphics::drawPolyLine(
434     const basegfx::B2DPolygon& /*rPolyPolygon*/,
435     double /*fTransparency*/,
436     const basegfx::B2DVector& /*rLineWidths*/,
437     basegfx::B2DLineJoin /*eLineJoin*/,
438     com::sun::star::drawing::LineCap /*eLineCap*/)
439 {
440     return false;
441 }
442 
443 void SalGraphics::DrawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
444 {
445 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
446 	{
447 		SalPoint* pPtAry2 = new SalPoint[nPoints];
448 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
449 		drawPolyLine( nPoints, bCopied ? pPtAry2 : pPtAry );
450 		delete [] pPtAry2;
451 	}
452 	else
453 		drawPolyLine( nPoints, pPtAry );
454 }
455 
456 void SalGraphics::DrawPolygon( sal_uLong nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
457 {
458 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
459 	{
460 		SalPoint* pPtAry2 = new SalPoint[nPoints];
461 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
462 		drawPolygon( nPoints, bCopied ? pPtAry2 : pPtAry );
463 		delete [] pPtAry2;
464 	}
465 	else
466 		drawPolygon( nPoints, pPtAry );
467 }
468 
469 void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry, const OutputDevice *pOutDev )
470 {
471 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
472 	{
473         // TODO: optimize, reduce new/delete calls
474         SalPoint **pPtAry2 = new SalPoint*[nPoly];
475         sal_uLong i;
476         for(i=0; i<nPoly; i++)
477         {
478             sal_uLong nPoints = pPoints[i];
479             pPtAry2[i] = new SalPoint[ nPoints ];
480 		    mirror( nPoints, pPtAry[i], pPtAry2[i], pOutDev );
481         }
482 
483         drawPolyPolygon( nPoly, pPoints, (PCONSTSALPOINT*)pPtAry2 );
484 
485         for(i=0; i<nPoly; i++)
486             delete [] pPtAry2[i];
487         delete [] pPtAry2;
488     }
489     else
490 	    drawPolyPolygon( nPoly, pPoints, pPtAry );
491 }
492 
493 bool SalGraphics::DrawPolyPolygon( const ::basegfx::B2DPolyPolygon& i_rPolyPolygon, double i_fTransparency, const OutputDevice* i_pOutDev )
494 {
495     bool bRet = false;
496 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
497 	{
498         basegfx::B2DPolyPolygon aMirror( mirror( i_rPolyPolygon, i_pOutDev ) );
499         bRet = drawPolyPolygon( aMirror, i_fTransparency );
500     }
501     else
502         bRet = drawPolyPolygon( i_rPolyPolygon, i_fTransparency );
503     return bRet;
504 }
505 
506 bool SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/)
507 {
508 	return false;
509 }
510 
511 sal_Bool SalGraphics::DrawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
512 {
513     sal_Bool bResult = sal_False;
514 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
515 	{
516 		SalPoint* pPtAry2 = new SalPoint[nPoints];
517 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
518 		bResult = drawPolyLineBezier( nPoints, bCopied ? pPtAry2 : pPtAry, pFlgAry );
519 		delete [] pPtAry2;
520 	}
521 	else
522         bResult = drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
523     return bResult;
524 }
525 
526 sal_Bool SalGraphics::DrawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
527 {
528     sal_Bool bResult = sal_False;
529 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
530 	{
531 		SalPoint* pPtAry2 = new SalPoint[nPoints];
532 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
533 		bResult = drawPolygonBezier( nPoints, bCopied ? pPtAry2 : pPtAry, pFlgAry );
534 		delete [] pPtAry2;
535 	}
536 	else
537         bResult = drawPolygonBezier( nPoints, pPtAry, pFlgAry );
538     return bResult;
539 }
540 
541 sal_Bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt32* i_pPoints,
542                                                    const SalPoint* const* i_pPtAry, const sal_uInt8* const* i_pFlgAry, const OutputDevice* i_pOutDev )
543 {
544     sal_Bool bRet = sal_False;
545 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
546 	{
547         // TODO: optimize, reduce new/delete calls
548         SalPoint **pPtAry2 = new SalPoint*[i_nPoly];
549         sal_uLong i;
550         for(i=0; i<i_nPoly; i++)
551         {
552             sal_uLong nPoints = i_pPoints[i];
553             pPtAry2[i] = new SalPoint[ nPoints ];
554 		    mirror( nPoints, i_pPtAry[i], pPtAry2[i], i_pOutDev );
555         }
556 
557         bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, (PCONSTSALPOINT*)pPtAry2, i_pFlgAry );
558 
559         for(i=0; i<i_nPoly; i++)
560             delete [] pPtAry2[i];
561         delete [] pPtAry2;
562     }
563     else
564 	    bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, i_pPtAry, i_pFlgAry );
565     return bRet;
566 }
567 
568 bool SalGraphics::DrawPolyLine(
569     const ::basegfx::B2DPolygon& i_rPolygon,
570     double i_fTransparency,
571     const ::basegfx::B2DVector& i_rLineWidth,
572     basegfx::B2DLineJoin i_eLineJoin,
573     com::sun::star::drawing::LineCap i_eLineCap,
574     const OutputDevice* i_pOutDev )
575 {
576     bool bRet = false;
577 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
578 	{
579         basegfx::B2DPolygon aMirror( mirror( i_rPolygon, i_pOutDev ) );
580         bRet = drawPolyLine( aMirror, i_fTransparency, i_rLineWidth, i_eLineJoin, i_eLineCap );
581     }
582     else
583         bRet = drawPolyLine( i_rPolygon, i_fTransparency, i_rLineWidth, i_eLineJoin, i_eLineCap );
584     return bRet;
585 }
586 
587 void	SalGraphics::CopyArea( long nDestX, long nDestY,
588                                long nSrcX, long nSrcY,
589                                long nSrcWidth, long nSrcHeight,
590                                sal_uInt16 nFlags, const OutputDevice *pOutDev )
591 {
592 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
593 	{
594 		mirror( nDestX, nSrcWidth, pOutDev );
595 		mirror( nSrcX, nSrcWidth, pOutDev );
596 	}
597 	copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, nFlags );
598 }
599 void	SalGraphics::CopyBits( const SalTwoRect& rPosAry,
600                                SalGraphics* pSrcGraphics, const OutputDevice *pOutDev, const OutputDevice *pSrcOutDev )
601 {
602 	if( ( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) ) ||
603         (pSrcGraphics && ( (pSrcGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL)  || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) ) )
604 	{
605 		SalTwoRect aPosAry2 = rPosAry;
606 		if( (pSrcGraphics && (pSrcGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL)) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) )
607 			mirror( aPosAry2.mnSrcX, aPosAry2.mnSrcWidth, pSrcOutDev );
608 		if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
609 			mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
610 		copyBits( aPosAry2, pSrcGraphics );
611 	}
612 	else
613 		copyBits( rPosAry, pSrcGraphics );
614 }
615 void	SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
616 									const SalBitmap& rSalBitmap, const OutputDevice *pOutDev )
617 {
618 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
619 	{
620 		SalTwoRect aPosAry2 = rPosAry;
621 		mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
622 		drawBitmap( aPosAry2, rSalBitmap );
623 	}
624 	else
625 		drawBitmap( rPosAry, rSalBitmap );
626 }
627 void	SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
628 									const SalBitmap& rSalBitmap,
629 									SalColor nTransparentColor, const OutputDevice *pOutDev )
630 {
631 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
632 	{
633 		SalTwoRect aPosAry2 = rPosAry;
634 		mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
635 		drawBitmap( aPosAry2, rSalBitmap, nTransparentColor );
636 	}
637 	else
638 		drawBitmap( rPosAry, rSalBitmap, nTransparentColor );
639 }
640 void SalGraphics::DrawBitmap( const SalTwoRect& rPosAry,
641                               const SalBitmap& rSalBitmap,
642                               const SalBitmap& rTransparentBitmap, const OutputDevice *pOutDev )
643 {
644 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
645 	{
646 		SalTwoRect aPosAry2 = rPosAry;
647 		mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
648 		drawBitmap( aPosAry2, rSalBitmap, rTransparentBitmap );
649 	}
650 	else
651 		drawBitmap( rPosAry, rSalBitmap, rTransparentBitmap );
652 }
653 void	SalGraphics::DrawMask( const SalTwoRect& rPosAry,
654 								  const SalBitmap& rSalBitmap,
655 								  SalColor nMaskColor, const OutputDevice *pOutDev )
656 {
657 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
658 	{
659 		SalTwoRect aPosAry2 = rPosAry;
660 		mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
661 		drawMask( aPosAry2, rSalBitmap, nMaskColor );
662 	}
663 	else
664 		drawMask( rPosAry, rSalBitmap, nMaskColor );
665 }
666 SalBitmap*	SalGraphics::GetBitmap( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
667 {
668 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
669 		mirror( nX, nWidth, pOutDev );
670 	return getBitmap( nX, nY, nWidth, nHeight );
671 }
672 SalColor	SalGraphics::GetPixel( long nX, long nY, const OutputDevice *pOutDev )
673 {
674 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
675 		mirror( nX, pOutDev );
676 	return getPixel( nX, nY );
677 }
678 void	SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev )
679 {
680 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
681 		mirror( nX, nWidth, pOutDev );
682 	invert( nX, nY, nWidth, nHeight, nFlags );
683 }
684 void	SalGraphics::Invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nFlags, const OutputDevice *pOutDev )
685 {
686 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
687 	{
688 		SalPoint* pPtAry2 = new SalPoint[nPoints];
689 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
690 		invert( nPoints, bCopied ? pPtAry2 : pPtAry, nFlags );
691 		delete [] pPtAry2;
692 	}
693 	else
694 		invert( nPoints, pPtAry, nFlags );
695 }
696 
697 sal_Bool	SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize, const OutputDevice *pOutDev )
698 {
699 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
700 		mirror( nX, nWidth, pOutDev );
701 	return drawEPS( nX, nY, nWidth, nHeight,  pPtr, nSize );
702 }
703 
704 sal_Bool SalGraphics::HitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
705                                                 const Point& aPos, sal_Bool& rIsInside, const OutputDevice *pOutDev )
706 {
707 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
708     {
709         Point pt( aPos );
710         Rectangle rgn( rControlRegion );
711         mirror( pt.X(), pOutDev );
712         mirror( rgn, pOutDev );
713         return hitTestNativeControl( nType, nPart, rgn, pt, rIsInside );
714     }
715     else
716         return hitTestNativeControl( nType, nPart, rControlRegion, aPos, rIsInside );
717 }
718 
719 void SalGraphics::mirror( ControlType , const ImplControlValue& rVal, const OutputDevice* pOutDev, bool bBack ) const
720 {
721     switch( rVal.getType() )
722     {
723         case CTRL_SLIDER:
724         {
725             SliderValue* pSlVal = static_cast<SliderValue*>(const_cast<ImplControlValue*>(&rVal));
726             mirror(pSlVal->maThumbRect,pOutDev,bBack);
727         }
728         break;
729         case CTRL_SCROLLBAR:
730         {
731             ScrollbarValue* pScVal = static_cast<ScrollbarValue*>(const_cast<ImplControlValue*>(&rVal));
732             mirror(pScVal->maThumbRect,pOutDev,bBack);
733             mirror(pScVal->maButton1Rect,pOutDev,bBack);
734             mirror(pScVal->maButton2Rect,pOutDev,bBack);
735         }
736         break;
737         case CTRL_SPINBOX:
738         case CTRL_SPINBUTTONS:
739         {
740             SpinbuttonValue* pSpVal = static_cast<SpinbuttonValue*>(const_cast<ImplControlValue*>(&rVal));
741             mirror(pSpVal->maUpperRect,pOutDev,bBack);
742             mirror(pSpVal->maLowerRect,pOutDev,bBack);
743         }
744         break;
745         case CTRL_TOOLBAR:
746         {
747             ToolbarValue* pTVal = static_cast<ToolbarValue*>(const_cast<ImplControlValue*>(&rVal));
748             mirror(pTVal->maGripRect,pOutDev,bBack);
749         }
750         break;
751     }
752 }
753 
754 sal_Bool SalGraphics::DrawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
755                                                 ControlState nState, const ImplControlValue& aValue,
756                                                 const OUString& aCaption, const OutputDevice *pOutDev )
757 {
758 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
759     {
760         Rectangle rgn( rControlRegion );
761         mirror( rgn, pOutDev );
762         mirror( nType, aValue, pOutDev );
763         sal_Bool bRet = drawNativeControl( nType, nPart, rgn, nState, aValue, aCaption );
764         mirror( nType, aValue, pOutDev, true );
765         return bRet;
766     }
767     else
768         return drawNativeControl( nType, nPart, rControlRegion, nState, aValue, aCaption );
769 }
770 
771 sal_Bool SalGraphics::DrawNativeControlText( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
772                                                 ControlState nState, const ImplControlValue& aValue,
773                                                 const OUString& aCaption, const OutputDevice *pOutDev )
774 {
775 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
776     {
777         Rectangle rgn( rControlRegion );
778         mirror( rgn, pOutDev );
779         mirror( nType, aValue, pOutDev );
780         sal_Bool bRet = drawNativeControlText( nType, nPart, rgn, nState, aValue, aCaption );
781         mirror( nType, aValue, pOutDev, true );
782         return bRet;
783     }
784     else
785         return drawNativeControlText( nType, nPart, rControlRegion, nState, aValue, aCaption );
786 }
787 
788 sal_Bool SalGraphics::GetNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState nState,
789                                                 const ImplControlValue& aValue, const OUString& aCaption,
790                                                 Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion, const OutputDevice *pOutDev )
791 {
792 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
793     {
794         Rectangle rgn( rControlRegion );
795         mirror( rgn, pOutDev );
796         mirror( nType, aValue, pOutDev );
797         if( getNativeControlRegion( nType, nPart, rgn, nState, aValue, aCaption,
798                                                 rNativeBoundingRegion, rNativeContentRegion ) )
799         {
800             mirror( rNativeBoundingRegion, pOutDev, true );
801             mirror( rNativeContentRegion, pOutDev, true );
802             mirror( nType, aValue, pOutDev, true );
803             return sal_True;
804         }
805         else
806         {
807             mirror( nType, aValue, pOutDev, true );
808             return sal_False;
809         }
810     }
811     else
812         return getNativeControlRegion( nType, nPart, rControlRegion, nState, aValue, aCaption,
813                                                 rNativeBoundingRegion, rNativeContentRegion );
814 }
815 
816 bool SalGraphics::DrawAlphaBitmap( const SalTwoRect& rPosAry,
817                                    const SalBitmap& rSourceBitmap,
818                                    const SalBitmap& rAlphaBitmap,
819                                    const OutputDevice *pOutDev )
820 {
821 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
822 	{
823 		SalTwoRect aPosAry2 = rPosAry;
824 		mirror( aPosAry2.mnDestX, aPosAry2.mnDestWidth, pOutDev );
825 		return drawAlphaBitmap( aPosAry2, rSourceBitmap, rAlphaBitmap );
826 	}
827 	else
828 		return drawAlphaBitmap( rPosAry, rSourceBitmap, rAlphaBitmap );
829 }
830 
831 bool SalGraphics::DrawTransformedBitmap(
832     const basegfx::B2DPoint& rNull,
833     const basegfx::B2DPoint& rX,
834     const basegfx::B2DPoint& rY,
835     const SalBitmap& rSourceBitmap,
836     const SalBitmap* pAlphaBitmap,
837     const OutputDevice* pOutDev)
838 {
839     if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
840     {
841         basegfx::B2DPoint aNull(rNull);
842         basegfx::B2DPoint aX(rX);
843         basegfx::B2DPoint aY(rY);
844 
845         mirror(aNull, pOutDev);
846         mirror(aX, pOutDev);
847         mirror(aY, pOutDev);
848 
849         return drawTransformedBitmap(aNull, aX, aY, rSourceBitmap, pAlphaBitmap);
850     }
851     else
852     {
853         return drawTransformedBitmap(rNull, rX, rY, rSourceBitmap, pAlphaBitmap);
854     }
855 }
856 
857 bool SalGraphics::DrawAlphaRect( long nX, long nY, long nWidth, long nHeight,
858                                  sal_uInt8 nTransparency, const OutputDevice *pOutDev )
859 {
860 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
861 		mirror( nX, nWidth, pOutDev );
862 
863 	return drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency );
864 }
865 
866 bool SalGraphics::filterText( const String&, String&, xub_StrLen, xub_StrLen&, xub_StrLen&, xub_StrLen& )
867 {
868     return false;
869 }
870 
871 void SalGraphics::AddDevFontSubstitute( OutputDevice* pOutDev,
872                                         const String& rFontName,
873                                         const String& rReplaceFontName,
874                                         sal_uInt16 nFlags )
875 {
876     pOutDev->ImplAddDevFontSubstitute( rFontName, rReplaceFontName, nFlags );
877 }
878 
879