1 #   include	"drawMetaConfig.h"
2 
3 #   include	<stddef.h>
4 #   include	<stdlib.h>
5 #   include	<string.h>
6 #   include	<math.h>
7 
8 #   include	"drawWinMetaImpl.h"
9 #   include	<sioEndian.h>
10 #   include	<psDocumentFontStyle.h>
11 #   include	<geoUnits.h>
12 #   include	<bmio.h>
13 #   include	<bmWmfIo.h>
14 #   include	<textConverter.h>
15 
16 #   include	<appDebugon.h>
17 
18 # if 0
19 #    define	WMFDEB(x)	(x)
20 # else
21 #    define	WMFDEB(x)	/*nothing*/
22 # endif
23 
appCleanPatternBrush(PatternBrush * pb)24 static void appCleanPatternBrush(	PatternBrush *	pb )
25     {
26     if  ( pb->pbAbi )
27 	{
28 	bmCleanRasterImage( pb->pbAbi );
29 	free( pb->pbAbi );
30 	pb->pbAbi= (RasterImage *)0;
31 	}
32     }
33 
34 /************************************************************************/
35 /*									*/
36 /*  Calculate the device to output transform based on the map mode.	*/
37 /*									*/
38 /************************************************************************/
39 
appWinMetaRefreshTransform(DeviceContext * dc)40 static void appWinMetaRefreshTransform(	DeviceContext *		dc )
41     {
42     DeviceCoordinateTransform *	t= &(dc->dcTransform);
43     AffineTransform2D		logicalToDevice;
44     int				twipsWide;
45     int				twipsHigh;
46     double			high;
47     double			wide;
48 
49     twipsWide= dc->dcTwipsRect.drX1- dc->dcTwipsRect.drX0+ 1;
50     twipsHigh= dc->dcTwipsRect.drY1- dc->dcTwipsRect.drY0+ 1;
51 
52     switch( dc->dcMapMode )
53 	{
54 	case MM_TEXT:
55 	    /* Unit pixel, Y Down */
56 	    LDEB(dc->dcMapMode); return;
57 
58 	case MM_LOMETRIC:
59 	    /* Unit 0.1mm, Y Up */
60 	    wide= ( 10000.0* twipsWide )/ TWIPS_PER_M;
61 	    high= ( 10000.0* twipsHigh )/ TWIPS_PER_M;
62 	    t->dctDeviceRect.drX0= 0;
63 	    t->dctDeviceRect.drY0= 0;
64 	    t->dctDeviceRect.drX1= t->dctDeviceRect.drX0+ wide- 1;
65 	    t->dctDeviceRect.drY1= t->dctDeviceRect.drY0+ high- 1;
66 	    t->dctLogicalRect.drX1= t->dctLogicalRect.drX0+ wide- 1;
67 	    t->dctLogicalRect.drY1= t->dctLogicalRect.drY0+ high- 1;
68 	    break;
69 
70 	case MM_HIMETRIC:
71 	    /* Unit 0.01mm, Y Up */
72 	    wide= ( 100000.0* twipsWide )/ TWIPS_PER_M;
73 	    high= ( 100000.0* twipsHigh )/ TWIPS_PER_M;
74 	    t->dctDeviceRect.drX0= 0;
75 	    t->dctDeviceRect.drY0= 0;
76 	    t->dctDeviceRect.drX1= t->dctDeviceRect.drX0+ wide- 1;
77 	    t->dctDeviceRect.drY1= t->dctDeviceRect.drY0+ high- 1;
78 	    t->dctLogicalRect.drX1= t->dctLogicalRect.drX0+ wide- 1;
79 	    t->dctLogicalRect.drY1= t->dctLogicalRect.drY0+ high- 1;
80 	    break;
81 
82 	case MM_LOENGLISH:
83 	    /* Unit 0.01inch, Y Up */
84 	    wide= ( 100000.0* twipsWide )/ ( 20* 72 );
85 	    high= ( 100000.0* twipsHigh )/ ( 20* 72 );
86 	    t->dctDeviceRect.drX0= 0;
87 	    t->dctDeviceRect.drY0= 0;
88 	    t->dctDeviceRect.drX1= t->dctDeviceRect.drX0+ wide- 1;
89 	    t->dctDeviceRect.drY1= t->dctDeviceRect.drY0+ high- 1;
90 	    t->dctLogicalRect.drX1= t->dctLogicalRect.drX0+ wide- 1;
91 	    t->dctLogicalRect.drY1= t->dctLogicalRect.drY0+ high- 1;
92 	    break;
93 
94 	case MM_HIENGLISH:
95 	    /* Unit 0.001inch, Y Up */
96 	    wide= ( 1000000.0* twipsWide )/ ( 20* 72 );
97 	    high= ( 1000000.0* twipsHigh )/ ( 20* 72 );
98 	    t->dctDeviceRect.drX0= 0;
99 	    t->dctDeviceRect.drY0= 0;
100 	    t->dctDeviceRect.drX1= t->dctDeviceRect.drX0+ wide- 1;
101 	    t->dctDeviceRect.drY1= t->dctDeviceRect.drY0+ high- 1;
102 	    t->dctLogicalRect.drX1= t->dctLogicalRect.drX0+ wide- 1;
103 	    t->dctLogicalRect.drY1= t->dctLogicalRect.drY0+ high- 1;
104 	    break;
105 
106 	case MM_TWIPS:
107 	    /* Unit twips, Y Up */
108 	    t->dctDeviceRect.drX0= 0;
109 	    t->dctDeviceRect.drY0= 0;
110 	    t->dctDeviceRect.drX1= t->dctDeviceRect.drX0+ twipsWide- 1;
111 	    t->dctDeviceRect.drY1= t->dctDeviceRect.drY0+ twipsHigh- 1;
112 	    t->dctLogicalRect.drX1= t->dctLogicalRect.drX0+ twipsWide- 1;
113 	    t->dctLogicalRect.drY1= t->dctLogicalRect.drY0+ twipsHigh- 1;
114 	    break;
115 
116 	case MM_ISOTROPIC:
117 	case MM_ANISOTROPIC:
118 	    break;
119 
120 	default:
121 	    LDEB(dc->dcMapMode); return;
122 	}
123 
124     if  ( geoAffineTransformForTriangles( &logicalToDevice,
125 	    t->dctLogicalRect.drX0,	t->dctLogicalRect.drY0,
126 	    t->dctLogicalRect.drX1,	t->dctLogicalRect.drY0,
127 	    t->dctLogicalRect.drX0,	t->dctLogicalRect.drY1,
128 
129 	    t->dctDeviceRect.drX0,	t->dctDeviceRect.drY0,
130 	    t->dctDeviceRect.drX1,	t->dctDeviceRect.drY0,
131 	    t->dctDeviceRect.drX0,	t->dctDeviceRect.drY1 ) )
132 	{ LDEB(1);	}
133 
134     if  ( geoAffineTransformForTriangles( &(t->dctDeviceToOutput),
135 	    t->dctDeviceRect.drX0,	t->dctDeviceRect.drY0,
136 	    t->dctDeviceRect.drX1,	t->dctDeviceRect.drY0,
137 	    t->dctDeviceRect.drX0,	t->dctDeviceRect.drY1,
138 
139 	    dc->dcOutputRect.drX0,	dc->dcOutputRect.drY0,
140 	    dc->dcOutputRect.drX1,	dc->dcOutputRect.drY0,
141 	    dc->dcOutputRect.drX0,	dc->dcOutputRect.drY1 ) )
142 	{ LDEB(1);	}
143 
144     geoAffineTransform2DProduct( &(dc->dcTransform.dctLogicalToOutput),
145 					&(dc->dcTransform.dctDeviceToOutput),
146 					&logicalToDevice );
147     }
148 
appMetaInitDeviceContext(DeviceContext * dc,const MetafilePlayer * player,int objectCount,const DocumentRectangle * drLogical,int mapMode,int outputWide,int outputHigh,int twipsWide,int twipsHigh)149 int appMetaInitDeviceContext(	DeviceContext *			dc,
150 				const MetafilePlayer *		player,
151 				int				objectCount,
152 				const DocumentRectangle *	drLogical,
153 				int				mapMode,
154 				int				outputWide,
155 				int				outputHigh,
156 				int				twipsWide,
157 				int				twipsHigh )
158     {
159     dc->dcDrawBorders= 1;
160     dc->dcFillInsides= 1;
161 
162     dc->dcFillHatched= 0;
163     dc->dcFillPattern= 0;
164 
165     docInitFontList( &(dc->dcFontList) );
166     dc->dcPlayer= player;
167     textInitTextConverter( &(dc->dcTextConverter) );
168     utilInitMemoryBuffer( &(dc->dcCollectedText) );
169 
170     dc->dcPen.lpStyle= PS_SOLID;
171     dc->dcPen.lpWidth= 1;
172     utilRGB8SolidBlack( &(dc->dcPen.lpColor) );
173 
174     dc->dcBrush.lbStyle= BS_SOLID;
175     utilRGB8SolidWhite( &(dc->dcBrush.lbColor) );
176 
177     utilRGB8SolidWhite( &(dc->dcBkColor) );
178     utilRGB8SolidBlack( &(dc->dcTextColor) );
179 
180     utilRGB8SolidBlack( &(dc->dcMacPictForeColor) );
181     utilRGB8SolidWhite( &(dc->dcMacPictBackColor) );
182 
183     utilRGB8SolidBlack( &(dc->dcMacPictPenSolid) );
184     utilRGB8SolidBlack( &(dc->dcMacPictFillSolid) );
185     utilRGB8SolidWhite( &(dc->dcMacPictBackSolid) );
186 
187     dc->dcCurrentBrushObject= -1;
188 
189     dc->dcMacPictPenIsSolid= 1;
190     dc->dcMacPictFillIsSolid= 1;
191     dc->dcMacPictBackIsSolid= 1;
192 
193     memset( dc->dcMacPictPenPattern, 0xff, 8 );
194     memset( dc->dcMacPictFillPattern, 0xff, 8 );
195     memset( dc->dcMacPictBackPattern, 0xff, 8 );
196 
197     dc->dcBkMode= TRANSPARENT;
198     dc->dcPolyFillMode= WINDING;
199 
200     dc->dcExtraTextSpacing= 0;
201     dc->dcJustificationAmount= 0;
202     dc->dcJustificationSpaces= 0;
203     dc->dcTextAlignment= TA_LEFT|TA_TOP;
204 
205     dc->dcTwipsRect.drX0= 0;
206     dc->dcTwipsRect.drY0= 0;
207     dc->dcTwipsRect.drX1= twipsWide- 1;
208     dc->dcTwipsRect.drY1= twipsHigh- 1;
209 
210     dc->dcOutputRect.drX0= 0;
211     dc->dcOutputRect.drY0= 0;
212     dc->dcOutputRect.drX1= outputWide- 1;
213     dc->dcOutputRect.drY1= outputHigh- 1;
214 
215     dc->dcTransform.dctLogicalRect= *drLogical;
216     /* A good initial guess: */
217     dc->dcTransform.dctDeviceRect= *drLogical;
218 
219     dc->dcMapMode= mapMode;
220     appWinMetaRefreshTransform( dc );
221     appWinMetaUpdateTransform( dc );
222 
223     dc->dcFont.lfHeight= 0;
224     dc->dcFont.lfWidth= 0;
225     dc->dcFont.lfEscapement= 0;
226     dc->dcFont.lfOrientation= 0;
227     dc->dcFont.lfWeight= 0;
228     dc->dcFont.lfItalic= 0;
229     dc->dcFont.lfUnderline= 0;
230     dc->dcFont.lfStrikeOut= 0;
231     dc->dcFont.lfCharSet= 0;
232     dc->dcFont.lfOutPrecision= 0;
233     dc->dcFont.lfClipPrecision= 0;
234     dc->dcFont.lfQuality= 0;
235     dc->dcFont.lfPitchAndFamily= 0;
236     dc->dcFont.lfFaceNameUtf8[0]= '\0';
237     utilInitTextAttribute( &(dc->dcFont.lfTextAttribute) );
238 
239     /* A good initial guess: */
240     dc->dcTransform.dctDeviceRect= dc->dcTransform.dctLogicalRect;
241     dc->dcTransform.dctDeviceToOutput= dc->dcTransform.dctLogicalToOutput;
242 
243     dc->dcTransform.dctPushed= (DeviceCoordinateTransform *)0;
244 
245     dc->dcClipRect.drX0= 0;
246     dc->dcClipRect.drY0= 0;
247     dc->dcClipRect.drX1= 0;
248     dc->dcClipRect.drY1= 0;
249 
250     dc->dcObjects= (MetaFileObject *)0;
251     dc->dcObjectCount= 0;
252 
253     if  ( objectCount > 0 )
254 	{
255 	int		ob;
256 
257 	dc->dcObjects= (MetaFileObject *)
258 			    malloc( objectCount* sizeof(MetaFileObject) );
259 	if  ( ! dc->dcObjects )
260 	    { XDEB(dc->dcObjects); return -1;	}
261 
262 	for ( ob= 0; ob < objectCount; ob++ )
263 	    { dc->dcObjects[ob].mfoType= MFtypeFREE;	}
264 
265 	dc->dcObjectCount= objectCount;
266 	}
267 
268     dc->dcPoints= (Point2DI *)0;
269     dc->dcCounts= (int *)0;
270     dc->dcAfi= (AfmFontInfo *)0;
271     dc->dcFontEncoding= -1;
272 
273     utilInitRGB8Color( &(dc->dcColorSet) );
274     dc->dcPenSet.lpStyle= -1;
275     dc->dcX= dc->dcTransform.dctLogicalRect.drX0;
276     dc->dcY= dc->dcTransform.dctLogicalRect.drY0;
277 
278     utilInitTextAttribute( &(dc->dcTextAttributeSet) );
279 
280     return 0;
281     }
282 
appMetaCleanObject(MetaFileObject * mfo)283 void appMetaCleanObject( MetaFileObject *	mfo )
284     {
285     switch( mfo->mfoType )
286 	{
287 	case MFtypeFREE:
288 	    return;
289 	case MFtypeBRUSH:
290 	    return;
291 	case MFtypePEN:
292 	    return;
293 	case MFtypeFONT:
294 	    return;
295 	case MFtypePALETTE:
296 	    return;
297 	case MFtypeREGION:
298 	    return;
299 	case MFtypePATTERNBRUSH:
300 	    appCleanPatternBrush( &(mfo->mfoPatternBrush) );
301 	    return;
302 
303 	default:
304 	    LDEB(mfo->mfoType);
305 	    return;
306 	}
307     }
308 
appMetaCleanDeviceContext(DeviceContext * dc,void * through)309 void appMetaCleanDeviceContext(	DeviceContext *		dc,
310 				void *			through )
311     {
312     int		ob;
313 
314     docCleanFontList( &(dc->dcFontList) );
315     textCleanTextConverter( &(dc->dcTextConverter) );
316     utilCleanMemoryBuffer( &(dc->dcCollectedText) );
317 
318     for ( ob= 0; ob < dc->dcObjectCount; ob++ )
319 	{
320 	if  ( dc->dcObjects[ob].mfoType != MFtypeFREE )
321 	    {
322 	    (*dc->dcCleanObject)( dc, through, dc->dcObjects+ ob );
323 	    appMetaCleanObject( dc->dcObjects+ ob );
324 	    }
325 	}
326 
327     if  ( dc->dcObjects )
328 	{ free( dc->dcObjects );	}
329 
330     if  ( dc->dcPoints )
331 	{ free( dc->dcPoints );	}
332     if  ( dc->dcCounts )
333 	{ free( dc->dcCounts );	}
334 
335     while( dc->dcTransform.dctPushed )
336 	{
337 	DeviceCoordinateTransform *	toFree= dc->dcTransform.dctPushed;
338 
339 	dc->dcTransform= *dc->dcTransform.dctPushed;
340 
341 	free( toFree );
342 	}
343 
344     return;
345     }
346 
appWinMetaRememberFontInList(DeviceContext * dc,TextAttribute * ta,const LogicalFont * lf)347 int appWinMetaRememberFontInList(	DeviceContext *		dc,
348 					TextAttribute *		ta,
349 					const LogicalFont *	lf )
350     {
351     int				rval= 0;
352 
353     int				familyStyle= DFstyleFNIL;
354 
355     int				fontNum;
356     DocumentFont		dfNew;
357     DocumentFontList *		dfl= &(dc->dcFontList);
358     const MetafilePlayer *	player= dc->dcPlayer;
359 
360     const IndexSet *		unicodesWanted;
361 
362     docInitDocumentFont( &dfNew );
363 
364     utilInitTextAttribute( ta );
365 
366     ta->taFontNumber= 0;
367     if  ( lf->lfHeight < 0 )
368 	{ ta->taFontSizeHalfPoints= -lf->lfHeight; }	/* Value not used */
369     else{ ta->taFontSizeHalfPoints=  lf->lfHeight; }	/* Value not used */
370     ta->taFontIsBold= lf->lfWeight > 500;
371     ta->taFontIsSlanted= lf->lfItalic != 0;
372     ta->taTextIsUnderlined= lf->lfUnderline != 0;
373     ta->taHasStrikethrough= lf->lfStrikeOut != 0;
374 
375     switch( lf->lfPitchAndFamily & 0xf0 )
376 	{
377 	case FF_ROMAN:		familyStyle= DFstyleFROMAN;	break;
378 	case FF_SWISS:		familyStyle= DFstyleFSWISS;	break;
379 	case FF_MODERN:		familyStyle= DFstyleFMODERN;	break;
380 	case FF_SCRIPT:		familyStyle= DFstyleFSCRIPT;	break;
381 	case FF_DECORATIVE:	familyStyle= DFstyleFDECOR;	break;
382 	case 0x60:		familyStyle= DFstyleFTECH;	break;
383 
384 	case FF_DONTCARE:
385 	default:
386 	    break;
387 	}
388 
389     if  ( docFontSetFamilyName( &dfNew, lf->lfFaceNameUtf8 ) )
390 	{ LDEB(1); rval= -1; goto ready;	}
391     if  ( docFontSetFamilyStyle( &dfNew, familyStyle ) )
392 	{ LDEB(1); rval= -1; goto ready;	}
393 
394     fontNum= docMergeFontIntoFontlist( dfl, &dfNew );
395     if  ( fontNum < 0 )
396 	{ SLDEB(lf->lfFaceNameUtf8,fontNum); goto ready;	}
397 
398     ta->taFontNumber= fontNum;
399 
400     if  ( ! (*player->mpGetFontForAttribute)( &unicodesWanted, ta, dfl,
401 					    player->mpPostScriptFontList ) )
402 	{ SLDEB(lf->lfFaceNameUtf8,fontNum); goto ready;	}
403 
404     WMFDEB(appDebug("CreateFontIndirect(h=%d,w=%d,..\"%s\")\n",
405 			    lf->lfHeight,
406 			    lf->lfWidth,
407 			    lf->lfFaceNameUtf8 ));
408 
409   ready:
410 
411     docCleanDocumentFont( &dfNew );
412 
413     return rval;
414     }
415 
416 /************************************************************************/
417 /*									*/
418 /*  Save the current coordinate transform.				*/
419 /*									*/
420 /************************************************************************/
421 
appMetaSaveDC(DeviceContext * dc)422 int appMetaSaveDC(		DeviceContext *		dc )
423     {
424     DeviceCoordinateTransform *	dct;
425 
426     WMFDEB(appDebug("SaveDC()\n" ));
427 
428     dct= (DeviceCoordinateTransform *)malloc( sizeof(DeviceCoordinateTransform) );
429     if  ( ! dct )
430 	{ XDEB(dct); return -1;	}
431 
432     *dct= dc->dcTransform;
433     dc->dcTransform.dctPushed= dct;
434 
435     return 0;
436     }
437 
appMetaRestoreDC(DeviceContext * dc)438 int appMetaRestoreDC(		DeviceContext *		dc )
439     {
440     DeviceCoordinateTransform *	prv= dc->dcTransform.dctPushed;
441 
442     if  ( ! prv )
443 	{ XDEB(prv); return -1;	}
444 
445     dc->dcTransform= *prv;
446     free( prv );
447 
448     return 0;
449     }
450 
451 /************************************************************************/
452 /*									*/
453 /*  Collect a series of points.						*/
454 /*									*/
455 /************************************************************************/
456 
appWinMetaGetPoints16(DeviceContext * dc,int count,SimpleInputStream * sis)457 int appWinMetaGetPoints16(	DeviceContext *		dc,
458 				int			count,
459 				SimpleInputStream *	sis )
460     {
461     Point2DI *		xp;
462     int			done= 0;
463 
464     int			p;
465 
466     xp= (Point2DI *)realloc( dc->dcPoints, (count+ 1)* sizeof(Point2DI) );
467     if  ( ! xp )
468 	{ LXDEB(count,xp); return -1;	}
469     dc->dcPoints= xp;
470 
471     for ( p= 0; p < count; xp++, p++ )
472 	{
473 	int	x= sioEndianGetLeInt16( sis );
474 	int	y= sioEndianGetLeInt16( sis );
475 
476 	done += 4;
477 
478 	xp->x= DC_xViewport( x, y, dc );
479 	xp->y= DC_yViewport( x, y, dc );
480 
481 #	if 0
482 	WMFDEB(appDebug("@%d: (%d,%d) :: (%d,%d)\n", p, x,y, xp->x,xp->y ));
483 #	endif
484 	}
485 
486     *xp= dc->dcPoints[0];
487 
488     return done;
489     }
490 
appWinMetaGetPoints32(DeviceContext * dc,int count,SimpleInputStream * sis)491 int appWinMetaGetPoints32(	DeviceContext *		dc,
492 				int			count,
493 				SimpleInputStream *	sis )
494     {
495     Point2DI *		xp;
496     int			done= 0;
497 
498     int			p;
499 
500     xp= (Point2DI *)realloc( dc->dcPoints, (count+ 1)* sizeof(Point2DI) );
501     if  ( ! xp )
502 	{ LXDEB(count,xp); return -1;	}
503     dc->dcPoints= xp;
504 
505     for ( p= 0; p < count; xp++, p++ )
506 	{
507 	int	x= sioEndianGetLeInt32( sis );
508 	int	y= sioEndianGetLeInt32( sis );
509 
510 	done += 8;
511 
512 	xp->x= DC_xViewport( x, y, dc );
513 	xp->y= DC_yViewport( x, y, dc );
514 	}
515 
516     *xp= dc->dcPoints[0];
517 
518     return done;
519     }
520 
521 /************************************************************************/
522 /*									*/
523 /*  Handle Clipping by ignoring it.					*/
524 /*									*/
525 /************************************************************************/
526 
appMetaExcludeClipRect(DeviceContext * dc,int recordSize,SimpleInputStream * sis)527 int appMetaExcludeClipRect(	DeviceContext *		dc,
528 				int			recordSize,
529 				SimpleInputStream *	sis )
530     {
531     DocumentRectangle	dr;
532 
533     bmWmfReadRectangle( &dr, sis );
534 
535     WMFDEB(appDebug("ExcludeClipRect(%d..%d,%d..%d)\n", x0,x1,y0,y1));
536 
537     return 0;
538     }
539 
appMetaIntersectClipRect(DeviceContext * dc,int recordSize,SimpleInputStream * sis)540 int appMetaIntersectClipRect(	DeviceContext *		dc,
541 				int			recordSize,
542 				SimpleInputStream *	sis )
543     {
544     DocumentRectangle	dr;
545 
546     bmWmfReadRectangle( &dr, sis );
547 
548     WMFDEB(appDebug("IntersectClipRect(%d..%d,%d..%d)\n", x0,x1,y0,y1));
549 
550     return 0;
551     }
552 
553 /************************************************************************/
554 /*									*/
555 /*  Remember text alighnment.						*/
556 /*									*/
557 /************************************************************************/
558 
appMetaSetTextAlign(DeviceContext * dc,int arg)559 int appMetaSetTextAlign(	DeviceContext *		dc,
560 				int			arg )
561     {
562     dc->dcTextAlignment= arg;
563 
564     WMFDEB(appDebug("SetTextAlign( 0x%x: ", arg ));
565 
566     switch( dc->dcTextAlignment & 0x01 )
567 	{
568 	case TA_NOUPDATECP:	WMFDEB(appDebug(" NOUPDATECP" )); break;
569 	case TA_UPDATECP:	WMFDEB(appDebug(" UPDATECP" )); break;
570 	default:
571 	    WMFDEB(appDebug(" 0x%x", dc->dcTextAlignment & 0x01 ));
572 	    break;
573 	}
574 
575     switch( dc->dcTextAlignment & 0x07 )
576 	{
577 	case TA_LEFT:	WMFDEB(appDebug(" LEFT" )); break;
578 	case TA_RIGHT:	WMFDEB(appDebug(" RIGHT" )); break;
579 	case TA_CENTER:	WMFDEB(appDebug(" CENTER" )); break;
580 	default:
581 	    WMFDEB(appDebug(" 0x%x", dc->dcTextAlignment & 0x07 ));
582 	    break;
583 	}
584 
585     switch( dc->dcTextAlignment & 0x18 )
586 	{
587 	case TA_TOP:		WMFDEB(appDebug(" TOP" )); break;
588 	case TA_BOTTOM:		WMFDEB(appDebug(" BOTTOM" )); break;
589 	case TA_BASELINE:	WMFDEB(appDebug(" BASELINE" )); break;
590 	default:
591 	    WMFDEB(appDebug(" 0x%x", dc->dcTextAlignment & 0x18 ));
592 	    break;
593 	}
594 
595     WMFDEB(appDebug(" )\n" ));
596 
597     return 0;
598     }
599 
600 /************************************************************************/
601 /*									*/
602 /*  Extract a bitmap from the metafile stream.				*/
603 /*									*/
604 /************************************************************************/
605 
appMetaReadBitmapImage(int * pSkip,RasterImage ** pRi,SimpleInputStream * sis,int expectBytes)606 int appMetaReadBitmapImage(	int *			pSkip,
607 				RasterImage **		pRi,
608 				SimpleInputStream *	sis,
609 				int			expectBytes )
610     {
611     int			rval= 0;
612     RasterImage *	ri= (RasterImage *)0;
613     int			done= 0;
614 
615     if  ( expectBytes < 40 )
616 	{
617 	/* LDEB(expectBytes); */
618 
619 	while( done < expectBytes )
620 	    {
621 	    if  ( sioInGetByte( sis ) < 0 )
622 		{ LDEB(1); rval= -1; goto ready;	}
623 	    done++;
624 	    }
625 
626 	*pSkip= 1;
627 	*pRi= ri;
628 	goto ready;
629 	}
630 
631     ri= (RasterImage *)malloc( sizeof(RasterImage) );
632     if  ( ! ri )
633 	{ XDEB(ri); rval= -1; goto ready;	}
634     bmInitRasterImage( ri );
635 
636     done= bmBmpReadDib( &(ri->riDescription), &(ri->riBytes), sis );
637     if  ( done < 0 || done > expectBytes )
638 	{ LLDEB(done,expectBytes); rval= -1; goto ready;	}
639 
640     while( done < expectBytes )
641 	{
642 	if  ( sioInGetByte( sis ) < 0 )
643 	    { LDEB(1); rval= -1; goto ready;	}
644 
645 	done++;
646 	}
647 
648     *pSkip= 0;
649     *pRi= ri; ri= (RasterImage *)0;
650 
651   ready:
652     if  ( ri )
653 	{
654 	bmCleanRasterImage( ri );
655 	free( ri );
656 	}
657 
658     return rval;
659     }
660 
661 /************************************************************************/
662 /*									*/
663 /*  Handle a raster image in the metafile input.			*/
664 /*									*/
665 /************************************************************************/
666 
appMetaDrawRasterImage(SimpleInputStream * sis,void * through,int expectBytes,DeviceContext * dc,const DocumentRectangle * drSrc,const DocumentRectangle * drDest)667 int appMetaDrawRasterImage(	SimpleInputStream *		sis,
668 				void *				through,
669 				int				expectBytes,
670 				DeviceContext *			dc,
671 				const DocumentRectangle *	drSrc,
672 				const DocumentRectangle *	drDest )
673     {
674     int				rval= 0;
675     int				skip;
676 
677     RasterImage *		abi= (RasterImage *)0;
678     BitmapDescription *		bd;
679 
680     int				adjusted= 0;
681     DocumentRectangle		drSrcAdjusted= *drSrc;
682     DocumentRectangle		drOutput;
683 
684     if  ( appMetaReadBitmapImage( &skip, &abi, sis, expectBytes ) )
685 	{ LDEB(expectBytes); rval= -1; goto ready;	}
686 
687     if  ( skip )
688 	{
689 	if  ( expectBytes > 2 )
690 	    { LLDEB(expectBytes,skip);	}
691 
692 	goto ready;
693 	}
694 
695     bd= &(abi->riDescription);
696 
697     appWinMetaTransformRectangle( &drOutput, dc, drDest );
698 
699     if  ( drSrcAdjusted.drX0 < 0 )
700 	{ drSrcAdjusted.drX0=  0; adjusted= 1;	}
701     if  ( drSrcAdjusted.drY0 < 0 )
702 	{ drSrcAdjusted.drY0=  0; adjusted= 1;	}
703 
704     if  ( drSrcAdjusted.drX1 > bd->bdPixelsWide- 1 )
705 	{ drSrcAdjusted.drX1=  bd->bdPixelsWide- 1; adjusted= 1;	}
706     if  ( drSrcAdjusted.drY1 > bd->bdPixelsHigh- 1 )
707 	{ drSrcAdjusted.drY1=  bd->bdPixelsHigh- 1; adjusted= 1;	}
708 
709     if  ( adjusted )
710 	{
711 	LLDEB(bd->bdPixelsWide,bd->bdPixelsHigh);
712 	RECTDEB(drSrc);
713 	}
714 
715     if  ( drSrcAdjusted.drX0 > drSrcAdjusted.drX1 )
716 	{ LLDEB( drSrcAdjusted.drX0,drSrcAdjusted.drX1); rval= -1; goto ready; }
717     if  ( drSrcAdjusted.drY0 > drSrcAdjusted.drY1 )
718 	{ LLDEB( drSrcAdjusted.drY0,drSrcAdjusted.drY1); rval= -1; goto ready; }
719 
720     rval= (*dc->dcDrawRasterImage)( dc, through, abi,
721 					    &drSrcAdjusted, &drOutput );
722     if  ( rval )
723 	{ LDEB(rval);	}
724 
725   ready:
726 
727     if  ( abi )
728 	{ bmCleanRasterImage( abi ); free( abi );	}
729 
730     return rval;
731     }
732 
appWinMetaSelectObject(DeviceContext * dc,void * through,int ob)733 int appWinMetaSelectObject(	DeviceContext *		dc,
734 				void *			through,
735 				int			ob )
736     {
737     MetaFileObject *		mfo= &(dc->dcObjects[ob]);
738 
739     switch( mfo->mfoType )
740 	{
741 	case MFtypePEN:
742 	    {
743 	    LogicalPen *	lp= &(mfo->mfoLogicalPen);
744 
745 	    WMFDEB(appDebug(
746 		    "SelectObject( ob= %d ) PEN width=%d, rgba=%d:%d:%d:%d\n",
747 		    ob, lp->lpWidth,
748 		    lp->lpColor.rgb8Red, lp->lpColor.rgb8Green,
749 		    lp->lpColor.rgb8Blue, lp->lpColor.rgb8Alpha ));
750 
751 	    if  ( (*dc->dcSelectPenObject)( dc, through, lp ) )
752 		{ LDEB(ob); return -1;	}
753 
754 	    }
755 	    break;
756 
757 	case MFtypeBRUSH:
758 	    WMFDEB(appDebug( "SelectObject( ob= %d ) BRUSH\n", ob ));
759 	    if  ( (*dc->dcSelectBrushObject)( dc, through, &(mfo->mfoLogicalBrush) ) )
760 		{ LDEB(ob); return -1;	}
761 	    dc->dcCurrentBrushObject= ob;
762 	    break;
763 
764 	case MFtypePATTERNBRUSH:
765 	    WMFDEB(appDebug( "SelectObject( ob= %d ) PATTERNBRUSH\n", ob ));
766 	    if  ( (*dc->dcSelectPatternBrushObject)( dc, through, &(mfo->mfoPatternBrush) ) )
767 		{ LDEB(ob); return -1;	}
768 	    dc->dcCurrentBrushObject= ob;
769 	    break;
770 
771 	case MFtypeFONT:
772 	    WMFDEB(appDebug( "SelectObject( ob= %d ) FONT\n", ob ));
773 	    if  ( (*dc->dcSelectFontObject)( dc, through, &(mfo->mfoLogicalFont) ) )
774 		{ LDEB(ob); return -1;	}
775 	    dc->dcFont= mfo->mfoLogicalFont;
776 	    break;
777 
778 	default:
779 	    WMFDEB(appDebug( "SelectObject( ob= %d ) type= %d\n", ob, mfo->mfoType));
780 	    break;
781 	}
782 
783     return 0;
784     }
785 
appWinMetaTransformRectangle(DocumentRectangle * drOutput,DeviceContext * dc,const DocumentRectangle * drLogical)786 void appWinMetaTransformRectangle(
787 				DocumentRectangle *		drOutput,
788 				DeviceContext *			dc,
789 				const DocumentRectangle *	drLogical )
790     {
791     DocumentRectangle	dr;
792 
793     dr.drX0= DC_xViewport( drLogical->drX0, drLogical->drY0, dc );
794     dr.drY0= DC_yViewport( drLogical->drX0, drLogical->drY0, dc );
795     dr.drX1= DC_xViewport( drLogical->drX1, drLogical->drY1, dc );
796     dr.drY1= DC_yViewport( drLogical->drX1, drLogical->drY1, dc );
797 
798     geoNormalizeRectangle( drOutput, &dr );
799     }
800 
appWinMetaDrawRectangle(DeviceContext * dc,void * through,const DocumentRectangle * drLogical,int fillInside,int drawBorder)801 int appWinMetaDrawRectangle(	DeviceContext *			dc,
802 				void *				through,
803 				const DocumentRectangle *	drLogical,
804 				int				fillInside,
805 				int				drawBorder )
806     {
807     DocumentRectangle		drOutput;
808     Point2DI			points[4];
809     int				pointCount= 4;
810 
811     appWinMetaTransformRectangle( &drOutput, dc, drLogical );
812 
813     points[0].x= drOutput.drX0;
814     points[0].y= drOutput.drY0;
815 
816     points[1].x= drOutput.drX0;
817     points[1].y= drOutput.drY1;
818 
819     points[2].x= drOutput.drX1;
820     points[2].y= drOutput.drY1;
821 
822     points[3].x= drOutput.drX1;
823     points[3].y= drOutput.drY0;
824 
825     if  ( (*dc->dcDrawPolyPolygon)( dc, through, 1, &pointCount, points,
826 						fillInside, drawBorder, 1 ) )
827 	{ LDEB(1); return -1;	}
828 
829     return 0;
830     }
831 
appWinMetaDrawEllipse(DeviceContext * dc,void * through,const DocumentRectangle * drLogical,int fillInside,int drawBorder)832 int appWinMetaDrawEllipse(	DeviceContext *			dc,
833 				void *				through,
834 				const DocumentRectangle *	drLogical,
835 				int				fillInside,
836 				int				drawBorder )
837     {
838     DocumentRectangle		drOutput;
839 
840     appWinMetaTransformRectangle( &drOutput, dc, drLogical );
841 
842     if  ( (*dc->dcDrawEllipse)( dc, through, &drOutput,
843 						    fillInside, drawBorder ) )
844 	{ LDEB(1); return -1;	}
845 
846     return 0;
847     }
848 
appWinMetaUpdateTransform(DeviceContext * dc)849 void appWinMetaUpdateTransform(	DeviceContext *			dc )
850     {
851     DeviceCoordinateTransform *	t= &(dc->dcTransform);
852 
853     if  ( geoAffineTransformForTriangles( &(t->dctLogicalToOutput),
854 		    t->dctLogicalRect.drX0,	t->dctLogicalRect.drY0,
855 		    t->dctLogicalRect.drX1,	t->dctLogicalRect.drY0,
856 		    t->dctLogicalRect.drX0,	t->dctLogicalRect.drY1,
857 
858 		    dc->dcOutputRect.drX0,	dc->dcOutputRect.drY0,
859 		    dc->dcOutputRect.drX1,	dc->dcOutputRect.drY0,
860 		    dc->dcOutputRect.drX0,	dc->dcOutputRect.drY1 ) )
861 	{
862 	RECTDEB(&(t->dctLogicalRect));
863 	RECTDEB(&(dc->dcOutputRect));
864 	}
865 
866     return;
867     }
868 
appWinMetaOutputSize(DeviceContext * dc,int logicalSize)869 int appWinMetaOutputSize(	DeviceContext *		dc,
870 				int			logicalSize )
871     {
872     DocumentRectangle	drLogical;
873     DocumentRectangle	drOutput;
874     int			w, h;
875 
876     drLogical.drX0= 0;
877     drLogical.drY0= 0;
878     drLogical.drX1= logicalSize;
879     drLogical.drY1= logicalSize;
880 
881     drOutput.drX0= DC_xViewport( drLogical.drX0, drLogical.drY0, dc );
882     drOutput.drY0= DC_yViewport( drLogical.drX0, drLogical.drY0, dc );
883     drOutput.drX1= DC_xViewport( drLogical.drX1, drLogical.drY1, dc );
884     drOutput.drY1= DC_yViewport( drLogical.drX1, drLogical.drY1, dc );
885 
886     w= drOutput.drX1- drOutput.drX0;
887     h= drOutput.drY1- drOutput.drY0;
888 
889     return M_SQRT1_2* sqrt( w*w+ h*h )+ 0.4999;
890     }
891