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