Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1995, 1996, 1998 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gdevcgml.c,v 1.5 2002/06/16 05:48:54 lpd Exp $ */
18
/* CGM-writing library */
19
#include "memory_.h"
20
#include "stdio_.h"
21
#include "gdevcgmx.h"
22
 
23
/* Forward references to command-writing procedures */
24
private void begin_command(cgm_state *, cgm_op_index);
25
 
26
#define OP(op) begin_command(st, op)
27
private cgm_result end_command(cgm_state *);
28
 
29
#define END_OP (void)end_command(st)
30
#define DONE return end_command(st)
31
/* Parameters */
32
private void put_int(cgm_state *, cgm_int, int);
33
 
34
#define CI(ci) put_int(st, ci, st->metafile.color_index_precision)
35
#define I(i) put_int(st, i, st->metafile.integer_precision)
36
#define IX(ix) put_int(st, ix, st->metafile.index_precision)
37
#define E(e) put_int(st, (int)(e), 16)
38
private void put_real(cgm_state *, cgm_real, const cgm_precision *);
39
 
40
#define R(r) put_real(st, r, &st->metafile.real_precision)
41
private void put_vdc(cgm_state *, const cgm_vdc *);
42
 
43
#define VDC(vdc) put_vdc(st, vdc)
44
#define VDC2(vdc1, vdc2) VDC(vdc1); VDC(vdc2)
45
#define VDC4(vdc1, vdc2, vdc3, vdc4) VDC2(vdc1, vdc2); VDC2(vdc3, vdc4)
46
private void put_vdc_r(cgm_state *, const cgm_line_marker_extent *, cgm_line_marker_specification_mode);
47
 
48
#define VDC_R(vdcr, mode) put_vdc_r(st, vdcr, mode)
49
private void put_point(cgm_state *, const cgm_point *);
50
 
51
#define P(p) put_point(st, p)
52
private void put_points(cgm_state *, const cgm_point *, int);
53
 
54
#define nP(p, n) put_points(st, p, n)
55
private void put_string(cgm_state *, const char *, uint);
56
 
57
#define S(s, l) put_string(st, s, l)
58
private void put_color(cgm_state *, const cgm_color *);
59
 
60
#define CO(co) put_color(st, co)
61
private void put_rgb(cgm_state *, const cgm_rgb *);
62
 
63
#define CD(cd) put_rgb(st, cd)
64
/* Other data types */
65
#define put_byte(st, b)\
66
  if ( st->command_count == command_max_count ) write_command(st, false);\
67
  st->command[st->command_count++] = (byte)(b)
68
private void put_bytes(cgm_state *, const byte *, uint);
69
private void write_command(cgm_state *, bool);
70
private void put_real_precision(cgm_state *, const cgm_precision *);
71
 
72
/* ================ Public routines ================ */
73
 
74
/* ---------------- Initialize/terminate ---------------- */
75
 
76
/* Initialize a CGM writer. */
77
cgm_state *
78
cgm_initialize(FILE * file, const cgm_allocator * cal)
79
{
80
    cgm_state *st = (*cal->alloc) (cal->private_data, sizeof(cgm_state));
81
 
82
    if (st == 0)
83
	return 0;
84
    st->file = file;
85
    st->allocator = *cal;
86
    /* Initialize metafile elements. */
87
    st->metafile.vdc_type = cgm_vdc_integer;
88
    st->metafile.integer_precision = 16;
89
    st->metafile.real_precision.representation = cgm_representation_fixed;
90
    st->metafile.real_precision.exponent_or_whole_width = 16;
91
    st->metafile.real_precision.fraction_width = 16;
92
    st->metafile.index_precision = 16;
93
    st->metafile.color_precision = 8;
94
    st->metafile.color_index_precision = 8;
95
    st->metafile.maximum_color_index = 63;
96
    /* color_value_extent */
97
    /*st->metafile.character_coding_announcer = 0; */
98
    /* Initialize picture elements. */
99
    st->picture.scaling_mode = cgm_scaling_abstract;
100
    st->picture.color_selection_mode = cgm_color_selection_indexed;
101
    st->picture.line_width_specification_mode = cgm_line_marker_absolute;
102
    st->picture.marker_size_specification_mode = cgm_line_marker_absolute;
103
    st->picture.edge_width_specification_mode = cgm_line_marker_absolute;
104
    /* vdc_extent */
105
    /* background_color */
106
    /* Initialize control elements. */
107
    st->vdc_integer_precision = st->metafile.integer_precision;
108
    st->vdc_real_precision = st->metafile.real_precision;
109
    st->transparency = cgm_transparency_on;
110
    /* clip_rectangle */
111
    st->clip_indicator = cgm_clip_on;
112
    /* Initialize other state elements. */
113
    st->line_bundle_index = 1;
114
    st->line_type = cgm_line_solid;
115
    /* line_width */
116
    /* line_color */
117
    st->marker_bundle_index = 1;
118
    st->marker_type = cgm_marker_asterisk;
119
    /* marker_size */
120
    /* marker_color */
121
    st->text_bundle_index = 1;
122
    st->text_font_index = 1;
123
    st->text_precision = cgm_text_precision_string;
124
    st->character_expansion_factor = 1.0;
125
    st->character_spacing = 0.0;
126
    /* text_color */
127
    /* character_height */
128
    /* character_orientation */
129
    st->text_path = cgm_text_path_right;
130
    /* text_alignment */
131
    st->character_set_index = 1;
132
    st->alternate_character_set_index = 1;
133
    st->fill_bundle_index = 1;
134
    st->interior_style = cgm_interior_style_hollow;
135
    st->hatch_index = cgm_hatch_horizontal;
136
    st->pattern_index = 1;
137
    st->edge_bundle_index = 1;
138
    st->edge_type = cgm_edge_solid;
139
    /* edge_width */
140
    st->edge_visibility = false;
141
    /* fill_reference_point */
142
    /* pattern_table */
143
    /* pattern_size */
144
    /* color_table */
145
    memset(st->source_flags, (byte) cgm_aspect_source_individual,
146
	   sizeof(st->source_flags));
147
    return st;
148
}
149
 
