~ubuntu-branches/ubuntu/natty/imagemagick/natty-updates

« back to all changes in this revision

Viewing changes to coders/wmf.c

  • Committer: Bazaar Package Importer
  • Author(s): Nelson A. de Oliveira
  • Date: 2010-06-20 19:59:55 UTC
  • mfrom: (6.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100620195955-n3eq0yenhycw888i
Tags: 7:6.6.2.6-1
* New upstream release;
* Change Recommends on ufraw to ufraw-batch (Closes: #579775);
* Fix FTBFS when using dash to run the configure script, by setting
  CONFIG_SHELL=/bin/bash (Closes: #582073, #583024). Thank you, Niko Tyni!

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
%                        Read Windows Metafile Format                         %
14
14
%                                                                             %
15
15
%                              Software Design                                %
16
 
%                              Bob Friesenhahn                                %
17
 
%                            Dec 2000 - May 2001                              %
18
 
%                            Oct 2001 - May 2002                              %
19
 
%                                                                             %
20
 
%                           Port to libwmf 0.2 API                            %
21
 
%                            Francis J. Franklin                              %
22
 
%                            May 2001 - Oct 2001                              %
23
 
%                                                                             %
24
 
%                                                                             %
25
 
%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
 
16
%                                John Cristy                                  %
 
17
%                               December 2000                                 %
 
18
%                                                                             %
 
19
%                                                                             %
 
20
%  Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization      %
26
21
%  dedicated to making software imaging solutions freely available.           %
27
22
%                                                                             %
28
23
%  You may not use this file except in compliance with the License.  You may  %
68
63
#include "magick/module.h"
69
64
#include "wand/MagickWand.h"
70
65
 
71
 
#if defined(MAGICKCORE_WMF_DELEGATE) || defined(MAGICKCORE_WMFLITE_DELEGATE)
72
 
 
73
 
#define ERR(API)  ((API)->err != wmf_E_None)
74
 
#define XC(x) ((double) x)
75
 
#define YC(y) ((double) y)
76
 
 
77
 
#if !defined(M_PI)
78
 
#  define M_PI  MagickPI
79
 
#endif
80
 
 
81
 
#if defined(MAGICKCORE_HAVE_FT2BUILD_H)
82
 
#  include <ft2build.h>
83
 
#endif
84
 
 
85
 
#include "libwmf/fund.h"
86
 
#include "libwmf/types.h"
 
66
#if defined(MAGICKCORE_WMF_DELEGATE)
87
67
#include "libwmf/api.h"
88
 
#undef SRCCOPY
89
 
#undef SRCPAINT
90
 
#undef SRCAND
91
 
#undef SRCINVERT
92
 
#undef SRCERASE
93
 
#undef NOTSRCCOPY
94
 
#undef NOTSRCERASE
95
 
#undef MERGECOPY
96
 
#undef MERGEPAINT
97
 
#undef PATCOPY
98
 
#undef PATPAINT
99
 
#undef PATINVERT
100
 
#undef DSTINVERT
101
 
#undef BLACKNESS
102
 
#undef WHITENESS
103
 
 
104
 
/* The following additinal undefs were required for MinGW */
105
 
#undef BS_HOLLOW
106
 
#undef PS_STYLE_MASK
107
 
#undef PS_ENDCAP_ROUND
108
 
#undef PS_ENDCAP_SQUARE
109
 
#undef PS_ENDCAP_FLAT
110
 
#undef PS_ENDCAP_MASK
111
 
#undef PS_JOIN_ROUND
112
 
#undef PS_JOIN_BEVEL
113
 
#undef PS_JOIN_MITER
114
 
#undef PS_COSMETIC
115
 
#undef PS_GEOMETRIC
116
 
#undef PS_TYPE_MASK
117
 
#undef STRETCH_ANDSCANS
118
 
#undef STRETCH_ORSCANS
119
 
#undef STRETCH_DELETESCANS
120
 
#undef STRETCH_HALFTONE
121
 
#undef ETO_OPAQUE
122
 
#undef ETO_CLIPPED
123
 
#undef ETO_GLYPH_INDEX
124
 
#undef ETO_RTLREADING
125
 
 
126
 
#include "libwmf/defs.h"
127
 
#include "libwmf/ipa.h"
128
 
#include "libwmf/color.h"
129
 
#include "libwmf/macro.h"
130
 
 
131
 
/* Unit conversions */
132
 
#define TWIPS_PER_INCH        1440
133
 
#define CENTIMETERS_PER_INCH  2.54
134
 
#define POINTS_PER_INCH       72
135
 
 
136
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
137
 
# define wmf_api_create(api,flags,options) wmf_lite_create(api,flags,options)
138
 
# define wmf_api_destroy(api) wmf_lite_destroy(api)
139
 
# undef WMF_FONT_PSNAME
140
 
# define WMF_FONT_PSNAME(F) ((F)->user_data ? ((wmf_magick_font_t*) (F)->user_data)->ps_name : 0)
141
 
 
142
 
typedef struct _wmf_magick_font_t wmf_magick_font_t;
143
 
 
144
 
struct _wmf_magick_font_t
145
 
{
146
 
  char*  ps_name;
147
 
  double pointsize;
148
 
};
149
 
 
150
 
#endif
151
 
 
152
 
typedef struct _wmf_magick_t wmf_magick_t;
153
 
 
154
 
struct _wmf_magick_t
155
 
{
156
 
  /* Bounding box */
157
 
  wmfD_Rect
158
 
    bbox;
159
 
 
160
 
  /* Scale and translation factors */
161
 
  double
162
 
    scale_x,
163
 
    scale_y,
164
 
    translate_x,
165
 
    translate_y,
166
 
    rotate;
167
 
 
168
 
  /* Vector output */
169
 
  DrawingWand
170
 
    *draw_wand;
171
 
 
172
 
  /* ImageMagick image */
173
 
  Image
174
 
    *image;
175
 
 
176
 
  /* ImageInfo */
177
 
  const ImageInfo
178
 
    *image_info;
179
 
 
180
 
  /* DrawInfo */
181
 
  DrawInfo
182
 
    *draw_info;
183
 
 
184
 
  /* Pattern ID */
185
 
  unsigned long
186
 
    pattern_id;
187
 
 
188
 
  /* Clip path flag */
189
 
  MagickBooleanType
190
 
    clipping;
191
 
 
192
 
  /* Clip path ID */
193
 
  unsigned long
194
 
    clip_mask_id;
195
 
 
196
 
  /* Push depth */
197
 
  long
198
 
    push_depth;
199
 
};
200
 
 
201
 
 
202
 
#define WMF_MAGICK_GetData(Z) ((wmf_magick_t*)((Z)->device_data))
203
 
#define WMF_MAGICK_GetFontData(Z) \
204
 
  ((wmf_magick_font_t*)((wmfFontData *)Z->font_data)->user_data)
205
 
 
206
 
#define WmfDrawingWand (((wmf_magick_t*)((API)->device_data))->draw_wand)
207
 
 
208
 
/* Enum to control whether util_set_brush applies brush to fill or
209
 
   stroke. */
210
 
typedef enum
211
 
{
212
 
  BrushApplyFill,
213
 
  BrushApplyStroke
214
 
} BrushApply;
215
 
 
216
 
 
217
 
/* Enum to specify arc type */
218
 
typedef enum
219
 
{
220
 
  magick_arc_ellipse = 0,
221
 
  magick_arc_open,
222
 
  magick_arc_pie,
223
 
  magick_arc_chord
224
 
}
225
 
magick_arc_t;
226
 
 
227
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
228
 
static void  lite_font_init (wmfAPI* API, wmfAPI_Options* options);
229
 
static void  lite_font_map(wmfAPI* API,wmfFont* font);
230
 
static float lite_font_stringwidth(wmfAPI* API, wmfFont* font, char* str);
231
 
#endif
232
 
 
233
 
static void         draw_fill_color_rgb(wmfAPI* API, const wmfRGB* rgb);
234
 
static void         draw_stroke_color_rgb(wmfAPI* API, const wmfRGB* rgb);
235
 
static void         draw_pattern_push(wmfAPI* API, unsigned long id, unsigned long columns, unsigned long rows);
236
 
static int          ipa_blob_read(void* wand);
237
 
static int          ipa_blob_seek(void* wand,long position);
238
 
static long         ipa_blob_tell(void* wand);
239
 
static void         ipa_bmp_draw(wmfAPI * API, wmfBMP_Draw_t * bmp_draw);
240
 
static void         ipa_bmp_free(wmfAPI * API, wmfBMP * bmp);
241
 
static void         ipa_bmp_read(wmfAPI * API, wmfBMP_Read_t * bmp_read);
242
 
static void         ipa_device_begin(wmfAPI * API);
243
 
static void         ipa_device_close(wmfAPI * API);
244
 
static void         ipa_device_end(wmfAPI * API);
245
 
static void         ipa_device_open(wmfAPI * API);
246
 
static void         ipa_draw_arc(wmfAPI * API, wmfDrawArc_t * draw_arc);
247
 
static void         ipa_draw_chord(wmfAPI * API, wmfDrawArc_t * draw_arc);
248
 
static void         ipa_draw_ellipse(wmfAPI * API, wmfDrawArc_t * draw_arc);
249
 
static void         ipa_draw_line(wmfAPI * API, wmfDrawLine_t * draw_line);
250
 
static void         ipa_draw_pie(wmfAPI * API, wmfDrawArc_t * draw_arc);
251
 
static void         ipa_draw_pixel(wmfAPI * API, wmfDrawPixel_t * draw_pixel);
252
 
static void         ipa_draw_polygon(wmfAPI * API, wmfPolyLine_t * poly_line);
253
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
254
 
static void         ipa_draw_polypolygon(wmfAPI * API, wmfPolyPoly_t* polypolygon);
255
 
#endif
256
 
static void         ipa_draw_rectangle(wmfAPI * API, wmfDrawRectangle_t * draw_rect);
257
 
static void         ipa_draw_text(wmfAPI * API, wmfDrawText_t * draw_text);
258
 
static void         ipa_flood_exterior(wmfAPI * API, wmfFlood_t * flood);
259
 
static void         ipa_flood_interior(wmfAPI * API, wmfFlood_t * flood);
260
 
static void         ipa_functions(wmfAPI * API);
261
 
static void         ipa_poly_line(wmfAPI * API, wmfPolyLine_t * poly_line);
262
 
static void         ipa_region_clip(wmfAPI * API, wmfPolyRectangle_t * poly_rect);
263
 
static void         ipa_region_frame(wmfAPI * API, wmfPolyRectangle_t * poly_rect);
264
 
static void         ipa_region_paint(wmfAPI * API, wmfPolyRectangle_t * poly_rect);
265
 
static void         ipa_rop_draw(wmfAPI * API, wmfROP_Draw_t * rop_draw);
266
 
static void         ipa_udata_copy(wmfAPI * API, wmfUserData_t * userdata);
267
 
static void         ipa_udata_free(wmfAPI * API, wmfUserData_t * userdata);
268
 
static void         ipa_udata_init(wmfAPI * API, wmfUserData_t * userdata);
269
 
static void         ipa_udata_set(wmfAPI * API, wmfUserData_t * userdata);
270
 
static int          magick_progress_callback(void* wand,float quantum);
271
 
static void         util_draw_arc(wmfAPI * API, wmfDrawArc_t * draw_arc,magick_arc_t finish);
272
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
273
 
/*static int          util_font_weight( const char* font );*/
274
 
#endif
275
 
static double       util_pointsize( wmfAPI* API, wmfFont* font, char* str, double font_height);
276
 
static void         util_set_brush(wmfAPI * API, wmfDC * dc, const BrushApply brush_apply);
277
 
static void         util_set_pen(wmfAPI * API, wmfDC * dc);
278
 
 
279
 
/* Progress callback */
280
 
int magick_progress_callback(void *context,float quantum)
281
 
{
282
 
  Image
283
 
    *image;
 
68
#include "libwmf/eps.h"
 
69
 
 
70
/*
 
71
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
72
%                                                                             %
 
73
%                                                                             %
 
74
%                                                                             %
 
75
%   R e a d W M F I m a g e                                                   %
 
76
%                                                                             %
 
77
%                                                                             %
 
78
%                                                                             %
 
79
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
80
%
 
81
%  ReadWMFImage() reads an Windows Metafile image file and returns it.  It
 
82
%  allocates the memory necessary for the new Image structure and returns a
 
83
%  pointer to the new image.
 
84
%
 
85
%  The format of the ReadWMFImage method is:
 
86
%
 
87
%      Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
88
%
 
89
%  A description of each parameter follows:
 
90
%
 
91
%    o image_info: the image info.
 
92
%
 
93
%    o exception: return any errors or warnings in this structure.
 
94
%
 
95
*/
 
96
 
 
97
static int WMFReadBlob(void *image)
 
98
{
 
99
  return(ReadBlobByte((Image *) image));
 
100
}
 
101
 
 
102
static int WMFSeekBlob(void *image,long offset)
 
103
{
 
104
  return((int) SeekBlob((Image *) image,(MagickOffsetType) offset,SEEK_SET));
 
105
}
 
106
 
 
107
static long WMFTellBlob(void *image)
 
108
{
 
109
  return((long) TellBlob((Image*) image));
 
110
}
 
111
 
 
112
static Image *ReadWMFImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
113
{
 
114
  char
 
115
    filename[MaxTextExtent];
 
116
 
 
117
  int
 
118
    unique_file;
 
119
 
 
120
  FILE
 
121
    *file;
 
122
 
 
123
  Image
 
124
    *image;
 
125
 
 
126
  ImageInfo
 
127
    *read_info;
284
128
 
285
129
  MagickBooleanType
286
130
    status;
287
131
 
288
 
  MagickOffsetType
289
 
    offset;
290
 
 
291
 
  MagickSizeType
292
 
    span;
293
 
 
294
 
  image=(Image *) context;
295
 
  assert(image->signature == MagickSignature);
296
 
  offset=(MagickOffsetType) floor((double) (100.0*quantum));
297
 
  span=100;
298
 
  status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
299
 
    GetBlobSize(image));
300
 
  return(status == MagickTrue ? 0 : 1);
301
 
}
302
 
 
303
 
/* Set fill color */
304
 
static void draw_fill_color_string(DrawingWand *drawing_wand,const char *color)
305
 
{
306
 
  PixelWand
307
 
    *fill_color;
308
 
 
309
 
  fill_color=NewPixelWand();
310
 
  PixelSetColor(fill_color,color);
311
 
  DrawSetFillColor(drawing_wand,fill_color);
312
 
  fill_color=DestroyPixelWand(fill_color);
313
 
}
314
 
static void draw_fill_color_rgb( wmfAPI* API, const wmfRGB* rgb )
315
 
{
316
 
  PixelWand
317
 
    *fill_color;
318
 
 
319
 
  fill_color=NewPixelWand();
320
 
  PixelSetRedQuantum(fill_color,ScaleCharToQuantum(rgb->r));
321
 
  PixelSetGreenQuantum(fill_color,ScaleCharToQuantum(rgb->g));
322
 
  PixelSetBlueQuantum(fill_color,ScaleCharToQuantum(rgb->b));
323
 
  PixelSetOpacityQuantum(fill_color,OpaqueOpacity);
324
 
  DrawSetFillColor(WmfDrawingWand,fill_color);
325
 
  fill_color=DestroyPixelWand(fill_color);
326
 
}
327
 
 
328
 
/* Set stroke color */
329
 
static void draw_stroke_color_string(DrawingWand *drawing_wand,const char *color)
330
 
{
331
 
  PixelWand
332
 
    *stroke_color;
333
 
 
334
 
  stroke_color=NewPixelWand();
335
 
  PixelSetColor(stroke_color,color);
336
 
  DrawSetStrokeColor(drawing_wand,stroke_color);
337
 
  stroke_color=DestroyPixelWand(stroke_color);
338
 
}
339
 
 
340
 
static void draw_stroke_color_rgb( wmfAPI* API, const wmfRGB* rgb )
341
 
{
342
 
  PixelWand
343
 
    *stroke_color;
344
 
 
345
 
  stroke_color=NewPixelWand();
346
 
  PixelSetRedQuantum(stroke_color,ScaleCharToQuantum(rgb->r));
347
 
  PixelSetGreenQuantum(stroke_color,ScaleCharToQuantum(rgb->g));
348
 
  PixelSetBlueQuantum(stroke_color,ScaleCharToQuantum(rgb->b));
349
 
  PixelSetOpacityQuantum(stroke_color,OpaqueOpacity);
350
 
  DrawSetStrokeColor(WmfDrawingWand,stroke_color);
351
 
  stroke_color=DestroyPixelWand(stroke_color);
352
 
}
353
 
 
354
 
/* Set under color */
355
 
static void draw_under_color_string(DrawingWand *drawing_wand,const char *color)
356
 
{
357
 
  PixelWand
358
 
    *under_color;
359
 
 
360
 
  under_color=NewPixelWand();
361
 
  PixelSetColor(under_color,color);
362
 
  DrawSetTextUnderColor(drawing_wand,under_color);
363
 
  under_color=DestroyPixelWand(under_color);
364
 
}
365
 
 
366
 
static void draw_pattern_push( wmfAPI* API,
367
 
                               unsigned long id,
368
 
                               unsigned long columns,
369
 
                               unsigned long rows )
370
 
{
371
 
  char
372
 
    pattern_id[30];
373
 
 
374
 
  (void) FormatMagickString(pattern_id,MaxTextExtent,"brush_%lu",id);
375
 
  (void) DrawPushPattern(WmfDrawingWand,pattern_id,0,0,columns,rows);
376
 
}
377
 
 
378
 
/* Pattern/Bit BLT with raster operation (ROP) support.  Invoked by
379
 
   META_PATBLT, which is equivalent to Windows PatBlt() call, or by
380
 
   META_DIBBITBLT which is equivalent to Windows BitBlt() call. */
381
 
 
382
 
/* The BitBlt function transfers pixels from a rectangular area in one
383
 
   device wand called the 'source', to a rectangular area of the
384
 
   same size in another device wand, called the 'destination'. */
385
 
 
386
 
static void ipa_rop_draw(wmfAPI * API, wmfROP_Draw_t * rop_draw)
387
 
{
388
 
/*   wmfBrush */
389
 
/*     *brush = WMF_DC_BRUSH(rop_draw->dc); */
390
 
 
391
 
/*   wmfBMP */
392
 
/*     *brush_bmp = WMF_BRUSH_BITMAP(brush); */
393
 
 
394
 
  if (TO_FILL(rop_draw) == 0)
395
 
    return;
396
 
 
397
 
  /* Save graphic wand */
398
 
  (void) PushDrawingWand(WmfDrawingWand);
399
 
 
400
 
  /* FIXME: finish implementing (once we know what it is supposed to do!) */
401
 
 
402
 
  /*
403
 
  struct _wmfROP_Draw_t
404
 
  {       wmfDC* dc;
405
 
 
406
 
    wmfD_Coord TL;
407
 
    wmfD_Coord BR;
408
 
 
409
 
    U32 ROP;
410
 
 
411
 
    double pixel_width;
412
 
    double pixel_height;
413
 
  };
414
 
  */
415
 
 
416
 
/*   if (brush_bmp && brush_bmp->data != 0) */
417
 
/*     printf("Have an image!\n"); */
418
 
 
419
 
  switch (rop_draw->ROP) /* Ternary raster operations */
420
 
    {
421
 
    case SRCCOPY: /* dest = source */
422
 
      printf("ipa_rop_draw SRCCOPY ROP mode not implemented\n");
423
 
      break;
424
 
    case SRCPAINT: /* dest = source OR dest */
425
 
      printf("ipa_rop_draw SRCPAINT ROP mode not implemented\n");
426
 
      break;
427
 
    case SRCAND: /* dest = source AND dest */
428
 
      printf("ipa_rop_draw SRCAND ROP mode not implemented\n");
429
 
      break;
430
 
    case SRCINVERT: /* dest = source XOR dest */
431
 
      printf("ipa_rop_draw SRCINVERT ROP mode not implemented\n");
432
 
      break;
433
 
    case SRCERASE: /* dest = source AND (NOT dest) */
434
 
      printf("ipa_rop_draw SRCERASE ROP mode not implemented\n");
435
 
      break;
436
 
    case NOTSRCCOPY: /* dest = (NOT source) */
437
 
      printf("ipa_rop_draw NOTSRCCOPY ROP mode not implemented\n");
438
 
      break;
439
 
    case NOTSRCERASE: /* dest = (NOT src) AND (NOT dest) */
440
 
      printf("ipa_rop_draw NOTSRCERASE ROP mode not implemented\n");
441
 
      break;
442
 
    case MERGECOPY: /* dest = (source AND pattern) */
443
 
      printf("ipa_rop_draw MERGECOPY ROP mode not implemented\n");
444
 
      break;
445
 
    case MERGEPAINT: /* dest = (NOT source) OR dest */
446
 
      printf("ipa_rop_draw MERGEPAINT ROP mode not implemented\n");
447
 
      break;
448
 
    case PATCOPY: /* dest = pattern */
449
 
      util_set_brush(API, rop_draw->dc, BrushApplyFill);
450
 
      break;
451
 
    case PATPAINT: /* dest = DPSnoo */
452
 
      printf("ipa_rop_draw PATPAINT ROP mode not implemented\n");
453
 
      break;
454
 
    case PATINVERT: /* dest = pattern XOR dest */
455
 
      printf("ipa_rop_draw PATINVERT ROP mode not implemented\n");
456
 
      break;
457
 
    case DSTINVERT: /* dest = (NOT dest) */
458
 
      printf("ipa_rop_draw DSTINVERT ROP mode not implemented\n");
459
 
      break;
460
 
    case BLACKNESS: /* dest = BLACK */
461
 
      draw_fill_color_string(WmfDrawingWand,"black");
462
 
      break;
463
 
    case WHITENESS: /* dest = WHITE */
464
 
      draw_fill_color_string(WmfDrawingWand,"white");
465
 
      break;
466
 
    default:
467
 
      printf("ipa_rop_draw 0x%x ROP mode not implemented\n", rop_draw->ROP);
468
 
      break;
469
 
    }
470
 
 
471
 
  DrawRectangle(WmfDrawingWand,
472
 
                 XC(rop_draw->TL.x), YC(rop_draw->TL.y),
473
 
                 XC(rop_draw->BR.x), YC(rop_draw->BR.y));
474
 
 
475
 
  /* Restore graphic wand */
476
 
  (void) PopDrawingWand(WmfDrawingWand);
477
 
}
478
 
 
479
 
static void ipa_bmp_draw(wmfAPI *API, wmfBMP_Draw_t *bmp_draw)
480
 
{
481
 
  wmf_magick_t
482
 
    *ddata = WMF_MAGICK_GetData(API);
483
 
 
484
 
  ExceptionInfo
485
 
    exception;
486
 
 
487
 
  Image
488
 
    *image;
489
 
 
490
 
  MagickWand
491
 
    *magick_wand;
492
 
 
493
 
  MagickRealType
494
 
    height,
495
 
    width;
496
 
 
497
 
  PixelPacket
498
 
    white;
499
 
 
500
 
  if (bmp_draw->bmp.data == 0)
501
 
    return;
502
 
 
503
 
  GetExceptionInfo(&exception);
504
 
  image = (Image*)bmp_draw->bmp.data;
505
 
  if (!image)
506
 
    {
507
 
       InheritException(&ddata->image->exception,&exception);
508
 
       return;
509
 
    }
510
 
 
511
 
  if (bmp_draw->crop.x || bmp_draw->crop.y ||
512
 
     (bmp_draw->crop.w != bmp_draw->bmp.width) ||
513
 
     (bmp_draw->crop.h != bmp_draw->bmp.height))
514
 
    {
515
 
      /* Image needs to be cropped */
516
 
      Image
517
 
        *crop_image;
518
 
 
519
 
      RectangleInfo
520
 
        crop_info;
521
 
 
522
 
      crop_info.x = bmp_draw->crop.x;
523
 
      crop_info.y = bmp_draw->crop.y;
524
 
      crop_info.width = bmp_draw->crop.w;
525
 
      crop_info.height = bmp_draw->crop.h;
526
 
 
527
 
      crop_image = CropImage( image, &crop_info, &exception );
528
 
      if (crop_image)
529
 
        {
530
 
          image=DestroyImageList(image);
531
 
          image = crop_image;
532
 
          bmp_draw->bmp.data = (void*)image;
533
 
        }
534
 
      else
535
 
        InheritException(&ddata->image->exception,&exception);
536
 
    }
537
 
 
538
 
  QueryColorDatabase( "white", &white, &exception );
539
 
 
540
 
  if ( ddata->image_info->texture ||
541
 
       !(IsColorEqual(&ddata->image_info->background_color,&white)) ||
542
 
       ddata->image_info->background_color.opacity != OpaqueOpacity )
543
 
  {
544
 
    MagickPixelPacket
545
 
      white;
546
 
 
547
 
    /*
548
 
      Set image white background to transparent so that it may be
549
 
      overlaid over non-white backgrounds.
550
 
    */
551
 
    QueryMagickColor( "white", &white, &exception );
552
 
    TransparentPaintImage( image, &white, QuantumRange, MagickFalse );
553
 
  }
554
 
 
555
 
  width = fabs(bmp_draw->pixel_width * (double) bmp_draw->crop.w);
556
 
  height = fabs(bmp_draw->pixel_height * (double) bmp_draw->crop.h);
557
 
  magick_wand=NewMagickWandFromImage(image);
558
 
  (void) DrawComposite(WmfDrawingWand, CopyCompositeOp,
559
 
    XC(bmp_draw->pt.x) * ddata->scale_x, YC(bmp_draw->pt.y) * ddata->scale_y,
560
 
    width * ddata->scale_x, height * ddata->scale_y, magick_wand);
561
 
  magick_wand=DestroyMagickWand(magick_wand);
562
 
 
563
 
#if 0
564
 
  printf("bmp_draw->bmp.data   = 0x%lx\n", (long)bmp_draw->bmp.data);
565
 
  printf("registry id          = %li\n", id);
566
 
  /* printf("pixel_width          = %g\n", bmp_draw->pixel_width); */
567
 
  /* printf("pixel_height         = %g\n", bmp_draw->pixel_height); */
568
 
  printf("bmp_draw->bmp WxH    = %ix%i\n", bmp_draw->bmp.width, bmp_draw->bmp.height);
569
 
  printf("bmp_draw->crop WxH   = %ix%i\n", bmp_draw->crop.w, bmp_draw->crop.h);
570
 
  printf("bmp_draw->crop x,y   = %i,%i\n", bmp_draw->crop.x, bmp_draw->crop.y);
571
 
  printf("image size WxH       = %lux%lu\n", image->columns, image->rows);
572
 
#endif
573
 
}
574
 
 
575
 
static void ipa_bmp_read(wmfAPI * API, wmfBMP_Read_t * bmp_read) {
576
 
  wmf_magick_t
577
 
    *ddata = WMF_MAGICK_GetData(API);
578
 
 
579
 
  ExceptionInfo
580
 
    exception;
581
 
 
582
 
  Image
583
 
    *image;
584
 
 
585
 
  ImageInfo
586
 
    *image_info;
587
 
 
588
 
  bmp_read->bmp.data = 0;
589
 
 
590
 
  GetExceptionInfo(&exception);
591
 
 
592
 
  image_info=CloneImageInfo((ImageInfo *) 0);
593
 
  (void) CopyMagickString(image_info->magick,"DIB",MaxTextExtent);
594
 
  if (bmp_read->width || bmp_read->height)
595
 
    {
596
 
      char
597
 
        size[MaxTextExtent];
598
 
 
599
 
      (void) FormatMagickString(size,MaxTextExtent,"%ux%u",bmp_read->width,
600
 
        bmp_read->height);
601
 
      CloneString(&image_info->size,size);
602
 
    }
603
 
#if 0
604
 
  printf("ipa_bmp_read: buffer=0x%lx length=%ld, width=%i, height=%i\n",
605
 
   (long) bmp_read->buffer, bmp_read->length,
606
 
   bmp_read->width, bmp_read->height);
607
 
#endif
608
 
  image=BlobToImage(image_info, (const void *) bmp_read->buffer,
609
 
    bmp_read->length, &exception);
610
 
  image_info=DestroyImageInfo(image_info);
611
 
  if (image == (Image *) NULL)
612
 
    {
613
 
      char
614
 
        description[MaxTextExtent];
615
 
 
616
 
      (void) FormatMagickString(description,MaxTextExtent,
617
 
        "packed DIB at offset %ld",bmp_read->offset);
618
 
      (void) ThrowMagickException(&ddata->image->exception,GetMagickModule(),
619
 
        CorruptImageError,exception.reason,"`%s'",exception.description);
620
 
    }
621
 
  else
622
 
    {
623
 
#if 0
624
 
      printf("ipa_bmp_read: rows=%ld,columns=%ld\n\n", image->rows, image->columns);
625
 
#endif
626
 
 
627
 
      bmp_read->bmp.data   = (void*)image;
628
 
      bmp_read->bmp.width  = (U16)image->columns;
629
 
      bmp_read->bmp.height = (U16)image->rows;
630
 
    }
631
 
}
632
 
 
633
 
static void ipa_bmp_free(wmfAPI * API, wmfBMP * bmp)
634
 
{
635
 
  (void) API;
636
 
  DestroyImageList((Image*)bmp->data);
637
 
  bmp->data = (void*) 0;
638
 
  bmp->width = (U16) 0;
639
 
  bmp->height = (U16) 0;
640
 
}
641
 
 
642
 
/*
643
 
  This called by wmf_play() the *first* time the meta file is played
644
 
 */
645
 
static void ipa_device_open(wmfAPI * API)
646
 
{
647
 
  wmf_magick_t
648
 
    *ddata = WMF_MAGICK_GetData (API);
649
 
 
650
 
  ddata->pattern_id = 0;
651
 
  ddata->clipping = MagickFalse;
652
 
  ddata->clip_mask_id = 0;
653
 
 
654
 
  ddata->push_depth = 0;
655
 
 
656
 
  ddata->draw_wand = DrawAllocateWand(ddata->draw_info,ddata->image);
657
 
}
658
 
 
659
 
/*
660
 
  This called by wmf_api_destroy()
661
 
 */
662
 
static void ipa_device_close(wmfAPI * API)
663
 
{
664
 
  wmf_magick_t
665
 
    *ddata = WMF_MAGICK_GetData(API);
666
 
 
667
 
  DestroyDrawingWand(ddata->draw_wand);
668
 
  DestroyDrawInfo(ddata->draw_info);
669
 
  RelinquishMagickMemory(WMF_MAGICK_GetFontData(API)->ps_name);
670
 
}
671
 
 
672
 
/*
673
 
  This called from the beginning of each play for initial page setup
674
 
 */
675
 
static void ipa_device_begin(wmfAPI * API)
676
 
{
677
 
  char
678
 
    comment[MaxTextExtent];
679
 
 
680
 
  wmf_magick_t
681
 
    *ddata = WMF_MAGICK_GetData(API);
682
 
 
683
 
  /* Make SVG output happy */
684
 
  (void) PushDrawingWand(WmfDrawingWand);
685
 
 
686
 
  DrawSetViewbox(WmfDrawingWand, 0, 0, ddata->image->columns, ddata->image->rows );
687
 
 
688
 
  (void) FormatMagickString(comment,MaxTextExtent,"Created by ImageMagick %s",
689
 
    GetMagickVersion((unsigned long *) NULL));
690
 
  DrawComment(WmfDrawingWand,comment);
691
 
 
692
 
  /* Scale width and height to image */
693
 
  DrawScale(WmfDrawingWand, ddata->scale_x, ddata->scale_y);
694
 
 
695
 
  /* Translate to TL corner of bounding box */
696
 
  DrawTranslate(WmfDrawingWand, ddata->translate_x, ddata->translate_y);
697
 
 
698
 
  /* Apply rotation */
699
 
  DrawRotate(WmfDrawingWand, ddata->rotate);
700
 
 
701
 
  if (ddata->image_info->texture == NULL)
702
 
    {
703
 
      PixelWand
704
 
        *background_color;
705
 
 
706
 
      /* Draw rectangle in background color */
707
 
      background_color=NewPixelWand();
708
 
      PixelSetQuantumColor(background_color,&ddata->image->background_color);
709
 
      DrawSetFillColor(WmfDrawingWand,background_color);
710
 
      background_color=DestroyPixelWand(background_color);
711
 
      DrawRectangle(WmfDrawingWand,
712
 
                     XC(ddata->bbox.TL.x),YC(ddata->bbox.TL.y),
713
 
                     XC(ddata->bbox.BR.x),YC(ddata->bbox.BR.y));
714
 
    }
715
 
  else
716
 
    {
717
 
      /* Draw rectangle with texture image the SVG way */
718
 
      Image
719
 
        *image;
720
 
 
721
 
      ImageInfo
722
 
        *image_info;
723
 
 
724
 
      ExceptionInfo
725
 
        exception;
726
 
 
727
 
      GetExceptionInfo(&exception);
728
 
 
729
 
      image_info = CloneImageInfo((ImageInfo *) 0);
730
 
      (void) CopyMagickString(image_info->filename,ddata->image_info->texture,
731
 
        MaxTextExtent);
732
 
      if ( ddata->image_info->size )
733
 
        CloneString(&image_info->size,ddata->image_info->size);
734
 
 
735
 
      image = ReadImage(image_info,&exception);
736
 
      image_info=DestroyImageInfo(image_info);
737
 
      if (image)
738
 
        {
739
 
          char
740
 
            pattern_id[30];
741
 
 
742
 
          MagickWand
743
 
            *magick_wand;
744
 
 
745
 
          (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent);
746
 
          DrawPushDefs(WmfDrawingWand);
747
 
          draw_pattern_push(API,ddata->pattern_id,image->columns,image->rows);
748
 
          magick_wand=NewMagickWandFromImage(image);
749
 
          (void) DrawComposite(WmfDrawingWand,CopyCompositeOp,0,0,
750
 
            image->columns,image->rows,magick_wand);
751
 
          magick_wand=DestroyMagickWand(magick_wand);
752
 
          (void) DrawPopPattern(WmfDrawingWand);
753
 
          DrawPopDefs(WmfDrawingWand);
754
 
          (void) FormatMagickString(pattern_id,MaxTextExtent,"#brush_%lu",
755
 
            ddata->pattern_id);
756
 
          (void) DrawSetFillPatternURL(WmfDrawingWand,pattern_id);
757
 
          ++ddata->pattern_id;
758
 
 
759
 
          DrawRectangle(WmfDrawingWand,
760
 
                         XC(ddata->bbox.TL.x),YC(ddata->bbox.TL.y),
761
 
                         XC(ddata->bbox.BR.x),YC(ddata->bbox.BR.y));
762
 
          image=DestroyImageList(image);
763
 
        }
764
 
      else
765
 
        {
766
 
          LogMagickEvent(CoderEvent,GetMagickModule(),
767
 
            "reading texture image failed!");
768
 
          InheritException(&ddata->image->exception,&exception);
769
 
        }
770
 
    }
771
 
 
772
 
  DrawSetClipRule(WmfDrawingWand,EvenOddRule); /* Default for WMF is ALTERNATE polygon fill mode */
773
 
  draw_fill_color_string(WmfDrawingWand,"none"); /* Default brush is WHITE_BRUSH */
774
 
  draw_stroke_color_string(WmfDrawingWand,"none"); /* Default pen is BLACK_PEN */
775
 
  DrawSetStrokeLineCap(WmfDrawingWand,ButtCap); /* Default linecap is PS_ENDCAP_FLAT */
776
 
  DrawSetStrokeLineJoin(WmfDrawingWand,MiterJoin); /* Default linejoin is PS_JOIN_MITER */
777
 
  draw_under_color_string(WmfDrawingWand,"white"); /* Default text box is white */
778
 
}
779
 
 
780
 
/*
781
 
  This called from the end of each play for page termination
782
 
 */
783
 
static void ipa_device_end(wmfAPI * API)
784
 
{
785
 
  wmf_magick_t
786
 
    *ddata = WMF_MAGICK_GetData(API);
787
 
 
788
 
  /* Reset any existing clip paths by popping wand */
789
 
  if (ddata->clipping)
790
 
    (void) PopDrawingWand(WmfDrawingWand);
791
 
  ddata->clipping = MagickFalse;
792
 
 
793
 
  /* Make SVG output happy */
794
 
  (void) PopDrawingWand(WmfDrawingWand);
795
 
}
796
 
 
797
 
static void ipa_flood_interior(wmfAPI * API, wmfFlood_t * flood)
798
 
{
799
 
  /* Save graphic wand */
800
 
  (void) PushDrawingWand(WmfDrawingWand);
801
 
 
802
 
  draw_fill_color_rgb(API,&(flood->color));
803
 
 
804
 
  DrawColor(WmfDrawingWand,XC(flood->pt.x), YC(flood->pt.y),
805
 
            FillToBorderMethod);
806
 
 
807
 
  /* Restore graphic wand */
808
 
  (void) PopDrawingWand(WmfDrawingWand);
809
 
}
810
 
 
811
 
static void ipa_flood_exterior(wmfAPI * API, wmfFlood_t * flood)
812
 
{
813
 
  /* Save graphic wand */
814
 
  (void) PushDrawingWand(WmfDrawingWand);
815
 
 
816
 
  draw_fill_color_rgb(API,&(flood->color));
817
 
 
818
 
  if (flood->type == FLOODFILLSURFACE)
819
 
    DrawColor(WmfDrawingWand, XC(flood->pt.x), YC(flood->pt.y),
820
 
              FloodfillMethod);
821
 
  else
822
 
    DrawColor(WmfDrawingWand, XC(flood->pt.x), YC(flood->pt.y),
823
 
              FillToBorderMethod);
824
 
 
825
 
  /* Restore graphic wand */
826
 
  (void) PopDrawingWand(WmfDrawingWand);
827
 
}
828
 
 
829
 
static void ipa_draw_pixel(wmfAPI * API, wmfDrawPixel_t * draw_pixel)
830
 
{
831
 
  /* Save graphic wand */
832
 
  (void) PushDrawingWand(WmfDrawingWand);
833
 
 
834
 
  draw_stroke_color_string(WmfDrawingWand,"none");
835
 
 
836
 
  draw_fill_color_rgb(API,&(draw_pixel->color));
837
 
 
838
 
  DrawRectangle(WmfDrawingWand,
839
 
                 XC(draw_pixel->pt.x),
840
 
                 YC(draw_pixel->pt.y),
841
 
                 XC(draw_pixel->pt.x + draw_pixel->pixel_width),
842
 
                 YC(draw_pixel->pt.y + draw_pixel->pixel_height));
843
 
 
844
 
  /* Restore graphic wand */
845
 
  (void) PopDrawingWand(WmfDrawingWand);
846
 
}
847
 
 
848
 
static void ipa_draw_pie(wmfAPI * API, wmfDrawArc_t * draw_arc)
849
 
{
850
 
  util_draw_arc(API, draw_arc, magick_arc_pie);
851
 
}
852
 
 
853
 
static void ipa_draw_chord(wmfAPI * API, wmfDrawArc_t * draw_arc)
854
 
{
855
 
  util_draw_arc(API, draw_arc, magick_arc_chord);
856
 
}
857
 
 
858
 
static void ipa_draw_arc(wmfAPI * API, wmfDrawArc_t * draw_arc)
859
 
{
860
 
  util_draw_arc(API, draw_arc, magick_arc_open);
861
 
}
862
 
 
863
 
static void ipa_draw_ellipse(wmfAPI * API, wmfDrawArc_t * draw_arc)
864
 
{
865
 
  util_draw_arc(API, draw_arc, magick_arc_ellipse);
866
 
}
867
 
 
868
 
static void util_draw_arc(wmfAPI * API,
869
 
          wmfDrawArc_t * draw_arc, magick_arc_t finish)
870
 
{
871
 
  wmfD_Coord
872
 
    BR,
873
 
    O,
874
 
    TL,
875
 
    center,
876
 
    end,
877
 
    start;
878
 
 
879
 
  double
880
 
    phi_e = 360,
881
 
    phi_s = 0;
882
 
 
883
 
  double
884
 
    Rx,
885
 
    Ry;
886
 
 
887
 
  /* Save graphic wand */
888
 
  (void) PushDrawingWand(WmfDrawingWand);
889
 
 
890
 
  if (TO_FILL(draw_arc) || TO_DRAW(draw_arc))
891
 
    {
892
 
      center.x = (draw_arc->TL.x + draw_arc->BR.x) / 2;
893
 
      center.y = (draw_arc->TL.y + draw_arc->BR.y) / 2;
894
 
      start = center;
895
 
      end = center;
896
 
 
897
 
      if (finish != magick_arc_ellipse)
898
 
        {
899
 
          draw_arc->start.x += center.x;
900
 
          draw_arc->start.y += center.y;
901
 
 
902
 
          draw_arc->end.x += center.x;
903
 
          draw_arc->end.y += center.y;
904
 
        }
905
 
 
906
 
      TL = draw_arc->TL;
907
 
      BR = draw_arc->BR;
908
 
 
909
 
      O = center;
910
 
 
911
 
      if (finish != magick_arc_ellipse)
912
 
        {
913
 
          start = draw_arc->start;
914
 
          end = draw_arc->end;
915
 
        }
916
 
 
917
 
      Rx = (BR.x - TL.x) / 2;
918
 
      Ry = (BR.y - TL.y) / 2;
919
 
 
920
 
      if (finish != magick_arc_ellipse)
921
 
        {
922
 
          start.x -= O.x;
923
 
          start.y -= O.y;
924
 
 
925
 
          end.x -= O.x;
926
 
          end.y -= O.y;
927
 
 
928
 
          phi_s = atan2((double) start.y, (double) start.x) * 180 / MagickPI;
929
 
          phi_e = atan2((double) end.y, (double) end.x) * 180 / MagickPI;
930
 
 
931
 
          if (phi_e <= phi_s)
932
 
            phi_e += 360;
933
 
        }
934
 
 
935
 
      util_set_pen(API, draw_arc->dc);
936
 
      if (finish == magick_arc_open)
937
 
        draw_fill_color_string(WmfDrawingWand,"none");
938
 
      else
939
 
        util_set_brush(API, draw_arc->dc, BrushApplyFill);
940
 
 
941
 
      if (finish == magick_arc_ellipse)
942
 
        DrawEllipse(WmfDrawingWand, XC(O.x), YC(O.y), Rx, Ry, 0, 360);
943
 
      else if (finish == magick_arc_pie)
944
 
        {
945
 
          DrawPathStart(WmfDrawingWand);
946
 
          DrawPathMoveToAbsolute(WmfDrawingWand, XC(O.x+start.x), 
947
 
            YC(O.y+start.y));
948
 
          DrawPathEllipticArcAbsolute(WmfDrawingWand, Rx, Ry, 0, MagickFalse,
949
 
            MagickTrue, XC(O.x+end.x), YC(O.y+end.y));
950
 
          DrawPathLineToAbsolute(WmfDrawingWand, XC(O.x), YC(O.y));
951
 
          DrawPathClose(WmfDrawingWand);
952
 
          DrawPathFinish(WmfDrawingWand);
953
 
        }
954
 
        else if (finish == magick_arc_chord)
955
 
        {
956
 
          DrawArc(WmfDrawingWand, XC(draw_arc->TL.x), YC(draw_arc->TL.y),
957
 
            XC(draw_arc->BR.x), XC(draw_arc->BR.y), phi_s, phi_e);
958
 
          DrawLine(WmfDrawingWand, XC(draw_arc->BR.x-start.x), 
959
 
            YC(draw_arc->BR.y-start.y), XC(draw_arc->BR.x-end.x),
960
 
            YC(draw_arc->BR.y-end.y));
961
 
        }
962
 
        else      /* if (finish == magick_arc_open) */
963
 
          DrawArc(WmfDrawingWand, XC(draw_arc->TL.x), YC(draw_arc->TL.y),
964
 
            XC(draw_arc->BR.x), XC(draw_arc->BR.y), phi_s, phi_e);
965
 
    }
966
 
 
967
 
  /* Restore graphic wand */
968
 
  (void) PopDrawingWand(WmfDrawingWand);
969
 
}
970
 
 
971
 
static void ipa_draw_line(wmfAPI * API, wmfDrawLine_t * draw_line)
972
 
{
973
 
  /* Save graphic wand */
974
 
  (void) PushDrawingWand(WmfDrawingWand);
975
 
 
976
 
  if (TO_DRAW(draw_line))
977
 
    {
978
 
      util_set_pen(API, draw_line->dc);
979
 
      DrawLine(WmfDrawingWand,
980
 
               XC(draw_line->from.x), YC(draw_line->from.y),
981
 
               XC(draw_line->to.x), YC(draw_line->to.y));
982
 
    }
983
 
 
984
 
  /* Restore graphic wand */
985
 
  (void) PopDrawingWand(WmfDrawingWand);
986
 
}
987
 
 
988
 
static void ipa_poly_line(wmfAPI * API, wmfPolyLine_t * polyline)
989
 
{
990
 
  if (polyline->count <= 2)
991
 
    return;
992
 
 
993
 
  if (TO_DRAW(polyline))
994
 
    {
995
 
      int
996
 
        point;
997
 
 
998
 
      /* Save graphic wand */
999
 
      (void) PushDrawingWand(WmfDrawingWand);
1000
 
 
1001
 
      util_set_pen(API, polyline->dc);
1002
 
 
1003
 
      DrawPathStart(WmfDrawingWand);
1004
 
      DrawPathMoveToAbsolute(WmfDrawingWand,
1005
 
                             XC(polyline->pt[0].x),
1006
 
                             YC(polyline->pt[0].y));
1007
 
      for (point = 1; point < polyline->count; point++)
1008
 
        {
1009
 
          DrawPathLineToAbsolute(WmfDrawingWand,
1010
 
                                 XC(polyline->pt[point].x),
1011
 
                                 YC(polyline->pt[point].y));
1012
 
        }
1013
 
      DrawPathFinish(WmfDrawingWand);
1014
 
 
1015
 
      /* Restore graphic wand */
1016
 
      (void) PopDrawingWand(WmfDrawingWand);
1017
 
    }
1018
 
}
1019
 
 
1020
 
static void ipa_draw_polygon(wmfAPI * API, wmfPolyLine_t * polyline)
1021
 
{
1022
 
  if (polyline->count <= 2)
1023
 
    return;
1024
 
 
1025
 
  if (TO_FILL(polyline) || TO_DRAW(polyline))
1026
 
    {
1027
 
      int
1028
 
        point;
1029
 
 
1030
 
      /* Save graphic wand */
1031
 
      (void) PushDrawingWand(WmfDrawingWand);
1032
 
 
1033
 
      util_set_pen(API, polyline->dc);
1034
 
      util_set_brush(API, polyline->dc, BrushApplyFill);
1035
 
 
1036
 
      DrawPathStart(WmfDrawingWand);
1037
 
      DrawPathMoveToAbsolute(WmfDrawingWand,
1038
 
                             XC(polyline->pt[0].x),
1039
 
                             YC(polyline->pt[0].y));
1040
 
      for (point = 1; point < polyline->count; point++)
1041
 
        {
1042
 
          DrawPathLineToAbsolute(WmfDrawingWand,
1043
 
                                 XC(polyline->pt[point].x),
1044
 
                                 YC(polyline->pt[point].y));
1045
 
        }
1046
 
      DrawPathClose(WmfDrawingWand);
1047
 
      DrawPathFinish(WmfDrawingWand);
1048
 
 
1049
 
      /* Restore graphic wand */
1050
 
      (void) PopDrawingWand(WmfDrawingWand);
1051
 
    }
1052
 
}
1053
 
 
1054
 
/* Draw a polypolygon.  A polypolygon is a list of polygons */
1055
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
1056
 
static void ipa_draw_polypolygon(wmfAPI * API, wmfPolyPoly_t* polypolygon)
1057
 
{
1058
 
  if (TO_FILL(polypolygon) || TO_DRAW(polypolygon))
1059
 
    {
1060
 
      int
1061
 
        polygon,
1062
 
        point;
1063
 
 
1064
 
      wmfPolyLine_t
1065
 
        polyline;
1066
 
 
1067
 
      /* Save graphic wand */
1068
 
      (void) PushDrawingWand(WmfDrawingWand);
1069
 
 
1070
 
      util_set_pen(API, polypolygon->dc);
1071
 
      util_set_brush(API, polypolygon->dc, BrushApplyFill);
1072
 
 
1073
 
      DrawPathStart(WmfDrawingWand);
1074
 
      for (polygon = 0; polygon < polypolygon->npoly; polygon++)
1075
 
        {
1076
 
          polyline.dc = polypolygon->dc;
1077
 
          polyline.pt = polypolygon->pt[polygon];
1078
 
          polyline.count = polypolygon->count[polygon];
1079
 
          if ((polyline.count > 2) && polyline.pt)
1080
 
            {
1081
 
              DrawPathMoveToAbsolute(WmfDrawingWand,
1082
 
                                     XC(polyline.pt[0].x),
1083
 
                                     YC(polyline.pt[0].y));
1084
 
              for (point = 1; point < polyline.count; point++)
1085
 
                {
1086
 
                  DrawPathLineToAbsolute(WmfDrawingWand,
1087
 
                                         XC(polyline.pt[point].x),
1088
 
                                         YC(polyline.pt[point].y));
1089
 
                }
1090
 
              DrawPathClose(WmfDrawingWand);
1091
 
            }
1092
 
        }
1093
 
      DrawPathFinish(WmfDrawingWand);
1094
 
 
1095
 
      /* Restore graphic wand */
1096
 
      (void) PopDrawingWand(WmfDrawingWand);
1097
 
    }
1098
 
}
1099
 
#endif
1100
 
 
1101
 
static void ipa_draw_rectangle(wmfAPI * API, wmfDrawRectangle_t * draw_rect)
1102
 
{
1103
 
  /* Save graphic wand */
1104
 
  (void) PushDrawingWand(WmfDrawingWand);
1105
 
 
1106
 
  if (TO_FILL(draw_rect) || TO_DRAW(draw_rect))
1107
 
    {
1108
 
      util_set_pen(API, draw_rect->dc);
1109
 
      util_set_brush(API, draw_rect->dc, BrushApplyFill);
1110
 
 
1111
 
      if ((draw_rect->width > 0) || (draw_rect->height > 0))
1112
 
        DrawRoundRectangle(WmfDrawingWand,
1113
 
                           XC(draw_rect->TL.x), YC(draw_rect->TL.y),
1114
 
                           XC(draw_rect->BR.x), YC(draw_rect->BR.y),
1115
 
                           draw_rect->width / 2, draw_rect->height / 2);
1116
 
      else
1117
 
        DrawRectangle(WmfDrawingWand,
1118
 
                      XC(draw_rect->TL.x), YC(draw_rect->TL.y),
1119
 
                      XC(draw_rect->BR.x), YC(draw_rect->BR.y));
1120
 
    }
1121
 
 
1122
 
  /* Restore graphic wand */
1123
 
  (void) PopDrawingWand(WmfDrawingWand);
1124
 
}
1125
 
 
1126
 
/* Draw an un-filled rectangle using the current brush */
1127
 
static void ipa_region_frame(wmfAPI * API, wmfPolyRectangle_t * poly_rect)
1128
 
{
1129
 
  /* Save graphic wand */
1130
 
  (void) PushDrawingWand(WmfDrawingWand);
1131
 
 
1132
 
  if (TO_FILL(poly_rect) || TO_DRAW(poly_rect))
1133
 
    {
1134
 
      long
1135
 
        i;
1136
 
 
1137
 
      draw_fill_color_string(WmfDrawingWand,"none");
1138
 
      util_set_brush(API, poly_rect->dc, BrushApplyStroke);
1139
 
 
1140
 
      for (i = 0; i < (long) poly_rect->count; i++)
1141
 
        {
1142
 
          DrawRectangle(WmfDrawingWand,
1143
 
                         XC(poly_rect->TL[i].x), YC(poly_rect->TL[i].y),
1144
 
                         XC(poly_rect->BR[i].x), YC(poly_rect->BR[i].y));
1145
 
        }
1146
 
    }
1147
 
 
1148
 
  /* Restore graphic wand */
1149
 
  (void) PopDrawingWand(WmfDrawingWand);
1150
 
}
1151
 
 
1152
 
static void ipa_region_paint(wmfAPI * API, wmfPolyRectangle_t * poly_rect)
1153
 
{
1154
 
 
1155
 
  if (poly_rect->count == 0)
1156
 
    return;
1157
 
 
1158
 
  /* Save graphic wand */
1159
 
  (void) PushDrawingWand(WmfDrawingWand);
1160
 
 
1161
 
  if (TO_FILL (poly_rect))
1162
 
    {
1163
 
      long
1164
 
        i;
1165
 
 
1166
 
      draw_stroke_color_string(WmfDrawingWand,"none");
1167
 
      util_set_brush(API, poly_rect->dc, BrushApplyFill);
1168
 
 
1169
 
      for (i = 0; i < (long) poly_rect->count; i++)
1170
 
        {
1171
 
          DrawRectangle(WmfDrawingWand,
1172
 
                         XC(poly_rect->TL[i].x), YC(poly_rect->TL[i].y),
1173
 
                         XC(poly_rect->BR[i].x), YC(poly_rect->BR[i].y));
1174
 
        }
1175
 
    }
1176
 
 
1177
 
  /* Restore graphic wand */
1178
 
  (void) PopDrawingWand(WmfDrawingWand);
1179
 
}
1180
 
 
1181
 
static void ipa_region_clip(wmfAPI *API, wmfPolyRectangle_t *poly_rect)
1182
 
{
1183
 
  long
1184
 
    i;
1185
 
 
1186
 
  wmf_magick_t
1187
 
    *ddata = WMF_MAGICK_GetData (API);
1188
 
 
1189
 
  /* Reset any existing clip paths by popping wand */
1190
 
  if (ddata->clipping)
1191
 
    (void) PopDrawingWand(WmfDrawingWand);
1192
 
  ddata->clipping = MagickFalse;
1193
 
 
1194
 
  if (poly_rect->count > 0)
1195
 
    {
1196
 
      char
1197
 
        clip_mask_id[30];
1198
 
 
1199
 
      /* Define clip path */
1200
 
      ddata->clip_mask_id++;
1201
 
      DrawPushDefs(WmfDrawingWand);
1202
 
      (void) FormatMagickString(clip_mask_id,MaxTextExtent,"clip_%lu",
1203
 
        ddata->clip_mask_id);
1204
 
      DrawPushClipPath(WmfDrawingWand,clip_mask_id);
1205
 
      (void) PushDrawingWand(WmfDrawingWand);
1206
 
      for (i = 0; i < (long) poly_rect->count; i++)
1207
 
        {
1208
 
          DrawRectangle(WmfDrawingWand,
1209
 
                         XC(poly_rect->TL[i].x), YC(poly_rect->TL[i].y),
1210
 
                         XC(poly_rect->BR[i].x), YC(poly_rect->BR[i].y));
1211
 
        }
1212
 
      (void) PopDrawingWand(WmfDrawingWand);
1213
 
      DrawPopClipPath(WmfDrawingWand);
1214
 
      DrawPopDefs(WmfDrawingWand);
1215
 
 
1216
 
      /* Push wand for new clip paths */
1217
 
      (void) PushDrawingWand(WmfDrawingWand);
1218
 
      (void) DrawSetClipPath(WmfDrawingWand,clip_mask_id);
1219
 
      ddata->clipping = MagickTrue;
1220
 
    }
1221
 
}
1222
 
 
1223
 
static void ipa_functions(wmfAPI *API)
1224
 
{
1225
 
  wmf_magick_t
1226
 
    *ddata = 0;
1227
 
 
1228
 
  wmfFunctionReference
1229
 
    *FR = (wmfFunctionReference *) API->function_reference;
1230
 
 
1231
 
  /*
1232
 
     IPA function reference links
1233
 
   */
1234
 
  FR->device_open = ipa_device_open;
1235
 
  FR->device_close = ipa_device_close;
1236
 
  FR->device_begin = ipa_device_begin;
1237
 
  FR->device_end = ipa_device_end;
1238
 
  FR->flood_interior = ipa_flood_interior;
1239
 
  FR->flood_exterior = ipa_flood_exterior;
1240
 
  FR->draw_pixel = ipa_draw_pixel;
1241
 
  FR->draw_pie = ipa_draw_pie;
1242
 
  FR->draw_chord = ipa_draw_chord;
1243
 
  FR->draw_arc = ipa_draw_arc;
1244
 
  FR->draw_ellipse = ipa_draw_ellipse;
1245
 
  FR->draw_line = ipa_draw_line;
1246
 
  FR->poly_line = ipa_poly_line;
1247
 
  FR->draw_polygon = ipa_draw_polygon;
1248
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
1249
 
  FR->draw_polypolygon = ipa_draw_polypolygon;
1250
 
#endif
1251
 
  FR->draw_rectangle = ipa_draw_rectangle;
1252
 
  FR->rop_draw = ipa_rop_draw;
1253
 
  FR->bmp_draw = ipa_bmp_draw;
1254
 
  FR->bmp_read = ipa_bmp_read;
1255
 
  FR->bmp_free = ipa_bmp_free;
1256
 
  FR->draw_text = ipa_draw_text;
1257
 
  FR->udata_init = ipa_udata_init;
1258
 
  FR->udata_copy = ipa_udata_copy;
1259
 
  FR->udata_set = ipa_udata_set;
1260
 
  FR->udata_free = ipa_udata_free;
1261
 
  FR->region_frame = ipa_region_frame;
1262
 
  FR->region_paint = ipa_region_paint;
1263
 
  FR->region_clip = ipa_region_clip;
1264
 
 
1265
 
  /*
1266
 
     Allocate device data structure
1267
 
   */
1268
 
  ddata = (wmf_magick_t *) wmf_malloc(API, sizeof(wmf_magick_t));
1269
 
  if (ERR(API))
1270
 
    return;
1271
 
 
1272
 
  (void) ResetMagickMemory((void *) ddata, 0, sizeof(wmf_magick_t));
1273
 
  API->device_data = (void *) ddata;
1274
 
 
1275
 
  /*
1276
 
     Device data defaults
1277
 
   */
1278
 
  ddata->image = 0;
1279
 
}
1280
 
 
1281
 
static void ipa_draw_text(wmfAPI * API, wmfDrawText_t * draw_text)
1282
 
{
1283
 
  double
1284
 
    angle = 0,      /* text rotation angle */
1285
 
    bbox_height,    /* bounding box height */
1286
 
    bbox_width,      /* bounding box width */
1287
 
    pointsize = 0;    /* pointsize to output font with desired height */
1288
 
 
1289
 
  TypeMetric
1290
 
    metrics;
1291
 
 
1292
 
  wmfD_Coord
1293
 
    BL,        /* bottom left of bounding box */
1294
 
    BR,        /* bottom right of bounding box */
1295
 
    TL,        /* top left of bounding box */
1296
 
    TR;        /* top right of bounding box */
1297
 
 
1298
 
  wmfD_Coord
1299
 
    point;      /* text placement point */
1300
 
 
1301
 
  wmfFont
1302
 
    *font;
1303
 
 
1304
 
  wmf_magick_t
1305
 
    * ddata = WMF_MAGICK_GetData(API);
1306
 
 
1307
 
  point = draw_text->pt;
1308
 
 
1309
 
  /* Choose bounding box and calculate its width and height */
1310
 
  {
1311
 
    double dx,
1312
 
      dy;
1313
 
 
1314
 
    if ( draw_text->flags)
1315
 
      {
1316
 
        TL = draw_text->TL;
1317
 
        BR = draw_text->BR;
1318
 
        TR.x = draw_text->BR.x;
1319
 
        TR.y = draw_text->TL.y;
1320
 
        BL.x = draw_text->TL.x;
1321
 
        BL.y = draw_text->BR.y;
1322
 
      }
1323
 
    else
1324
 
      {
1325
 
        TL = draw_text->bbox.TL;
1326
 
        BR = draw_text->bbox.BR;
1327
 
        TR = draw_text->bbox.TR;
1328
 
        BL = draw_text->bbox.BL;
1329
 
      }
1330
 
    dx = ((TR.x - TL.x) + (BR.x - BL.x)) / 2;
1331
 
    dy = ((TR.y - TL.y) + (BR.y - BL.y)) / 2;
1332
 
    bbox_width = hypot(dx,dy);
1333
 
    dx = ((BL.x - TL.x) + (BR.x - TR.x)) / 2;
1334
 
    dy = ((BL.y - TL.y) + (BR.y - TR.y)) / 2;
1335
 
    bbox_height = hypot(dx,dy);
1336
 
  }
1337
 
 
1338
 
  font = WMF_DC_FONT(draw_text->dc);
1339
 
 
1340
 
  /* Convert font_height to equivalent pointsize */
1341
 
  pointsize = util_pointsize( API, font, draw_text->str, draw_text->font_height);
1342
 
 
1343
 
  /* Save graphic wand */
1344
 
  (void) PushDrawingWand(WmfDrawingWand);
1345
 
 
1346
 
#if 0
1347
 
  printf("\nipa_draw_text\n");
1348
 
  printf("Text                    = \"%s\"\n", draw_text->str);
1349
 
  /* printf("WMF_FONT_NAME:          = \"%s\"\n", WMF_FONT_NAME(font)); */
1350
 
  printf("WMF_FONT_PSNAME:        = \"%s\"\n", WMF_FONT_PSNAME(font));
1351
 
  printf("Bounding box            TL=%g,%g BR=%g,%g\n",
1352
 
         TL.x, TL.y, BR.x, BR.y );
1353
 
  /* printf("Text box                = %gx%g\n", bbox_width, bbox_height); */
1354
 
  /* printf("WMF_FONT_HEIGHT         = %i\n", (int)WMF_FONT_HEIGHT(font)); */
1355
 
  printf("Pointsize               = %g\n", pointsize);
1356
 
  fflush(stdout);
1357
 
#endif
1358
 
 
1359
 
  /*
1360
 
   * Obtain font metrics if required
1361
 
   *
1362
 
   */
1363
 
  if ((WMF_DC_TEXTALIGN(draw_text->dc) & TA_CENTER) ||
1364
 
      (WMF_TEXT_UNDERLINE(font)) || (WMF_TEXT_STRIKEOUT(font)))
1365
 
    {
1366
 
      Image
1367
 
        *image = ddata->image;
1368
 
 
1369
 
      DrawInfo
1370
 
        *draw_info;
1371
 
 
1372
 
      draw_info=ddata->draw_info;
1373
 
      draw_info->font=WMF_FONT_PSNAME(font);
1374
 
      draw_info->pointsize = pointsize;
1375
 
      draw_info->text=draw_text->str;
1376
 
 
1377
 
      if (GetTypeMetrics(image, draw_info, &metrics) != MagickFalse)
1378
 
        {
1379
 
          /* Center the text if it is not yet centered and should be */
1380
 
          if ((WMF_DC_TEXTALIGN(draw_text->dc) & TA_CENTER))
1381
 
            {
1382
 
              double
1383
 
                text_width = metrics.width * (ddata->scale_y / ddata->scale_x);
1384
 
 
1385
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
1386
 
              point.x -= text_width / 2;
1387
 
#else
1388
 
              point.x += bbox_width / 2 - text_width / 2;
1389
 
#endif
1390
 
            }
1391
 
        }
1392
 
      draw_info->font=NULL;
1393
 
      draw_info->text=NULL;
1394
 
    }
1395
 
 
1396
 
  /* Set text background color */
1397
 
  if (draw_text->flags & ETO_OPAQUE)
1398
 
    {
1399
 
      /* Draw bounding-box background color (META_EXTTEXTOUT mode) */
1400
 
      draw_stroke_color_string(WmfDrawingWand,"none");
1401
 
      draw_fill_color_rgb(API,WMF_DC_BACKGROUND(draw_text->dc));
1402
 
      DrawRectangle(WmfDrawingWand,
1403
 
                    XC(draw_text->TL.x),YC(draw_text->TL.y),
1404
 
                    XC(draw_text->BR.x),YC(draw_text->BR.y));
1405
 
      draw_fill_color_string(WmfDrawingWand,"none");
1406
 
    }
1407
 
  else
1408
 
    {
1409
 
      /* Set text undercolor */
1410
 
      if (WMF_DC_OPAQUE(draw_text->dc))
1411
 
        {
1412
 
          wmfRGB
1413
 
            *box = WMF_DC_BACKGROUND(draw_text->dc);
1414
 
 
1415
 
          PixelWand
1416
 
            *under_color;
1417
 
 
1418
 
          under_color=NewPixelWand();
1419
 
          PixelSetRedQuantum(under_color,ScaleCharToQuantum(box->r));
1420
 
          PixelSetGreenQuantum(under_color,ScaleCharToQuantum(box->g));
1421
 
          PixelSetBlueQuantum(under_color,ScaleCharToQuantum(box->b));
1422
 
          PixelSetOpacityQuantum(under_color,OpaqueOpacity);
1423
 
          DrawSetTextUnderColor(WmfDrawingWand,under_color);
1424
 
          under_color=DestroyPixelWand(under_color);
1425
 
        }
1426
 
      else
1427
 
        draw_under_color_string(WmfDrawingWand,"none");
1428
 
    }
1429
 
 
1430
 
  /* Set text clipping (META_EXTTEXTOUT mode) */
1431
 
  if ( draw_text->flags & ETO_CLIPPED)
1432
 
    {
1433
 
    }
1434
 
 
1435
 
  /* Set stroke color */
1436
 
  draw_stroke_color_string(WmfDrawingWand,"none");
1437
 
 
1438
 
  /* Set fill color */
1439
 
  draw_fill_color_rgb(API,WMF_DC_TEXTCOLOR(draw_text->dc));
1440
 
 
1441
 
  /* Output font size */
1442
 
  (void) DrawSetFontSize(WmfDrawingWand,pointsize);
1443
 
 
1444
 
  /* Output Postscript font name */
1445
 
  (void) DrawSetFont(WmfDrawingWand, WMF_FONT_PSNAME(font));
1446
 
 
1447
 
  /* Translate coordinates so target is 0,0 */
1448
 
  DrawTranslate(WmfDrawingWand, XC(point.x), YC(point.y));
1449
 
 
1450
 
  /* Transform horizontal scale to draw text at 1:1 ratio */
1451
 
  DrawScale(WmfDrawingWand, ddata->scale_y / ddata->scale_x, 1.0);
1452
 
 
1453
 
  /* Apply rotation */
1454
 
  /* ImageMagick's drawing rotation is clockwise from horizontal
1455
 
     while WMF drawing rotation is counterclockwise from horizontal */
1456
 
  angle = fabs(RadiansToDegrees(2 * MagickPI - WMF_TEXT_ANGLE(font)));
1457
 
  if (angle == 360)
1458
 
    angle = 0;
1459
 
  if (angle != 0)
1460
 
    DrawRotate(WmfDrawingWand, angle);
1461
 
 
1462
 
  /*
1463
 
   * Render text
1464
 
   *
1465
 
   */
1466
 
 
1467
 
  /* Output string */
1468
 
  DrawAnnotation(WmfDrawingWand, 0, 0, (unsigned char*)draw_text->str);
1469
 
 
1470
 
  /* Underline text the Windows way (at the bottom) */
1471
 
  if (WMF_TEXT_UNDERLINE(font))
1472
 
    {
1473
 
      double
1474
 
        line_height;
1475
 
 
1476
 
      wmfD_Coord
1477
 
        ulBR,      /* bottom right of underline rectangle */
1478
 
        ulTL;      /* top left of underline rectangle */
1479
 
 
1480
 
      line_height = ((double)1/(ddata->scale_x))*metrics.underline_thickness;
1481
 
      if (metrics.underline_thickness < 1.5)
1482
 
        line_height *= 0.55;
1483
 
      ulTL.x = 0;
1484
 
      ulTL.y = fabs(metrics.descent) - line_height;
1485
 
      ulBR.x = metrics.width;
1486
 
      ulBR.y = fabs(metrics.descent);
1487
 
 
1488
 
      DrawRectangle(WmfDrawingWand,
1489
 
                    XC(ulTL.x), YC(ulTL.y), XC(ulBR.x), YC(ulBR.y));
1490
 
    }
1491
 
 
1492
 
  /* Strikeout text the Windows way */
1493
 
  if (WMF_TEXT_STRIKEOUT(font))
1494
 
    {
1495
 
      double line_height;
1496
 
 
1497
 
      wmfD_Coord
1498
 
        ulBR,      /* bottom right of strikeout rectangle */
1499
 
        ulTL;      /* top left of strikeout rectangle */
1500
 
 
1501
 
      line_height = ((double)1/(ddata->scale_x))*metrics.underline_thickness;
1502
 
 
1503
 
      if (metrics.underline_thickness < 2.0)
1504
 
        line_height *= 0.55;
1505
 
      ulTL.x = 0;
1506
 
      ulTL.y = -(((double) metrics.ascent) / 2 + line_height / 2);
1507
 
      ulBR.x = metrics.width;
1508
 
      ulBR.y = -(((double) metrics.ascent) / 2 - line_height / 2);
1509
 
 
1510
 
      DrawRectangle(WmfDrawingWand,
1511
 
                    XC(ulTL.x), YC(ulTL.y), XC(ulBR.x), YC(ulBR.y));
1512
 
 
1513
 
    }
1514
 
 
1515
 
  /* Restore graphic wand */
1516
 
  (void) PopDrawingWand(WmfDrawingWand);
1517
 
 
1518
 
#if 0
1519
 
  (void) PushDrawingWand(WmfDrawingWand);
1520
 
  draw_stroke_color_string(WmfDrawingWand,"red");
1521
 
  draw_fill_color_string(WmfDrawingWand,"none");
1522
 
  DrawRectangle(WmfDrawingWand,
1523
 
                XC(TL.x), YC(TL.y),
1524
 
                XC(BR.x), YC(BR.y));
1525
 
  draw_stroke_color_string(WmfDrawingWand,"none");
1526
 
  (void) PopDrawingWand(WmfDrawingWand);
1527
 
#endif
1528
 
 
1529
 
}
1530
 
 
1531
 
static void ipa_udata_init(wmfAPI * API, wmfUserData_t * userdata)
1532
 
{
1533
 
  (void) API;
1534
 
  (void) userdata;
1535
 
  /* wmf_magick_t* ddata = WMF_MAGICK_GetData (API); */
1536
 
 
1537
 
}
1538
 
 
1539
 
static void ipa_udata_copy(wmfAPI * API, wmfUserData_t * userdata)
1540
 
{
1541
 
  (void) API;
1542
 
  (void) userdata;
1543
 
  /* wmf_magick_t* ddata = WMF_MAGICK_GetData (API); */
1544
 
 
1545
 
}
1546
 
 
1547
 
static void ipa_udata_set(wmfAPI * API, wmfUserData_t * userdata)
1548
 
{
1549
 
  (void) API;
1550
 
  (void) userdata;
1551
 
  /* wmf_magick_t* ddata = WMF_MAGICK_GetData (API); */
1552
 
 
1553
 
}
1554
 
 
1555
 
static void ipa_udata_free(wmfAPI * API, wmfUserData_t * userdata)
1556
 
{
1557
 
  (void) API;
1558
 
  (void) userdata;
1559
 
  /* wmf_magick_t* ddata = WMF_MAGICK_GetData (API); */
1560
 
 
1561
 
}
1562
 
 
1563
 
static inline double MagickMin(const double x,const double y)
1564
 
{
1565
 
  if (x < y)
1566
 
    return(x);
1567
 
  return(y);
1568
 
}
1569
 
 
1570
 
static void util_set_brush(wmfAPI * API, wmfDC * dc, const BrushApply brush_apply)
1571
 
{
1572
 
  wmf_magick_t
1573
 
    *ddata = WMF_MAGICK_GetData(API);
1574
 
 
1575
 
  wmfBrush
1576
 
    *brush = WMF_DC_BRUSH(dc);
1577
 
 
1578
 
  /* Set polygon fill rule */
1579
 
  switch (WMF_DC_POLYFILL(dc))  /* Is this correct ?? */
1580
 
    {
1581
 
    case WINDING:
1582
 
      DrawSetClipRule(WmfDrawingWand,NonZeroRule);
1583
 
      break;
1584
 
 
1585
 
    case ALTERNATE:
1586
 
    default:
1587
 
      DrawSetClipRule(WmfDrawingWand,EvenOddRule);
1588
 
      break;
1589
 
    }
1590
 
 
1591
 
  switch (WMF_BRUSH_STYLE(brush))
1592
 
    {
1593
 
    case BS_SOLID /* 0 */:
1594
 
      /* WMF_BRUSH_COLOR specifies brush color, WMF_BRUSH_HATCH
1595
 
         ignored */
1596
 
      {
1597
 
        if ( brush_apply == BrushApplyStroke )
1598
 
          draw_stroke_color_rgb(API,WMF_BRUSH_COLOR(brush));
1599
 
        else
1600
 
          draw_fill_color_rgb(API,WMF_BRUSH_COLOR(brush));
1601
 
        break;
1602
 
      }
1603
 
    case BS_HOLLOW /* 1 */:    /* BS_HOLLOW & BS_NULL share enum */
1604
 
      /* WMF_BRUSH_COLOR and WMF_BRUSH_HATCH ignored */
1605
 
      {
1606
 
        if ( brush_apply == BrushApplyStroke )
1607
 
          draw_stroke_color_string(WmfDrawingWand,"none");
1608
 
        else
1609
 
          draw_fill_color_string(WmfDrawingWand,"none");
1610
 
        break;
1611
 
      }
1612
 
    case BS_HATCHED /* 2 */:
1613
 
      /* WMF_BRUSH_COLOR specifies the hatch color, WMF_BRUSH_HATCH
1614
 
         specifies the hatch brush style. If WMF_DC_OPAQUE, then
1615
 
         WMF_DC_BACKGROUND specifies hatch background color.  */
1616
 
      {
1617
 
        DrawPushDefs(WmfDrawingWand);
1618
 
        draw_pattern_push(API, ddata->pattern_id, 8, 8);
1619
 
        (void) PushDrawingWand(WmfDrawingWand);
1620
 
 
1621
 
        if (WMF_DC_OPAQUE(dc))
1622
 
          {
1623
 
            if ( brush_apply == BrushApplyStroke )
1624
 
              draw_stroke_color_rgb(API,WMF_DC_BACKGROUND(dc));
1625
 
            else
1626
 
              draw_fill_color_rgb(API,WMF_DC_BACKGROUND(dc));
1627
 
 
1628
 
            DrawRectangle(WmfDrawingWand, 0, 0, 7, 7 );
1629
 
          }
1630
 
 
1631
 
        DrawSetStrokeAntialias(WmfDrawingWand, MagickFalse);
1632
 
        DrawSetStrokeWidth(WmfDrawingWand, 1);
1633
 
 
1634
 
        draw_stroke_color_rgb(API,WMF_BRUSH_COLOR(brush));
1635
 
 
1636
 
        switch ((unsigned int) WMF_BRUSH_HATCH(brush))
1637
 
          {
1638
 
 
1639
 
          case HS_HORIZONTAL:  /* ----- */
1640
 
            {
1641
 
              DrawLine(WmfDrawingWand, 0, 3, 7,3);
1642
 
              break;
1643
 
            }
1644
 
          case HS_VERTICAL:  /* ||||| */
1645
 
            {
1646
 
              DrawLine(WmfDrawingWand, 3, 0, 3, 7);
1647
 
              break;
1648
 
            }
1649
 
          case HS_FDIAGONAL:  /* \\\\\ */
1650
 
            {
1651
 
              DrawLine(WmfDrawingWand, 0, 0, 7, 7);
1652
 
              break;
1653
 
            }
1654
 
          case HS_BDIAGONAL:  /* / */
1655
 
            {
1656
 
              DrawLine(WmfDrawingWand, 0, 7, 7, 0 );
1657
 
              break;
1658
 
            }
1659
 
          case HS_CROSS:  /* +++++ */
1660
 
            {
1661
 
              DrawLine(WmfDrawingWand, 0, 3, 7, 3 );
1662
 
              DrawLine(WmfDrawingWand, 3, 0, 3, 7 );
1663
 
              break;
1664
 
            }
1665
 
          case HS_DIAGCROSS:  /* xxxxx */
1666
 
            {
1667
 
              DrawLine(WmfDrawingWand, 0, 0, 7, 7 );
1668
 
              DrawLine(WmfDrawingWand, 0, 7, 7, 0 );
1669
 
              break;
1670
 
            }
1671
 
          default:
1672
 
            {
1673
 
              printf("util_set_brush: unexpected brush hatch enumeration %u\n",
1674
 
                     (unsigned int)WMF_BRUSH_HATCH(brush));
1675
 
            }
1676
 
          }
1677
 
        (void) PopDrawingWand(WmfDrawingWand);
1678
 
        (void) DrawPopPattern(WmfDrawingWand);
1679
 
        DrawPopDefs(WmfDrawingWand);
1680
 
        {
1681
 
          char
1682
 
            pattern_id[30];
1683
 
 
1684
 
          (void) FormatMagickString(pattern_id,MaxTextExtent,"#brush_%lu",
1685
 
            ddata->pattern_id);
1686
 
          if (brush_apply == BrushApplyStroke )
1687
 
            (void) DrawSetStrokePatternURL(WmfDrawingWand,pattern_id);
1688
 
          else
1689
 
            (void) DrawSetFillPatternURL(WmfDrawingWand,pattern_id);
1690
 
          ++ddata->pattern_id;
1691
 
        }
1692
 
        break;
1693
 
      }
1694
 
    case BS_PATTERN /* 3 */:
1695
 
      /* WMF_BRUSH_COLOR ignored, WMF_BRUSH_HATCH provides handle to
1696
 
         bitmap */
1697
 
      {
1698
 
        printf("util_set_brush: BS_PATTERN not supported\n");
1699
 
        break;
1700
 
      }
1701
 
    case BS_INDEXED /* 4 */:
1702
 
      {
1703
 
        printf("util_set_brush: BS_INDEXED not supported\n");
1704
 
        break;
1705
 
      }
1706
 
    case BS_DIBPATTERN /* 5 */:
1707
 
      {
1708
 
        wmfBMP
1709
 
          *brush_bmp = WMF_BRUSH_BITMAP(brush);
1710
 
 
1711
 
        if (brush_bmp && brush_bmp->data != 0)
1712
 
          {
1713
 
            CompositeOperator
1714
 
              mode;
1715
 
 
1716
 
            const Image
1717
 
              *image;
1718
 
 
1719
 
            ExceptionInfo
1720
 
              exception;
1721
 
 
1722
 
            MagickWand
1723
 
              *magick_wand;
1724
 
 
1725
 
            GetExceptionInfo(&exception);
1726
 
 
1727
 
            image = (Image*)brush_bmp->data;
1728
 
 
1729
 
            mode = CopyCompositeOp;  /* Default is copy */
1730
 
            switch (WMF_DC_ROP(dc))
1731
 
              {
1732
 
                /* Binary raster ops */
1733
 
              case R2_BLACK:
1734
 
                printf("util_set_brush: R2_BLACK ROP2 mode not supported!\n");
1735
 
                break;
1736
 
              case R2_NOTMERGEPEN:
1737
 
                printf("util_set_brush: R2_NOTMERGEPEN ROP2 mode not supported!\n");
1738
 
                break;
1739
 
              case R2_MASKNOTPEN:
1740
 
                printf("util_set_brush R2_MASKNOTPEN ROP2 mode not supported!\n");
1741
 
                break;
1742
 
              case R2_NOTCOPYPEN:
1743
 
                printf("util_set_brush: R2_NOTCOPYPEN ROP2 mode not supported!\n");
1744
 
                break;
1745
 
              case R2_MASKPENNOT:
1746
 
                printf("util_set_brush: R2_MASKPENNOT ROP2 mode not supported!\n");
1747
 
                break;
1748
 
              case R2_NOT:
1749
 
                printf("util_set_brush: R2_NOT ROP2 mode not supported!\n");
1750
 
                break;
1751
 
              case R2_XORPEN:
1752
 
                printf("util_set_brush: R2_XORPEN ROP2 mode not supported!\n");
1753
 
                break;
1754
 
              case R2_NOTMASKPEN:
1755
 
                printf("util_set_brush: R2_NOTMASKPEN ROP2 mode not supported!\n");
1756
 
                break;
1757
 
              case R2_MASKPEN:
1758
 
                printf("util_set_brush: R2_MASKPEN ROP2 mode not supported!\n");
1759
 
                break;
1760
 
              case R2_NOTXORPEN:
1761
 
                printf("util_set_brush: R2_NOTXORPEN ROP2 mode not supported!\n");
1762
 
                break;
1763
 
              case R2_NOP:
1764
 
                printf("util_set_brush: R2_NOP ROP2 mode not supported!\n");
1765
 
                break;
1766
 
              case R2_MERGENOTPEN:
1767
 
                printf("util_set_brush: R2_MERGENOTPEN ROP2 mode not supported!\n");
1768
 
                break;
1769
 
              case R2_COPYPEN:
1770
 
                mode = CopyCompositeOp;
1771
 
                break;
1772
 
              case R2_MERGEPENNOT:
1773
 
                printf("util_set_brush: R2_MERGEPENNOT ROP2 mode not supported!\n");
1774
 
                break;
1775
 
              case R2_MERGEPEN:
1776
 
                printf("util_set_brush: R2_MERGEPEN ROP2 mode not supported!\n");
1777
 
                break;
1778
 
              case R2_WHITE:
1779
 
                printf("util_set_brush: R2_WHITE ROP2 mode not supported!\n");
1780
 
                break;
1781
 
              default:
1782
 
                {
1783
 
                  printf("util_set_brush: unexpected ROP2 enumeration %u!\n",
1784
 
                         (unsigned int)WMF_DC_ROP(dc));
1785
 
                }
1786
 
              }
1787
 
 
1788
 
            DrawPushDefs(WmfDrawingWand);
1789
 
            draw_pattern_push(API, ddata->pattern_id, brush_bmp->width,
1790
 
              brush_bmp->height);
1791
 
            magick_wand=NewMagickWandFromImage(image);
1792
 
            (void) DrawComposite(WmfDrawingWand,mode, 0, 0, brush_bmp->width,
1793
 
              brush_bmp->height, magick_wand);
1794
 
            magick_wand=DestroyMagickWand(magick_wand);
1795
 
            (void) DrawPopPattern(WmfDrawingWand);
1796
 
            DrawPopDefs(WmfDrawingWand);
1797
 
 
1798
 
            {
1799
 
              char
1800
 
                pattern_id[30];
1801
 
 
1802
 
              (void) FormatMagickString(pattern_id,MaxTextExtent,"#brush_%lu",
1803
 
                ddata->pattern_id);
1804
 
 
1805
 
              if ( brush_apply == BrushApplyStroke )
1806
 
                (void) DrawSetStrokePatternURL(WmfDrawingWand,pattern_id);
1807
 
              else
1808
 
                (void) DrawSetFillPatternURL(WmfDrawingWand,pattern_id);
1809
 
              ++ddata->pattern_id;
1810
 
            }
1811
 
          }
1812
 
        else
1813
 
          printf("util_set_brush: no BMP image data!\n");
1814
 
 
1815
 
        break;
1816
 
      }
1817
 
    case BS_DIBPATTERNPT /* 6 */:
1818
 
      /* WMF_BRUSH_COLOR ignored, WMF_BRUSH_HATCH provides pointer to
1819
 
         DIB */
1820
 
      {
1821
 
        printf("util_set_brush: BS_DIBPATTERNPT not supported\n");
1822
 
        break;
1823
 
      }
1824
 
    case BS_PATTERN8X8 /* 7 */:
1825
 
      {
1826
 
        printf("util_set_brush: BS_PATTERN8X8 not supported\n");
1827
 
        break;
1828
 
      }
1829
 
    case BS_DIBPATTERN8X8 /* 8 */:
1830
 
      {
1831
 
        printf("util_set_brush: BS_DIBPATTERN8X8 not supported\n");
1832
 
        break;
1833
 
      }
1834
 
    default:
1835
 
      {
1836
 
      }
1837
 
    }
1838
 
}
1839
 
 
1840
 
static inline double MagickMax(const double x,const double y)
1841
 
{
1842
 
  if (x > y)
1843
 
    return(x);
1844
 
  return(y);
1845
 
}
1846
 
 
1847
 
static void util_set_pen(wmfAPI * API, wmfDC * dc)
1848
 
{
1849
 
  wmf_magick_t
1850
 
    *ddata = WMF_MAGICK_GetData(API);
1851
 
 
1852
 
  wmfPen
1853
 
    *pen = 0;
1854
 
 
1855
 
  double
1856
 
    pen_width,
1857
 
    pixel_width;
1858
 
 
1859
 
  unsigned int
1860
 
    pen_style,
1861
 
    pen_type;
1862
 
 
1863
 
  pen = WMF_DC_PEN(dc);
1864
 
 
1865
 
  pen_width = (WMF_PEN_WIDTH(pen) + WMF_PEN_HEIGHT(pen)) / 2;
1866
 
 
1867
 
  /* Pixel width is inverse of pixel scale */
1868
 
  pixel_width = (((double) 1 / (ddata->scale_x)) +
1869
 
                 ((double) 1 / (ddata->scale_y))) / 2;
1870
 
 
1871
 
  /* Don't allow pen_width to be much less than pixel_width in order
1872
 
     to avoid dissapearing or spider-web lines */
1873
 
  pen_width = MagickMax(pen_width, pixel_width*0.8);
1874
 
 
1875
 
  pen_style = (unsigned int) WMF_PEN_STYLE(pen);
1876
 
  pen_type = (unsigned int) WMF_PEN_TYPE(pen);
1877
 
 
1878
 
  /* Pen style specified? */
1879
 
  if (pen_style == PS_NULL)
1880
 
    {
1881
 
      draw_stroke_color_string(WmfDrawingWand,"none");
1882
 
      return;
1883
 
    }
1884
 
 
1885
 
  DrawSetStrokeAntialias(WmfDrawingWand, MagickTrue );
1886
 
  DrawSetStrokeWidth(WmfDrawingWand, (unsigned long) MagickMax(0.0, pen_width));
1887
 
 
1888
 
  {
1889
 
    LineCap
1890
 
      linecap;
1891
 
 
1892
 
    switch ((unsigned int) WMF_PEN_ENDCAP(pen))
1893
 
      {
1894
 
      case PS_ENDCAP_SQUARE:
1895
 
        linecap = SquareCap;
1896
 
        break;
1897
 
      case PS_ENDCAP_ROUND:
1898
 
        linecap = RoundCap;
1899
 
        break;
1900
 
      case PS_ENDCAP_FLAT:
1901
 
      default:
1902
 
        linecap = ButtCap;
1903
 
        break;
1904
 
      }
1905
 
    DrawSetStrokeLineCap(WmfDrawingWand, linecap);
1906
 
  }
1907
 
 
1908
 
  {
1909
 
    LineJoin
1910
 
      linejoin;
1911
 
 
1912
 
    switch ((unsigned int) WMF_PEN_JOIN(pen))
1913
 
      {
1914
 
      case PS_JOIN_BEVEL:
1915
 
        linejoin = BevelJoin;
1916
 
        break;
1917
 
      case PS_JOIN_ROUND:
1918
 
        linejoin = RoundJoin;
1919
 
        break;
1920
 
      case PS_JOIN_MITER:
1921
 
      default:
1922
 
        linejoin = MiterJoin;
1923
 
        break;
1924
 
      }
1925
 
    DrawSetStrokeLineJoin(WmfDrawingWand,linejoin);
1926
 
  }
1927
 
 
1928
 
  {
1929
 
    double
1930
 
      dasharray[7];
1931
 
 
1932
 
    switch (pen_style)
1933
 
      {
1934
 
      case PS_DASH:    /* -------  */
1935
 
        {
1936
 
          /* Pattern 18,7 */
1937
 
          dasharray[0] = pixel_width * 18;
1938
 
          dasharray[1] = pixel_width * 7;
1939
 
          dasharray[2] = 0;
1940
 
 
1941
 
          DrawSetStrokeAntialias(WmfDrawingWand,MagickFalse);
1942
 
          (void) DrawSetStrokeDashArray(WmfDrawingWand,2,dasharray);
1943
 
          break;
1944
 
        }
1945
 
      case PS_ALTERNATE:
1946
 
      case PS_DOT:    /* .......  */
1947
 
        {
1948
 
          /* Pattern 3,3 */
1949
 
          dasharray[0] = pixel_width * 3;
1950
 
          dasharray[1] = pixel_width * 3;
1951
 
          dasharray[2] = 0;
1952
 
 
1953
 
          DrawSetStrokeAntialias(WmfDrawingWand,MagickFalse);
1954
 
          (void) DrawSetStrokeDashArray(WmfDrawingWand,2,dasharray);
1955
 
          break;
1956
 
        }
1957
 
      case PS_DASHDOT:    /* _._._._  */
1958
 
        {
1959
 
          /* Pattern 9,6,3,6 */
1960
 
          dasharray[0] = pixel_width * 9;
1961
 
          dasharray[1] = pixel_width * 6;
1962
 
          dasharray[2] = pixel_width * 3;
1963
 
          dasharray[3] = pixel_width * 6;
1964
 
          dasharray[4] = 0;
1965
 
 
1966
 
          DrawSetStrokeAntialias(WmfDrawingWand,MagickFalse);
1967
 
          (void) DrawSetStrokeDashArray(WmfDrawingWand,4,dasharray);
1968
 
          break;
1969
 
        }
1970
 
      case PS_DASHDOTDOT:  /* _.._.._  */
1971
 
        {
1972
 
          /* Pattern 9,3,3,3,3,3 */
1973
 
          dasharray[0] = pixel_width * 9;
1974
 
          dasharray[1] = pixel_width * 3;
1975
 
          dasharray[2] = pixel_width * 3;
1976
 
          dasharray[3] = pixel_width * 3;
1977
 
          dasharray[4] = pixel_width * 3;
1978
 
          dasharray[5] = pixel_width * 3;
1979
 
          dasharray[6] = 0;
1980
 
 
1981
 
          DrawSetStrokeAntialias(WmfDrawingWand,MagickFalse);
1982
 
          (void) DrawSetStrokeDashArray(WmfDrawingWand,6,dasharray);
1983
 
          break;
1984
 
        }
1985
 
      case PS_INSIDEFRAME:  /* There is nothing to do in this case... */
1986
 
      case PS_SOLID:
1987
 
      default:
1988
 
        {
1989
 
          (void) DrawSetStrokeDashArray(WmfDrawingWand,0,(double *)NULL);
1990
 
          break;
1991
 
        }
1992
 
      }
1993
 
  }
1994
 
 
1995
 
  draw_stroke_color_rgb(API,WMF_PEN_COLOR(pen));
1996
 
}
1997
 
 
1998
 
/* Estimate font pointsize based on Windows font parameters */
1999
 
static double util_pointsize( wmfAPI* API, wmfFont* font, char* str, double font_height)
2000
 
{
2001
 
  wmf_magick_t
2002
 
    *ddata = WMF_MAGICK_GetData(API);
2003
 
 
2004
 
  Image
2005
 
    *image = ddata->image;
2006
 
 
2007
 
  TypeMetric
2008
 
    metrics;
2009
 
 
2010
 
  DrawInfo
2011
 
    *draw_info;
2012
 
 
2013
 
  double
2014
 
    pointsize = 0;
2015
 
 
2016
 
  draw_info=ddata->draw_info;
2017
 
  if (draw_info == (const DrawInfo *) NULL)
2018
 
    return 0;
2019
 
 
2020
 
  draw_info->font=WMF_FONT_PSNAME(font);
2021
 
  draw_info->pointsize=font_height;
2022
 
  draw_info->text=str;
2023
 
 
2024
 
  if (GetTypeMetrics(image, draw_info, &metrics) != MagickFalse)
2025
 
    {
2026
 
 
2027
 
      if (strlen(str) == 1)
2028
 
        {
2029
 
          pointsize = (font_height *
2030
 
                       ( font_height / (metrics.ascent + fabs(metrics.descent))));
2031
 
          draw_info->pointsize = pointsize;
2032
 
          if (GetTypeMetrics(image, draw_info, &metrics) != MagickFalse)
2033
 
            pointsize *= (font_height / ( metrics.ascent + fabs(metrics.descent)));
2034
 
        }
2035
 
      else
2036
 
        {
2037
 
          pointsize = (font_height * (font_height / (metrics.height)));
2038
 
          draw_info->pointsize = pointsize;
2039
 
          if (GetTypeMetrics(image, draw_info, &metrics) != MagickFalse)
2040
 
            pointsize *= (font_height / metrics.height);
2041
 
 
2042
 
        }
2043
 
#if 0
2044
 
      draw_info.pointsize = pointsize;
2045
 
      if (GetTypeMetrics(image, &draw_info, &metrics) != MagickFalse)
2046
 
        pointsize *= (font_height / (metrics.ascent + fabs(metrics.descent)));
2047
 
      pointsize *= 1.114286; /* Magic number computed through trial and error */
2048
 
#endif
2049
 
    }
2050
 
 
2051
 
  draw_info->font=NULL;
2052
 
  draw_info->text=NULL;
2053
 
#if 0
2054
 
  printf("String    = %s\n", str);
2055
 
  printf("Font      = %s\n", WMF_FONT_PSNAME(font));
2056
 
  printf("lfHeight  = %g\n", font_height);
2057
 
  printf("bounds    = %g,%g %g,%g\n", metrics.bounds.x1, metrics.bounds.y1,
2058
 
         metrics.bounds.x2,metrics.bounds.y2);
2059
 
  printf("ascent    = %g\n", metrics.ascent);
2060
 
  printf("descent   = %g\n", metrics.descent);
2061
 
  printf("height    = %g\n", metrics.height);
2062
 
  printf("Pointsize = %g\n", pointsize);
2063
 
#endif
2064
 
 
2065
 
  return floor(pointsize);
2066
 
}
2067
 
 
2068
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
2069
 
/* Estimate weight based on font name */
2070
 
/*
2071
 
static int util_font_weight( const char* font )
2072
 
{
2073
 
  int
2074
 
    weight;
2075
 
 
2076
 
  weight = 400;
2077
 
  if ((strstr(font,"Normal") || strstr(font,"Regular")))
2078
 
    weight = 400;
2079
 
  else if ( strstr(font,"Bold") )
2080
 
    {
2081
 
      weight = 700;
2082
 
      if ((strstr(font,"Semi") || strstr(font,"Demi")))
2083
 
        weight = 600;
2084
 
      if ( (strstr(font,"Extra") || strstr(font,"Ultra")))
2085
 
        weight = 800;
2086
 
    }
2087
 
  else if ( strstr(font,"Light") )
2088
 
    {
2089
 
      weight = 300;
2090
 
      if ( (strstr(font,"Extra") || strstr(font,"Ultra")))
2091
 
        weight = 200;
2092
 
    }
2093
 
  else if ((strstr(font,"Heavy") || strstr(font,"Black")))
2094
 
    weight = 900;
2095
 
  else if ( strstr(font,"Thin") )
2096
 
    weight = 100;
2097
 
  return weight;
2098
 
}
2099
 
*/
2100
 
 
2101
 
/*
2102
 
 * Returns width of string in points, assuming (unstretched) font size of 1pt
2103
 
 * (similar to wmf_ipa_font_stringwidth)
2104
 
 *
2105
 
 * This extremely odd at best, particularly since player/meta.h has access
2106
 
 * to the corrected font_height (as drawtext.font_height) when it invokes the
2107
 
 * stringwidth callback.  It should be possible to compute the real stringwidth!
2108
 
 */
2109
 
static float lite_font_stringwidth( wmfAPI* API, wmfFont* font, char* str)
2110
 
{
2111
 
  wmf_magick_t
2112
 
    *ddata = WMF_MAGICK_GetData(API);
2113
 
 
2114
 
  Image
2115
 
    *image = ddata->image;
2116
 
 
2117
 
  DrawInfo
2118
 
    *draw_info;
2119
 
 
2120
 
  TypeMetric
2121
 
    metrics;
2122
 
 
2123
 
  float
2124
 
    stringwidth = 0;
2125
 
 
2126
 
  double
2127
 
    orig_x_resolution,
2128
 
    orig_y_resolution;
2129
 
 
2130
 
  ResolutionType
2131
 
    orig_resolution_units;
2132
 
 
2133
 
  orig_x_resolution = image->x_resolution;
2134
 
  orig_y_resolution = image->y_resolution;
2135
 
  orig_resolution_units = image->units;
2136
 
 
2137
 
  draw_info=ddata->draw_info;
2138
 
  if (draw_info == (const DrawInfo *) NULL)
2139
 
    return 0;
2140
 
 
2141
 
  draw_info->font=WMF_FONT_PSNAME(font);
2142
 
  draw_info->pointsize=12;
2143
 
  draw_info->text=str;
2144
 
 
2145
 
  image->x_resolution = 72;
2146
 
  image->y_resolution = 72;
2147
 
  image->units = PixelsPerInchResolution;
2148
 
 
2149
 
  if (GetTypeMetrics(image, draw_info, &metrics) != MagickFalse)
2150
 
    stringwidth = ((metrics.width * 72)/(image->x_resolution * draw_info->pointsize)); /* *0.916348; */
2151
 
 
2152
 
  draw_info->font=NULL;
2153
 
  draw_info->text=NULL;
2154
 
 
2155
 
#if 0
2156
 
  printf("\nlite_font_stringwidth\n");
2157
 
  printf("string                  = \"%s\"\n", str);
2158
 
  printf("WMF_FONT_NAME           = \"%s\"\n", WMF_FONT_NAME(font));
2159
 
  printf("WMF_FONT_PSNAME         = \"%s\"\n", WMF_FONT_PSNAME(font));
2160
 
  printf("stringwidth             = %g\n", stringwidth);
2161
 
  /* printf("WMF_FONT_HEIGHT         = %i\n", (int)WMF_FONT_HEIGHT(font)); */
2162
 
  /* printf("WMF_FONT_WIDTH          = %i\n", (int)WMF_FONT_WIDTH(font)); */
2163
 
  fflush(stdout);
2164
 
#endif
2165
 
 
2166
 
  image->x_resolution = orig_x_resolution;
2167
 
  image->y_resolution = orig_y_resolution;
2168
 
  image->units = orig_resolution_units;
2169
 
 
2170
 
  return stringwidth;
2171
 
}
2172
 
 
2173
 
/* Map font (similar to wmf_ipa_font_map) */
2174
 
 
2175
 
/* Mappings to Postscript fonts: family, normal, italic, bold, bolditalic */
2176
 
static wmfFontMap WMFFontMap[] = {
2177
 
  { (char *) "Courier",            (char *) "Courier",     (char *) "Courier-Oblique",   (char *) "Courier-Bold", (char *) "Courier-BoldOblique"   },   { (char *) "Helvetica",          (char *) "Helvetica",   (char *) "Helvetica-Oblique", (char *) "Helvetica-Bold", (char *) "Helvetica-BoldOblique" },   { (char *) "Modern",             (char *) "Courier",     (char *) "Courier-Oblique",   (char *) "Courier-Bold", (char *) "Courier-BoldOblique"   },   { (char *) "Monotype Corsiva",   (char *) "Courier",     (char *) "Courier-Oblique",   (char *) "Courier-Bold", (char *) "Courier-BoldOblique"   },
2178
 
  { (char *) "News Gothic",        (char *) "Helvetica",   (char *) "Helvetica-Oblique", (char *) "Helvetica-Bold", (char *) "Helvetica-BoldOblique" },
2179
 
  { (char *) "Symbol",             (char *) "Symbol",      (char *) "Symbol",            (char *) "Symbol", (char *) "Symbol"                },
2180
 
  { (char *) "System",             (char *) "Courier",     (char *) "Courier-Oblique",   (char *) "Courier-Bold", (char *) "Courier-BoldOblique"   },
2181
 
  { (char *) "Times",              (char *) "Times-Roman", (char *) "Times-Italic",      (char *) "Times-Bold", (char *) "Times-BoldItalic"      },
2182
 
  {  (char *) NULL,                (char *) NULL,           (char *) NULL,               (char *) NULL,  (char *) NULL                   }
2183
 
};
2184
 
 
2185
 
 
2186
 
/* Mapping between base name and Ghostscript family name */
2187
 
static wmfMapping SubFontMap[] =
2188
 
{
2189
 
  { (char *) "Arial", (char *) "Helvetica", FT_ENCODING_NONE },
2190
 
  { (char *) "Courier", (char *) "Courier", FT_ENCODING_NONE },
2191
 
  { (char *) "Fixed", (char *) "Courier", FT_ENCODING_NONE },
2192
 
  { (char *) "Helvetica", (char *) "Helvetica", FT_ENCODING_NONE },
2193
 
  { (char *) "Sans", (char *) "Helvetica", FT_ENCODING_NONE },
2194
 
  { (char *) "Sym", (char *) "Symbol", FT_ENCODING_NONE },
2195
 
  { (char *) "Terminal", (char *) "Courier", FT_ENCODING_NONE },
2196
 
  { (char *) "Times", (char *) "Times", FT_ENCODING_NONE },
2197
 
  { (char *) "Wingdings", (char *) "Symbol", FT_ENCODING_NONE },
2198
 
  { (char *)  NULL, (char *) NULL, FT_ENCODING_NONE }
2199
 
};
2200
 
 
2201
 
static void lite_font_map( wmfAPI* API, wmfFont* font)
2202
 
{
2203
 
  wmfFontData
2204
 
    *font_data;
2205
 
 
2206
 
  wmf_magick_font_t
2207
 
    *magick_font;
2208
 
 
2209
 
  wmf_magick_t
2210
 
    *ddata = WMF_MAGICK_GetData(API);
2211
 
 
2212
 
  ExceptionInfo
2213
 
    exception;
2214
 
 
2215
 
  const TypeInfo
2216
 
    *type_info,
2217
 
    *type_info_base;
2218
 
 
2219
 
  const char
2220
 
    *wmf_font_name;
2221
 
 
2222
 
  if (font == 0)
2223
 
    return;
2224
 
 
2225
 
  font_data = (wmfFontData*)API->font_data;
2226
 
  font->user_data = font_data->user_data;
2227
 
  magick_font = (wmf_magick_font_t*)font->user_data;
2228
 
  wmf_font_name = WMF_FONT_NAME(font);
2229
 
 
2230
 
  if (magick_font->ps_name != (char *) NULL)
2231
 
    magick_font->ps_name=DestroyString(magick_font->ps_name);
2232
 
 
2233
 
  GetExceptionInfo(&exception);
2234
 
  type_info_base=GetTypeInfo("*",&exception);
2235
 
  if (type_info_base == 0)
2236
 
    {
2237
 
      InheritException(&ddata->image->exception,&exception);
2238
 
      return;
2239
 
    }
2240
 
 
2241
 
  /* Certain short-hand font names are not the proper Windows names
2242
 
     and should be promoted to the proper names */
2243
 
  if (LocaleCompare(wmf_font_name,"Times") == 0)
2244
 
    wmf_font_name = "Times New Roman";
2245
 
  else if (LocaleCompare(wmf_font_name,"Courier") == 0)
2246
 
    wmf_font_name = "Courier New";
2247
 
 
2248
 
  /* Look for a family-based best-match */
2249
 
  if (!magick_font->ps_name)
2250
 
    {
2251
 
      int
2252
 
        target_weight;
2253
 
 
2254
 
      if (WMF_FONT_WEIGHT(font) == 0)
2255
 
        target_weight = 400;
2256
 
      else
2257
 
        target_weight = WMF_FONT_WEIGHT(font);
2258
 
      type_info=GetTypeInfoByFamily(wmf_font_name,AnyStyle,AnyStretch,
2259
 
        target_weight,&exception);
2260
 
      if (type_info == (const TypeInfo *) NULL)
2261
 
        type_info=GetTypeInfoByFamily(wmf_font_name,AnyStyle,AnyStretch,0,
2262
 
          &exception);
2263
 
      if (type_info != (const TypeInfo *) NULL)
2264
 
        CloneString(&magick_font->ps_name,type_info->name);
2265
 
    }
2266
 
 
2267
 
  /* Now let's try simple substitution mappings from WMFFontMap */
2268
 
  if (!magick_font->ps_name)
2269
 
    {
2270
 
      char
2271
 
        target[MaxTextExtent];
2272
 
 
2273
 
      int
2274
 
        target_weight = 400,
2275
 
        want_italic = MagickFalse,
2276
 
        want_bold = MagickFalse,
2277
 
        i;
2278
 
 
2279
 
      if ( WMF_FONT_WEIGHT(font) != 0 )
2280
 
        target_weight = WMF_FONT_WEIGHT(font);
2281
 
 
2282
 
      if ( (target_weight > 550) || ((strstr(wmf_font_name,"Bold") ||
2283
 
                                     strstr(wmf_font_name,"Heavy") ||
2284
 
                                     strstr(wmf_font_name,"Black"))) )
2285
 
        want_bold = MagickTrue;
2286
 
 
2287
 
      if ( (WMF_FONT_ITALIC(font)) || ((strstr(wmf_font_name,"Italic") ||
2288
 
                                       strstr(wmf_font_name,"Oblique"))) )
2289
 
        want_italic = MagickTrue;
2290
 
 
2291
 
      (void) CopyMagickString(target,"Times",MaxTextExtent);
2292
 
      for( i=0; SubFontMap[i].name != NULL; i++ )
2293
 
        {
2294
 
          if (LocaleCompare(wmf_font_name, SubFontMap[i].name) == 0)
2295
 
            {
2296
 
              (void) CopyMagickString(target,SubFontMap[i].mapping,
2297
 
                MaxTextExtent);
2298
 
              break;
2299
 
            }
2300
 
        }
2301
 
 
2302
 
      for( i=0; WMFFontMap[i].name != NULL; i++ )
2303
 
        {
2304
 
          if (LocaleNCompare(WMFFontMap[i].name,target,strlen(WMFFontMap[i].name)) == 0)
2305
 
            {
2306
 
              if (want_bold && want_italic)
2307
 
                CloneString(&magick_font->ps_name,WMFFontMap[i].bolditalic);
2308
 
              else if (want_italic)
2309
 
                CloneString(&magick_font->ps_name,WMFFontMap[i].italic);
2310
 
              else if (want_bold)
2311
 
                CloneString(&magick_font->ps_name,WMFFontMap[i].bold);
2312
 
              else
2313
 
                CloneString(&magick_font->ps_name,WMFFontMap[i].normal);
2314
 
            }
2315
 
        }
2316
 
    }
2317
 
 
2318
 
#if 0
2319
 
  printf("\nlite_font_map\n");
2320
 
  printf("WMF_FONT_NAME           = \"%s\"\n", WMF_FONT_NAME(font));
2321
 
  printf("WMF_FONT_WEIGHT         = %i\n",  WMF_FONT_WEIGHT(font));
2322
 
  printf("WMF_FONT_PSNAME         = \"%s\"\n", WMF_FONT_PSNAME(font));
2323
 
  fflush(stdout);
2324
 
#endif
2325
 
 
2326
 
}
2327
 
 
2328
 
/* Initialize API font structures */
2329
 
static void lite_font_init( wmfAPI* API, wmfAPI_Options* options)
2330
 
{
2331
 
  wmfFontData
2332
 
    *font_data;
2333
 
 
2334
 
  (void) options;
2335
 
  API->fonts = 0;
2336
 
 
2337
 
  /* Allocate wmfFontData data structure */
2338
 
  API->font_data = wmf_malloc(API,sizeof(wmfFontData));
2339
 
  if (ERR (API))
2340
 
    return;
2341
 
 
2342
 
  font_data = (wmfFontData*)API->font_data;
2343
 
 
2344
 
  /* Assign function to map font (type wmfMap) */
2345
 
  font_data->map = lite_font_map;
2346
 
 
2347
 
  /* Assign function to return string width in points (type wmfStringWidth) */
2348
 
  font_data->stringwidth = lite_font_stringwidth;
2349
 
 
2350
 
  /* Assign user data, not used by libwmflite (type void*) */
2351
 
  font_data->user_data = wmf_malloc(API,sizeof(wmf_magick_font_t));
2352
 
  if (ERR(API))
2353
 
    return;
2354
 
  ((wmf_magick_font_t*)font_data->user_data)->ps_name = 0;
2355
 
  ((wmf_magick_font_t*)font_data->user_data)->pointsize = 0;
2356
 
}
2357
 
 
2358
 
#endif /* MAGICKCORE_WMFLITE_DELEGATE */
2359
 
 
2360
 
/* BLOB read byte */
2361
 
static int ipa_blob_read(void* wand)
2362
 
{
2363
 
  return ReadBlobByte((Image*)wand);
2364
 
}
2365
 
 
2366
 
/* BLOB seek */
2367
 
static int ipa_blob_seek(void* wand,long position)
2368
 
{
2369
 
  return (int)SeekBlob((Image*)wand,(MagickOffsetType) position,SEEK_SET);
2370
 
}
2371
 
 
2372
 
/* BLOB tell */
2373
 
static long ipa_blob_tell(void* wand)
2374
 
{
2375
 
  return (long)TellBlob((Image*)wand);
2376
 
}
2377
 
 
2378
 
static Image *ReadWMFImage(const ImageInfo * image_info, ExceptionInfo * exception)
2379
 
{
2380
 
  Image
2381
 
    *image;
2382
 
 
2383
 
  float
2384
 
    wmf_width,
2385
 
    wmf_height;
2386
 
 
2387
 
  double
2388
 
    bounding_height,
2389
 
    bounding_width,
2390
 
    image_height,
2391
 
    image_height_inch,
2392
 
    image_width,
2393
 
    image_width_inch,
2394
 
    resolution_y,
2395
 
    resolution_x,
2396
 
    units_per_inch;
2397
 
 
2398
 
  unsigned long
2399
 
    wmf_options_flags = 0;
2400
 
 
2401
 
  wmf_error_t
2402
 
    wmf_error;
2403
 
 
2404
 
  wmf_magick_t
2405
 
    *ddata = 0;
 
132
  size_t
 
133
    flags;
2406
134
 
2407
135
  wmfAPI
2408
 
    *API = 0;
 
136
    *wmf_info;
2409
137
 
2410
138
  wmfAPI_Options
2411
 
    wmf_api_options;
 
139
    options;
2412
140
 
2413
141
  wmfD_Rect
2414
 
    bbox;
2415
 
 
2416
 
  image = AcquireImage(image_info);
2417
 
  if (OpenBlob(image_info,image,ReadBinaryBlobMode,exception) == MagickFalse)
 
142
    bounding_box;
 
143
 
 
144
  wmf_eps_t
 
145
    *eps_info;
 
146
 
 
147
  wmf_error_t
 
148
    wmf_status;
 
149
 
 
150
  /*
 
151
    Read WMF image.
 
152
  */
 
153
  image=AcquireImage(image_info);
 
154
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
155
  if (status == MagickFalse)
2418
156
    {
2419
 
      if (image->debug != MagickFalse)
2420
 
        {
2421
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2422
 
            "  OpenBlob failed");
2423
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2424
 
            "leave ReadWMFImage()");
2425
 
        }
2426
157
      image=DestroyImageList(image);
2427
158
      return((Image *) NULL);
2428
159
    }
2429
 
 
2430
 
  /*
2431
 
   * Create WMF API
2432
 
   *
2433
 
   */
2434
 
 
2435
 
  /* Register callbacks */
2436
 
  wmf_options_flags |= WMF_OPT_FUNCTION;
2437
 
  (void) ResetMagickMemory(&wmf_api_options, 0, sizeof(wmf_api_options));
2438
 
  wmf_api_options.function = ipa_functions;
2439
 
 
2440
 
  /* Ignore non-fatal errors */
2441
 
  wmf_options_flags |= WMF_OPT_IGNORE_NONFATAL;
2442
 
 
2443
 
  wmf_error = wmf_api_create(&API, wmf_options_flags, &wmf_api_options);
2444
 
  if (wmf_error != wmf_E_None)
 
160
  wmf_info=(wmfAPI *) NULL;
 
161
  flags=0;
 
162
  flags|=WMF_OPT_IGNORE_NONFATAL;
 
163
  flags|=WMF_OPT_FUNCTION;
 
164
  options.function=wmf_eps_function;
 
165
  wmf_status=wmf_api_create(&wmf_info,(unsigned long) flags,&options);
 
166
  if (wmf_status != wmf_E_None)
2445
167
    {
2446
 
      if (API)
2447
 
        wmf_api_destroy(API);
2448
 
      if (image->debug != MagickFalse)
2449
 
        {
2450
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2451
 
            "  wmf_api_create failed");
2452
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2453
 
            "leave ReadWMFImage()");
2454
 
        }
 
168
      if (wmf_info != (wmfAPI *) NULL)
 
169
        wmf_api_destroy(wmf_info);
2455
170
      ThrowReaderException(DelegateError,"UnableToInitializeWMFLibrary");
2456
171
    }
