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