150
/* Terminate a CGM writer. */
151
cgm_result
152
cgm_terminate(cgm_state * st)
153
{
154
    (*st->allocator.free) (st->allocator.private_data, st);
155
    return cgm_result_ok;
156
}
157
 
158
/* ---------------- Metafile elements ---------------- */
159
 
160
cgm_result
161
cgm_BEGIN_METAFILE(cgm_state * st, const char *str, uint len)
162
{
163
    OP(BEGIN_METAFILE);
164
    S(str, len);
165
    DONE;
166
}
167
 
168
cgm_result
169
cgm_set_metafile_elements(cgm_state * st, const cgm_metafile_elements * meta, long mask)
170
{
171
    if ((mask & cgm_set_METAFILE_VERSION)) {
172
	OP(METAFILE_VERSION);
173
	I(meta->metafile_version);
174
	END_OP;
175
	st->metafile.metafile_version = meta->metafile_version;
176
    }
177
    if ((mask & cgm_set_METAFILE_DESCRIPTION)) {
178
	OP(METAFILE_DESCRIPTION);
179
	S(meta->metafile_description.chars, meta->metafile_description.length);
180
	END_OP;
181
	st->metafile.metafile_description = meta->metafile_description;
182
    }
183
    if ((mask & cgm_set_VDC_TYPE)) {
184
	OP(VDC_TYPE);
185
	E(meta->vdc_type);
186
	END_OP;
187
	st->metafile.vdc_type = meta->vdc_type;
188
    }
189
    if ((mask & cgm_set_INTEGER_PRECISION)) {
190
	OP(INTEGER_PRECISION);
191
	I(meta->integer_precision);
192
	END_OP;
193
	st->metafile.integer_precision = meta->integer_precision;
194
    }
195
    if ((mask & cgm_set_REAL_PRECISION)) {
196
	OP(REAL_PRECISION);
197
	put_real_precision(st, &meta->real_precision);
198
	END_OP;
199
	st->metafile.real_precision = meta->real_precision;
200
    }
201
    if ((mask & cgm_set_INDEX_PRECISION)) {
202
	OP(INDEX_PRECISION);
203
	I(meta->index_precision);
204
	END_OP;
205
	st->metafile.index_precision = meta->index_precision;
206
    }
207
    if ((mask & cgm_set_COLOR_PRECISION)) {
208
	OP(COLOR_PRECISION);
209
	I(meta->color_precision);
210
	END_OP;
211
	st->metafile.color_index_precision = meta->color_index_precision;
212
    }
213
    if ((mask & cgm_set_COLOR_INDEX_PRECISION)) {
214
	OP(COLOR_INDEX_PRECISION);
215
	I(meta->color_index_precision);
216
	END_OP;
217
	st->metafile.color_index_precision = meta->color_index_precision;
218
    }
219
    if ((mask & cgm_set_MAXIMUM_COLOR_INDEX)) {
220
	OP(MAXIMUM_COLOR_INDEX);
221
	CI(meta->maximum_color_index);
222
	END_OP;
223
	st->metafile.maximum_color_index = meta->maximum_color_index;
224
    }
225
    if ((mask & cgm_set_METAFILE_ELEMENT_LIST)) {
226
	int i;
227
	const int *p;
228
 
229
	OP(METAFILE_ELEMENT_LIST);
230
	for (i = 0, p = meta->metafile_element_list;
231
	     i < meta->metafile_element_list_count;
232
	     i++, p += 2
233
	    ) {
234
	    I(p[0]);
235
	    I(p[1]);
236
	}
237
	END_OP;
238
	st->metafile.metafile_element_list =
239
	    meta->metafile_element_list;
240
	st->metafile.metafile_element_list_count =
241
	    meta->metafile_element_list_count;
242
    }
243
    /* element list */
244
    if ((mask & cgm_set_FONT_LIST)) {
245
	int i;
246
 
247
	OP(FONT_LIST);
248
	for (i = 0; i < meta->font_list_count; ++i)
249
	    S(meta->font_list[i].chars, meta->font_list[i].length);
250
	END_OP;
251
	st->metafile.font_list = meta->font_list;
252
	st->metafile.font_list_count = meta->font_list_count;
253
    }
254
    /* character set list */
255
    /* character coding announcer */
256
    return st->result;
257
}
258
 