2457
 
 
2458
 
  /* Register progress monitor */
2459
 
  wmf_status_function(API,image,magick_progress_callback);
2460
 
 
2461
 
  ddata = WMF_MAGICK_GetData(API);
2462
 
  ddata->image = image;
2463
 
  ddata->image_info = image_info;
2464
 
  ddata->draw_info = CloneDrawInfo((const ImageInfo *) NULL, (const DrawInfo *) NULL);
2465
 
  RelinquishMagickMemory(ddata->draw_info->font);
2466
 
  RelinquishMagickMemory(ddata->draw_info->text);
2467
 
 
2468
 
 
2469
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)
2470
 
  /* Must initialize font subystem for WMFlite interface */
2471
 
  lite_font_init (API,&wmf_api_options); /* similar to wmf_ipa_font_init in src/font.c */
2472
 
  /* wmf_arg_fontdirs (API,options); */ /* similar to wmf_arg_fontdirs in src/wmf.c */
2473
 
 
2474
 
#endif
2475
 
 
2476
 
  /*
2477
 
   * Open BLOB input via libwmf API
2478
 
   *
2479
 
   */
2480
 
  wmf_error = wmf_bbuf_input(API,ipa_blob_read,ipa_blob_seek,
2481
 
                             ipa_blob_tell,(void*)image);
