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