259
cgm_result
260
cgm_END_METAFILE(cgm_state * st)
261
{
262
    OP(END_METAFILE);
263
    DONE;
264
}
265
 
266
/* ---------------- Picture elements ---------------- */
267
 
268
cgm_result
269
cgm_BEGIN_PICTURE(cgm_state * st, const char *str, uint len)
270
{
271
    OP(BEGIN_PICTURE);
272
    S(str, len);
273
    DONE;
274
}
275
 
276
cgm_result
277
cgm_set_picture_elements(cgm_state * st, const cgm_picture_elements * pic, long mask)
278
{
279
    if ((mask & cgm_set_SCALING_MODE)) {
280
	OP(SCALING_MODE);
281
	E(pic->scaling_mode);
282
	R(pic->scale_factor);
283
	st->picture.scaling_mode = pic->scaling_mode;
284
	st->picture.scale_factor = pic->scale_factor;
285
	END_OP;
286
    }
287
    if ((mask & cgm_set_COLOR_SELECTION_MODE)) {
288
	OP(COLOR_SELECTION_MODE);
289
	E(pic->color_selection_mode);
290
	END_OP;
291
	st->picture.color_selection_mode = pic->color_selection_mode;
292
    }
293
    if ((mask & cgm_set_LINE_WIDTH_SPECIFICATION_MODE)) {
294
	OP(LINE_WIDTH_SPECIFICATION_MODE);
295
	E(pic->line_width_specification_mode);
296
	END_OP;
297
	st->picture.line_width_specification_mode = pic->line_width_specification_mode;
298
    }
299
    if ((mask & cgm_set_MARKER_SIZE_SPECIFICATION_MODE)) {
300
	OP(MARKER_SIZE_SPECIFICATION_MODE);
301
	E(pic->marker_size_specification_mode);
302
	END_OP;
303
	st->picture.marker_size_specification_mode = pic->marker_size_specification_mode;
304
    }
305
    if ((mask & cgm_set_EDGE_WIDTH_SPECIFICATION_MODE)) {
306
	OP(EDGE_WIDTH_SPECIFICATION_MODE);
307
	E(pic->edge_width_specification_mode);
308
	END_OP;
309
	st->picture.edge_width_specification_mode = pic->edge_width_specification_mode;
310
    }
311
    if ((mask & cgm_set_VDC_EXTENT)) {
312
	OP(VDC_EXTENT);
313
	P(&pic->vdc_extent[0]);
314
	P(&pic->vdc_extent[1]);
315
	END_OP;
316
	st->picture.vdc_extent[0] = pic->vdc_extent[0];
317
	st->picture.vdc_extent[1] = pic->vdc_extent[1];
318
    }
319
    if ((mask & cgm_set_BACKGROUND_COLOR)) {
320
	OP(BACKGROUND_COLOR);
321
	CD(&pic->background_color.rgb);
322
	DONE;
323
	st->picture.background_color = pic->background_color;
324
    }
325
    return st->result;
326
}
327
 
328
cgm_result
329
cgm_BEGIN_PICTURE_BODY(cgm_state * st)
330
{
331
    OP(BEGIN_PICTURE_BODY);
332
    DONE;
333
}
334
 
335
cgm_result
336
cgm_END_PICTURE(cgm_state * st)
337
{
338
    OP(END_PICTURE);
339
    DONE;
340
}
341
 
342
/* ---------------- Control elements ---------------- */
343
 
344
cgm_result
345
cgm_VDC_INTEGER_PRECISION(cgm_state * st, int precision)
346
{
347
    if (st->vdc_integer_precision != precision) {
348
	OP(VDC_INTEGER_PRECISION);
349
	I(precision);
350
	st->vdc_integer_precision = precision;
351
	DONE;
352
    } else
353
	return cgm_result_ok;
354
}
355
 
356
cgm_result
357
cgm_VDC_REAL_PRECISION(cgm_state * st, const cgm_precision * precision)
358
{
359
    OP(VDC_REAL_PRECISION);
360
    put_real_precision(st, precision);
361
    st->vdc_real_precision = *precision;
362
    DONE;
363
}
364
 
365
cgm_result
366
cgm_AUXILIARY_COLOR(cgm_state * st, const cgm_color * color)
367
{
368
    OP(AUXILIARY_COLOR);
369
    CO(color);
370
    st->auxiliary_color = *color;
371
    DONE;
372
}
373
 
374
cgm_result
375
cgm_TRANSPARENCY(cgm_state * st, cgm_transparency transparency)
376
{
377
    OP(TRANSPARENCY);
378
    E(transparency);
379
    st->transparency = transparency;
380
    DONE;
381
}
382
 
383
cgm_result
384
cgm_CLIP_RECTANGLE(cgm_state * st, const cgm_point rectangle[2])
385
{
386
    OP(CLIP_RECTANGLE);
387
    P(&rectangle[0]);
388
    st->clip_rectangle[0] = rectangle[0];
389
    P(&rectangle[1]);
390
    st->clip_rectangle[1] = rectangle[1];
391
    DONE;
392
}
393
 