2482
 
  if (wmf_error != wmf_E_None)
 
172
  wmf_status=wmf_bbuf_input(wmf_info,WMFReadBlob,WMFSeekBlob,WMFTellBlob,
 
173
    (void *) image);
 
174
  if (wmf_status != wmf_E_None)
2483
175
    {
2484
 
      wmf_api_destroy(API);
2485
 
      if (image->debug != MagickFalse)
2486
 
        {
2487
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2488
 
            "  wmf_bbuf_input failed");
2489
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2490
 
            "leave ReadWMFImage()");
2491
 
        }
 
176
      wmf_api_destroy(wmf_info);
2492
177
      ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
2493
178
        image->filename);
2494
179
      image=DestroyImageList(image);
2495
180
      return((Image *) NULL);
2496
181
    }
2497
 
 
2498
 
  /*
2499
 
   * Scan WMF file
2500
 
   *
2501
 
   */
2502
 
  if (image->debug != MagickFalse)
2503
 
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2504
 
      "  Scanning WMF to obtain bounding box");
2505
 
  wmf_error = wmf_scan(API, 0, &bbox);
2506
 
  if (wmf_error != wmf_E_None)
 
182
  wmf_status=wmf_scan(wmf_info,0,&bounding_box);
 
183
  if (wmf_status != wmf_E_None)
