gdevcgml.c 28 KB

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