xref: /aoo42x/main/vcl/os2/source/gdi/salgdi.cxx (revision e6f63103)
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