2507
184
    {
2508
 
      wmf_api_destroy(API);
2509
 
      if (image->debug != MagickFalse)
2510
 
        {
2511
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2512
 
            "  wmf_scan failed with wmf_error %d", wmf_error);
2513
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2514
 
            "leave ReadWMFImage()");
2515
 
        }
 
185
      wmf_api_destroy(wmf_info);
2516
186
      ThrowReaderException(DelegateError,"FailedToScanFile");
2517
187
    }
2518
 
 
2519
 
  /*
2520
 
   * Compute dimensions and scale factors
2521
 
   *
2522
 
   */
2523
 
 
2524
 
  ddata->bbox = bbox;
2525
 
 
2526
 
  /* User specified resolution */
2527
 
  resolution_y=DefaultResolution;
2528
 
  if (image->y_resolution > 0)
2529
 
    {
2530
 
      resolution_y = image->y_resolution;
2531
 
      if (image->units == PixelsPerCentimeterResolution)
2532
 
        resolution_y *= CENTIMETERS_PER_INCH;
2533
 
    }
2534
 
 
2535
 
  resolution_x=DefaultResolution;
2536
 
  if (image->x_resolution > 0)
2537
 
    {
2538
 
      resolution_x = image->x_resolution;
2539
 
      if (image->units == PixelsPerCentimeterResolution)
2540
 
        resolution_x *= CENTIMETERS_PER_INCH;
2541
 
    }
