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