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