2542
 
 
2543
 
  /* Obtain output size expressed in metafile units */
2544
 
  wmf_error = wmf_size(API, &wmf_width, &wmf_height);
2545
 
  if (wmf_error != wmf_E_None)
2546
 
    {
2547
 
      wmf_api_destroy(API);
2548
 
      if (image->debug != MagickFalse)
2549
 
        {
2550
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2551
 
            "  wmf_size failed with wmf_error %d", wmf_error);
2552
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2553
 
            "leave ReadWMFImage()");
2554
 
        }
2555
 
      ThrowReaderException(DelegateError,"FailedToComputeOutputSize");
2556
 
    }
2557
 
 
2558
 
  /* Obtain (or guess) metafile units */
2559
 
  if ((API)->File->placeable)
2560
 
    units_per_inch = (API)->File->pmh->Inch;
2561
 
  else if ( (wmf_width*wmf_height) < 1024*1024)
2562
 
    units_per_inch = POINTS_PER_INCH;  /* MM_TEXT */
2563
 
  else
2564
 
    units_per_inch = TWIPS_PER_INCH;  /* MM_TWIPS */
2565
 
 
2566
 
  /* Calculate image width and height based on specified DPI
2567
 
     resolution */
2568
 
  image_width_inch  = (double) wmf_width / units_per_inch;