394
cgm_result
395
cgm_CLIP_INDICATOR(cgm_state * st, cgm_clip_indicator clip)
396
{
397
    OP(CLIP_INDICATOR);
398
    E(clip);
399
    st->clip_indicator = clip;
400
    DONE;
401
}
402
 
403
/* ---------------- Graphical primitive elements ---------------- */
404
 
405
cgm_result
406
cgm_POLYLINE(cgm_state * st, const cgm_point * vertices, int count)
407
{
408
    OP(POLYLINE);
409
    nP(vertices, count);
410
    DONE;
411
}
412
 
413
cgm_result
414
cgm_DISJOINT_POLYLINE(cgm_state * st, const cgm_point * endpoints, int count)
415
{
416
    OP(DISJOINT_POLYLINE);
417
    nP(endpoints, count);
418
    DONE;
419
}
420
 
421
cgm_result
422
cgm_POLYMARKER(cgm_state * st, const cgm_point * positions, int count)
423
{
424
    OP(POLYMARKER);
425
    nP(positions, count);
426
    DONE;
427
}
428
 
429
cgm_result
430
cgm_TEXT(cgm_state * st, const cgm_point * position, bool final, const char *str, uint len)
431
{
432
    OP(TEXT);
433
    P(position);
434
    E(final);
435
    S(str, len);
436
    DONE;
437
}
438
 
439
cgm_result
440
cgm_RESTRICTED_TEXT(cgm_state * st, const cgm_vdc * delta_width, const cgm_vdc * delta_height, const cgm_point * position, bool final, const char *str, uint len)
441
{
442
    OP(RESTRICTED_TEXT);
443
    VDC2(delta_width, delta_height);
444
    P(position);
445
    E(final);
446
    S(str, len);
447
    DONE;
448
}
449
 
450
cgm_result
451
cgm_APPEND_TEXT(cgm_state * st, bool final, const char *str, uint len)
452
{
453
    OP(APPEND_TEXT);
454
    E(final);
455
    S(str, len);
456
    DONE;
457
}
458
 
459
cgm_result
460
cgm_POLYGON(cgm_state * st, const cgm_point * vertices, int count)
461
{
462
    OP(POLYGON);
463
    nP(vertices, count);
464
    DONE;
465
}
466
 
467
cgm_result
468
cgm_POLYGON_SET(cgm_state * st, const cgm_polygon_edge * vertices, int count)
469
{
470
    int i;
471
 
472
    OP(POLYGON);
473
    for (i = 0; i < count; ++i) {
474
	P(&vertices[i].vertex);
475
	E(vertices[i].edge_out);
476
    }
477
    DONE;
478
}
479
 
480
cgm_result
481
cgm_CELL_ARRAY(cgm_state * st, const cgm_point * pqr /*[3] */ , cgm_int nx, cgm_int ny, cgm_int local_color_precision, cgm_cell_representation_mode mode, const byte * values, uint source_bit, uint raster)
482
{
483
    int precision = local_color_precision;
484
    int bits_per_pixel;
485
    uint row_bytes;
486
    const byte *row = values + (source_bit >> 3);
487
    int bit = source_bit & 7;
488
    int y;
489
 
490
    /* Currently we ignore the cell representation_mode, and always */
491
    /* produce cell arrays in 'packed' format. */
492
    mode = cgm_cell_mode_packed;
493
    OP(CELL_ARRAY);
494
    nP(pqr, 3);
495
    I(nx);
496
    I(ny);
497
    I(local_color_precision);
498
    E(mode);
499
    if (precision == 0)
500
	precision = (st->picture.color_selection_mode ==
501
		     cgm_color_selection_indexed ?
502
		     st->metafile.color_index_precision :
503
		     st->metafile.color_precision);
504
    bits_per_pixel =
505
	(st->picture.color_selection_mode == cgm_color_selection_indexed ?
506
	 precision : precision * 3);
507
    row_bytes = (bits_per_pixel * nx + 7) >> 3;
508
    for (y = 0; y < ny; y++, row += raster) {
509
	if (bit == 0)
510
	    put_bytes(st, row, row_bytes);
511
	else {
512
	    uint i;
513
 
514
	    for (i = 0; i < row_bytes; i++) {
515
		byte b = (row[i] << bit) +
516
		(row[i + 1] >> (8 - bit));
517
 
518
		put_byte(st, b);
519
	    }
520
	}
521
	if ((row_bytes & 1)) {
522
	    put_byte(st, 0);
523
	}
524
    }
525
    DONE;
526
}
527
 
528
cgm_result
529
cgm_RECTANGLE(cgm_state * st, const cgm_point * corner1, const cgm_point * corner2)
530
{
531
    OP(RECTANGLE);
532
    P(corner1);
533
    P(corner2);
534
    DONE;
535
}
536
 
537
cgm_result
538
cgm_CIRCLE(cgm_state * st, const cgm_point * center, const cgm_vdc * radius)
539
{
540
    OP(CIRCLE);
541
    P(center);
542
    VDC(radius);
543
    DONE;
544
}
545
 
546
cgm_result
547
cgm_CIRCULAR_ARC_3_POINT(cgm_state * st, const cgm_point * start, const cgm_point * intermediate, const cgm_point * end)
548
{
549
    OP(CIRCULAR_ARC_3_POINT);
550
    P(start);
551
    P(intermediate);
552
    P(end);
553
    DONE;
554
}
555
 
