xref: /AOO41X/main/vcl/os2/source/gdi/salgdi.cxx (revision 54ae6a3709853714848b4c639248f08787cf46a5)
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 #include <string.h>
25 #include <svpm.h>
26 
27 #define _SV_SALGDI_CXX
28 #include <tools/debug.hxx>
29 #include <os2/saldata.hxx>
30 #include <os2/salgdi.h>
31 #include <tools/debug.hxx>
32 #include <os2/salframe.h>
33 #include <tools/poly.hxx>
34 #ifndef _RTL_STRINGBUF_HXX
35 #include <rtl/strbuf.hxx>
36 #endif
37 
38 #ifndef __H_FT2LIB
39 #include <os2/wingdi.h>
40 #include <ft2lib.h>
41 #endif
42 
43 // -----------
44 // - Defines -
45 // -----------
46 
47 // ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern
48 #define SAL_PRINTER_CLIPPATH    1
49 // #define SAL_PRINTER_POLYPATH 1
50 
51 // =======================================================================
52 
ImplInitSalGDI()53 void ImplInitSalGDI()
54 {
55 }
56 
57 // -----------------------------------------------------------------------
58 
ImplFreeSalGDI()59 void ImplFreeSalGDI()
60 {
61     SalData*    pSalData = GetSalData();
62 
63     // delete icon cache
64     SalIcon* pIcon = pSalData->mpFirstIcon;
65     while( pIcon )
66     {
67         SalIcon* pTmp = pIcon->pNext;
68         WinDestroyPointer( pIcon->hIcon );
69         delete pIcon;
70         pIcon = pTmp;
71     }
72 
73 }
74 
75 // =======================================================================
76 
ImplSalInitGraphics(Os2SalGraphics * pData)77 void ImplSalInitGraphics( Os2SalGraphics* pData )
78 {
79     GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL );
80 }
81 
82 // -----------------------------------------------------------------------
83 
ImplSalDeInitGraphics(Os2SalGraphics * pData)84 void ImplSalDeInitGraphics( Os2SalGraphics* pData )
85 {
86 }
87 
88 // =======================================================================
89 
Os2SalGraphics()90 Os2SalGraphics::Os2SalGraphics()
91 {
92     for( int i = 0; i < MAX_FALLBACK; ++i )
93     {
94         mhFonts[ i ] = 0;
95         mpOs2FontData[ i ]  = NULL;
96         mpOs2FontEntry[ i ] = NULL;
97     }
98 
99     mfFontScale = 1.0;
100 
101     mhPS            = 0;
102     mhDC            = 0;
103     mbLine              = FALSE;
104     mbFill              = FALSE;
105     mbXORMode           = FALSE;
106     mnFontMetricCount   = 0;
107     mpFontMetrics       = NULL;
108     mpClipRectlAry      = NULL;
109 
110     mhDefFont           = 0;
111     mpFontKernPairs     = NULL;
112     mnFontKernPairCount = 0;
113     mbFontKernInit      = FALSE;
114 
115 }
116 
117 // -----------------------------------------------------------------------
118 
~Os2SalGraphics()119 Os2SalGraphics::~Os2SalGraphics()
120 {
121     Ft2DeleteSetId( mhPS, LCID_BASE);
122 
123     if ( mpFontMetrics )
124         delete mpFontMetrics;
125 
126     if ( mpFontKernPairs )
127         delete mpFontKernPairs;
128 
129 }
130 
131 // -----------------------------------------------------------------------
132 
ImplGetROPSalColor(SalROPColor nROPColor)133 static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
134 {
135     SalColor nSalColor;
136 
137     switch( nROPColor )
138     {
139         case SAL_ROP_0:
140             nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
141         break;
142 
143         case SAL_ROP_1:
144         case SAL_ROP_INVERT:
145             nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
146         break;
147     }
148 
149     return nSalColor;
150 }
151 
152 // -----------------------------------------------------------------------
153 
GetResolution(sal_Int32 & rDPIX,sal_Int32 & rDPIY)154 void Os2SalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
155 {
156     // since OOo asks for DPI, I will query FONT_RES, which seems to be
157     // more correct than _RESOLUTION fields (on my wide screen lcd)
158     // and does not require conversion
159     long nDPIX = 72, nDPIY = 72;
160     DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &nDPIX );
161     DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &nDPIY );
162     rDPIX = nDPIX;
163     rDPIY = nDPIY;
164 }
165 
166 // -----------------------------------------------------------------------
167 
GetBitCount()168 USHORT Os2SalGraphics::GetBitCount()
169 {
170     LONG nBitCount;
171     DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount );
172     return (USHORT)nBitCount;
173 }
174 
175 // -----------------------------------------------------------------------
176 
GetGraphicsWidth() const177 long Os2SalGraphics::GetGraphicsWidth() const
178 {
179     if( mhWnd )
180     {
181         Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd );
182         if( pFrame )
183         {
184             if( pFrame->maGeometry.nWidth )
185                 return pFrame->maGeometry.nWidth;
186             else
187             {
188                 // TODO: perhaps not needed, maGeometry should always be up-to-date
189                 RECTL aRect;
190                 WinQueryWindowRect( mhWnd, &aRect );
191                 return aRect.xRight;
192             }
193         }
194     }
195 
196     return 0;
197 }
198 
199 // -----------------------------------------------------------------------
200 
ResetClipRegion()201 void Os2SalGraphics::ResetClipRegion()
202 {
203 #ifdef SAL_PRINTER_CLIPPATH
204     if ( mbPrinter )
205         GpiSetClipPath( mhPS, 0, SCP_RESET );
206     else
207 #endif
208     {
209         HRGN hOldRegion;
210 
211         GpiSetClipRegion( mhPS, NULL, &hOldRegion );
212         if ( hOldRegion )
213             GpiDestroyRegion( mhPS, hOldRegion );
214     }
215 }
216 
217 // -----------------------------------------------------------------------
218 
setClipRegion(const Region & i_rClip)219 bool Os2SalGraphics::setClipRegion( const Region& i_rClip )
220 {
221     RectangleVector aRectangles;
222     i_rClip.GetRegionRectangles(aRectangles);
223     mnClipElementCount = aRectangles.size();
224     mpClipRectlAry = 0;
225 
226     if(mnClipElementCount)
227     {
228         mpClipRectlAry = new RECTL[mnClipElementCount];
229 
230         for(sal_uInt32 a(0); a < mnClipElementCount; a++)
231         {
232             const Rectangle& rRect = aRectangles[a];
233             RECTL* pClipRect = &mpClipRectlAry[a];
234 
235             pClipRect->xLeft = rRect.Left();
236             pClipRect->yTop = mnHeight - rRect.Top();
237             pClipRect->xRight = rRect.Right() + 1; // nX + nW -> L + ((R - L) + 1) -> R + 1
238             pClipRect->yBottom = mnHeight - (rRect.Bottom() + 1); // same for height
239         }
240     }
241 
242 //    ULONG nCount = i_rClip.GetRectCount();
243 //
244 //  mpClipRectlAry    = new RECTL[ nCount ];
245 //  mnClipElementCount = 0;
246 //
247 //    ImplRegionInfo aInfo;
248 //    long nX, nY, nW, nH;
249 //    bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
250 //    while( bRegionRect )
251 //    {
252 //        if ( nW && nH )
253 //        {
254 //            RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ];
255 //            pClipRect->xLeft   = nX;
256 //            pClipRect->yTop    = mnHeight - nY;
257 //            pClipRect->xRight  = nX + nW;
258 //            pClipRect->yBottom = mnHeight - (nY + nH);
259 //            mnClipElementCount++;
260 //        }
261 //        bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
262 //    }
263 #ifdef SAL_PRINTER_CLIPPATH
264     if ( mbPrinter )
265     {
266         GpiSetClipPath( mhPS, 0, SCP_RESET );
267         GpiBeginPath( mhPS, 1L );
268 
269         for( int i = 0; i < mnClipElementCount; i++ )
270         {
271             POINTL aPt;
272             RECTL* pClipRect = &mpClipRectlAry[ i ];
273 
274             aPt.x = pClipRect->xLeft;
275             aPt.y = pClipRect->yTop-1;
276             Ft2Move( mhPS, &aPt );
277 
278             aPt.x = pClipRect->xRight-1;
279             aPt.y = pClipRect->yBottom;
280 
281             Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
282         }
283 
284         GpiEndPath( mhPS );
285         GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND );
286     }
287     else
288 #endif
289     {
290         HRGN hClipRegion = GpiCreateRegion( mhPS,
291                                             mnClipElementCount,
292                                             mpClipRectlAry );
293         HRGN hOldRegion;
294 
295         GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion );
296         if( hOldRegion )
297             GpiDestroyRegion( mhPS, hOldRegion );
298     }
299 
300     delete [] mpClipRectlAry;
301 
302     return true;
303 }
304 
305 // -----------------------------------------------------------------------
306 
SetLineColor()307 void Os2SalGraphics::SetLineColor()
308 {
309     // don't draw line!
310     mbLine = FALSE;
311 }
312 
313 // -----------------------------------------------------------------------
314 
SetLineColor(SalColor nSalColor)315 void Os2SalGraphics::SetLineColor( SalColor nSalColor )
316 {
317     LINEBUNDLE lb;
318 
319     // set color
320     lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
321                           SALCOLOR_GREEN( nSalColor ),
322                           SALCOLOR_BLUE( nSalColor ) );
323 
324     Ft2SetAttrs( mhPS,
325                  PRIM_LINE,
326                  LBB_COLOR,
327                  0,
328                  &lb );
329 
330     // draw line!
331     mbLine = TRUE;
332 }
333 
334 // -----------------------------------------------------------------------
335 
SetFillColor()336 void Os2SalGraphics::SetFillColor()
337 {
338     // don't fill area!
339     mbFill = FALSE;
340 }
341 
342 // -----------------------------------------------------------------------
343 
SetFillColor(SalColor nSalColor)344 void Os2SalGraphics::SetFillColor( SalColor nSalColor )
345 {
346     AREABUNDLE ab;
347 
348     // set color
349     ab.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
350                           SALCOLOR_GREEN( nSalColor ),
351                           SALCOLOR_BLUE( nSalColor ) );
352 
353     Ft2SetAttrs( mhPS,
354                  PRIM_AREA,
355                  ABB_COLOR,
356                  0,
357                  &ab );
358 
359     // fill area!
360     mbFill = TRUE;
361 }
362 
363 // -----------------------------------------------------------------------
364 
SetXORMode(bool bSet,bool)365 void Os2SalGraphics::SetXORMode( bool bSet, bool )
366 {
367     mbXORMode = bSet;
368     LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT;
369 
370     // set mix mode for lines
371     LINEBUNDLE lb;
372     lb.usMixMode = nMixMode;
373     Ft2SetAttrs( mhPS,
374                  PRIM_LINE,
375                  LBB_MIX_MODE,
376                  0,
377                  &lb );
378 
379     // set mix mode for areas
380     AREABUNDLE ab;
381     ab.usMixMode = nMixMode;
382     Ft2SetAttrs( mhPS,
383                  PRIM_AREA,
384                  ABB_MIX_MODE,
385                  0,
386                  &ab );
387 
388     // set mix mode for text
389     CHARBUNDLE cb;
390     cb.usMixMode = nMixMode;
391     Ft2SetAttrs( mhPS,
392                  PRIM_CHAR,
393                  CBB_MIX_MODE,
394                  0,
395                  &cb );
396 }
397 
398 // -----------------------------------------------------------------------
399 
SetROPLineColor(SalROPColor nROPColor)400 void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor )
401 {
402     SetLineColor( ImplGetROPSalColor( nROPColor ) );
403 }
404 
405 // -----------------------------------------------------------------------
406 
SetROPFillColor(SalROPColor nROPColor)407 void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor )
408 {
409     SetFillColor( ImplGetROPSalColor( nROPColor ) );
410 }
411 
412 // -----------------------------------------------------------------------
413 
drawPixel(long nX,long nY)414 void Os2SalGraphics::drawPixel( long nX, long nY )
415 {
416     POINTL aPt;
417 
418     aPt.x = nX;
419     aPt.y = TY( nY );
420 
421     // set color
422     Ft2SetPel( mhPS, &aPt );
423 }
424 
425 // -----------------------------------------------------------------------
426 
drawPixel(long nX,long nY,SalColor nSalColor)427 void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
428 {
429     // save old color
430     LINEBUNDLE oldLb;
431     GpiQueryAttrs( mhPS,
432                    PRIM_LINE,
433                    LBB_COLOR,
434                    &oldLb );
435 
436     // set new color
437     LINEBUNDLE lb;
438     lb.lColor = MAKE_SALCOLOR( SALCOLOR_RED( nSalColor ),
439                           SALCOLOR_GREEN( nSalColor ),
440                           SALCOLOR_BLUE( nSalColor ) );
441     Ft2SetAttrs( mhPS,
442                  PRIM_LINE,
443                  LBB_COLOR,
444                  0,
445                  &lb );
446 
447     // set color of pixel
448     POINTL aPt;
449     aPt.x = nX;
450     aPt.y = TY( nY );
451     Ft2SetPel( mhPS, &aPt );
452 
453     // restore old color
454     Ft2SetAttrs( mhPS,
455                  PRIM_LINE,
456                  LBB_COLOR,
457                  0,
458                  &oldLb );
459 }
460 
461 // -----------------------------------------------------------------------
462 
drawLine(long nX1,long nY1,long nX2,long nY2)463 void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
464 {
465     // OS2 zeichnet den Endpunkt mit
466     POINTL aPt;
467     aPt.x = nX1;
468     aPt.y = TY( nY1 );
469     Ft2Move( mhPS, &aPt );
470     aPt.x = nX2;
471     aPt.y = TY( nY2 );
472     GpiLine( mhPS, &aPt );
473 }
474 
475 // -----------------------------------------------------------------------
476 
drawRect(long nX,long nY,long nWidth,long nHeight)477 void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
478 {
479     POINTL aPt;
480     long lControl;
481 
482     if ( mbFill )
483     {
484         if ( mbLine )
485             lControl = DRO_OUTLINEFILL;
486         else
487             lControl = DRO_FILL;
488     }
489     else
490     {
491         if ( mbLine )
492             lControl = DRO_OUTLINE;
493         else
494             return;
495     }
496 
497     aPt.x = nX;
498     aPt.y = TY( nY );
499     Ft2Move( mhPS, &aPt );
500     aPt.x = nX + nWidth - 1;
501     aPt.y = TY( nY + nHeight - 1 );
502     Ft2Box( mhPS, lControl, &aPt, 0, 0 );
503 }
504 
505 // -----------------------------------------------------------------------
506 
drawPolyLine(sal_uInt32 nPoints,const SalPoint * pPtAry)507 void Os2SalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
508 {
509     // convert all points to sys orientation
510     POINTL*             pOS2PtAry = new POINTL[ nPoints ];
511     POINTL*             pTempOS2PtAry = pOS2PtAry;
512     const SalPoint*     pTempPtAry = pPtAry;
513     sal_uInt32          nTempPoints = nPoints;
514     long                nHeight = mnHeight - 1;
515 
516     while( nTempPoints-- )
517     {
518         (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
519         (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
520         pTempOS2PtAry++;
521         pTempPtAry++;
522     }
523 
524     Ft2Move( mhPS, pOS2PtAry );
525     GpiPolyLine( mhPS, nPoints, pOS2PtAry );
526     delete [] pOS2PtAry;
527 }
528 
529 // -----------------------------------------------------------------------
530 
drawPolygon(sal_uInt32 nPoints,const SalPoint * pPtAry)531 void Os2SalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
532 {
533     PM_POLYGON aPolygon;
534 
535     // create polygon
536     aPolygon.aPointl = new POINTL[ nPoints ];
537     aPolygon.ulPoints = nPoints;
538 
539     // convert all points to sys orientation
540     POINTL*             pTempOS2PtAry = aPolygon.aPointl;
541     const SalPoint*     pTempPtAry = pPtAry;
542     sal_uInt32          nTempPoints = nPoints;
543     long                nHeight = mnHeight - 1;
544 
545     while( nTempPoints-- )
546     {
547         (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
548         (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
549         pTempOS2PtAry++;
550         pTempPtAry++;
551     }
552 
553     // Innenleben zeichnen
554     if ( mbFill )
555     {
556 #ifdef SAL_PRINTER_POLYPATH
557         if ( mbPrinter )
558         {
559             Ft2BeginPath( mhPS, 1 );
560             Ft2Move( mhPS, aPolygon.aPointl );
561             Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
562             Ft2EndPath( mhPS );
563             Ft2FillPath( mhPS, 1, 0 );
564 
565             if ( mbLine )
566             {
567                 Ft2Move( mhPS, aPolygon.aPointl );
568                 Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl );
569             }
570         }
571         else
572 #endif
573         {
574             ULONG nOptions = POLYGON_ALTERNATE;
575 
576             if ( mbLine )
577                 nOptions |= POLYGON_BOUNDARY;
578             else
579                 nOptions |= POLYGON_NOBOUNDARY;
580 
581             Ft2Move( mhPS, aPolygon.aPointl );
582             GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL );
583         }
584     }
585     else
586     {
587         if ( mbLine )
588         {
589             Ft2Move( mhPS, aPolygon.aPointl );
590             GpiPolyLine( mhPS, nPoints, aPolygon.aPointl );
591         }
592     }
593 
594     delete [] aPolygon.aPointl;
595 }
596 
597 // -----------------------------------------------------------------------
598 
drawPolyPolygon(sal_uInt32 nPoly,const sal_uInt32 * pPoints,PCONSTSALPOINT * pPtAry)599 void Os2SalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
600                                    PCONSTSALPOINT* pPtAry )
601 {
602     ULONG       i;
603     long        nHeight = mnHeight - 1;
604     PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ];
605 
606     for( i = 0; i < nPoly; i++ )
607     {
608         const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ];
609 
610         // create polygon
611         ULONG nTempPoints = pPoints[ i ];
612         POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ];
613 
614         // convert all points to sys orientation
615         aPolygonAry[ i ].ulPoints = nTempPoints;
616         aPolygonAry[ i ].aPointl = pTempOS2PtAry;
617 
618         while( nTempPoints-- )
619         {
620             (*pTempOS2PtAry).x = (*pTempPtAry).mnX;
621             (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY;
622             pTempOS2PtAry++;
623             pTempPtAry++;
624         }
625     }
626 
627     // Innenleben zeichnen
628     if ( mbFill )
629     {
630 #ifdef SAL_PRINTER_POLYPATH
631         if ( mbPrinter )
632         {
633             Ft2BeginPath( mhPS, 1 );
634             for ( i = 0; i < nPoly; i++ )
635             {
636                 Ft2Move( mhPS, aPolygonAry[i].aPointl );
637                 Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl );
638             }
639             Ft2EndPath( mhPS );
640             Ft2FillPath( mhPS, 1, 0 );
641         }
642         else
643 #endif
644         {
645             ULONG nOptions = POLYGON_ALTERNATE;
646 
647             if ( mbLine )
648                 nOptions |= POLYGON_BOUNDARY;
649             else
650                 nOptions |= POLYGON_NOBOUNDARY;
651 
652             Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl );
653             GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL );
654         }
655     }
656     else
657     {
658         if ( mbLine )
659         {
660             for( i = 0; i < nPoly; i++ )
661             {
662                 Ft2Move( mhPS, aPolygonAry[ i ].aPointl );
663                 GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl );
664             }
665         }
666     }
667 
668     // cleanup
669     for( i = 0; i < nPoly; i++ )
670         delete [] aPolygonAry[ i ].aPointl;
671     delete [] aPolygonAry;
672 }
673 
674 // -----------------------------------------------------------------------
675 
drawPolyPolygon(const::basegfx::B2DPolyPolygon &,double)676 bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
677 {
678     // TODO: implement and advertise OutDevSupport_B2DDraw support
679     return false;
680 }
681 
682 // -----------------------------------------------------------------------
683 
drawPolyLine(const basegfx::B2DPolygon &,double,const basegfx::B2DVector &,basegfx::B2DLineJoin,com::sun::star::drawing::LineCap)684 bool Os2SalGraphics::drawPolyLine(
685     const basegfx::B2DPolygon& /*rPolygon*/,
686     double /*fTransparency*/,
687     const basegfx::B2DVector& /*rLineWidths*/,
688     basegfx::B2DLineJoin /*eLineJoin*/,
689     com::sun::star::drawing::LineCap /*eLineCap*/)
690 {
691     // TODO: implement
692     return false;
693 }
694 
695 // -----------------------------------------------------------------------
696 
drawPolyLineBezier(sal_uInt32,const SalPoint * pPtAry,const sal_uInt8 * pFlgAry)697 sal_Bool Os2SalGraphics::drawPolyLineBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
698 {
699     return sal_False;
700 }
701 
702 // -----------------------------------------------------------------------
703 
drawPolygonBezier(sal_uInt32,const SalPoint * pPtAry,const sal_uInt8 * pFlgAry)704 sal_Bool Os2SalGraphics::drawPolygonBezier( sal_uInt32 /*nPoints*/, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
705 {
706     return sal_False;
707 }
708 
709 // -----------------------------------------------------------------------
710 
drawPolyPolygonBezier(sal_uInt32,const sal_uInt32 *,const SalPoint * const * pPtAry,const sal_uInt8 * const * pFlgAry)711 sal_Bool Os2SalGraphics::drawPolyPolygonBezier( sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/,
712                                              const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry )
713 {
714     return sal_False;
715 }
716 
717 // =======================================================================
718 
719 // MAXIMUM BUFSIZE EQ 0xFFFF
720 #define POSTSCRIPT_BUFSIZE          0x4000
721 // we only try to get the BoundingBox in the first 4096 PM_BYTEs
722 #define POSTSCRIPT_BOUNDINGSEARCH   0x1000
723 
ImplSearchEntry(PM_BYTE * pSource,PM_BYTE * pDest,ULONG nComp,ULONG nSize)724 static PM_BYTE* ImplSearchEntry( PM_BYTE* pSource, PM_BYTE* pDest, ULONG nComp, ULONG nSize )
725 {
726     while ( nComp-- >= nSize )
727     {
728         ULONG   i;
729         for ( i = 0; i < nSize; i++ )
730         {
731             if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
732                 break;
733         }
734         if ( i == nSize )
735             return pSource;
736         pSource++;
737     }
738     return NULL;
739 }
740 
741 
ImplGetBoundingBox(double * nNumb,PM_BYTE * pSource,ULONG nSize)742 static PM_BOOL ImplGetBoundingBox( double* nNumb, PM_BYTE* pSource, ULONG nSize )
743 {
744     PM_BOOL bRetValue = FALSE;
745     PM_BYTE* pDest = ImplSearchEntry( pSource, (PM_BYTE*)"%%BoundingBox:", nSize, 14 );
746     if ( pDest )
747     {
748         nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
749         pDest += 14;
750 
751         int nSizeLeft = nSize - ( pDest - pSource );
752         if ( nSizeLeft > 100 )
753             nSizeLeft = 100;    // only 100 PM_BYTEs following the bounding box will be checked
754 
755         int i;
756         for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
757         {
758             int     nDivision = 1;
759             PM_BOOL bDivision = FALSE;
760             PM_BOOL bNegative = FALSE;
761             PM_BOOL bValid = TRUE;
762 
763             while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
764             PM_BYTE nPM_BYTE = *pDest;
765             while ( nSizeLeft && ( nPM_BYTE != ' ' ) && ( nPM_BYTE != 0x9 ) && ( nPM_BYTE != 0xd ) && ( nPM_BYTE != 0xa ) )
766             {
767                 switch ( nPM_BYTE )
768                 {
769                     case '.' :
770                         if ( bDivision )
771                             bValid = FALSE;
772                         else
773                             bDivision = TRUE;
774                         break;
775                     case '-' :
776                         bNegative = TRUE;
777                         break;
778                     default :
779                         if ( ( nPM_BYTE < '0' ) || ( nPM_BYTE > '9' ) )
780                             nSizeLeft = 1;  // error parsing the bounding box values
781                         else if ( bValid )
782                         {
783                             if ( bDivision )
784                                 nDivision*=10;
785                             nNumb[i] *= 10;
786                             nNumb[i] += nPM_BYTE - '0';
787                         }
788                         break;
789                 }
790                 nSizeLeft--;
791                 nPM_BYTE = *(++pDest);
792             }
793             if ( bNegative )
794                 nNumb[i] = -nNumb[i];
795             if ( bDivision && ( nDivision != 1 ) )
796                 nNumb[i] /= nDivision;
797         }
798         if ( i == 4 )
799             bRetValue = TRUE;
800     }
801     return bRetValue;
802 }
803 
804 #if 0
805 static void ImplWriteDouble( PM_BYTE** pBuf, double nNumber )
806 {
807 //  *pBuf += sprintf( (char*)*pBuf, "%f", nNumber );
808 
809     if ( nNumber < 0 )
810     {
811         *(*pBuf)++ = (PM_BYTE)'-';
812         nNumber = -nNumber;
813     }
814     ULONG nTemp = (ULONG)nNumber;
815     const String aNumber1( nTemp );
816     ULONG nLen = aNumber1.Len();
817 
818     for ( USHORT n = 0; n < nLen; n++ )
819         *(*pBuf)++ = aNumber1[ n ];
820 
821     nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 );
822     if ( nTemp )
823     {
824         *(*pBuf)++ = (PM_BYTE)'.';
825         const String aNumber2( nTemp );
826 
827         ULONG nLen = aNumber2.Len();
828         if ( nLen < 8 )
829         {
830             for ( n = 0; n < ( 5 - nLen ); n++ )
831             {
832                 *(*pBuf)++ = (PM_BYTE)'0';
833             }
834         }
835         for ( USHORT n = 0; n < nLen; n++ )
836         {
837             *(*pBuf)++ = aNumber2[ n ];
838         }
839     }
840     *(*pBuf)++ = ' ';
841 }
842 #endif
843 
ImplWriteString(PM_BYTE ** pBuf,const char * sString)844 inline void ImplWriteString( PM_BYTE** pBuf, const char* sString )
845 {
846     strcpy( (char*)*pBuf, sString );
847     *pBuf += strlen( sString );
848 }
849 
drawEPS(long nX,long nY,long nWidth,long nHeight,void * pPtr,ULONG nSize)850 sal_Bool Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize )
851 {
852     if ( !mbPrinter )
853         return FALSE;
854 
855     PM_BOOL bRet  = FALSE;
856     LONG    nLong = 0;
857     if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) &&
858            (CAPS_TECH_POSTSCRIPT == nLong)) )
859         return FALSE;
860 
861     PM_BYTE*    pBuf = new PM_BYTE[ POSTSCRIPT_BUFSIZE ];
862     double  nBoundingBox[4];
863 
864     if ( pBuf && ImplGetBoundingBox( nBoundingBox, (PM_BYTE*)pPtr, nSize ) )
865     {
866         LONG pOS2DXAry[4];        // hack -> print always 2 white space
867         POINTL aPt;
868         aPt.x = 0;
869         aPt.y = 0;
870         PCH pStr = (PCH) "  ";
871         for( long i = 0; i < 4; i++ )
872             pOS2DXAry[i] = i;
873         Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] );
874 
875         OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
876 
877                 // reserve place for a USHORT
878                 aBuf.append( "aa" );
879 
880                 // #107797# Write out EPS encapsulation header
881                 // ----------------------------------------------------------------------------------
882 
883                 // directly taken from the PLRM 3.0, p. 726. Note:
884                 // this will definitely cause problems when
885                 // recursively creating and embedding PostScript files
886                 // in OOo, since we use statically-named variables
887                 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
888                 // op_count_salWin). Currently, I have no idea on how to
889                 // work around that, except from scanning and
890                 // interpreting the EPS for unused identifiers.
891 
892                 // append the real text
893                 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
894                              "/dict_count_salWin countdictstack def\n"
895                              "/op_count_salWin count 1 sub def\n"
896                              "userdict begin\n"
897                              "/showpage {} def\n"
898                              "0 setgray 0 setlinecap\n"
899                              "1 setlinewidth 0 setlinejoin\n"
900                              "10 setmiterlimit [] 0 setdash newpath\n"
901                              "/languagelevel where\n"
902                              "{\n"
903                              "  pop languagelevel\n"
904                              "  1 ne\n"
905                              "  {\n"
906                              "    false setstrokeadjust false setoverprint\n"
907                              "  } if\n"
908                              "} if\n\n" );
909 
910 #if 0
911                 // #i10737# Apply clipping manually
912                 // ----------------------------------------------------------------------------------
913 
914                 // Windows seems to ignore any clipping at the HDC,
915                 // when followed by a POSTSCRIPT_PASSTHROUGH
916 
917                 // Check whether we've got a clipping, consisting of
918                 // exactly one rect (other cases should be, but aren't
919                 // handled currently)
920 
921                 // TODO: Handle more than one rectangle here (take
922                 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
923                 // characters!)
924                 if ( mhRegion != 0 &&
925                      mpStdClipRgnData != NULL &&
926                      mpClipRgnData == mpStdClipRgnData &&
927                      mpClipRgnData->rdh.nCount == 1 )
928                 {
929                     RECT* pRect = &(mpClipRgnData->rdh.rcBound);
930 
931                     aBuf.append( "\nnewpath\n" );
932                     aBuf.append( pRect->left );
933                     aBuf.append( " " );
934                     aBuf.append( pRect->top );
935                     aBuf.append( " moveto\n" );
936                     aBuf.append( pRect->right );
937                     aBuf.append( " " );
938                     aBuf.append( pRect->top );
939                     aBuf.append( " lineto\n" );
940                     aBuf.append( pRect->right );
941                     aBuf.append( " " );
942                     aBuf.append( pRect->bottom );
943                     aBuf.append( " lineto\n" );
944                     aBuf.append( pRect->left );
945                     aBuf.append( " " );
946                     aBuf.append( pRect->bottom );
947                     aBuf.append( " lineto\n"
948                                  "closepath\n"
949                                  "clip\n"
950                                  "newpath\n" );
951                 }
952 #endif
953 
954                 // #107797# Write out buffer
955                 // ----------------------------------------------------------------------------------
956                 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
957                 //Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
958                 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
959                         (PM_BYTE*)aBuf.getStr(), 0, NULL );
960 
961         double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
962         double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) );
963 
964                 // reserve a USHORT again
965                 aBuf.setLength( 2 );
966                 aBuf.append( "\n\n[" );
967                 aBuf.append( dM11 );
968                 aBuf.append( " 0 0 " );
969                 aBuf.append( dM22 );
970                 aBuf.append( ' ' );
971                 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
972                 aBuf.append( ' ' );
973                 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
974                 aBuf.append( "] concat\n"
975                              "%%BeginDocument:\n" );
976                 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
977                 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
978                         (PM_BYTE*)aBuf.getStr(), 0, NULL );
979 #if 0
980         PM_BYTE* pTemp = pBuf;
981         ImplWriteString( &pTemp, "save\n[ " );
982         ImplWriteDouble( &pTemp, dM11 );
983         ImplWriteDouble( &pTemp, 0 );
984         ImplWriteDouble( &pTemp, 0 );
985         ImplWriteDouble( &pTemp, dM22 );
986         ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) );
987         ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) );
988         ImplWriteString( &pTemp, "] concat /showpage {} def\n" );
989 
990         if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf,
991             (PM_BYTE*)pBuf, 0, NULL ) == DEV_OK )
992 #endif //
993         {
994             sal_uInt32 nToDo = nSize;
995             sal_uInt32 nDoNow;
996             bRet = TRUE;
997             while( nToDo && bRet )
998             {
999                 nDoNow = 0x4000;
1000                 if ( nToDo < nDoNow )
1001                     nDoNow = nToDo;
1002 
1003                 if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PM_BYTE*)pPtr + nSize - nToDo,
1004                    0, NULL ) == -1 )
1005                     bRet = FALSE;
1006                 nToDo -= nDoNow;
1007             }
1008 
1009             if ( bRet )
1010             {
1011                 strcpy ( (char*)pBuf, "\nrestore\n" );
1012                 if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PM_BYTE*)pBuf,
1013                     0, NULL ) == DEV_OK ) bRet = TRUE;
1014             }
1015 
1016                 // #107797# Write out EPS encapsulation footer
1017                 // ----------------------------------------------------------------------------------
1018                 // reserve a USHORT again
1019                 aBuf.setLength( 2 );
1020                 aBuf.append( "%%EndDocument\n"
1021                              "count op_count_salWin sub {pop} repeat\n"
1022                              "countdictstack dict_count_salWin sub {end} repeat\n"
1023                              "b4_Inc_state_salWin restore\n\n" );
1024                 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 );
1025                 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(),
1026                         (PM_BYTE*)aBuf.getStr(), 0, NULL );
1027                 bRet = TRUE;
1028 
1029         }
1030     }
1031     delete [] pBuf;
1032     return bRet;
1033 }
1034 
1035 /*
1036  * IsNativeControlSupported()
1037  *
1038  *  Returns TRUE if the platform supports native
1039  *  drawing of the control defined by nPart
1040  */
IsNativeControlSupported(ControlType nType,ControlPart nPart)1041 sal_Bool Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart )
1042 {
1043     return( FALSE );
1044 }
1045 
1046 // -----------------------------------------------------------------------
1047 
GetGraphicsData() const1048 SystemGraphicsData Os2SalGraphics::GetGraphicsData() const
1049 {
1050     SystemGraphicsData aRes;
1051     aRes.nSize = sizeof(aRes);
1052 #if 0
1053     aRes.hDC = mhDC;
1054 #endif
1055     return aRes;
1056 }
1057 
1058 // -----------------------------------------------------------------------
1059