2569
 
  image_height_inch = (double) wmf_height / units_per_inch;
2570
 
  image_width       = image_width_inch * resolution_x;
2571
 
  image_height      = image_height_inch * resolution_y;
2572
 
 
2573
 
  /* Compute bounding box scale factors and origin translations
2574
 
   *
2575
 
   * This all just a hack since libwmf does not currently seem to
2576
 
   * provide the mapping between LOGICAL coordinates and DEVICE
2577
 
   * coordinates. This mapping is necessary in order to know
2578
 
   * where to place the logical bounding box within the image.
2579
 
   *
2580
 
   */
2581
 
 
2582
 
  bounding_width  = bbox.BR.x - bbox.TL.x;
2583
 
  bounding_height = bbox.BR.y - bbox.TL.y;
2584
 
 
2585
 
  ddata->scale_x = image_width/bounding_width;
2586
 
  ddata->translate_x = 0-bbox.TL.x;
2587
 
  ddata->rotate = 0;
2588
 
 
2589
 
  /* Heuristic: guess that if the vertical coordinates mostly span
2590
 
     negative values, then the image must be inverted. */
2591
 
  if ( fabs(bbox.BR.y) > fabs(bbox.TL.y) )
2592
 
    {
2593
 
      /* Normal (Origin at top left of image) */
2594
 
      ddata->scale_y = (image_height/bounding_height);
2595
 
      ddata->translate_y = 0-bbox.TL.y;
2596
 
    }
