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