556
cgm_result
557
cgm_CIRCULAR_ARC_3_POINT_CLOSE(cgm_state * st, const cgm_point * start, const cgm_point * intermediate, const cgm_point * end, cgm_arc_closure closure)
558
{
559
    OP(CIRCULAR_ARC_3_POINT_CLOSE);
560
    P(start);
561
    P(intermediate);
562
    P(end);
563
    E(closure);
564
    DONE;
565
}
566
 
567
cgm_result
568
cgm_CIRCULAR_ARC_CENTER(cgm_state * st, const cgm_point * center, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, const cgm_vdc * radius)
569
{
570
    OP(CIRCULAR_ARC_CENTER);
571
    P(center);
572
    VDC4(dx_start, dy_start, dx_end, dy_end);
573
    VDC(radius);
574
    DONE;
575
}
576
 
577
cgm_result
578
cgm_CIRCULAR_ARC_CENTER_CLOSE(cgm_state * st, const cgm_point * center, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, const cgm_vdc * radius, cgm_arc_closure closure)
579
{
580
    OP(CIRCULAR_ARC_CENTER_CLOSE);
581
    P(center);
582
    VDC4(dx_start, dy_start, dx_end, dy_end);
583
    VDC(radius);
584
    E(closure);
585
    DONE;
586
}
587
 
588
cgm_result
589
cgm_ELLIPSE(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end)
590
{
591
    OP(ELLIPSE);
592
    P(center);
593
    P(cd1_end);
594
    P(cd2_end);
595
    DONE;
596
}
597
 
598
cgm_result
599
cgm_ELLIPTICAL_ARC(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end)
600
{
601
    OP(ELLIPTICAL_ARC);
602
    P(center);
603
    P(cd1_end);
604
    P(cd2_end);
605
    VDC4(dx_start, dy_start, dx_end, dy_end);
606
    DONE;
607
}
608
 
609
cgm_result
610
cgm_ELLIPTICAL_ARC_CLOSE(cgm_state * st, const cgm_point * center, const cgm_point * cd1_end, const cgm_point * cd2_end, const cgm_vdc * dx_start, const cgm_vdc * dy_start, const cgm_vdc * dx_end, const cgm_vdc * dy_end, cgm_arc_closure closure)
611
{
612
    OP(ELLIPTICAL_ARC_CLOSE);
613
    P(center);
614
    P(cd1_end);
615
    P(cd2_end);
616
    VDC4(dx_start, dy_start, dx_end, dy_end);
617
    E(closure);
618
    DONE;
619
}
620
 
621
/* ---------------- Attribute elements ---------------- */
622
 
623
cgm_result
624
cgm_LINE_BUNDLE_INDEX(cgm_state * st, cgm_int index)
625
{
626
    OP(LINE_BUNDLE_INDEX);
627
    IX(index);
628
    st->line_bundle_index = index;
629
    DONE;
630
}
631
 
632
cgm_result
633
cgm_LINE_TYPE(cgm_state * st, cgm_line_type line_type)
634
{
635
    OP(LINE_TYPE);
636
    IX((int)line_type);
637
    st->line_type = line_type;
638
    DONE;
639
}
640
 
641
cgm_result
642
cgm_LINE_WIDTH(cgm_state * st, const cgm_line_width * line_width)
643
{
644
    OP(LINE_WIDTH);
645
    VDC_R(line_width, st->picture.line_width_specification_mode);
646
    st->line_width = *line_width;
647
    DONE;
648
}
649
 
650
cgm_result
651
cgm_LINE_COLOR(cgm_state * st, const cgm_color * color)
652
{
653
    OP(LINE_COLOR);
654
    CO(color);
655
    st->line_color = *color;
656
    DONE;
657
}
658
 
659
cgm_result
660
cgm_MARKER_BUNDLE_INDEX(cgm_state * st, cgm_int index)
661
{
662
    OP(MARKER_BUNDLE_INDEX);
663
    IX(index);
664
    st->marker_bundle_index = index;
665
    DONE;
666
}
667
 
668
cgm_result
669
cgm_MARKER_TYPE(cgm_state * st, cgm_marker_type marker_type)
670
{
671
    OP(MARKER_TYPE);
672
    IX((int)marker_type);
673
    st->marker_type = marker_type;
674
    DONE;
675
}
676
 
677
cgm_result
678
cgm_MARKER_SIZE(cgm_state * st, const cgm_marker_size * marker_size)
679
{
680
    OP(MARKER_SIZE);
681
    VDC_R(marker_size, st->picture.marker_size_specification_mode);
682
    st->marker_size = *marker_size;
683
    DONE;
684
}
685
 
686
cgm_result
687
cgm_MARKER_COLOR(cgm_state * st, const cgm_color * color)
688
{
689
    OP(MARKER_COLOR);
690
    CO(color);
691
    st->marker_color = *color;
692
    DONE;
693
}
694
 
695
cgm_result
696
cgm_TEXT_BUNDLE_INDEX(cgm_state * st, cgm_int index)
697
{
698
    OP(TEXT_BUNDLE_INDEX);
699
    IX(index);
700
    st->text_bundle_index = index;
701
    DONE;
702
}
703
 