2597
 
  else
2598
 
    {
2599
 
      /* Inverted (Origin at bottom left of image) */
2600
 
      ddata->scale_y = (-image_height/bounding_height);
2601
 
      ddata->translate_y = 0-bbox.BR.y;
2602
 
    }
2603
 
 
2604
 
  if (image->debug != MagickFalse)
2605
 
    {
2606
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2607
 
         "  Placeable metafile:          %s",
2608
 
         (API)->File->placeable ? "Yes" : "No");
2609
 
 
2610
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2611
 
        "  Size in metafile units:      %gx%g",wmf_width,wmf_height);
2612
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2613
 
        "  Metafile units/inch:         %g",units_per_inch);
2614
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2615
 
        "  Size in inches:              %gx%g",
2616
 
        image_width_inch,image_height_inch);
2617
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2618
 
        "  Bounding Box:                %g,%g %g,%g",
2619
 
        bbox.TL.x, bbox.TL.y, bbox.BR.x, bbox.BR.y);
2620
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2621
 
        "  Bounding width x height:     %gx%g",bounding_width,bounding_height);
2622
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2623
 
        "  Output resolution:           %gx%g",resolution_x,resolution_y);
2624
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2625
 
        "  Image size:                  %gx%g",image_width,image_height);
2626
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2627
 
        "  Bounding box scale factor:   %g,%g",ddata->scale_x,ddata->scale_y);
