1 /* output-dr2d.c: output in DR2D format
2
3 Copyright (C) 2002 Andrew Elia
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2.1 of
8 the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 USA. */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif /* Def: HAVE_CONFIG_H */
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "spline.h"
28 #include "color.h"
29 #include "output-dr2d.h"
30
31
32 /* Globals: Values are set by output_dr2d_writer() */
33 float XFactor;
34 float YFactor;
35 float LineThickness;
36
37 #define FIXOFFS 10
38
39 #define LF_ACTIVE 0x01
40 #define LF_DISPLAYED 0x02
41
42 #define FT_NONE 0
43 #define FT_COLOR 1
44
45 #define JT_NONE 0
46 #define JT_MITER 1
47 #define JT_BEVEL 2
48 #define JT_ROUND 3
49
50 #define INDICATOR 0xFFFFFFFF
51 #define IND_SPLINE 0x00000001
52 #define IND_MOVETO 0x00000002
53
54 struct Chunk {
55 unsigned char ID[4];
56 unsigned int Size;
57 unsigned char * Data;
58 };
59
60 static struct Chunk * BuildDRHD(int, int, int, int);
61 static struct Chunk * BuildPPRF(char *, int, char *, float);
62 static struct Chunk * BuildCMAP(spline_list_array_type);
63 static struct Chunk * BuildLAYR(void);
64 static struct Chunk * BuildDASH(void);
65 static struct Chunk * BuildBBOX(spline_list_type, int);
66 static struct Chunk * BuildATTR(at_color_type, int, struct Chunk *);
67 static int GetCMAPEntry(at_color_type, struct Chunk *);
68 static int CountSplines(spline_list_type);
69 static int SizeFloat(float, char *);
70 static void ShortAsBytes(int, unsigned char *);
71 static void IntAsBytes(int, unsigned char *);
72 static void FloatAsIEEEBytes(float, unsigned char *);
73 /* static void ieee2flt(long *, float *); */
74 static void flt2ieee(float *, unsigned char *);
75 static void FreeChunk(struct Chunk *);
76 static void FreeChunks(struct Chunk **, int);
77 static int TotalSizeChunks(struct Chunk **, int);
78 static int SizeChunk(struct Chunk *);
79 static void PushPolyPoint(unsigned char *, int *, float, float);
80 static void PushPolyIndicator(unsigned char *, int *, unsigned int);
81 static struct Chunk ** GeneratexPLY(struct Chunk *, spline_list_array_type, int);
82
BuildCMAP(spline_list_array_type shape)83 static struct Chunk * BuildCMAP(spline_list_array_type shape) {
84 unsigned this_list;
85 unsigned this_list_length;
86 int ListSize, MaxListSize;
87 int WalkCol, FoundCol;
88 unsigned char Red, Green, Blue;
89 unsigned char * CMAP;
90 unsigned char * IndexCol;
91 struct Chunk * CMAPChunk;
92
93 MaxListSize = SPLINE_LIST_ARRAY_LENGTH(shape);
94
95 if ((CMAPChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
96 fprintf(stderr, "Insufficient memory to allocate CMAP chunk\n");
97 return NULL;
98 }
99
100 if ((CMAP = (unsigned char *) malloc(MaxListSize * 3)) == NULL) {
101 fprintf(stderr, "Insufficient memory to allocate colour map (size %d)\n", MaxListSize);
102 free(CMAPChunk);
103 return NULL;
104 }
105
106 ListSize = 0;
107 this_list_length = SPLINE_LIST_ARRAY_LENGTH(shape);
108 for (this_list = 0; this_list < this_list_length; this_list++) {
109 spline_list_type list = SPLINE_LIST_ARRAY_ELT(shape, this_list);
110 color_type curr_color = curr_color = (list.clockwise && shape.background_color != NULL)? *(shape.background_color) : list.color;
111
112 Red = curr_color.r;
113 Green = curr_color.g;
114 Blue = curr_color.b;
115
116 FoundCol = 0;
117 for (WalkCol = 0; WalkCol < ListSize; WalkCol++) {
118 IndexCol = CMAP + (WalkCol * 3);
119 if ((*IndexCol == Red) && (*(IndexCol + 1) == Green) && (*(IndexCol + 2) == Blue)) {
120 FoundCol = 1;
121 break;
122 }
123 }
124
125 if (FoundCol == 0) {
126 IndexCol = CMAP + (ListSize * 3);
127 *IndexCol = Red;
128 *(IndexCol + 1) = Green;
129 *(IndexCol + 2) = Blue;
130 ++ListSize;
131 }
132 }
133
134 strncpy(CMAPChunk->ID, "CMAP", 4);
135 CMAPChunk->Size = ListSize * 3;
136 CMAPChunk->Data = CMAP;
137
138 return CMAPChunk;
139 }
140
GetCMAPEntry(at_color_type colour,struct Chunk * CMAPChunk)141 static int GetCMAPEntry(at_color_type colour, struct Chunk * CMAPChunk) {
142 int WalkCol, ListSize;
143 unsigned char Red, Green, Blue;
144 unsigned char * IndexCol;
145 unsigned char * CMAPTable;
146
147 ListSize = (CMAPChunk->Size) / 3;
148 CMAPTable = CMAPChunk->Data;
149
150 Red = colour.r;
151 Green = colour.g;
152 Blue = colour.b;
153
154 for (WalkCol = 0; WalkCol < ListSize; WalkCol++) {
155 IndexCol = CMAPTable + (WalkCol * 3);
156 if ((*IndexCol == Red) && (*(IndexCol + 1) == Green) && (*(IndexCol + 2) == Blue)) {
157 return WalkCol;
158 }
159 }
160
161 return -1;
162 }
163
BuildBBOX(spline_list_type list,int height)164 static struct Chunk * BuildBBOX(spline_list_type list, int height) {
165 unsigned this_spline;
166 unsigned this_spline_length;
167 float x1, y1, x2, y2;
168 float ex, ey;
169 struct Chunk * BBOXChunk;
170 unsigned char * BBOXData;
171 spline_type s;
172
173 if ((BBOXChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
174 fprintf(stderr, "Insufficient memory to allocate BBOX chunk\n");
175 return NULL;
176 }
177
178 if ((BBOXData = (unsigned char *) malloc(16)) == NULL) {
179 fprintf(stderr, "Insufficient memory to allocate BBOX data\n");
180 free(BBOXChunk);
181 return NULL;
182 }
183
184 s = SPLINE_LIST_ELT(list, 0);
185
186 x1 = START_POINT(s).x;
187 y1 = START_POINT(s).y;
188 x2 = START_POINT(s).x;
189 y2 = START_POINT(s).y;
190
191 this_spline_length = SPLINE_LIST_LENGTH(list);
192 for (this_spline = 0; this_spline < this_spline_length; this_spline++) {
193 s = SPLINE_LIST_ELT(list, this_spline);
194 ex = END_POINT(s).x;
195 ey = height - END_POINT(s).y;
196
197 if (x1 > ex) {
198 x1 = ex;
199 }
200
201 if (y1 > ey) {
202 y1 = ey;
203 }
204
205 if (x2 < ex) {
206 x2 = ex;
207 }
208
209 if (y2 < ey) {
210 y2 = ey;
211 }
212 }
213
214 FloatAsIEEEBytes(x1 * XFactor, BBOXData);
215 FloatAsIEEEBytes(y1 * YFactor, BBOXData + 4);
216 FloatAsIEEEBytes(x2 * XFactor, BBOXData + 8);
217 FloatAsIEEEBytes(y2 * YFactor, BBOXData + 12);
218
219 strncpy(BBOXChunk->ID, "BBOX", 4);
220 BBOXChunk->Size = 16;
221 BBOXChunk->Data = BBOXData;
222
223 return BBOXChunk;
224 }
225
BuildATTR(at_color_type colour,int StrokeOrFill,struct Chunk * CMAPChunk)226 static struct Chunk * BuildATTR(at_color_type colour, int StrokeOrFill, struct Chunk * CMAPChunk) {
227 struct Chunk * ATTRChunk;
228 unsigned char * ATTRData;
229 int ColourIndex;
230
231 if ((ATTRChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
232 fprintf(stderr, "Insufficient memory to allocate ATTR chunk\n");
233 return NULL;
234 }
235
236 if ((ATTRData = (unsigned char *) malloc(14)) == NULL) {
237 fprintf(stderr, "Insufficient memory to allocate ATTR data\n");
238 free(ATTRChunk);
239 return NULL;
240 }
241
242 ColourIndex = GetCMAPEntry(colour, CMAPChunk);
243
244 ATTRData[0] = (StrokeOrFill) ? FT_NONE : FT_COLOR;
245 ATTRData[1] = JT_ROUND;
246 ATTRData[2] = 1;
247 ATTRData[3] = 0;
248 ShortAsBytes(ColourIndex, ATTRData + 4);
249 ShortAsBytes(ColourIndex, ATTRData + 6);
250 ShortAsBytes(0, ATTRData + 8);
251 FloatAsIEEEBytes(LineThickness, ATTRData + 10);
252
253 strncpy(ATTRChunk->ID, "ATTR", 4);
254 ATTRChunk->Size = 14;
255 ATTRChunk->Data = ATTRData;
256
257 return ATTRChunk;
258 }
259
BuildDRHD(int x1,int y1,int x2,int y2)260 static struct Chunk * BuildDRHD(int x1, int y1, int x2, int y2) {
261 struct Chunk * DRHDChunk;
262 unsigned char * DRHDData;
263
264 if ((DRHDChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
265 fprintf(stderr, "Insufficient memory to allocate DRHD chunk\n");
266 return NULL;
267 }
268
269 if ((DRHDData = (unsigned char *) malloc(16)) == NULL) {
270 fprintf(stderr, "Insufficient memory to allocate DRHD data\n");
271 free(DRHDChunk);
272 return NULL;
273 }
274
275 FloatAsIEEEBytes(x1 * XFactor, DRHDData);
276 FloatAsIEEEBytes(y1 * YFactor, DRHDData + 4);
277 FloatAsIEEEBytes(x2 * XFactor, DRHDData + 8);
278 FloatAsIEEEBytes(y2 * YFactor, DRHDData + 12);
279
280 strncpy(DRHDChunk->ID, "DRHD", 4);
281 DRHDChunk->Size = 16;
282 DRHDChunk->Data = DRHDData;
283
284 return DRHDChunk;
285 }
286
BuildPPRF(char * Units,int Portrait,char * PageType,float GridSize)287 static struct Chunk * BuildPPRF(char * Units, int Portrait, char * PageType, float GridSize) {
288 struct Chunk * PPRFChunk;
289 char * PPRFData;
290 char * PPRFPos;
291 int ChunkSize;
292
293 if ((PPRFChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
294 fprintf(stderr, "Insufficient memory to allocate PPRF chunk\n");
295 return NULL;
296 }
297
298 ChunkSize = strlen("Units=") + strlen(Units) + 1;
299 ChunkSize += strlen("Portrait=") + (Portrait ? 4 : 5) + 1;
300 ChunkSize += strlen("PageType=") + strlen(PageType) + 1;
301 ChunkSize += strlen("GridSize=") + SizeFloat(GridSize, "%f") + 1;
302
303 if ((PPRFData = (char *) malloc(ChunkSize)) == NULL) {
304 fprintf(stderr, "Insufficient memory to allocate PPRF data\n");
305 free(PPRFChunk);
306 return NULL;
307 }
308
309 PPRFPos = PPRFData;
310 sprintf(PPRFPos, "Units=%s", Units);
311 PPRFPos += strlen(PPRFPos) + 1;
312 sprintf(PPRFPos, "Portrait=%s", (Portrait ? "True" : "False"));
313 PPRFPos += strlen(PPRFPos) + 1;
314 sprintf(PPRFPos, "PageType=%s", PageType);
315 PPRFPos += strlen(PPRFPos) + 1;
316 sprintf(PPRFPos, "GridSize=%f", GridSize);
317
318 strncpy(PPRFChunk->ID, "PPRF", 4);
319 PPRFChunk->Size = ChunkSize;
320 PPRFChunk->Data = (unsigned char *) PPRFData;
321
322 return PPRFChunk;
323 }
324
BuildLAYR()325 static struct Chunk * BuildLAYR() {
326 struct Chunk * LAYRChunk;
327 unsigned char * LAYRData;
328
329 if ((LAYRChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
330 fprintf(stderr, "Insufficient memory to allocate LAYR chunk\n");
331 return NULL;
332 }
333
334 if ((LAYRData = (unsigned char *) malloc(20)) == NULL) {
335 fprintf(stderr, "Insufficient memory to allocate LAYR data\n");
336 free(LAYRChunk);
337 return NULL;
338 }
339
340 ShortAsBytes(0, LAYRData);
341 memset(LAYRData + 2, (char) NULL, 16);
342 strcpy(LAYRData + 2, "Default layer");
343 *(LAYRData + 18) = LF_ACTIVE | LF_DISPLAYED;
344 *(LAYRData + 19) = 0;
345
346 strncpy(LAYRChunk->ID, "LAYR", 4);
347 LAYRChunk->Size = 20;
348 LAYRChunk->Data = LAYRData;
349
350 return LAYRChunk;
351 }
352
BuildDASH(void)353 static struct Chunk * BuildDASH(void) {
354 struct Chunk * DASHChunk;
355 unsigned char * DASHData;
356
357 if ((DASHChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
358 fprintf(stderr, "Insufficient memory to allocate DASH chunk\n");
359 return NULL;
360 }
361
362 if ((DASHData = (unsigned char *) malloc(4)) == NULL) {
363 fprintf(stderr, "Insufficient memory to allocate DASH data\n");
364 free(DASHChunk);
365 return NULL;
366 }
367
368 ShortAsBytes(1, DASHData);
369 ShortAsBytes(0, DASHData + 2);
370
371 strncpy(DASHChunk->ID, "DASH", 4);
372 DASHChunk->Size = 4;
373 DASHChunk->Data = DASHData;
374
375 return DASHChunk;
376 }
377
GeneratexPLY(struct Chunk * CMAP,spline_list_array_type shape,int height)378 static struct Chunk ** GeneratexPLY(struct Chunk * CMAP, spline_list_array_type shape, int height) {
379 unsigned this_list;
380 unsigned this_list_length;
381 unsigned this_spline;
382 unsigned this_spline_length;
383 spline_type s;
384 struct Chunk ** ChunkList;
385 struct Chunk * PolyChunk;
386 int ListPoint, PolySize, PolyPoint, NumPoints;
387 int StrokeOrFill;
388 unsigned char * PolyData;
389
390 this_list_length = SPLINE_LIST_ARRAY_LENGTH(shape);
391
392 /* We store three chunks for every spline (one for BBOX, one for ATTR, and one for xPLY) */
393 if ((ChunkList = (struct Chunk **) malloc(sizeof(struct Chunk) * (this_list_length * 3))) == NULL) {
394 fprintf(stderr, "Insufficient memory to allocate chunk list\n");
395 return NULL;
396 }
397
398 ListPoint = 0;
399 for (this_list = 0; this_list < this_list_length; this_list++) {
400 spline_list_type list = SPLINE_LIST_ARRAY_ELT(shape, this_list);
401 spline_type first = SPLINE_LIST_ELT(list, 0);
402 color_type curr_color = curr_color = (list.clockwise && shape.background_color != NULL)? *(shape.background_color) : list.color;
403
404 StrokeOrFill = (shape.centerline || list.open);
405 this_spline_length = SPLINE_LIST_LENGTH(list);
406
407 ChunkList[ListPoint++] = BuildBBOX(list, height);
408 ChunkList[ListPoint++] = BuildATTR(curr_color, StrokeOrFill, CMAP);
409
410 if ((PolyChunk = (struct Chunk *) malloc(sizeof(struct Chunk))) == NULL) {
411 fprintf(stderr, "Insufficient memory to allocate xPLY chunk\n");
412 FreeChunks(ChunkList, ListPoint);
413 return NULL;
414 }
415
416 NumPoints = CountSplines(list);
417
418 /* Store an extra 2 bytes for length header */
419 PolySize = (NumPoints << 3) + 2;
420 if ((PolyData = (unsigned char *) malloc(PolySize)) == NULL) {
421 fprintf(stderr, "Insufficient memory to allocate xPLY data\n");
422 free(PolyChunk);
423 free(PolyData);
424 FreeChunks(ChunkList, ListPoint);
425 return NULL;
426 }
427
428 ChunkList[ListPoint++] = PolyChunk;
429 strncpy(PolyChunk->ID, (StrokeOrFill) ? "OPLY" : "CPLY", 4);
430 PolyChunk->Size = PolySize;
431 PolyChunk->Data = PolyData;
432
433 ShortAsBytes(NumPoints, PolyData);
434 PolyPoint = 2;
435
436 if (SPLINE_DEGREE(first) == LINEARTYPE) {
437 PushPolyPoint(PolyData, &PolyPoint, START_POINT(first).x, height - START_POINT(first).y);
438 }
439
440 for (this_spline = 0; this_spline < this_spline_length; this_spline++) {
441 s = SPLINE_LIST_ELT(list, this_spline);
442
443 if (SPLINE_DEGREE(s) == LINEARTYPE) {
444 PushPolyPoint(PolyData, &PolyPoint, END_POINT(s).x, height - END_POINT(s).y);
445 } else {
446 PushPolyIndicator(PolyData, &PolyPoint, IND_SPLINE);
447 PushPolyPoint(PolyData, &PolyPoint, START_POINT(s).x, height - START_POINT(s).y);
448 PushPolyPoint(PolyData, &PolyPoint, CONTROL1(s).x, height - CONTROL1(s).y);
449 PushPolyPoint(PolyData, &PolyPoint, CONTROL2(s).x, height - CONTROL2(s).y);
450 PushPolyPoint(PolyData, &PolyPoint, END_POINT(s).x, height - END_POINT(s).y);
451 }
452 }
453 }
454
455 return ChunkList;
456 }
457
CountSplines(spline_list_type list)458 static int CountSplines(spline_list_type list) {
459 unsigned this_spline;
460 unsigned this_spline_length;
461 int Total;
462
463 Total = 0;
464
465 if (SPLINE_DEGREE(SPLINE_LIST_ELT(list, 0)) == LINEARTYPE) {
466 ++Total;
467 }
468
469 this_spline_length = SPLINE_LIST_LENGTH(list);
470 for (this_spline = 0; this_spline < this_spline_length; this_spline++) {
471 if (SPLINE_DEGREE(SPLINE_LIST_ELT(list, this_spline)) == LINEARTYPE) {
472 ++Total;
473 } else {
474 Total += 5;
475 }
476 }
477
478 return Total;
479 }
480
PushPolyPoint(unsigned char * PolyData,int * PolyPoint,float x,float y)481 static void PushPolyPoint(unsigned char * PolyData, int * PolyPoint, float x, float y) {
482 int PolyLocal;
483
484 PolyLocal = *PolyPoint;
485
486 FloatAsIEEEBytes(x * XFactor, PolyData + PolyLocal);
487 PolyLocal += 4;
488 FloatAsIEEEBytes(y * YFactor, PolyData + PolyLocal);
489
490 *PolyPoint = PolyLocal + 4;
491 }
492
PushPolyIndicator(unsigned char * PolyData,int * PolyPoint,unsigned int flags)493 static void PushPolyIndicator(unsigned char * PolyData, int * PolyPoint, unsigned int flags) {
494 int PolyLocal;
495
496 PolyLocal = *PolyPoint;
497
498 IntAsBytes(INDICATOR, PolyData + PolyLocal);
499 PolyLocal += 4;
500 IntAsBytes(flags, PolyData + PolyLocal);
501
502 *PolyPoint = PolyLocal + 4;
503 }
504
WriteChunk(FILE * file,struct Chunk * Chunk)505 static void WriteChunk(FILE * file, struct Chunk * Chunk) {
506 unsigned char SizeBytes[4];
507 int Size;
508
509 Size = Chunk->Size;
510 IntAsBytes(Size, SizeBytes);
511
512 fwrite(Chunk->ID, 4, 1, file);
513 fwrite(SizeBytes, 4, 1, file);
514 fwrite(Chunk->Data, Size, 1, file);
515 if (Size & 0x01) {
516 fprintf(file, "%c", (char) NULL);
517 }
518 }
519
WriteChunks(FILE * file,struct Chunk ** ChunkList,int NumChunks)520 static void WriteChunks(FILE * file, struct Chunk ** ChunkList, int NumChunks) {
521 int WalkChunks;
522
523 for (WalkChunks = 0; WalkChunks < NumChunks; WalkChunks++) {
524 WriteChunk(file, ChunkList[WalkChunks]);
525 }
526 }
527
TotalSizeChunks(struct Chunk ** ChunkList,int NumChunks)528 static int TotalSizeChunks(struct Chunk ** ChunkList, int NumChunks) {
529 int WalkChunks;
530 int Size;
531 int Total;
532
533 Total = 0;
534 for (WalkChunks = 0; WalkChunks < NumChunks; WalkChunks++) {
535 /* 4 bytes for ID and 4 bytes for length */
536 Size = ChunkList[WalkChunks]->Size;
537 Size += Size & 0x01;
538 Total += (Size) + 8;
539 }
540
541 return Total;
542 }
543
SizeChunk(struct Chunk * ThisChunk)544 static int SizeChunk(struct Chunk * ThisChunk) {
545 int Size;
546
547 Size = ThisChunk->Size;
548 Size += Size & 0x01;
549
550 return Size;
551 }
552
FreeChunk(struct Chunk * ThisChunk)553 static void FreeChunk(struct Chunk * ThisChunk) {
554 free(ThisChunk->Data);
555 free(ThisChunk);
556 }
557
FreeChunks(struct Chunk ** ChunkList,int NumChunks)558 static void FreeChunks(struct Chunk ** ChunkList, int NumChunks) {
559 int WalkChunks;
560
561 for (WalkChunks = 0; WalkChunks < NumChunks; WalkChunks++) {
562 FreeChunk(ChunkList[WalkChunks]);
563 }
564 }
565
output_dr2d_writer(FILE * file,at_string name,int llx,int lly,int urx,int ury,at_output_opts_type * opts,spline_list_array_type shape,at_msg_func msg_func,at_address msg_data)566 int output_dr2d_writer(FILE * file, at_string name, int llx, int lly, int urx, int ury,
567 at_output_opts_type * opts,
568 spline_list_array_type shape, at_msg_func msg_func, at_address msg_data)
569 {
570 int width = urx - llx;
571 int height = ury - lly;
572 int NumSplines, FORMSize;
573 int Portrait;
574 struct Chunk * DRHDChunk;
575 struct Chunk * PPRFChunk;
576 struct Chunk * LAYRChunk;
577 struct Chunk * DASHChunk;
578 struct Chunk * CMAPChunk;
579 struct Chunk ** ChunkList;
580 unsigned char SizeBytes[4];
581
582 Portrait = width < height;
583
584 if (Portrait) {
585 XFactor = ((float)11.6930 / (float) width) * (1 << FIXOFFS);
586 YFactor = XFactor;
587 } else {
588 YFactor = ((float)8.2681 / (float) height) * (1 << FIXOFFS);
589 XFactor = YFactor;
590 }
591
592 LineThickness = (float)1.0 / opts->dpi;
593
594 DRHDChunk = BuildDRHD(llx, lly, urx, ury);
595 PPRFChunk = BuildPPRF("Inch", Portrait, "A4", 1.0);
596 LAYRChunk = BuildLAYR();
597 DASHChunk = BuildDASH();
598 CMAPChunk = BuildCMAP(shape);
599
600 ChunkList = GeneratexPLY(CMAPChunk, shape, height);
601
602 NumSplines = SPLINE_LIST_ARRAY_LENGTH(shape) * 3;
603 FORMSize = 4 + (SizeChunk(DRHDChunk) + 8) + (SizeChunk(PPRFChunk) + 8) + (SizeChunk(LAYRChunk) + 8) + (SizeChunk(DASHChunk) + 8) + (SizeChunk(CMAPChunk) + 8) + TotalSizeChunks(ChunkList, NumSplines);
604
605 IntAsBytes(FORMSize, SizeBytes);
606 fprintf(file, "FORM");
607 fwrite(SizeBytes, 4, 1, file);
608 fprintf(file, "DR2D");
609
610 WriteChunk(file, DRHDChunk);
611 FreeChunk(DRHDChunk);
612 WriteChunk(file, PPRFChunk);
613 FreeChunk(PPRFChunk);
614 WriteChunk(file, LAYRChunk);
615 FreeChunk(LAYRChunk);
616 WriteChunk(file, DASHChunk);
617 FreeChunk(DASHChunk);
618 WriteChunk(file, CMAPChunk);
619 FreeChunk(CMAPChunk);
620 WriteChunks(file, ChunkList, NumSplines);
621 FreeChunks(ChunkList, NumSplines);
622
623 return 0;
624 }
625
SizeFloat(float f,char * Format)626 static int SizeFloat(float f, char * Format) {
627 char FloatString[100];
628
629 return (sprintf(FloatString, Format, f));
630 }
631
IntAsBytes(int value,unsigned char * bytes)632 static void IntAsBytes(int value, unsigned char * bytes) {
633 *bytes = (value >> 24) & 0xFF;
634 *(bytes + 1) = (value >> 16) & 0xFF;
635 *(bytes + 2) = (value >> 8) & 0xFF;
636 *(bytes + 3) = value & 0xFF;
637 }
638
ShortAsBytes(int value,unsigned char * bytes)639 static void ShortAsBytes(int value, unsigned char * bytes) {
640 *(bytes + 0) = (value >> 8) & 0xFF;
641 *(bytes + 1) = value & 0xFF;
642 }
643
FloatAsIEEEBytes(float value,unsigned char * bytes)644 static void FloatAsIEEEBytes(float value, unsigned char * bytes) {
645 flt2ieee(&value, bytes);
646 }
647
flt2ieee(float * flt,unsigned char * bytes)648 static void flt2ieee(float * flt, unsigned char * bytes) {
649 long RealMant, RealMask, RealExp;
650 long MoveExp;
651
652 RealMant = (long) *flt;
653
654 *bytes = 0;
655 *(bytes + 1) = 0;
656 *(bytes + 2) = 0;
657 *(bytes + 3) = 0;
658
659 if (RealMant) {
660 if (RealMant < 0) {
661 *bytes |= 0x80;
662 RealMant = -RealMant;
663 }
664
665 for (RealMask = 0x40000000, RealExp = 31; RealMask; RealMask >>= 1, RealExp--) {
666 if (RealMant & RealMask) {
667 break;
668 }
669 }
670
671 if (RealExp > 24) {
672 RealMant >>= RealExp - 24;
673 } else {
674 RealMant <<= 24 - RealExp;
675 }
676 RealExp -= FIXOFFS;
677 RealExp += 126;
678
679 MoveExp = RealExp << 23;
680 *bytes |= (MoveExp >> 24) & 0x7F;
681 *(bytes + 1) |= ((MoveExp >> 16) & 0x80) | ((RealMant >> 16) & 0x7F);
682 *(bytes + 2) |= (RealMant >> 8) & 0xFF;
683 *(bytes + 3) |= RealMant & 0xFF;
684 }
685 }
686