704
cgm_result
705
cgm_TEXT_FONT_INDEX(cgm_state * st, cgm_int index)
706
{
707
    OP(TEXT_FONT_INDEX);
708
    IX(index);
709
    st->text_font_index = index;
710
    DONE;
711
}
712
 
713
cgm_result
714
cgm_TEXT_PRECISION(cgm_state * st, cgm_text_precision precision)
715
{
716
    OP(TEXT_PRECISION);
717
    E(precision);
718
    st->text_precision = precision;
719
    DONE;
720
}
721
 
722
cgm_result
723
cgm_CHARACTER_EXPANSION_FACTOR(cgm_state * st, cgm_real factor)
724
{
725
    OP(CHARACTER_EXPANSION_FACTOR);
726
    R(factor);
727
    st->character_expansion_factor = factor;
728
    DONE;
729
}
730
 
731
cgm_result
732
cgm_CHARACTER_SPACING(cgm_state * st, cgm_real spacing)
733
{
734
    OP(CHARACTER_SPACING);
735
    R(spacing);
736
    st->character_spacing = spacing;
737
    DONE;
738
}
739
 
740
cgm_result
741
cgm_TEXT_COLOR(cgm_state * st, const cgm_color * color)
742
{
743
    OP(TEXT_COLOR);
744
    CO(color);
745
    st->text_color = *color;
746
    DONE;
747
}
748
 
749
cgm_result
750
cgm_CHARACTER_HEIGHT(cgm_state * st, const cgm_vdc * height)
751
{
752
    OP(CHARACTER_HEIGHT);
753
    VDC(height);
754
    st->character_height = *height;
755
    DONE;
756
}
757
 
758
cgm_result
759
cgm_CHARACTER_ORIENTATION(cgm_state * st, const cgm_vdc * x_up, const cgm_vdc * y_up, const cgm_vdc * x_base, const cgm_vdc * y_base)
760
{
761
    OP(CHARACTER_ORIENTATION);
762
    VDC4(x_up, y_up, x_base, y_base);
763
    st->character_orientation[0] = *x_up;
764
    st->character_orientation[1] = *y_up;
765
    st->character_orientation[2] = *x_base;
766
    st->character_orientation[3] = *y_base;
767
    DONE;
768
}
769
 
770
cgm_result
771
cgm_TEXT_PATH(cgm_state * st, cgm_text_path text_path)
772
{
773
    OP(TEXT_PATH);
774
    E(text_path);
775
    st->text_path = text_path;
776
    DONE;
777
}
778
 
779
cgm_result
780
cgm_TEXT_ALIGNMENT(cgm_state * st, cgm_text_alignment_horizontal align_h, cgm_text_alignment_vertical align_v, cgm_real align_cont_h, cgm_real align_cont_v)
781
{
782
    OP(TEXT_ALIGNMENT);
783
    E(align_h);
784
    E(align_v);
785
    R(align_cont_h);
786
    R(align_cont_v);
787
    DONE;
788
}
789
 
790
cgm_result
791
cgm_CHARACTER_SET_INDEX(cgm_state * st, cgm_int index)
792
{
793
    OP(CHARACTER_SET_INDEX);
794
    IX(index);
795
    st->character_set_index = index;
796
    DONE;
797
}
798
 
799
/* See gdevcgml.c for why this isn't named cgm_ALTERNATE_.... */
800
cgm_result
801
cgm_ALT_CHARACTER_SET_INDEX(cgm_state * st, cgm_int index)
802
{
803
    OP(ALTERNATE_CHARACTER_SET_INDEX);
804
    IX(index);
805
    st->alternate_character_set_index = index;
806
    DONE;
807
}
808
 
809
cgm_result
810
cgm_FILL_BUNDLE_INDEX(cgm_state * st, cgm_int index)
811
{
812
    OP(FILL_BUNDLE_INDEX);
813
    IX(index);
814
    st->fill_bundle_index = index;
815
    DONE;
816
}
817
 
818
cgm_result
819
cgm_INTERIOR_STYLE(cgm_state * st, cgm_interior_style interior_style)
820
{
821
    OP(INTERIOR_STYLE);
822
    E(interior_style);
823
    st->interior_style = interior_style;
824
    DONE;
825
}
826
 
827
cgm_result
828
cgm_FILL_COLOR(cgm_state * st, const cgm_color * color)
829
{
830
    OP(FILL_COLOR);
831
    CO(color);
832
    st->fill_color = *color;
833
    DONE;
834
}
835
 
836
cgm_result
837
cgm_HATCH_INDEX(cgm_state * st, cgm_hatch_index hatch_index)
838
{
839
    OP(HATCH_INDEX);
840
    IX((int)hatch_index);
841
    st->hatch_index = hatch_index;
842
    DONE;
843
}
844
 
845
cgm_result
846
cgm_PATTERN_INDEX(cgm_state * st, cgm_int index)
847
{
848
    OP(PATTERN_INDEX);
849
    IX(index);
850
    st->pattern_index = index;
851
    DONE;
852
}
853
 
