0023510: Integration of test grid "vis" into the new testing system
[occt.git] / src / CGM / cgmobin.c
CommitLineData
b311480e 1/*
2 Copyright (c) 1999-2012 OPEN CASCADE SAS
3
4 The content of this file is subject to the Open CASCADE Technology Public
5 License Version 6.5 (the "License"). You may not use the content of this file
6 except in compliance with the License. Please obtain a copy of the License
7 at http://www.opencascade.org and read it completely before using this file.
8
9 The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11
12 The Original Code and all software distributed under the License is
13 distributed on an "AS IS" basis, without warranty of any kind, and the
14 Initial Developer hereby disclaims all such warranties, including without
15 limitation, any warranties of merchantability, fitness for a particular
16 purpose or non-infringement. Please see the License for the specific terms
17 and conditions governing the rights and limitations under the License.
18
19*/
20
7fd59977 21#include <limits.h>
22#include "cgmout.h"
23
24/* File stream name */
25
26static FILE *cgmob;
27
28/* declare internal functions */
29# if (defined __STDC__ && __STDC__) || defined __cplusplus
30/* use function prototypes, they are requred for ANSI C and C++ compilers */
31void CGMObin(FILE *stream, Code c, Long *pi, Float *pr, char *str);
32/* Main Output Routine */
33static void MOBopcode(Code c, Long len), /* Output an Op code */
34 MOBint(Long n, Prec prec, Enum sign), /* Output an Integer */
35 MOBreal(Double x, Enum real_type, Enum real_or_vdc), /* Output a real number */
36 MOBcolour(struct colour *col, Enum type), /* Output a colour */
37 MOBvdc(Int n, Long *pi, Float *pr), /* Output a number of VDCs */
38 MOBpointlist(Long n, Long *pi, Float *pr, Enum set), /* Output a Points List */
39 MOBclist(register Long num, register Long *col,
40 Prec mode, Enum type, Prec prec), /* Output a colour list */
41 MOBbits(Posint value, Prec prec, Long *bit), /* Output a value to a bit stream */
42 MOBstring(char *s), /* Output a string */
43 MOBout(Posint hex, Prec bytes), /* Output values to the output buffer */
44 MOBcharci(Code c, Int *class, Int *id); /* Convert Op code value to Class and Id */
45#else
46void CGMObin(); /* Main Output Routine */
47static void MOBopcode(), /* Output an Op code */
48 MOBint(), /* Output an Integer */
49 MOBreal(), /* Output a real number */
50 MOBcolour(), /* Output a colour */
51 MOBvdc(), /* Output a number of VDCs */
52 MOBpointlist(), /* Output a Points List */
53 MOBclist(), /* Output a colour list */
54 MOBbits(), /* Output a value to a bit stream */
55 MOBstring(), /* Output a string */
56 MOBout(), /* Output values to the output buffer */
57 MOBcharci(); /* Convert Op code value to Class and Id */
58#endif
59/* Local Parameters */
60
61#define ENUMERATED (Prec) 16
62
63#define PARTITION (Code) 0xff
64
65#define UNSIGNED (Enum) 0
66#define SIGNED (Enum) 1
67
68#define FLOATING (Enum) 0
69#define FIXED (Enum) 1
70
71#define RUNLENGTH (Enum) 0
72#define PACKED (Enum) 1
73
74#define BYTE (Prec) 1
75#define WORD (Prec) 2
76#define LONGINT (Prec) 4
77
78/* Parameter sizes */
79
80#define ENUMSIZE ( (Long) 2 )
81#define INDEXSIZE ( (Long) curbin.index_prec>>3 )
82#define COLINDEXSIZE ( (Long) curbin.colind_prec>>3 )
83#define INTSIZE ( (Long) curbin.int_prec>>3 )
84#define REALSIZE ( (Long) (curbin.real_whole + curbin.real_fraction)>>3 )
85#define VDCSIZE ( (Long) (cur.vdc_type == REAL\
86 ? (curbin.vdc_whole + curbin.vdc_fraction)>>3 \
87 : curbin.vdcint_prec>>3 ) )
88#define COLOURSIZE ( (Long) (cur.color_mode == DIRECT\
89 ? 3*curbin.col_prec>>3 : curbin.colind_prec>>3 ) )
90#define STRINGSIZE(x) ( (Long) (256 * strlen(x) / 255 + 1) )
91
92/* Basic Common Output functions */
93
94#define PUTBYTE(x) MOBout( (Posint) x, (Prec) 1 )
95#define PUTWORD(x) MOBout( (Posint) x, (Prec) 2 )
96#define PUTINT(x) MOBint( (Long) x, curbin.int_prec, SIGNED )
97#define PUTREAL(x) MOBreal ( (Double)x, curbin.real_type, REAL )
98#define PUTINDEX(x) MOBint( (Long) x, curbin.index_prec, SIGNED )
99#define PUTENUM(x) MOBint( (Long) x, ENUMERATED, SIGNED )
100#define PUTINTVDC(x) MOBint( (Long) x, curbin.vdcint_prec, SIGNED )
101#define PUTREALVDC(x) MOBreal( (Double)x, curbin.vdc_type, VDC )
102
103/* Local Variables */
104
105static size_t mobblen = BUFF_LEN, /* Normal Output Buffer length */
106 mobparmlen, /* Parameter length in bytes */
107 mobremainder, /* Bytes left after partition */
108 mobdeflen, /* MF Defaults replacement length */
109 mobindex = 0; /* Output buffer pointer */
110static char mobstdbuff[BUFF_LEN], /* Normal Output buffer */
111 *mobbuff = mobstdbuff, /* Buffer origin */
112 *mobdefbuff; /* MF Defaults replacement buffer */
113
114/*static char *func="CGMobin", mess[40];*/
115static char mess[40];
116
117/********************************************************* CGMObin *****/
118void
119CGMObin(FILE *stream, Code c, Long *pi, Float *pr, char *str)
120{
121 register Long j, n, num;
122 Code major;
123 Long parmlen = ZERO;
124 static Long defindex, saveparmlen;
125 static Logical first = TRUE, first_pic = TRUE;
126 Int class, id;
127
128 if ( c == (Code) EOF )
129 {
130 MOBout ( (Posint) 0, (Prec) 0); /* flush output buffer */
131 exit(0);
132 }
133
134 major=c>>8;
135 num = *pi++;
136
137 switch(major)
138 {
139 case 0x00: /* Graphics Primitives */
140
141 switch(c)
142 {
143 case NONOP: /* Ignore Non-Op */
144 break;
145
146 case LINE: /* Polyline */
147 case DISJTLINE: /* Disjoint Polyline */
148 case MARKER: /* Polymarker */
149 parmlen = 2*num*VDCSIZE;
150 if ( first ) MOBopcode(c, parmlen);
151 else MOBopcode(PARTITION, parmlen);
152 first = ( parmlen >= ZERO );
153 MOBpointlist(num, pi, pr, NOSET);
154 break;
155
156 case TEXT: /* Text */
157 parmlen = 2*VDCSIZE + ENUMSIZE + STRINGSIZE(str);
158 MOBopcode(c, parmlen);
159 MOBvdc( (Int)2, pi, pr);
160 PUTENUM ( num );
161 MOBstring(str);
162 break;
163
164 case RESTRTEXT: /* Restricted Text */
165 parmlen = 4*VDCSIZE + ENUMSIZE + STRINGSIZE(str);
166 MOBopcode(c, parmlen);
167 MOBvdc( (Int)4, pi, pr);
168 PUTENUM ( num );
169 MOBstring(str);
170 break;
171
172 case APNDTEXT: /* Append Text */
173 parmlen = ENUMSIZE + STRINGSIZE(str);
174 MOBopcode(c, parmlen);
175 PUTENUM ( num );
176 MOBstring(str);
177 break;
178
179 case POLYGON: /* Polygon */
180 parmlen = 2*num*VDCSIZE;
181 if ( first ) MOBopcode(c, parmlen);
182 else MOBopcode(PARTITION, parmlen);
183 first = ( parmlen >= ZERO );
184 MOBpointlist(num, pi, pr, NOSET);
185 break;
186
187 case POLYGONSET: /* Polygon Set */
188 parmlen = num * ( 2*VDCSIZE + ENUMSIZE );
189 if ( first ) MOBopcode(c, parmlen);
190 else MOBopcode(PARTITION, parmlen);
191 first = ( parmlen >= ZERO );
192 MOBpointlist(num, pi, pr, SET);
193 break;
194
195 case CELLARRAY: /* Cell Array */
196 {
197 register Long *pt = pi, i, k;
198 Long red, green, blue, nc, ncol;
60be1f9b 199 Long run, packed;
7fd59977 200 Long last, lastred, lastgreen, lastblue;
201 static Long nx, ny;
202 static Prec lprec;
203 static Enum runlength;
204
205/* Number of colour cells */
206
207 nc = abs( num );
208 ncol = abs(cur.color_mode == DIRECT ? 3*num : num );
209
210 if ( first )
211 {
212
213/* set up basic parameter length */
214 parmlen = 6*VDCSIZE + 3*INTSIZE + ENUMSIZE;
215 pt += 6; /* skip 3 points */
216 nx = *pt++; /* Number of columns */
217 ny = *pt++; /* Number of rows */
218 j = *pt++; /* Local precision */
219
220 if ( j == ZERO || num > 0 )
221 {
222
223/* Find largest colour value if cell within buffer */
224
225 for ( i = 0, k = 0; i < ncol; i++, pt++ )
226 {
227 if ( *pt > k ) k = *pt;
228 }
229 j = 0;
230 while ( k )
231 {
232 k >>= 1; j++;
233 }
234 }
235 lprec = ( j <= 1 ? 1
236 : j <= 2 ? 2
237 : j <= 4 ? 4
238 : j <= 8 ? 8
239 : j <= 16 ? 16
240 : j <= 24 ? 24
241 : 32 );
242 pt = pi + 9;
243 }
244
245/* Find number of bytes for both coding methods */
246
247 run = 0; packed = 0;
248 for ( j = 0; j < nc; j += nx )
249 {
250
251/* Make sure row starts on a word boundary */
252
253 if ( packed & 1 ) packed++;
254 if ( run & 1 ) run++;
255
256/* Calculate length of packed list in bytes per row */
257
258 packed += ( (cur.color_mode == DIRECT ? 3*nx : nx)
259 * lprec + 7 )>>3;
260
261/* Calculate length of run length in bits */
262
263 k = 0;
264 if ( cur.color_mode == INDEXED )
265 {
266 last = -1;
267 for ( i = 0; i < nx; i++, pt++ )
268 {
269 if ( *pt != last)
270 {
271 k += curbin.int_prec + lprec;
272 last = *pt;
273 }
274 }
275 }
276 else
277 {
278 lastred = -1; lastgreen = -1; lastblue = -1;
279 for ( i = 0; i < nx; i++ )
280 {
281 red = *pt++; green = *pt++; blue = *pt++;
282 if ( red != lastred || green != lastgreen
283 || blue != lastblue )
284 {
285 k += curbin.int_prec + 3*lprec;
286 lastred = red;
287 lastgreen = green;
288 lastblue = blue;
289 }
290 }
291 }
292
293/* Convert runlength to bytes */
294 run += (k + 7) >>3;
295 }
296
297 if ( first )
298 {
299
300/* Decide which encoding is smallest */
301
302 if ( run < packed )
303 {
304 runlength = RUNLENGTH;
305 parmlen += run;
306 }
307 else
308 {
309 runlength = PACKED;
310 parmlen += packed;
311 }
312
313 if ( num < 0 ) parmlen = - parmlen;
314 MOBopcode(c, parmlen);
315
316 MOBvdc ( (Int)6, pi, pr );
317 PUTINT ( nx );
318 PUTINT ( ny );
319 PUTINT ( lprec );
320
321 pi += 9;
322 PUTENUM ( runlength );
323 }
324 else
325 {
326 parmlen = ( runlength = RUNLENGTH ? run : packed );
327 if ( num < 0 ) parmlen = - parmlen;
328 MOBopcode(PARTITION, parmlen);
329 }
330
331 first = ( num >= ZERO );
332
333/* Output cell array a row at a time */
334
335 for ( j = 0; j < nc; j += nx )
336 {
337 MOBclist (nx, pi, cur.color_mode, runlength, lprec);
338 pi += ( cur.color_mode == DIRECT ? 3*nx : nx );
339 }
340 break;
341 }
342
343 case GDP: /* Generalised Drawing Primitive */
344 parmlen = 2*INTSIZE + 2*num*VDCSIZE + STRINGSIZE(str);
345 if ( first ) MOBopcode(c, parmlen);
346 else MOBopcode(PARTITION, parmlen);
347 first = ( parmlen >= ZERO );
348 PUTINT ( *pi );
349 PUTINT ( num );
350 MOBpointlist(num, pi, pr, NOSET);
351 MOBstring(str);
352 break;
353
354 case RECT: /* Rectangle */
355 parmlen = 4*VDCSIZE;
356 MOBopcode(c, parmlen);
357 MOBvdc( (Int)4, pi, pr);
358 break;
359
360 default:
361 (void) sprintf( mess, "(code: 0x%x)", c);
362 break;
363 }
364 break;
365
366 case 0x30: /* Delimiter Elements */
367
368 switch(c)
369 {
370
371 case BEGMF: /* Begin Metafile */
372 cgmob = stream;
373 curbin = bindef;
374 parmlen = STRINGSIZE(str);
375 MOBopcode(c, parmlen);
376 MOBstring(str);
377 break;
378
379 case ENDMF: /* End Metafile */
380 MOBopcode(c, (Long)0 );
381 break;
382
383 case BEGPIC: /* Begin Picture Descriptor */
384 parmlen = STRINGSIZE(str);
385 MOBopcode(c, parmlen);
386 MOBstring(str);
387 if ( first_pic )
388 {
389 first_pic = FALSE;
390 mfbin = curbin;
391 }
392 else
393 curbin = mfbin;
394 break;
395
396 case BEGPICBODY: /* Begin Picture Body */
397 MOBopcode(c, (Long)0 );
398 break;
399
400 case ENDPIC: /* End Picture */
401 MOBopcode(c, (Long)0 );
402 break;
403
404 default:
405 (void) sprintf( mess, "(code: 0x%x)", c);
406 break;
407 }
408 break;
409
410
411 case 0x31: /* Metafile Descriptor Elements */
412 switch(c)
413 {
414 case MFVERSION: /* Metafile version */
415 parmlen = INTSIZE;
416 MOBopcode(c, parmlen);
417 PUTINT ( num );
418 break;
419
420 case MFDESC: /* Metafile Description */
421 parmlen = STRINGSIZE(str);
422 MOBopcode(c, parmlen);
423 MOBstring(str);
424 break;
425
426 case VDCTYPE: /* VDC Type */
427 parmlen = ENUMSIZE;
428 MOBopcode(c, parmlen);
429 PUTENUM ( cur.vdc_type );
430 break;
431
432 case INTEGERPREC: /* Integer Precision */
433 parmlen = INTSIZE;
434 MOBopcode(c, parmlen);
435 j = ( cur.int_bits <= 8 ? 8
436 : cur.int_bits <= 16 ? 16
437 : cur.int_bits <= 24 ? 24
438 :32 );
439 PUTINT ( j );
440 curbin.int_prec = j;
441 break;
442
443 case REALPREC: /* Real Precision */
444 parmlen = ENUMSIZE + 2*INTSIZE;
445 MOBopcode(c, parmlen);
446 PUTENUM ( curbin.real_type );
447 if ( curbin.real_type == FIXED )
448 { /* NB: only 16,16 and 32,32 are permitted */
449 curbin.real_whole =
450 (cur.real_bits > 16 || -cur.real_places > 16 ? 32 : 16);
451 curbin.real_fraction = curbin.real_whole;
452 }
453 PUTINT ( curbin.real_whole );
454 PUTINT ( curbin.real_fraction );
455 break;
456
457 case INDEXPREC: /* Index Precision */
458 parmlen = INTSIZE;
459 MOBopcode(c, parmlen);
460 curbin.index_prec = ( cur.index_bits <= 8 ? 8
461 : cur.index_bits <= 16 ? 16
462 : cur.index_bits <= 24 ? 24
463 : 32 );
464 PUTINT ( curbin.index_prec );
465 break;
466
467 case COLRPREC: /* Colour Precision */
468 parmlen = INTSIZE;
469 MOBopcode(c, parmlen);
470 curbin.col_prec = ( cur.col_bits <= 8 ? 8
471 : cur.col_bits <= 16 ? 16
472 : cur.col_bits <= 24 ? 24
473 : 32 );
474 PUTINT ( curbin.col_prec );
475 break;
476
477 case COLRINDEXPREC: /* Colour Index Precision */
478 parmlen = INTSIZE;
479 MOBopcode(c, parmlen);
480 curbin.colind_prec = ( cur.colind_bits <= 8 ? 8
481 : cur.colind_bits <= 16 ? 16
482 : cur.colind_bits <= 24 ? 24
483 : 32 );
484 PUTINT ( curbin.colind_prec );
485 break;
486
487 case MAXCOLRINDEX: /* Maximum Colour Index */
488 parmlen = COLINDEXSIZE;
489 MOBopcode(c, parmlen);
490 MOBint (cur.max_colind, curbin.colind_prec, UNSIGNED);
491 break;
492
493 case COLRVALUEEXT: /* Colour value extent */
494 parmlen = 6 * curbin.col_prec >>3;
495 MOBopcode(c, parmlen);
496 curbin.min_rgb.red = cur.min_rgb.red;
497 curbin.min_rgb.green = cur.min_rgb.green;
498 curbin.min_rgb.blue = cur.min_rgb.blue;
499 MOBcolour ( &curbin.min_rgb, DIRECT );
500 curbin.max_rgb.red = cur.max_rgb.red;
501 curbin.max_rgb.green = cur.max_rgb.green;
502 curbin.max_rgb.blue = cur.max_rgb.blue;
503 MOBcolour ( &curbin.max_rgb, DIRECT );
504 break;
505
506 case MFELEMLIST: /* Metafile element List */
507 parmlen = INTSIZE + 2*num*INDEXSIZE;
508 MOBopcode(c, parmlen);
509 PUTINT ( num );
510 for(n = 0; n < num; n++, pi++)
511 {
512 switch ( (Int)*pi )
513 {
514 case 0:
515 case 1:
516 class = -1; id = (Int)*pi;
517 break;
518 default:
519 MOBcharci( (Code)*pi, &class, &id);
520 break;
521 }
522 PUTINDEX ( class );
523 PUTINDEX ( id );
524 }
525 break;
526
527 case BEGMFDEFAULTS: /* Begin Metafile defaults Replacement */
528/* Save current index value */
529 defindex = mobindex;
530 saveparmlen = mobparmlen;
531 mobparmlen = 0;
532/* Create new buffer */
533 mobblen = ARRAY_MAX;
534 mobbuff = mobdefbuff = (char *) malloc( (size_t)mobblen );
535 mobindex = 0;
536 break;
537
538 case ENDMFDEFAULTS: /* End Metafile defaults Replacement */
539/* reset buffer and index */
540 mobbuff = mobstdbuff;
541 mobdeflen = mobindex;
542 mobindex = defindex;
543 mobblen = BUFF_LEN;
544 mobparmlen = saveparmlen;
545 MOBopcode(BEGMFDEFAULTS, mobdeflen);
546
547/* copy defaults buffer to output */
548 for ( n = 0; n < (int)mobdeflen; n++ )
549 PUTBYTE( mobdefbuff[n] );
550 FREE( mobdefbuff );
551 break;
552
553 case FONTLIST: /* Font List */
554 {
555 register Long *pt = pi;
556
557 for ( j=0, parmlen=0; j < num; j = *pt++ )
558 parmlen += STRINGSIZE( &str[j] );
559 MOBopcode(c, parmlen);
560 for ( j=0, pt = pi; j < num; j = *pt++ )
561 MOBstring( &str[j] );
562 break;
563 }
564
565 case CHARSETLIST: /* Character set list */
566 {
567 register Long *pt = pi;
568
569 for ( j=0, parmlen=0; j < num; j = *pt++ )
570 {
571 parmlen += ENUMSIZE + STRINGSIZE(&str[j]);
572 pt++;
573 }
574 MOBopcode(c, parmlen);
575 for ( j=0, pt = pi; j < num; j = *pt++ )
576 {
577 PUTENUM ( *pt++ );
578 MOBstring( &str[j] );
579 }
580 break;
581 }
582
583 case CHARCODING: /* Character coding Announcer */
584 parmlen = ENUMSIZE;
585 MOBopcode(c, parmlen);
586 PUTENUM ( num );
587 break;
588
589 default:
590 (void) sprintf( mess, "(code: 0x%x)", c);
591 break;
592 }
593 break;
594
595 case 0x32: /* Picture Descriptor Elements */
596 switch(c)
597 {
598 case SCALEMODE: /* Scaling Mode */
599 parmlen = ENUMSIZE + REALSIZE;
600 MOBopcode(c, parmlen);
601 PUTENUM ( cur.scale_mode );
602 MOBreal ( (Double)cur.scale_factor, FLOATING, REAL );
603 break;
604
605 case COLRMODE: /* Colour Selection Mode */
606 parmlen = ENUMSIZE;
607 MOBopcode(c, parmlen);
608 PUTENUM ( cur.color_mode );
609 break;
610
611 case LINEWIDTHMODE: /* Line width Specification */
612 parmlen = ENUMSIZE;
613 MOBopcode(c, parmlen);
614 PUTENUM ( cur.linewidth_mode );
615 break;
616
617 case MARKERSIZEMODE: /* Marker size Specification */
618 parmlen = ENUMSIZE;
619 MOBopcode(c, parmlen);
620 PUTENUM ( cur.markersize_mode );
621 break;
622
623 case EDGEWIDTHMODE: /* Edge width Specification */
624 parmlen = ENUMSIZE;
625 MOBopcode(c, parmlen);
626 PUTENUM ( cur.edgewidth_mode );
627 break;
628
629 case VDCEXT: /* VDC Extent */
630 parmlen = 4*VDCSIZE;
631 MOBopcode(c, parmlen);
632 if (cur.vdc_type == REAL)
633 {
634 PUTREALVDC ( cur.vdc_extent.a.x.real );
635 PUTREALVDC ( cur.vdc_extent.a.y.real );
636 PUTREALVDC ( cur.vdc_extent.b.x.real );
637 PUTREALVDC ( cur.vdc_extent.b.y.real );
638 }
639 else
640 {
641 PUTINTVDC ( cur.vdc_extent.a.x.intr );
642 PUTINTVDC ( cur.vdc_extent.a.y.intr );
643 PUTINTVDC ( cur.vdc_extent.b.x.intr );
644 PUTINTVDC ( cur.vdc_extent.b.y.intr );
645 }
646 break;
647
648 case BACKCOLR: /* Background Colour */
649 parmlen = 3 * curbin.col_prec >>3;
650 MOBopcode(c, parmlen);
651 MOBcolour( &cur.back, DIRECT );
652 break;
653
654 default:
655 (void) sprintf( mess, "(code: 0x%x)", c);
656 }
657 break;
658
659 case 0x33: /* Control Elements */
660 switch(c)
661 {
662 case VDCINTEGERPREC: /* VDC Integer Precision */
663 parmlen = INTSIZE;
664 MOBopcode(c, parmlen);
665 curbin.vdcint_prec = ( cur.vdcint_bits <= 8 ? 8
666 : cur.int_bits <= 16 ? 16
667 : cur.int_bits <= 24 ? 24
668 :32 );
669 PUTINT ( curbin.vdcint_prec );
670 break;
671
672 case VDCREALPREC: /* VDC Real Precision */
673 parmlen = ENUMSIZE + 2*INTSIZE;
674 MOBopcode(c, parmlen);
675 PUTENUM ( curbin.vdc_type );
676 if ( curbin.real_type == FIXED )
677 { /* NB: only 16,16 or 32,32 permitted */
678 curbin.vdc_whole =
679 (cur.vdc_bits > 16 || -cur.vdc_places > 16 ? 32 : 16);
680 curbin.vdc_fraction = curbin.vdc_whole;
681 }
682 PUTINT ( curbin.vdc_whole );
683 PUTINT ( curbin.vdc_fraction );
684 break;
685
686 case AUXCOLR: /* Auxiliary Colour */
687 parmlen = COLOURSIZE;
688 MOBopcode(c, parmlen);
689 MOBcolour( &cur.aux, cur.color_mode );
690 break;
691
692 case TRANSPARENCY: /* Transparency */
693 parmlen = ENUMSIZE;
694 MOBopcode(c, parmlen);
695 PUTENUM ( cur.transparency );
696 break;
697
698 case CLIPRECT: /* Clip Rectangle */
699 parmlen = 4*VDCSIZE;
700 MOBopcode(c, parmlen);
701 if ( cur.vdc_type == REAL )
702 {
703 PUTREALVDC ( cur.clip_rect.a.x.real );
704 PUTREALVDC ( cur.clip_rect.a.y.real );
705 PUTREALVDC ( cur.clip_rect.b.x.real );
706 PUTREALVDC ( cur.clip_rect.b.y.real );
707 }
708 else
709 {
710 PUTINTVDC ( cur.clip_rect.a.x.intr );
711 PUTINTVDC ( cur.clip_rect.a.y.intr );
712 PUTINTVDC ( cur.clip_rect.b.x.intr );
713 PUTINTVDC ( cur.clip_rect.b.y.intr );
714 }
715 break;
716
717 case CLIP: /* Clip Indicator */
718 parmlen = ENUMSIZE;
719 MOBopcode(c, parmlen);
720 PUTENUM ( cur.clip_ind );
721 break;
722
723 default:
724 (void) sprintf( mess, "(code: 0x%x)", c);
725 break;
726 }
727 break;
728
729 case 0x34: /* Circles and Ellipses */
730 switch(c)
731 {
732 case CIRCLE: /* Circle */
733 parmlen = 3*VDCSIZE;
734 MOBopcode(c, parmlen);
735 MOBvdc( (Int)3, pi, pr );
736 break;
737
738 case ARC3PT: /* Circular Arc 3 point */
739 parmlen = 6*VDCSIZE;
740 MOBopcode(c, parmlen);
741 MOBvdc( (Int)6, pi, pr );
742 break;
743
744 case ARC3PTCLOSE: /* Circular Arc 3 point close */
745 parmlen = 6*VDCSIZE + ENUMSIZE;
746 MOBopcode(c, parmlen);
747 MOBvdc( (Int)6, pi, pr );
748 PUTENUM ( *(pi+6) );
749 break;
750
751 case ARCCTR: /* Circle Arc centre */
752 parmlen = 7*VDCSIZE;
753 MOBopcode(c, parmlen);
754 MOBvdc( (Int)7, pi, pr );
755 break;
756
757 case ARCCTRCLOSE: /* Circle Arc centre close */
758 parmlen = 7*VDCSIZE + ENUMSIZE;
759 MOBopcode(c, parmlen);
760 MOBvdc( (Int)7, pi, pr );
761 PUTENUM ( *(pi+7) );
762 break;
763
764 case ELLIPSE: /* Ellipse */
765 parmlen = 6*VDCSIZE;
766 MOBopcode(c, parmlen);
767 MOBvdc( (Int)6, pi, pr );
768 break;
769
770 case ELLIPARC: /* Elliptical Arc */
771 parmlen = 10*VDCSIZE;
772 MOBopcode(c, parmlen);
773 MOBvdc( (Int)10, pi, pr );
774 break;
775
776 case ELLIPARCCLOSE: /* Elliptical Arc close */
777 parmlen = 10*VDCSIZE + ENUMSIZE;
778 MOBopcode(c, parmlen);
779 MOBvdc( (Int)10, pi, pr );
780 PUTENUM ( *(pi+10) );
781 break;
782
783 default:
784 (void) sprintf( mess, "(code: 0x%x)", c);
785 break;
786 }
787 break;
788
789 case 0x35: /* Attributes */
790
791 switch(c)
792 {
793 case LINEINDEX: /* Line Bundle index */
794 parmlen = INDEXSIZE;
795 MOBopcode(c, parmlen);
796 PUTINDEX ( curatt.line_ind );
797 break;
798
799 case LINETYPE: /* Line Type */
800 parmlen = INDEXSIZE;
801 MOBopcode(c, parmlen);
802 PUTINDEX ( curatt.line_type );
803 break;
804
805 case LINEWIDTH: /* Line Width */
806 if(cur.linewidth_mode == SCALED)
807 {
808 parmlen = REALSIZE;
809 MOBopcode(c, parmlen);
810 PUTREAL ( curatt.line_width.real );
811 }
812 else
813 {
814 parmlen = VDCSIZE;
815 MOBopcode(c, parmlen);
816 if ( cur.vdc_type == REAL )
817 PUTREALVDC ( curatt.line_width.real );
818 else PUTINTVDC ( curatt.line_width.intr );
819 }
820 break;
821
822 case LINECOLR: /* Line Colour */
823 parmlen = COLOURSIZE;
824 MOBopcode(c, parmlen);
825 MOBcolour( &curatt.line, cur.color_mode);
826 break;
827
828 case MARKERINDEX: /* Marker Bundle index */
829 parmlen = INDEXSIZE;
830 MOBopcode(c, parmlen);
831 PUTINDEX ( curatt.mark_ind );
832 break;
833
834 case MARKERTYPE: /* Marker Type */
835 parmlen = INDEXSIZE;
836 MOBopcode(c, parmlen);
837 PUTINDEX ( curatt.mark_type );
838 break;
839
840 case MARKERSIZE: /* Marker Size */
841 if(cur.markersize_mode == SCALED)
842 {
843 parmlen = REALSIZE;
844 MOBopcode(c, parmlen);
845 PUTREAL ( curatt.mark_size.real );
846 }
847 else
848 {
849 parmlen = VDCSIZE;
850 MOBopcode(c, parmlen);
851 if ( cur.vdc_type == REAL )
852 PUTREALVDC ( curatt.mark_size.real );
853 else PUTINTVDC ( curatt.mark_size.intr );
854 }
855 break;
856
857 case MARKERCOLR: /* Marker Colour */
858 parmlen = COLOURSIZE;
859 MOBopcode(c, parmlen);
860 MOBcolour( &curatt.marker, cur.color_mode);
861 break;
862
863 case TEXTINDEX: /* Text Bundle index */
864 parmlen = INDEXSIZE;
865 MOBopcode(c, parmlen);
866 PUTINDEX ( curatt.text_ind );
867 break;
868
869 case TEXTFONTINDEX: /* Text Font Index */
870 parmlen = INDEXSIZE;
871 MOBopcode(c, parmlen);
872 PUTINDEX ( curatt.text_font );
873 break;
874
875 case TEXTPREC: /* Text Precision */
876 parmlen = ENUMSIZE;
877 MOBopcode(c, parmlen);
878 PUTENUM ( curatt.text_prec );
879 break;
880
881 case CHAREXPAN: /* Character Expansion Factor */
882 parmlen = REALSIZE;
883 MOBopcode(c, parmlen);
884 PUTREAL ( curatt.char_exp );
885 break;
886
887 case CHARSPACE: /* Character Spacing */
888 parmlen = REALSIZE;
889 MOBopcode(c, parmlen);
890 PUTREAL ( curatt.char_space );
891 break;
892
893 case TEXTCOLR: /* Text Colour */
894 parmlen = COLOURSIZE;
895 MOBopcode(c, parmlen);
896 MOBcolour( &curatt.text, cur.color_mode);
897 break;
898
899 case CHARHEIGHT: /* Character Height */
900 parmlen = VDCSIZE;
901 MOBopcode(c, parmlen);
902 if ( cur.vdc_type == REAL )
903 PUTREALVDC ( curatt.char_height.real );
904 else PUTINTVDC ( curatt.char_height.intr );
905 break;
906
907 case CHARORI: /* Character Orientation */
908 parmlen = 4*VDCSIZE;
909 MOBopcode(c, parmlen);
910 if ( cur.vdc_type == REAL )
911 {
912 PUTREALVDC ( curatt.char_up.x.real );
913 PUTREALVDC ( curatt.char_up.y.real );
914 PUTREALVDC ( curatt.char_base.x.real );
915 PUTREALVDC ( curatt.char_base.y.real );
916 }
917 else
918 {
919 PUTINTVDC (curatt.char_up.x.intr );
920 PUTINTVDC (curatt.char_up.y.intr );
921 PUTINTVDC (curatt.char_base.x.intr );
922 PUTINTVDC (curatt.char_base.y.intr );
923 }
924 break;
925
926 case TEXTPATH: /* Text Path */
927 parmlen = ENUMSIZE;
928 MOBopcode(c, parmlen);
929 PUTENUM ( curatt.text_path );
930 break;
931
932 case TEXTALIGN: /* Text Alignment */
933 parmlen = 2*ENUMSIZE + 2*REALSIZE;
934 MOBopcode(c, parmlen);
935 PUTENUM ( curatt.text_halign );
936 PUTENUM ( curatt.text_valign );
937 PUTREAL ( curatt.text_hcont );
938 PUTREAL ( curatt.text_vcont );
939 break;
940
941 case CHARSETINDEX: /* Character Set Index */
942 parmlen = INDEXSIZE;
943 MOBopcode(c, parmlen);
944 PUTINDEX ( curatt.char_set );
945 break;
946
947 case ALTCHARSETINDEX: /* Alt Character Set Index */
948 parmlen = INDEXSIZE;
949 MOBopcode(c, parmlen);
950 PUTINDEX ( curatt.altchar_set );
951 break;
952
953 default:
954 (void) sprintf( mess, "(code: 0x%x)", c);
955 break;
956 }
957 break;
958
959 case 0x36: /* More Attributes */
960 switch(c)
961 {
962 case FILLINDEX: /* Fill Bundle index */
963 parmlen = INDEXSIZE;
964 MOBopcode(c, parmlen);
965 PUTINDEX ( curatt.fill_ind );
966 break;
967
968 case INTSTYLE: /* Interior Style */
969 parmlen = ENUMSIZE;
970 MOBopcode(c, parmlen);
971 PUTENUM ( curatt.int_style );
972 break;
973
974 case FILLCOLR: /* Fill Colour */
975 parmlen = COLOURSIZE;
976 MOBopcode(c, parmlen);
977 MOBcolour( &curatt.fill, cur.color_mode);
978 break;
979
980 case HATCHINDEX: /* Hatch Index */
981 parmlen = INDEXSIZE;
982 MOBopcode(c, parmlen);
983 PUTINDEX(curatt.hatch_ind );
984 break;
985
986 case PATINDEX: /* Pattern Index */
987 parmlen = INDEXSIZE;
988 MOBopcode(c, parmlen);
989 PUTINDEX(curatt.pat_ind );
990 break;
991
992 case EDGEINDEX: /* Edge Bundle index */
993 parmlen = INDEXSIZE;
994 MOBopcode(c, parmlen);
995 PUTINDEX(curatt.edge_ind );
996 break;
997
998 case EDGETYPE: /* Edge Type */
999 parmlen = INDEXSIZE;
1000 MOBopcode(c, parmlen);
1001 PUTINDEX(curatt.edge_type );
1002 break;
1003
1004 case EDGEWIDTH: /* Edge Width */
1005 if(cur.edgewidth_mode == SCALED)
1006 {
1007 parmlen = REALSIZE;
1008 MOBopcode(c, parmlen);
1009 PUTREAL ( curatt.edge_width.real );
1010 }
1011 else
1012 {
1013 parmlen = VDCSIZE;
1014 MOBopcode(c, parmlen);
1015 if ( cur.vdc_type == REAL )
1016 PUTREALVDC ( curatt.edge_width.real );
1017 else PUTINTVDC ( curatt.edge_width.intr );
1018 }
1019 break;
1020
1021 case EDGECOLR: /* Edge Colour */
1022 parmlen = COLOURSIZE;
1023 MOBopcode(c, parmlen);
1024 MOBcolour( &curatt.edge, cur.color_mode);
1025 break;
1026
1027 case EDGEVIS: /* Edge Visibility */
1028 parmlen = ENUMSIZE;
1029 MOBopcode(c, parmlen);
1030 PUTENUM ( curatt.edge_vis );
1031 break;
1032
1033 case FILLREFPT: /* Fill Reference Point */
1034 parmlen = 2*VDCSIZE;
1035 MOBopcode(c, parmlen);
1036 if ( cur.vdc_type == REAL )
1037 {
1038 PUTREALVDC ( curatt.fill_ref.x.real );
1039 PUTREALVDC ( curatt.fill_ref.y.real );
1040 }
1041 else
1042 {
1043 PUTINTVDC ( curatt.fill_ref.x.intr );
1044 PUTINTVDC ( curatt.fill_ref.y.intr );
1045 }
1046 break;
1047
1048 case PATTABLE: /* Pattern Table */
1049 {
1050 register Long *pt = pi, patind, i, k;
1051 Long nx, ny;
1052 Prec lprec;
1053
1054 parmlen = INDEXSIZE + 3*INTSIZE;
1055 patind = *pt++;
1056 nx = *pt++;
1057 ny = *pt++;
1058 pt++; /* ignore previous local precision */
1059
1060/* Find local precision */
1061
1062 n = (cur.color_mode == DIRECT ? 3*num : num );
1063 for ( i = 0, k = 0; i < n; i++, pt++ )
1064 {
1065 if ( *pt > k ) k = *pt;
1066 }
1067 j = 0;
1068 while ( k )
1069 {
1070 k >>= 1; j++;
1071 }
1072 lprec = ( j <= 1 ? 1
1073 : j <= 2 ? 2
1074 : j <= 4 ? 4
1075 : j <= 8 ? 8
1076 : j <= 16 ? 16
1077 : j <= 24 ? 24
1078 : 32 );
1079
1080/* Work out parameter length in bytes */
1081
1082 parmlen += ( lprec * (cur.color_mode == DIRECT ? 3*num : num )
1083 + 7 )>>3;
1084
1085 MOBopcode(c, parmlen);
1086
1087 PUTINDEX ( patind );
1088 PUTINT ( nx );
1089 PUTINT ( ny );
1090 PUTINT ( lprec );
1091
1092/* Output whole cell array */
1093
1094 MOBclist ( num, pi + 4, cur.color_mode, PACKED, lprec);
1095 break;
1096 }
1097
1098 case PATSIZE: /* Pattern Size */
1099 parmlen = 4*VDCSIZE;
1100 MOBopcode(c, parmlen);
1101 if ( cur.vdc_type == REAL )
1102 {
1103 PUTREALVDC ( curatt.pat_size.a.x.real );
1104 PUTREALVDC ( curatt.pat_size.a.y.real );
1105 PUTREALVDC ( curatt.pat_size.b.x.real );
1106 PUTREALVDC ( curatt.pat_size.b.y.real );
1107 }
1108 else
1109 {
1110 PUTINTVDC ( curatt.pat_size.a.x.intr );
1111 PUTINTVDC ( curatt.pat_size.a.y.intr );
1112 PUTINTVDC ( curatt.pat_size.b.x.intr );
1113 PUTINTVDC ( curatt.pat_size.b.y.intr );
1114 }
1115 break;
1116
1117 case COLRTABLE: /* Colour Table */
1118 parmlen = COLINDEXSIZE + ((3*num*curbin.col_prec)>>3);
1119 MOBopcode(c, parmlen);
1120 MOBint(*pi++, curbin.colind_prec, UNSIGNED);
1121 for ( j=0; j < num; j++)
1122 {
1123 MOBint(*pi++, curbin.col_prec, UNSIGNED);
1124 MOBint(*pi++, curbin.col_prec, UNSIGNED);
1125 MOBint(*pi++, curbin.col_prec, UNSIGNED);
1126 }
1127 break;
1128
1129 case ASF: /* Aspect source flags */
1130 {
1131 Long k, l, *pt=pi;
1132 Int type, value;
1133 Logical asflag[ASFS];
1134
1135 for ( j=0; j < ASFS; j++) asflag[j] = FALSE;
1136 for ( j=0; j < num; j++ )
1137 {
1138 type = *pt++; value = (*pt++) + 1;
1139 if ( type < ASFS ) asflag[type] = value;
1140 else
1141 {
1142 switch ( type )
1143 {
1144 case 506: /* all edge */
1145 k = 15; l = 17; break;
1146 case 507: /* all fill */
1147 k = 11; l = 14; break;
1148 case 508: /* all text */
1149 k = 6; l = 10; break;
1150 case 509: /* all marker */
1151 k = 3; l = 5; break;
1152 case 510: /* all line */
1153 k = 0; l = 2; break;
1154 case 511: /* all */
1155 k = 0; l = 17; break;
1156 default: /* ignore */
1157 k = 1; l = 0; break;
1158 }
1159 for ( n = k; n < l; n++ ) asflag[n] = value;
1160 }
1161 }
1162 for ( j=0; j < ASFS; j++)
1163 if ( asflag[j] ) parmlen += 2*ENUMSIZE;
1164 MOBopcode(c, parmlen);
1165 for ( j=0; j < ASFS; j++)
1166 if ( asflag[j] )
1167 {
1168 PUTENUM ( j );
1169 PUTENUM ( curatt.asf[j] );
1170 }
1171 break;
1172 }
1173
1174 default:
1175 (void) sprintf( mess, "(code: 0x%x)", c);
1176 break;
1177 }
1178 break;
1179
1180 case 0x37: /* Escape And External Elements */
1181 switch(c)
1182 {
1183 case ESCAPE: /* Escape */
1184 parmlen = INTSIZE + STRINGSIZE(str);
1185 MOBopcode(c, parmlen);
1186 PUTINT ( num );
1187 MOBstring(str);
1188 break;
1189
1190 case MESSAGE: /* Message */
1191 parmlen = ENUMSIZE + STRINGSIZE(str);
1192 MOBopcode(c, parmlen);
1193 PUTENUM ( num );
1194 MOBstring(str);
1195 break;
1196
1197 case APPLDATA: /* Application Data */
1198 parmlen = INTSIZE + STRINGSIZE(str);
1199 MOBopcode(c, parmlen);
1200 PUTINT ( num );
1201 MOBstring(str);
1202 break;
1203
1204 default:
1205 (void) sprintf( mess, "(code: 0x%x)", c);
1206 break;
1207 }
1208 break;
1209
1210 default:
1211 (void) sprintf( mess, "(code: 0x%x)", c);
1212 break;
1213 }
1214 return;
1215}
1216
1217/******************************************************** MOBopcode ****/
1218
1219static void
1220MOBopcode( Code c, Long len )
1221{
1222 Int class, id;
1223 unsigned Long oneword, plen, remainder;
1224 Logical part;
1225
1226/* Pad out last element if necessary */
1227 while ( mobparmlen && mobparmlen < 0x8000 ) PUTBYTE( ZERO );
1228
1229 plen = abs(len);
1230 part = (len < 0);
1231
1232/* check for parameter length > 32766 */
1233
1234 if ( plen > 0x7ffe )
1235 {
1236 remainder = plen - 0x7ffe;
1237 part = TRUE;
1238 plen = 0x7ffe;
1239 }
1240 else remainder = 0;
1241
1242 if ( c != PARTITION )
1243 {
1244 MOBcharci(c, &class, &id);
1245 oneword = (class<<12) + (id<<5) + ( part || (plen > 0x1e) ? 0x1f : plen );
1246 PUTWORD ( oneword );
1247 }
1248
1249/* Put out parameter length as integer */
1250
1251 if ( c == PARTITION || plen > 0x1e )
1252 {
1253 oneword = ( part ? plen | 0x8000 : plen );
1254 PUTWORD ( oneword );
1255 }
1256
1257 mobparmlen = plen;
1258 mobremainder = remainder;
1259 if (mobparmlen & 1) mobparmlen++;
1260 return;
1261}
1262
1263/******************************************************** MOBcharci ****/
1264static void
1265MOBcharci( Code c, Int *class, Int *id )
1266{
1267/* Converts Code c to class and Id */
1268
1269 Code major = c>>8, minor = c & 0xff;
1270
1271 *class = -1; *id = 0;
1272 switch ( major )
1273 {
1274 case 0x00: /* Graphics Primitives */
1275 if ( minor >= 0x20 && minor <= 0x2A )
1276 {
1277 *class = 4; *id = minor - 0x20 + 1;
1278 }
1279 else if ( minor == 0 ) *class = ZERO; /* Non-Op */
1280 break;
1281
1282 case 0x30: /* Metafile delimiters */
1283 if ( minor >= 0x20 && minor <= 0x24 )
1284 {
1285 *class = 0; *id = minor - 0x20 + 1;
1286 }
1287 break;
1288
1289 case 0x31: /* Metafile Descriptor Elements */
1290 if ( minor >= 0x20 && minor <= 0x2b )
1291 {
1292 *class = 1; *id = minor - 0x20 + 1;
1293 }
1294 else if ( minor > 0x2c && minor <= 0x2f )
1295 {
1296 *class = 1; *id = minor - 0x20;
1297 }
1298 break;
1299
1300 case 0x32: /* Picture Descriptor Elements */
1301 if ( minor >= 0x20 && minor <= 0x26 )
1302 {
1303 *class = 2; *id = minor - 0x20 + 1;
1304 }
1305 break;
1306
1307 case 0x33: /* Control Elements */
1308 if ( minor >= 0x20 && minor <= 0x25 )
1309 {
1310 *class = 3; *id = minor - 0x20 + 1;
1311 }
1312 break;
1313
1314 case 0x34: /* More Graphics Primitives */
1315 if ( minor >= 0x20 && minor <= 0x27 )
1316 {
1317 *class = 4; *id = minor - 0x20 + 12;
1318 }
1319 break;
1320
1321 case 0x35: /* Attributes */
1322 if ( minor >= 0x20 && minor <= 0x27 )
1323 {
1324 *class = 5; *id = minor - 0x20 + 1;
1325 }
1326 else if ( minor >= 0x30 && minor <= 0x3b )
1327 {
1328 *class = 5; *id = minor - 0x30 + 9;
1329 }
1330 break;
1331
1332 case 0x36: /* More Attributes */
1333 if ( minor >= 0x20 && minor <= 0x2c )
1334 {
1335 *class = 5; *id = minor - 0x20 + 21;
1336 }
1337 else if ( minor >= 0x30 && minor <= 0x31 )
1338 {
1339 *class = 5; *id = minor - 0x30 + 34;
1340 }
1341 break;
1342
1343 case 0x37: /* External elements */
1344 if ( minor == 0x20 )
1345 {
1346 *class = 6; *id = 1;
1347 }
1348 else if ( minor >= 0x21 && minor <= 0x22 )
1349 {
1350 *class = 7; *id = minor - 0x20;
1351 }
1352 break;
1353
1354 default:
1355 break;
1356 }
1357
1358 if ( *class < 0 )
1359 {
1360 (void) sprintf( mess, "(code: 0x%x)", c);
1361 *class = 0;
1362 }
1363
1364 return;
1365}
1366
1367/******************************************************** MOBint *******/
1368static void
1369MOBint( Long n, Prec prec, Enum sign )
1370{
1371/*
1372 if ( sign == SIGNED && n < 0 )
1373 n = (-n | (Posint) 1L<<(prec-1));
1374*/
1375 MOBout( (Posint) n, prec>>3 );
1376 return;
1377}
1378
1379/******************************************************** MOBcolour ****/
1380static void
1381MOBcolour( struct colour *col, Enum type )
1382{
1383
1384 if ( type == DIRECT )
1385 {
1386 MOBint( (Long) col->red, curbin.col_prec, UNSIGNED );
1387 MOBint( (Long) col->green, curbin.col_prec, UNSIGNED );
1388 MOBint( (Long) col->blue, curbin.col_prec, UNSIGNED );
1389 }
1390 else
1391 {
1392 MOBint( (Long) col->index, curbin.colind_prec, UNSIGNED );
1393 }
1394
1395 return;
1396}
1397
1398/******************************************************** MOBvdc *******/
1399static void
1400MOBvdc( Int n, Long *pi, Float *pr)
1401{
1402 Int i;
1403 for ( i = 0; i < n; i++)
1404 {
1405 if ( cur.vdc_type == INTEGER )
1406 {
1407 PUTINTVDC ( *pi++ );
1408 }
1409 else
1410 {
1411 PUTREALVDC ( *pr++ );
1412 }
1413 }
1414
1415 return;
1416}
1417
1418/******************************************************** MOBpointlist */
1419static void
1420MOBpointlist(Long n, Long *pi, Float *pr, Enum set)
1421{
1422 Int i;
1423 for ( i = 0; i < n; i++)
1424 {
1425 if ( cur.vdc_type == INTEGER )
1426 {
1427 PUTINTVDC ( *pi++ );
1428 PUTINTVDC ( *pi++ );
1429 }
1430 else
1431 {
1432 PUTREALVDC ( *pr++ );
1433 PUTREALVDC ( *pr++ );
1434 }
1435 if ( set ) PUTENUM ( *pi++ );
1436 }
1437
1438 return;
1439}
1440
1441/******************************************************** MOBreal ******/
1442static void
1443MOBreal(Double x, Enum real_type, Enum real_or_vdc )
1444{
1445 Posint whole, exponent, fract, neg;
1446 Prec prec;
1447 Double f;
1448 neg = ( x < 0.0 ) << 15;
1449
1450 if ( real_type == FIXED )
1451 {
1452 prec = (real_or_vdc == VDC ? curbin.vdc_whole
1453 : curbin.real_whole);
1454 whole = (Posint)( neg ? -((floor(x))) : x );
1455 fract = (Posint)( ( neg ? x + (Double)whole : x - (Double)whole )
1456 * ( 1L<<(prec-2) ) * 4.0 );
1457
1458 if ( prec == 32 )
1459 {
1460 PUTWORD( whole>>16 | neg );
1461 PUTWORD( whole & (Posint)0xffff );
1462 PUTWORD( fract>>16 );
1463 PUTWORD( fract & (Posint)0xffff );
1464 }
1465 else
1466 {
1467 PUTWORD( whole | neg );
1468 PUTWORD( fract );
1469 }
1470 }
1471 else
1472 {
1473/* IEEE Floating point reals */
1474
1475 prec = (real_or_vdc == VDC ? curbin.vdc_whole + curbin.vdc_fraction
1476 : curbin.real_whole + curbin.real_fraction);
1477 prec = (prec == 64 ? 12 : 9);
1478 f = ( neg ? -x : x );
1479
1480 if ( f < (Double)(real_or_vdc == VDC ? cur.vdcmin : cur.realmin) )
1481 {
1482 exponent = ZERO;
1483 fract = ZERO;
1484 }
1485 else
1486 {
1487
1488/* check if greater than smallest exponent */
1489
1490 exponent = ( prec == 12 ? 1023 : 127 );
1491
1492 if ( f <= 1.0 / (Double) (prec-1) )
1493 {
1494 exponent = ZERO;
1495 }
1496 else
1497 {
1498 while ( f >= 2.0 )
1499 {
1500 f /= 2.0;
1501 exponent++;
1502 }
1503 while ( f < 1.0 )
1504 {
1505 f *= 2.0;
1506 exponent--;
1507 }
1508 }
1509 fract = (Long) ( (f - 1.0) * (Double)(1L<<(prec == 12 ? 52 : 23)) );
1510 }
1511
1512#if defined(_LP64)
1513 if ( prec == 12 )
1514 {
1515 PUTWORD( (exponent<<4) | neg | (fract>>48) );
1516 PUTWORD( (fract >> 32) & (Posint)0xffff );
1517 PUTWORD( (fract >> 16) & (Posint)0xffff );
1518 PUTWORD( fract & (Posint)0xffff );
1519 }
1520 else
1521#endif
1522 {
1523 PUTWORD( (exponent<<7) | neg | (fract>>16) );
1524 PUTWORD( fract & (Posint)0xffff );
1525 }
1526 }
1527 return;
1528}
1529
1530/******************************************************** MOBstring ****/
1531static void
1532MOBstring( char *s )
1533{
1534/* Output a text string if CMS translate from EBCDIC to ASCII */
1535
1536 register Int i, len, slen = strlen(s);
1537 register char chr;
1538 len = slen;
1539 do
1540 {
1541 PUTBYTE ( len >= 0xff ? 0xff : len );
1542 len -= 0xff;
1543 } while ( len >= 0 );
1544
1545 for (i = 0; i < slen; i++)
1546 {
1547 chr = *s++;
1548 PUTBYTE ( chr );
1549 }
1550return;
1551}
1552
1553/******************************************************** MOBclist *****/
1554static void
1555MOBclist( register Long num, register Long *col,
1556 Prec mode, Enum type, Prec prec )
1557{
1558/* Output a colour list */
1559
1560 register Long j, k, n;
1561 Long bits, bytes = 0;
1562 if ( type == RUNLENGTH )
1563 {
1564 Long run = 1, bit = 0;
1565
1566 if ( mode == DIRECT )
1567 {
1568 Posint red, green, blue, lastred, lastgreen, lastblue;
1569
1570 lastred = (*col++);
1571 lastgreen = (*col++);
1572 lastblue = (*col++);
1573 for ( j = 1; j <= num; j++ )
1574 {
1575 red = (*col++); green = (*col++); blue = (*col++);
1576 if ( j == num ||
1577 red != lastred || green != lastgreen || blue != lastblue )
1578 {
1579 MOBbits ( run, curbin.int_prec, &bit );
1580 MOBbits ( lastred, prec, &bit );
1581 MOBbits ( lastgreen, prec, &bit );
1582 MOBbits ( lastblue, prec, &bit );
1583 if ( j == num ) break;
1584 lastred = red; lastgreen = green; lastblue = blue;
1585 run = 1;
1586 }
1587 else run++;
1588 }
1589 }
1590 else /* Indexed runlength */
1591 {
1592 Long lastcol;
1593
1594 lastcol = (*col++);
1595 for ( j = 1; j <= num; j++, col++ )
1596 {
1597 if ( j == num || *col != lastcol )
1598 {
1599 MOBbits ( run, curbin.int_prec, &bit );
1600 MOBbits ( lastcol, prec, &bit );
1601 if ( j == num ) break;
1602 lastcol = *col;
1603 run = 1;
1604 }
1605 else run++;
1606 }
1607 }
1608
1609/* make sure list ends on a word boundary */
1610
1611 if ( bit ) MOBbits ( (Posint) 0 , (Prec) 16, &bit );
1612
1613 }
1614 else /* Packed mode */
1615 {
1616 n = ( mode == DIRECT ? 3*num : num );
1617 bytes = ( n*prec + 7 ) >>3;
1618
1619 for ( j = 0, bits = 0, k = 0; j < n; j++)
1620 {
1621 if ( bits ) k <<= prec;
1622 else k = 0;
1623 k += (*col++);
1624 bits += prec;
1625
1626 while ( bits >= 8 )
1627 {
1628 bits -= 8;
1629 PUTBYTE ( (k>>bits) & 0xff );
1630 }
1631 }
1632 if ( bits > 0 ) PUTBYTE ( k<<(8-bits) );
1633
1634/* Pad buffer if necessary */
1635 if ( bytes & 1 ) PUTBYTE ( 0 );
1636 }
1637 return;
1638}
1639
1640/******************************************************** MOBbits ******/
1641static void
1642MOBbits ( Posint value, Prec prec, Long *bit )
1643{
1644/* Output 'value' as 'prec' bits
1645 using 'word' to hold current value
1646 returns number of bits left in 'bits' */
1647
1648 static Posint oneword = 0;
1649 Posint mask = (Posint)0xffffffff;
1650 *bit += prec;
1651 if ( *bit <= 16 )
1652 {
1653 oneword |= value<<(16 - *bit);
1654 }
1655 else
1656 {
1657 while ( *bit > 16 )
1658 {
1659 *bit -= 16;
1660/* k = prec + *bit - 16; */
1661 oneword |= value>>*bit;
1662 value &= mask>>(32 - *bit);
1663 MOBout ( oneword, WORD );
1664 oneword = value<<16;
1665 }
1666 oneword = value<<(16 - *bit);
1667 }
1668 return;
1669}
1670
1671/******************************************************** MOBout *******/
1672static void
1673MOBout( Posint hex, Prec bytes )
1674{
1675/* Output 'hex' as 'bytes' bytes to output file 'cgmob'
1676 which is either the file or MF defaults buffer */
1677
1678 register Int /*i,*/ b_len;
1679 b_len = bytes;
1680 mobindex = ZERO;
1681 if ( bytes > 0 ) for( ; bytes ; mobindex++ )
1682 {
1683 bytes--;
1684 mobbuff[mobindex] = (char)((hex >> (8*bytes) ) & 0xff);
1685 mobparmlen--;
1686 }
1687 fwrite(mobbuff,b_len,(size_t)1,cgmob);
1688/*
1689start:
1690 if ( bytes > 0 ) for( ; bytes ; mobindex++ )
1691 {
1692 if ( mobindex == mobblen )
1693 {
1694 if ( cgmstate != MF_DEFAULTS )
1695 {
1696 fwrite(mobbuff,mobblen,(size_t)1,cgmob);
1697 mobindex=ZERO;
1698 }
1699 else
1700 {
1701 mobblen += BUFF_LEN;
1702 mobbuff = (char *)realloc (mobbuff, (size_t)mobblen);
1703 }
1704 }
1705 if ( mobindex == ZERO )
1706 {
1707 for(i = ZERO; i < mobblen ; i++) mobbuff[i] = '\0';
1708 }
1709 bytes--;
1710 mobbuff[mobindex] = ( hex>>(8*bytes) ) & 0xff;
1711 mobparmlen--;
1712 }
1713 else
1714 {
1715 fwrite(mobbuff,BUFF_LEN,(size_t)1,cgmob);
1716 mobindex = ZERO;
1717 }
1718 fflush(cgmob);
1719 if ( mobremainder && mobparmlen == 0 )
1720 {
1721 if ( mobremainder > 0x7ffe )
1722 {
1723 hex = 0xfffe;
1724 mobremainder -= 0x7ffe;
1725 }
1726 else
1727 {
1728 hex = mobremainder;
1729 mobremainder = 0;
1730 }
1731 mobparmlen = hex & 0x7fff;
1732 bytes = 2;
1733 mobparmlen += 2;
1734 goto start;
1735 }
1736*/
1737 return;
1738}