2628
 
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2629
 
        "  Translation:                 %g,%g",
2630
 
        ddata->translate_x, ddata->translate_y);
2631
 
    }
2632
 
 
2633
 
#if 0
2634
 
#if 0
2635
 
  {
2636
 
    typedef struct _wmfPlayer_t wmfPlayer_t;
2637
 
    struct _wmfPlayer_t
2638
 
    {
2639
 
      wmfPen   default_pen;
2640
 
      wmfBrush default_brush;
2641
 
      wmfFont  default_font;
2642
 
 
2643
 
      wmfDC* dc; /* current dc */
2644
 
    };
2645
 
 
2646
 
    wmfDC
2647
 
      *dc;
2648
 
 
2649
 
#define WMF_ELICIT_DC(API) (((wmfPlayer_t*)((API)->player_data))->dc)
2650
 
 
2651
 
    dc = WMF_ELICIT_DC(API);
2652
 
 
2653
 
    printf("dc->Window.Ox     = %d\n", dc->Window.Ox);
2654
 
    printf("dc->Window.Oy     = %d\n", dc->Window.Oy);
2655
 
    printf("dc->Window.width  = %d\n", dc->Window.width);
2656
 
    printf("dc->Window.height = %d\n", dc->Window.height);
2657
 
    printf("dc->pixel_width   = %g\n", dc->pixel_width);
2658
 
    printf("dc->pixel_height  = %g\n", dc->pixel_height);
2659
 
#if defined(MAGICKCORE_WMFLITE_DELEGATE)  /* Only in libwmf 0.3 */
2660
 
    printf("dc->Ox            = %.d\n", dc->Ox);
2661
 
    printf("dc->Oy            = %.d\n", dc->Oy);
2662
 
    printf("dc->width         = %.d\n", dc->width);
2663
 
    printf("dc->height        = %.d\n", dc->height);
2664
 
#endif
2665
 
 
2666
 
  }
2667
 
#endif
2668
 
 
2669
 
#endif
2670
 
 
2671
 
  /*
2672
 
   * Create canvas image
2673
 
   *
2674
 
   */
2675
 
  image->rows=(unsigned long) ceil(image_height);
2676
 
  image->columns=(unsigned long) ceil(image_width);
2677
 
 
2678
 
  if (image_info->ping != MagickFalse)
2679
 
    {
2680
 
      wmf_api_destroy(API);
2681
 
      (void) CloseBlob(image);
2682
 
      if (image->debug != MagickFalse)
2683
 
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2684
 
          "leave ReadWMFImage()");
2685
 
      return(GetFirstImageInList(image));
2686
 
    }
2687
 
  if (image->debug != MagickFalse)
2688
 
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2689
 
       "  Creating canvas image with size %ldx%ld",
2690
 
       image->rows,image->columns);
2691
 
 
2692
 
  /*
2693
 
   * Set solid background color
2694
 
   */
2695
 
  {
2696
 
    unsigned long
2697
 
      column,
2698
 
      row;
2699
 
 
2700
 
    PixelPacket
2701
 
      *pixel,
2702
 
      background_color;
2703
 
 
2704
 
    background_color = image_info->background_color;
2705
 
    image->background_color = background_color;
2706
 
    if (background_color.opacity != OpaqueOpacity)
2707
 
      image->matte = MagickTrue;
2708
 
 
2709
 
    for (row=0; row < image->rows; row++)
2710
 
      {
2711
 
        pixel=QueueAuthenticPixels(image,0,row,image->columns,1,exception);
2712
 
        if (pixel == (PixelPacket *) NULL)
2713
 
          break;
2714
 
        for (column=image->columns; column; column--)
2715
 
          *pixel++ = background_color;
2716
 
        if (SyncAuthenticPixels(image,exception) == MagickFalse)
2717
 
          break;
2718
 
      }
2719
 
  }
2720
 
  /*
2721
 
   * Play file to generate Vector drawing commands
2722
 
   *
2723
 
   */
2724
 
 
2725
 
  if (image->debug != MagickFalse)
2726
 
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2727
 
      "  Playing WMF to prepare vectors");
2728
 
 
2729
 
  wmf_error = wmf_play(API, 0, &bbox);
2730
 
  if (wmf_error != wmf_E_None)
2731
 
    {
2732
 
      wmf_api_destroy(API);
2733
 
      if (image->debug != MagickFalse)
2734
 
        {
2735
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2736
 
            "  Playing WMF failed with wmf_error %d", wmf_error);
2737
 
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2738
 
            "leave ReadWMFImage()");
2739
 
        }
 
188
  eps_info=WMF_EPS_GetData(wmf_info);
 
189
  file=(FILE *) NULL;
 
190
  unique_file=AcquireUniqueFileResource(filename);
 
191
  if (unique_file != -1)
 
192
    file=fdopen(unique_file,"wb");
 
193
  if ((unique_file == -1) || (file == (FILE *) NULL))
 
194
    {
 
195
      wmf_api_destroy(wmf_info);
 
196
      ThrowReaderException(FileOpenError,"UnableToCreateTemporaryFile");
 
197
    }
 
198
  eps_info->out=wmf_stream_create(wmf_info,file);
 
199
  eps_info->bbox=bounding_box;
 
200
  wmf_status=wmf_play(wmf_info,0,&bounding_box);
 
201
  if (wmf_status != wmf_E_None)
 
202
    {
 
203
      wmf_api_destroy(wmf_info);
2740
204
      ThrowReaderException(DelegateError,"FailedToRenderFile");
2741
205
    }
2742
 
 
2743
 
  /*
2744
 
   * Scribble on canvas image
2745
 
   *
2746
 
   */
2747
 
 
2748
 
  if (image->debug != MagickFalse)
2749
 
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2750
 
      "  Rendering WMF vectors");
2751
 
  DrawRender(ddata->draw_wand);
2752
 
 
2753
 
  /* Check for and report any rendering error */
2754
 
  if (image->exception.severity != UndefinedException)
2755
 
    (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
2756
 
      ddata->image->exception.reason,"`%s'",ddata->image->exception.description);
2757
 
 
2758
 
  if (image->debug != MagickFalse)
2759
 
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),"leave ReadWMFImage()");
2760
 
 
2761
 
  /* Cleanup allocated data */
2762
 
  wmf_api_destroy(API);
 
206
  (void) fclose(file);
 
207
  wmf_api_destroy(wmf_info);
2763
208
  (void) CloseBlob(image);
2764
 
 
2765
 
  /* Return image */
2766
 
  return image;
 
209
  image=DestroyImage(image);
 
210
  /*
 
211
    Read EPS image.
 
212
  */
 
213
  read_info=CloneImageInfo(image_info);
 
214
  (void) FormatMagickString(read_info->filename,MaxTextExtent,"eps:%.1024s",
 
215
    filename);
 
216
  image=ReadImage(read_info,exception);
 
217
  read_info=DestroyImageInfo(read_info);
 
218
  if (image != (Image *) NULL)
 
219
    {
 
220
      (void) CopyMagickString(image->filename,image_info->filename,
 
221
        MaxTextExtent);
 
222
      (void) CopyMagickString(image->magick_filename,image_info->filename,
 
223
        MaxTextExtent);
 
224
      (void) CopyMagickString(image->magick,"WMF",MaxTextExtent);
 
225
    }
 
226
  (void) RelinquishUniqueFileResource(filename);
 
227
  return(GetFirstImageInList(image));
2767
228
}
2768
 
/* #endif */
2769
 
#endif /* MAGICKCORE_WMF_DELEGATE || MAGICKCORE_WMFLITE_DELEGATE */
 
229
#endif
2770
230
 
2771
231
/*
2772
232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2788
248
%
2789
249
%  The format of the RegisterWMFImage method is:
2790
250
%
2791
 
%      unsigned long RegisterWMFImage(void)
 
251
%      size_t RegisterWMFImage(void)
2792
252
%
2793
253
*/
2794
 
ModuleExport unsigned long RegisterWMFImage(void)
 
254
ModuleExport size_t RegisterWMFImage(void)
2795
255
{
2796
256
  MagickInfo
2797
257
    *entry;
2798
258
 
2799
259
  entry = SetMagickInfo("WMZ");
2800
 
#if defined(MAGICKCORE_WMF_DELEGATE) || defined(MAGICKCORE_WMFLITE_DELEGATE)
 
260
#if defined(MAGICKCORE_WMF_DELEGATE)
2801
261
  entry->decoder=ReadWMFImage;
2802
262
#endif
2803
263
  entry->description=ConstantString("Compressed Windows Meta File");
2804
 
  entry->blob_support=MagickTrue;
2805
 
  entry->seekable_stream=MagickTrue;
2806
264
  entry->module=ConstantString("WMZ");
2807
265
  (void) RegisterMagickInfo(entry);
2808
266
  entry=SetMagickInfo("WMF");
2809
 
#if defined(MAGICKCORE_WMF_DELEGATE) || defined(MAGICKCORE_WMFLITE_DELEGATE)
 
267
#if defined(MAGICKCORE_WMF_DELEGATE)
2810
268
  entry->decoder=ReadWMFImage;
2811
269
#endif
2812
270
  entry->description=ConstantString("Windows Meta File");
2813
 
  entry->blob_support=MagickTrue;
2814
 
  entry->seekable_stream=MagickTrue;
2815
271
  entry->module=ConstantString("WMF");
2816
272
  (void) RegisterMagickInfo(entry);
2817
273
  return(MagickImageCoderSignature);