854
cgm_result
855
cgm_EDGE_BUNDLE_INDEX(cgm_state * st, cgm_int index)
856
{
857
    OP(EDGE_BUNDLE_INDEX);
858
    IX(index);
859
    st->edge_bundle_index = index;
860
    DONE;
861
}
862
 
863
cgm_result
864
cgm_EDGE_TYPE(cgm_state * st, cgm_edge_type edge_type)
865
{
866
    OP(EDGE_TYPE);
867
    IX((int)edge_type);
868
    st->edge_type = edge_type;
869
    DONE;
870
}
871
 
872
cgm_result
873
cgm_EDGE_WIDTH(cgm_state * st, const cgm_edge_width * edge_width)
874
{
875
    OP(EDGE_WIDTH);
876
    VDC_R(edge_width, st->picture.edge_width_specification_mode);
877
    st->edge_width = *edge_width;
878
    DONE;
879
}
880
 
881
cgm_result
882
cgm_EDGE_COLOR(cgm_state * st, const cgm_color * color)
883
{
884
    OP(EDGE_COLOR);
885
    CO(color);
886
    DONE;
887
}
888
 
889
cgm_result
890
cgm_EDGE_VISIBILITY(cgm_state * st, bool visibility)
891
{
892
    OP(EDGE_VISIBILITY);
893
    E(visibility);
894
    st->edge_visibility = visibility;
895
    DONE;
896
}
897
 
898
cgm_result
899
cgm_FILL_REFERENCE_POINT(cgm_state * st, const cgm_point * reference_point)
900
{
901
    OP(FILL_REFERENCE_POINT);
902
    P(reference_point);
903
    st->fill_reference_point = *reference_point;
904
    DONE;
905
}
906
 
907
/* PATTERN_TABLE */
908
 
909
cgm_result
910
cgm_PATTERN_SIZE(cgm_state * st, const cgm_vdc * x_height, const cgm_vdc * y_height, const cgm_vdc * x_width, const cgm_vdc * y_width)
911
{
912
    OP(PATTERN_SIZE);
913
    VDC4(x_height, y_height, x_width, y_width);
914
    st->pattern_size[0] = *x_height;
915
    st->pattern_size[1] = *y_height;
916
    st->pattern_size[2] = *x_width;
917
    st->pattern_size[3] = *y_width;
918
    DONE;
919
}
920
 
921
cgm_result
922
cgm_COLOR_TABLE(cgm_state * st, cgm_int index, const cgm_color * values, int count)
923
{
924
    int i;
925
 
926
    OP(COLOR_TABLE);
927
    CI(index);
928
    for (i = 0; i < count; ++i)
929
	CD(&values[i].rgb);
930
    DONE;
931
}
932
 
933
cgm_result 
934
cgm_ASPECT_SOURCE_FLAGS(cgm_state * st, const cgm_aspect_source_flag * flags, int count)
935
{
936
    int i;
937
 
938
    OP(ASPECT_SOURCE_FLAGS);
939
    for (i = 0; i < count; ++i) {
940
	E(flags[i].type);
941
	E(flags[i].source);
942
	st->source_flags[flags[i].type] = (byte) flags[i].source;
943
    }
944
    DONE;
945
}
946
 
947
/* ================ Internal routines ================ */
948
 
949
/* Begin a command. */
950
private void
951
begin_command(cgm_state * st, cgm_op_index op)
952
{
953
    uint op_word = (uint) op << cgm_op_id_shift;
954
 
955
    st->command[0] = (byte) (op_word >> 8);
956
    st->command[1] = (byte) (op_word);
957
    st->command_count = 4;	/* leave room for extension */
958
    st->command_first = true;
959
    st->result = cgm_result_ok;
960
}
961
 
962
/* Write the buffer for a partial command. */
963
/* Note that we always write an even number of bytes. */
964
private void
965
write_command(cgm_state * st, bool last)
966
{
967
    byte *command = st->command;
968
    int count = st->command_count;
969
 
970
    if (st->command_first) {
971
	if (count <= 34) {
972
	    command[2] = command[0];
973
	    command[3] = command[1] + count - 4;
974
	    command += 2, count -= 2;
975
	} else {
976
	    int pcount = count - 4;
977
 
978
	    command[1] |= 31;
979
	    command[2] = (byte) (pcount >> 8);
980
	    if (!last)
981
		command[2] |= 0x80;
982
	    command[3] = (byte) pcount;
983
	}
984
	st->command_first = false;
985
    } else {
986
	int pcount = count - 2;
987
 
988
	command[0] = (byte) (pcount >> 8);
989
	if (!last)
990
	    command[0] |= 0x80;
991
	command[1] = (byte) pcount;
992
    }
993
    fwrite(command, sizeof(byte), count + (count & 1), st->file);
994
    st->command_count = 2;	/* leave room for extension header */
995
    if (ferror(st->file))
996
	st->result = cgm_result_io_error;
997
}
998
 
999
/* End a command. */
1000
private cgm_result
1001
end_command(cgm_state * st)
1002
{
1003
    write_command(st, true);
1004
    return st->result;
1005
}
1006
 
