xref: /AOO41X/main/vcl/source/gdi/salgdilayout.cxx (revision b2937f997bda0a05141a2d862a64f7be893955b7)
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