xref: /trunk/main/vcl/source/gdi/salgdilayout.cxx (revision 79aad27f)
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     com::sun::star::drawing::LineCap /*eLineCap*/)
417 {
418     return false;
419 }
420 
421 void SalGraphics::DrawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
422 {
423 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
424 	{
425 		SalPoint* pPtAry2 = new SalPoint[nPoints];
426 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
427 		drawPolyLine( nPoints, bCopied ? pPtAry2 : pPtAry );
428 		delete [] pPtAry2;
429 	}
430 	else
431 		drawPolyLine( nPoints, pPtAry );
432 }
433 
434 void SalGraphics::DrawPolygon( sal_uLong nPoints, const SalPoint* pPtAry, const OutputDevice *pOutDev )
435 {
436 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
437 	{
438 		SalPoint* pPtAry2 = new SalPoint[nPoints];
439 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
440 		drawPolygon( nPoints, bCopied ? pPtAry2 : pPtAry );
441 		delete [] pPtAry2;
442 	}
443 	else
444 		drawPolygon( nPoints, pPtAry );
445 }
446 
447 void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry, const OutputDevice *pOutDev )
448 {
449 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
450 	{
451         // TODO: optimize, reduce new/delete calls
452         SalPoint **pPtAry2 = new SalPoint*[nPoly];
453         sal_uLong i;
454         for(i=0; i<nPoly; i++)
455         {
456             sal_uLong nPoints = pPoints[i];
457             pPtAry2[i] = new SalPoint[ nPoints ];
458 		    mirror( nPoints, pPtAry[i], pPtAry2[i], pOutDev );
459         }
460 
461         drawPolyPolygon( nPoly, pPoints, (PCONSTSALPOINT*)pPtAry2 );
462 
463         for(i=0; i<nPoly; i++)
464             delete [] pPtAry2[i];
465         delete [] pPtAry2;
466     }
467     else
468 	    drawPolyPolygon( nPoly, pPoints, pPtAry );
469 }
470 
471 bool SalGraphics::DrawPolyPolygon( const ::basegfx::B2DPolyPolygon& i_rPolyPolygon, double i_fTransparency, const OutputDevice* i_pOutDev )
472 {
473     bool bRet = false;
474 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
475 	{
476         basegfx::B2DPolyPolygon aMirror( mirror( i_rPolyPolygon, i_pOutDev ) );
477         bRet = drawPolyPolygon( aMirror, i_fTransparency );
478     }
479     else
480         bRet = drawPolyPolygon( i_rPolyPolygon, i_fTransparency );
481     return bRet;
482 }
483 
484 bool SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/)
485 {
486 	return false;
487 }
488 
489 sal_Bool SalGraphics::DrawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
490 {
491     sal_Bool bResult = sal_False;
492 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
493 	{
494 		SalPoint* pPtAry2 = new SalPoint[nPoints];
495 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
496 		bResult = drawPolyLineBezier( nPoints, bCopied ? pPtAry2 : pPtAry, pFlgAry );
497 		delete [] pPtAry2;
498 	}
499 	else
500         bResult = drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
501     return bResult;
502 }
503 
504 sal_Bool SalGraphics::DrawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
505 {
506     sal_Bool bResult = sal_False;
507 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
508 	{
509 		SalPoint* pPtAry2 = new SalPoint[nPoints];
510 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
511 		bResult = drawPolygonBezier( nPoints, bCopied ? pPtAry2 : pPtAry, pFlgAry );
512 		delete [] pPtAry2;
513 	}
514 	else
515         bResult = drawPolygonBezier( nPoints, pPtAry, pFlgAry );
516     return bResult;
517 }
518 
519 sal_Bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt32* i_pPoints,
520                                                    const SalPoint* const* i_pPtAry, const sal_uInt8* const* i_pFlgAry, const OutputDevice* i_pOutDev )
521 {
522     sal_Bool bRet = sal_False;
523 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
524 	{
525         // TODO: optimize, reduce new/delete calls
526         SalPoint **pPtAry2 = new SalPoint*[i_nPoly];
527         sal_uLong i;
528         for(i=0; i<i_nPoly; i++)
529         {
530             sal_uLong nPoints = i_pPoints[i];
531             pPtAry2[i] = new SalPoint[ nPoints ];
532 		    mirror( nPoints, i_pPtAry[i], pPtAry2[i], i_pOutDev );
533         }
534 
535         bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, (PCONSTSALPOINT*)pPtAry2, i_pFlgAry );
536 
537         for(i=0; i<i_nPoly; i++)
538             delete [] pPtAry2[i];
539         delete [] pPtAry2;
540     }
541     else
542 	    bRet = drawPolyPolygonBezier( i_nPoly, i_pPoints, i_pPtAry, i_pFlgAry );
543     return bRet;
544 }
545 
546 bool SalGraphics::DrawPolyLine(
547     const ::basegfx::B2DPolygon& i_rPolygon,
548     double i_fTransparency,
549     const ::basegfx::B2DVector& i_rLineWidth,
550     basegfx::B2DLineJoin i_eLineJoin,
551     com::sun::star::drawing::LineCap i_eLineCap,
552     const OutputDevice* i_pOutDev )
553 {
554     bool bRet = false;
555 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
556 	{
557         basegfx::B2DPolygon aMirror( mirror( i_rPolygon, i_pOutDev ) );
558         bRet = drawPolyLine( aMirror, i_fTransparency, i_rLineWidth, i_eLineJoin, i_eLineCap );
559     }
560     else
561         bRet = drawPolyLine( i_rPolygon, i_fTransparency, i_rLineWidth, i_eLineJoin, i_eLineCap );
562     return bRet;
563 }
564 
565 void	SalGraphics::CopyArea( long nDestX, long nDestY,
566                                long nSrcX, long nSrcY,
567                                long nSrcWidth, long nSrcHeight,
568                                sal_uInt16 nFlags, const OutputDevice *pOutDev )
569 {
570 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
571 	{
572 		mirror( nDestX, nSrcWidth, pOutDev );
573 		mirror( nSrcX, nSrcWidth, pOutDev );
574 	}
575 	copyArea( nDestX, nDestY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, nFlags );
576 }
577 void	SalGraphics::CopyBits( const SalTwoRect* pPosAry,
578                                SalGraphics* pSrcGraphics, const OutputDevice *pOutDev, const OutputDevice *pSrcOutDev )
579 {
580 	if( ( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) ) ||
581         (pSrcGraphics && ( (pSrcGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL)  || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) ) ) )
582 	{
583 		SalTwoRect pPosAry2 = *pPosAry;
584 		if( (pSrcGraphics && (pSrcGraphics->GetLayout() & SAL_LAYOUT_BIDI_RTL)) || (pSrcOutDev && pSrcOutDev->IsRTLEnabled()) )
585 			mirror( pPosAry2.mnSrcX, pPosAry2.mnSrcWidth, pSrcOutDev );
586 		if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
587 			mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
588 		copyBits( &pPosAry2, pSrcGraphics );
589 	}
590 	else
591 		copyBits( pPosAry, pSrcGraphics );
592 }
593 void	SalGraphics::DrawBitmap( const SalTwoRect* pPosAry,
594 									const SalBitmap& rSalBitmap, const OutputDevice *pOutDev )
595 {
596 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
597 	{
598 		SalTwoRect pPosAry2 = *pPosAry;
599 		mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
600 		drawBitmap( &pPosAry2, rSalBitmap );
601 	}
602 	else
603 		drawBitmap( pPosAry, rSalBitmap );
604 }
605 void	SalGraphics::DrawBitmap( const SalTwoRect* pPosAry,
606 									const SalBitmap& rSalBitmap,
607 									SalColor nTransparentColor, const OutputDevice *pOutDev )
608 {
609 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
610 	{
611 		SalTwoRect pPosAry2 = *pPosAry;
612 		mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
613 		drawBitmap( &pPosAry2, rSalBitmap, nTransparentColor );
614 	}
615 	else
616 		drawBitmap( pPosAry, rSalBitmap, nTransparentColor );
617 }
618 void SalGraphics::DrawBitmap( const SalTwoRect* pPosAry,
619                               const SalBitmap& rSalBitmap,
620                               const SalBitmap& rTransparentBitmap, const OutputDevice *pOutDev )
621 {
622 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
623 	{
624 		SalTwoRect pPosAry2 = *pPosAry;
625 		mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
626 		drawBitmap( &pPosAry2, rSalBitmap, rTransparentBitmap );
627 	}
628 	else
629 		drawBitmap( pPosAry, rSalBitmap, rTransparentBitmap );
630 }
631 void	SalGraphics::DrawMask( const SalTwoRect* pPosAry,
632 								  const SalBitmap& rSalBitmap,
633 								  SalColor nMaskColor, const OutputDevice *pOutDev )
634 {
635 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
636 	{
637 		SalTwoRect pPosAry2 = *pPosAry;
638 		mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
639 		drawMask( &pPosAry2, rSalBitmap, nMaskColor );
640 	}
641 	else
642 		drawMask( pPosAry, rSalBitmap, nMaskColor );
643 }
644 SalBitmap*	SalGraphics::GetBitmap( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
645 {
646 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
647 		mirror( nX, nWidth, pOutDev );
648 	return getBitmap( nX, nY, nWidth, nHeight );
649 }
650 SalColor	SalGraphics::GetPixel( long nX, long nY, const OutputDevice *pOutDev )
651 {
652 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
653 		mirror( nX, pOutDev );
654 	return getPixel( nX, nY );
655 }
656 void	SalGraphics::Invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags, const OutputDevice *pOutDev )
657 {
658 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
659 		mirror( nX, nWidth, pOutDev );
660 	invert( nX, nY, nWidth, nHeight, nFlags );
661 }
662 void	SalGraphics::Invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nFlags, const OutputDevice *pOutDev )
663 {
664 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
665 	{
666 		SalPoint* pPtAry2 = new SalPoint[nPoints];
667 		sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
668 		invert( nPoints, bCopied ? pPtAry2 : pPtAry, nFlags );
669 		delete [] pPtAry2;
670 	}
671 	else
672 		invert( nPoints, pPtAry, nFlags );
673 }
674 
675 sal_Bool	SalGraphics::DrawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize, const OutputDevice *pOutDev )
676 {
677 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
678 		mirror( nX, nWidth, pOutDev );
679 	return drawEPS( nX, nY, nWidth, nHeight,  pPtr, nSize );
680 }
681 
682 sal_Bool SalGraphics::HitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
683                                                 const Point& aPos, sal_Bool& rIsInside, const OutputDevice *pOutDev )
684 {
685 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
686     {
687         Point pt( aPos );
688         Rectangle rgn( rControlRegion );
689         mirror( pt.X(), pOutDev );
690         mirror( rgn, pOutDev );
691         return hitTestNativeControl( nType, nPart, rgn, pt, rIsInside );
692     }
693     else
694         return hitTestNativeControl( nType, nPart, rControlRegion, aPos, rIsInside );
695 }
696 
697 void SalGraphics::mirror( ControlType , const ImplControlValue& rVal, const OutputDevice* pOutDev, bool bBack ) const
698 {
699     switch( rVal.getType() )
700     {
701         case CTRL_SLIDER:
702         {
703             SliderValue* pSlVal = static_cast<SliderValue*>(const_cast<ImplControlValue*>(&rVal));
704             mirror(pSlVal->maThumbRect,pOutDev,bBack);
705         }
706         break;
707         case CTRL_SCROLLBAR:
708         {
709             ScrollbarValue* pScVal = static_cast<ScrollbarValue*>(const_cast<ImplControlValue*>(&rVal));
710             mirror(pScVal->maThumbRect,pOutDev,bBack);
711             mirror(pScVal->maButton1Rect,pOutDev,bBack);
712             mirror(pScVal->maButton2Rect,pOutDev,bBack);
713         }
714         break;
715         case CTRL_SPINBOX:
716         case CTRL_SPINBUTTONS:
717         {
718             SpinbuttonValue* pSpVal = static_cast<SpinbuttonValue*>(const_cast<ImplControlValue*>(&rVal));
719             mirror(pSpVal->maUpperRect,pOutDev,bBack);
720             mirror(pSpVal->maLowerRect,pOutDev,bBack);
721         }
722         break;
723         case CTRL_TOOLBAR:
724         {
725             ToolbarValue* pTVal = static_cast<ToolbarValue*>(const_cast<ImplControlValue*>(&rVal));
726             mirror(pTVal->maGripRect,pOutDev,bBack);
727         }
728         break;
729     }
730 }
731 
732 sal_Bool SalGraphics::DrawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
733                                                 ControlState nState, const ImplControlValue& aValue,
734                                                 const OUString& aCaption, const OutputDevice *pOutDev )
735 {
736 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
737     {
738         Rectangle rgn( rControlRegion );
739         mirror( rgn, pOutDev );
740         mirror( nType, aValue, pOutDev );
741         sal_Bool bRet = drawNativeControl( nType, nPart, rgn, nState, aValue, aCaption );
742         mirror( nType, aValue, pOutDev, true );
743         return bRet;
744     }
745     else
746         return drawNativeControl( nType, nPart, rControlRegion, nState, aValue, aCaption );
747 }
748 
749 sal_Bool SalGraphics::DrawNativeControlText( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion,
750                                                 ControlState nState, const ImplControlValue& aValue,
751                                                 const OUString& aCaption, const OutputDevice *pOutDev )
752 {
753 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
754     {
755         Rectangle rgn( rControlRegion );
756         mirror( rgn, pOutDev );
757         mirror( nType, aValue, pOutDev );
758         sal_Bool bRet = drawNativeControlText( nType, nPart, rgn, nState, aValue, aCaption );
759         mirror( nType, aValue, pOutDev, true );
760         return bRet;
761     }
762     else
763         return drawNativeControlText( nType, nPart, rControlRegion, nState, aValue, aCaption );
764 }
765 
766 sal_Bool SalGraphics::GetNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, ControlState nState,
767                                                 const ImplControlValue& aValue, const OUString& aCaption,
768                                                 Rectangle &rNativeBoundingRegion, Rectangle &rNativeContentRegion, const OutputDevice *pOutDev )
769 {
770 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
771     {
772         Rectangle rgn( rControlRegion );
773         mirror( rgn, pOutDev );
774         mirror( nType, aValue, pOutDev );
775         if( getNativeControlRegion( nType, nPart, rgn, nState, aValue, aCaption,
776                                                 rNativeBoundingRegion, rNativeContentRegion ) )
777         {
778             mirror( rNativeBoundingRegion, pOutDev, true );
779             mirror( rNativeContentRegion, pOutDev, true );
780             mirror( nType, aValue, pOutDev, true );
781             return sal_True;
782         }
783         else
784         {
785             mirror( nType, aValue, pOutDev, true );
786             return sal_False;
787         }
788     }
789     else
790         return getNativeControlRegion( nType, nPart, rControlRegion, nState, aValue, aCaption,
791                                                 rNativeBoundingRegion, rNativeContentRegion );
792 }
793 
794 bool SalGraphics::DrawAlphaBitmap( const SalTwoRect& rPosAry,
795                                    const SalBitmap& rSourceBitmap,
796                                    const SalBitmap& rAlphaBitmap,
797                                    const OutputDevice *pOutDev )
798 {
799 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
800 	{
801 		SalTwoRect pPosAry2 = rPosAry;
802 		mirror( pPosAry2.mnDestX, pPosAry2.mnDestWidth, pOutDev );
803 		return drawAlphaBitmap( pPosAry2, rSourceBitmap, rAlphaBitmap );
804 	}
805 	else
806 		return drawAlphaBitmap( rPosAry, rSourceBitmap, rAlphaBitmap );
807 }
808 
809 bool SalGraphics::DrawAlphaRect( long nX, long nY, long nWidth, long nHeight,
810                                  sal_uInt8 nTransparency, const OutputDevice *pOutDev )
811 {
812 	if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
813 		mirror( nX, nWidth, pOutDev );
814 
815 	return drawAlphaRect( nX, nY, nWidth, nHeight, nTransparency );
816 }
817 
818 bool SalGraphics::filterText( const String&, String&, xub_StrLen, xub_StrLen&, xub_StrLen&, xub_StrLen& )
819 {
820     return false;
821 }
822 
823 void SalGraphics::AddDevFontSubstitute( OutputDevice* pOutDev,
824                                         const String& rFontName,
825                                         const String& rReplaceFontName,
826                                         sal_uInt16 nFlags )
827 {
828     pOutDev->ImplAddDevFontSubstitute( rFontName, rReplaceFontName, nFlags );
829 }
830 
831