1007
/* Put an integer value. */
1008
private void
1009
put_int(cgm_state * st, cgm_int value, int precision)
1010
{
1011
    switch (precision) {
1012
	case 32:
1013
	    put_byte(st, value >> 24);
1014
	case 24:
1015
	    put_byte(st, value >> 16);
1016
	case 16:
1017
	    put_byte(st, value >> 8);
1018
	case 8:
1019
	    put_byte(st, value);
1020
    }
1021
}
1022
 
1023
/* Put a real value. */
1024
private void
1025
put_real(cgm_state * st, cgm_real value, const cgm_precision * pr)
1026
{
1027
    if (pr->representation == cgm_representation_floating) {
1028
    } else {			/* Casting to integer simply discards the fraction, */
1029
	/* so we need to be careful with negative values. */
1030
	long whole = (long)value;
1031
	double fpart;
1032
 
1033
	if (value < whole)
1034
	    --whole;
1035
	fpart = value - whole;
1036
	put_int(st, whole, pr->exponent_or_whole_width);
1037
	if (pr->fraction_width == 16) {
1038
	    uint fraction = (uint) (fpart * (1.0 * 0x10000));
1039
 
1040
	    put_int(st, fraction, 16);
1041
	} else {		/* pr->fraction_width == 32 */
1042
	    ulong fraction =
1043
	    (ulong) (fpart * (1.0 * 0x10000 * 0x10000));
1044
 
1045
	    put_int(st, fraction, 32);
1046
	}
1047
    }
1048
}
1049
 
1050
/* Put a real precision. */
1051
private void
1052
put_real_precision(cgm_state * st, const cgm_precision * precision)
1053
{
1054
    I((int)precision->representation);
1055
    I(precision->exponent_or_whole_width);
1056
    I(precision->fraction_width);
1057
}
1058
 
1059
/* Put a VDC. */
1060
private void
1061
put_vdc(cgm_state * st, const cgm_vdc * pvdc)
1062
{
1063
    if (st->metafile.vdc_type == cgm_vdc_integer)
1064
	put_int(st, pvdc->integer, st->vdc_integer_precision);
1065
    else
1066
	put_real(st, pvdc->real, &st->vdc_real_precision);
1067
}
1068
 
1069
/* Put a VDC or a real. */
1070
private void
1071
put_vdc_r(cgm_state * st, const cgm_line_marker_extent * extent,
1072
	  cgm_line_marker_specification_mode mode)
1073
{
1074
    if (mode == cgm_line_marker_absolute)
1075
	VDC(&extent->absolute);
1076
    else
1077
	R(extent->scaled);
1078
}
1079
 
1080
/* Put a point (pair of VDCs). */
1081
private void
1082
put_point(cgm_state * st, const cgm_point * ppt)
1083
{
1084
    if (st->metafile.vdc_type == cgm_vdc_integer) {
1085
	put_int(st, ppt->integer.x, st->vdc_integer_precision);
1086
	put_int(st, ppt->integer.y, st->vdc_integer_precision);
1087
    } else {
1088
	put_real(st, ppt->real.x, &st->vdc_real_precision);
1089
	put_real(st, ppt->real.y, &st->vdc_real_precision);
1090
    }
1091
}
1092
 
1093
/* Put a list of points. */
1094
private void
1095
put_points(cgm_state * st, const cgm_point * ppt, int count)
1096
{
1097
    int i;
1098
 
1099
    for (i = 0; i < count; i++)
1100
	P(ppt + i);
1101
}
1102
 
1103
/* Put bytes. */
1104
private void
1105
put_bytes(cgm_state * st, const byte * data, uint length)
1106
{
1107
    int count;
1108
 
1109
    while (length > (count = command_max_count - st->command_count)) {
1110
	memcpy(st->command + st->command_count, data, count);
1111
	st->command_count += count;
1112
	write_command(st, false);
1113
	data += count;
1114
	length -= count;
1115
    }
1116
    memcpy(st->command + st->command_count, data, length);
1117
    st->command_count += length;
1118
}
1119
 
1120
/* Put a string. */
1121
private void
1122
put_string(cgm_state * st, const char *data, uint length)
1123
{				/* The CGM specification seems to imply that the continuation */
1124
    /* mechanism for commands and the mechanism for strings */
1125
    /* are orthogonal; we take this interpretation. */
1126
    if (length >= 255) {
1127
	put_byte(st, 255);
1128
	while (length > 32767) {
1129
	    put_int(st, 65535, 2);
1130
	    put_bytes(st, (const byte *)data, 32767);
1131
	    data += 32767;
1132
	    length -= 32767;
1133
	}
1134
    }
1135
    put_byte(st, length);
1136
    put_bytes(st, (const byte *)data, length);
1137
}
1138
 
1139
/* Put a color. */
1140
private void
1141
put_color(cgm_state * st, const cgm_color * color)
1142
{
1143
    if (st->picture.color_selection_mode == cgm_color_selection_indexed)
1144
	CI(color->index);
1145
    else
1146
	CD(&color->rgb);
1147
}
1148
 
1149
/* Put an RGB value. */
1150
private void
1151
put_rgb(cgm_state * st, const cgm_rgb * rgb)
1152
{
1153
    put_int(st, rgb->r, st->metafile.color_precision);
1154
    put_int(st, rgb->g, st->metafile.color_precision);
1155
    put_int(st, rgb->b, st->metafile.color_precision);
1156
}