tioga 1.11 → 1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. data/Tioga_README +58 -35
  2. data/{split/scripts → bin}/tioga +1 -1
  3. data/{split → ext/Dobjects}/Dtable/dtable.c +81 -15
  4. data/{split → ext/Dobjects}/Dtable/dtable_intern.h +0 -0
  5. data/ext/Dobjects/Dtable/extconf.rb +7 -0
  6. data/{split → ext/Dobjects}/Dtable/include/dtable.h +0 -0
  7. data/{split → ext/Dobjects}/Dvector/dvector.c +361 -51
  8. data/{split → ext/Dobjects}/Dvector/dvector_intern.h +0 -0
  9. data/ext/Dobjects/Dvector/extconf.rb +22 -0
  10. data/{split/Dtable → ext/Dobjects/Dvector/include}/dvector.h +0 -0
  11. data/ext/Dobjects/Function/extconf.rb +7 -0
  12. data/{split → ext/Dobjects}/Function/function.c +636 -11
  13. data/{split → ext/Dobjects}/Function/joint_qsort.c +0 -0
  14. data/ext/Flate/extconf.rb +26 -0
  15. data/{split → ext}/Flate/flate.c +7 -3
  16. data/{split → ext}/Flate/flate_intern.h +0 -0
  17. data/{split → ext}/Flate/include/flate.h +0 -0
  18. data/ext/Flate/zlib/adler32.c +149 -0
  19. data/ext/Flate/zlib/compress.c +79 -0
  20. data/ext/Flate/zlib/crc32.c +423 -0
  21. data/ext/Flate/zlib/crc32.h +441 -0
  22. data/ext/Flate/zlib/deflate.c +1736 -0
  23. data/ext/Flate/zlib/deflate.h +331 -0
  24. data/ext/Flate/zlib/gzio.c +1026 -0
  25. data/ext/Flate/zlib/infback.c +623 -0
  26. data/ext/Flate/zlib/inffast.c +318 -0
  27. data/ext/Flate/zlib/inffast.h +11 -0
  28. data/ext/Flate/zlib/inffixed.h +94 -0
  29. data/ext/Flate/zlib/inflate.c +1368 -0
  30. data/ext/Flate/zlib/inflate.h +115 -0
  31. data/ext/Flate/zlib/inftrees.c +329 -0
  32. data/ext/Flate/zlib/inftrees.h +55 -0
  33. data/ext/Flate/zlib/trees.c +1219 -0
  34. data/ext/Flate/zlib/trees.h +128 -0
  35. data/ext/Flate/zlib/uncompr.c +61 -0
  36. data/ext/Flate/zlib/zlib.h +1357 -0
  37. data/ext/Flate/zlib/zutil.c +318 -0
  38. data/ext/Flate/zlib/zutil.h +269 -0
  39. data/ext/Tioga/FigureMaker/__shared_axes.c +1373 -0
  40. data/ext/Tioga/FigureMaker/__shared_makers.c +1303 -0
  41. data/{split/Tioga/pdf_font_dicts.c → ext/Tioga/FigureMaker/__shared_pdf_font_dicts.c} +0 -0
  42. data/{split/Tioga/pdfcolor.c → ext/Tioga/FigureMaker/__shared_pdfcolor.c} +0 -0
  43. data/{split/Tioga/pdfcoords.c → ext/Tioga/FigureMaker/__shared_pdfcoords.c} +0 -0
  44. data/{split/Tioga/pdffile.c → ext/Tioga/FigureMaker/__shared_pdffile.c} +0 -0
  45. data/{split/Tioga/pdfimage.c → ext/Tioga/FigureMaker/__shared_pdfimage.c} +0 -0
  46. data/{split/Tioga/pdfpath.c → ext/Tioga/FigureMaker/__shared_pdfpath.c} +0 -0
  47. data/{split/Tioga/pdftext.c → ext/Tioga/FigureMaker/__shared_pdftext.c} +0 -0
  48. data/{split/Tioga/texout.c → ext/Tioga/FigureMaker/__shared_texout.c} +0 -0
  49. data/ext/Tioga/FigureMaker/extconf.rb +7 -0
  50. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.c +14 -2
  51. data/{split/Tioga → ext/Tioga/FigureMaker}/figures.h +0 -0
  52. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.c +1 -2
  53. data/{split/Tioga → ext/Tioga/FigureMaker}/generic.h +0 -1
  54. data/{split/Tioga → ext/Tioga/FigureMaker}/init.c +0 -0
  55. data/{split/Tioga → ext/Tioga/FigureMaker}/pdfs.h +0 -0
  56. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/axes.c +32 -7
  57. data/{split/Tioga → ext/Tioga/FigureMaker/shared}/makers.c +2 -2
  58. data/ext/Tioga/FigureMaker/shared/pdf_font_dicts.c +18253 -0
  59. data/ext/Tioga/FigureMaker/shared/pdfcolor.c +904 -0
  60. data/ext/Tioga/FigureMaker/shared/pdfcoords.c +518 -0
  61. data/ext/Tioga/FigureMaker/shared/pdffile.c +451 -0
  62. data/ext/Tioga/FigureMaker/shared/pdfimage.c +539 -0
  63. data/ext/Tioga/FigureMaker/shared/pdfpath.c +766 -0
  64. data/ext/Tioga/FigureMaker/shared/pdftext.c +710 -0
  65. data/ext/Tioga/FigureMaker/shared/texout.c +533 -0
  66. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.c +5 -5
  67. data/{split/Tioga → ext/Tioga/FigureMaker}/wrappers.h +0 -0
  68. data/{split/Dtable → ext/includes}/defs.h +0 -0
  69. data/{split/Dtable → ext/includes}/namespace.h +0 -0
  70. data/{split/Dtable → ext/includes}/safe_double.h +0 -0
  71. data/{split → ext/includes}/symbols.c +0 -1
  72. data/{split/Dtable → ext/includes}/symbols.h +0 -0
  73. data/{split/Dtable/lib → lib/Dobjects}/Dtable_extras.rb +0 -0
  74. data/{split/Dvector/lib → lib/Dobjects}/Dvector_extras.rb +1 -0
  75. data/{split/Function/lib → lib/Dobjects}/Function_extras.rb +0 -0
  76. data/{split/Dvector/lib → lib/Dobjects}/Numeric_extras.rb +0 -0
  77. data/{split/Tioga/lib → lib/Tioga}/Arcs_and_Circles.rb +0 -0
  78. data/{split/Tioga/lib → lib/Tioga}/ColorConstants.rb +0 -0
  79. data/{split/Tioga/lib → lib/Tioga}/Colorbars.rb +0 -0
  80. data/{split/Tioga/lib → lib/Tioga}/Colormaps.rb +0 -0
  81. data/{split/Tioga/lib → lib/Tioga}/Coordinate_Conversions.rb +0 -0
  82. data/{split/Tioga/lib → lib/Tioga}/Creating_Paths.rb +0 -0
  83. data/{split/Tioga/lib → lib/Tioga}/Doc.rb +0 -0
  84. data/{split/Tioga/lib → lib/Tioga}/Executive.rb +0 -0
  85. data/{split/Tioga/lib → lib/Tioga}/FigMkr.rb +13 -70
  86. data/{split/Tioga/lib → lib/Tioga}/FigureConstants.rb +0 -0
  87. data/{split/Tioga/lib → lib/Tioga}/Figures_and_Plots.rb +0 -0
  88. data/{split/Tioga/lib → lib/Tioga}/Images.rb +0 -0
  89. data/{split/Tioga/lib → lib/Tioga}/Legends.rb +0 -0
  90. data/{split/Tioga/lib → lib/Tioga}/MarkerConstants.rb +0 -0
  91. data/{split/Tioga/lib → lib/Tioga}/Markers.rb +0 -0
  92. data/{split/Tioga/lib → lib/Tioga}/Page_Frame_Bounds.rb +0 -0
  93. data/{split/Tioga/lib → lib/Tioga}/Rectangles.rb +0 -0
  94. data/{split/Tioga/lib → lib/Tioga}/Shading.rb +0 -0
  95. data/{split/Tioga/lib → lib/Tioga}/Special_Paths.rb +0 -0
  96. data/{split/Tioga/lib → lib/Tioga}/Strokes.rb +0 -0
  97. data/{split/Tioga/lib → lib/Tioga}/TeX_Text.rb +0 -0
  98. data/{split/Tioga/lib → lib/Tioga}/TexPreamble.rb +0 -0
  99. data/{split/Tioga/lib → lib/Tioga}/Titles_and_Labels.rb +0 -0
  100. data/{split/Tioga/lib → lib/Tioga}/Transparency.rb +0 -0
  101. data/{split/Tioga/lib → lib/Tioga}/Using_Paths.rb +0 -0
  102. data/{split/Tioga/lib → lib/Tioga}/Utils.rb +74 -0
  103. data/{split/Tioga/lib → lib/Tioga}/X_and_Y_Axes.rb +0 -0
  104. data/{split/Tioga/lib → lib/Tioga}/irb_tioga.rb +0 -0
  105. data/{split/Tioga/lib → lib/Tioga}/maker.rb +0 -0
  106. data/{split/Tioga/lib → lib/Tioga}/tioga.rb +0 -0
  107. data/{split/Tioga/lib → lib/Tioga}/tioga_ui.rb +0 -0
  108. data/{split/Tioga/lib → lib/Tioga}/tioga_ui_cmds.rb +0 -0
  109. data/tests/Icon_Test.pdf +0 -0
  110. data/tests/benchmark_dvector_reads.rb +20 -42
  111. data/tests/tc_Dvector.rb +45 -4
  112. data/tests/tc_Flate.rb +4 -5
  113. data/tests/tc_Function.rb +79 -0
  114. data/tests/vg.log +1453 -0
  115. metadata +141 -122
  116. data/split/Dtable/extconf.rb +0 -4
  117. data/split/Dvector/defs.h +0 -39
  118. data/split/Dvector/extconf.rb +0 -4
  119. data/split/Dvector/include/dvector.h +0 -77
  120. data/split/Dvector/namespace.h +0 -59
  121. data/split/Dvector/safe_double.h +0 -104
  122. data/split/Dvector/symbols.h +0 -52
  123. data/split/Flate/defs.h +0 -39
  124. data/split/Flate/extconf.rb +0 -19
  125. data/split/Flate/namespace.h +0 -59
  126. data/split/Flate/safe_double.h +0 -104
  127. data/split/Flate/symbols.h +0 -52
  128. data/split/Function/defs.h +0 -39
  129. data/split/Function/dvector.h +0 -77
  130. data/split/Function/extconf.rb +0 -4
  131. data/split/Function/namespace.h +0 -59
  132. data/split/Function/safe_double.h +0 -104
  133. data/split/Function/symbols.h +0 -52
  134. data/split/Tioga/defs.h +0 -39
  135. data/split/Tioga/dtable.h +0 -35
  136. data/split/Tioga/dvector.h +0 -77
  137. data/split/Tioga/extconf.rb +0 -4
  138. data/split/Tioga/flate.h +0 -98
  139. data/split/Tioga/mk_tioga_sty.rb +0 -53
  140. data/split/Tioga/namespace.h +0 -59
  141. data/split/Tioga/safe_double.h +0 -104
  142. data/split/Tioga/symbols.h +0 -52
  143. data/split/defs.h +0 -39
  144. data/split/extconf.rb +0 -125
  145. data/split/mkmf2.rb +0 -1623
  146. data/split/namespace.h +0 -59
  147. data/split/safe_double.h +0 -104
  148. data/split/symbols.h +0 -52
@@ -0,0 +1,451 @@
1
+ /* pdffile.c */
2
+ /*
3
+ Copyright (C) 2005 Bill Paxton
4
+
5
+ This file is part of Tioga.
6
+
7
+ Tioga is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Library Public License as published
9
+ by the Free Software Foundation; either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Tioga is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Library General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Library General Public License
18
+ along with Tioga; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #include <time.h>
23
+ #include "figures.h"
24
+ #include "pdfs.h"
25
+
26
+ #define FLATE_ENCODE 1
27
+
28
+ #define Get_pdf_xoffset() 5.0
29
+ #define Get_pdf_yoffset() 5.0
30
+
31
+
32
+ /* must match the font numbers in FigureConstants.rb */
33
+ char *predefined_Fonts[] = {
34
+ NULL,
35
+ "Times-Roman",
36
+ "Times-Italic", // 2
37
+ "Times-Bold",
38
+ "Times-BoldItalic",
39
+ "Helvetica",
40
+ "Helvetica-Oblique", // 6
41
+ "Helvetica-Bold",
42
+ "Helvetica-BoldOblique",
43
+ "Courier",
44
+ "Courier-Oblique", // 10
45
+ "Courier-Bold",
46
+ "Courier-BoldOblique",
47
+ "Symbol",
48
+ "ZapfDingbats" // 14
49
+ };
50
+ int num_predefined_fonts = 14;
51
+ int num_pdf_standard_fonts = 14;
52
+
53
+ long *obj_offsets, capacity_obj_offsets, stream_start, stream_end;
54
+ long length_offset, xref_offset;
55
+ long num_objects, next_available_object_number, next_available_gs_number;
56
+ long next_available_xo_number;
57
+ long next_available_shade_number, next_available_font_number;
58
+ Stroke_Opacity_State *stroke_opacities = NULL;
59
+ Fill_Opacity_State *fill_opacities = NULL;
60
+ XObject_Info *xobj_list = NULL;
61
+ Function_Info *functions_list;
62
+ Shading_Info *shades_list = NULL;
63
+ Font_Dictionary *font_dictionaries = NULL;
64
+ Old_Font_Dictionary *old_font_dictionaries = NULL;
65
+ FILE *OF = NULL; // for the PDF file
66
+ FILE *TF = NULL; // for the temp file
67
+
68
+
69
+ /* PDF File Management */
70
+
71
+ static void
72
+ Free_XObjects(int *ierr)
73
+ {
74
+ XObject_Info *xo;
75
+ while (xobj_list != NULL) {
76
+ xo = xobj_list;
77
+ xobj_list = xo->next;
78
+ switch (xo->xobj_subtype) {
79
+ case JPG_SUBTYPE:
80
+ Free_JPG((JPG_Info *)xo);
81
+ break;
82
+ case SAMPLED_SUBTYPE:
83
+ Free_Sampled((Sampled_Info *)xo);
84
+ break;
85
+ default:
86
+ RAISE_ERROR_i("Invalid XObject subtype (%i)",
87
+ xo->xobj_subtype, ierr);
88
+ return;
89
+ }
90
+ free(xo);
91
+ }
92
+ }
93
+
94
+
95
+ void
96
+ Init_pdf(int *ierr)
97
+ {
98
+ int i;
99
+ writing_file = false;
100
+ capacity_obj_offsets = 1000;
101
+ num_objects = 0;
102
+ obj_offsets = ALLOC_N_long(capacity_obj_offsets);
103
+ for (i=0; i < capacity_obj_offsets; i++) obj_offsets[i] = 0;
104
+ }
105
+
106
+
107
+ void
108
+ Record_Object_Offset(int obj_number)
109
+ {
110
+ long int offset = ftell(OF);
111
+ if (obj_number >= capacity_obj_offsets) {
112
+ int size_increment = 50, i;
113
+ REALLOC_long(&obj_offsets, obj_number + size_increment);
114
+ capacity_obj_offsets = obj_number + size_increment;
115
+ for (i=num_objects; i < capacity_obj_offsets; i++) obj_offsets[i] = 0;
116
+ }
117
+ obj_offsets[obj_number] = offset;
118
+ if (obj_number >= num_objects) num_objects = obj_number + 1;
119
+ }
120
+
121
+
122
+ static void
123
+ Write_XObjects(int *ierr)
124
+ {
125
+ XObject_Info *xo;
126
+ for (xo = xobj_list; xo != NULL; xo = xo->next) {
127
+ Record_Object_Offset(xo->obj_num);
128
+ fprintf(OF, "%i 0 obj << /Type /XObject ", xo->obj_num);
129
+ switch (xo->xobj_subtype) {
130
+ case JPG_SUBTYPE:
131
+ Write_JPG((JPG_Info *)xo, ierr);
132
+ break;
133
+ case SAMPLED_SUBTYPE:
134
+ Write_Sampled((Sampled_Info *)xo, ierr);
135
+ break;
136
+ default:
137
+ RAISE_ERROR_i("Invalid XObject subtype (%i)", xo->xobj_subtype, ierr);
138
+ }
139
+ if (*ierr != 0) return;
140
+ fprintf(OF, ">> endobj\n");
141
+ }
142
+ }
143
+
144
+
145
+ #define INFO_OBJ 1
146
+ #define PAGES_OBJ 2
147
+ #define STREAM_OBJ 3
148
+ #define PAGE_OBJ 4
149
+ #define CATALOG_OBJ 5
150
+ #define FIRST_OTHER_OBJ 6
151
+
152
+
153
+ static void
154
+ Free_Records(int *ierr)
155
+ {
156
+ Free_Stroke_Opacities();
157
+ Free_Fill_Opacities();
158
+ Free_XObjects(ierr);
159
+ Free_Shadings();
160
+ Free_Functions();
161
+ }
162
+
163
+
164
+ static void
165
+ Get_pdf_name(char *ofile, char *filename, int maxlen)
166
+ {
167
+ char *dot;
168
+ strncpy(ofile, filename, maxlen);
169
+ dot = strrchr(ofile, '.');
170
+ if (dot != NULL) dot[0] = '\0';
171
+ strcat(ofile, "_figure.pdf");
172
+ }
173
+
174
+
175
+ void
176
+ Open_pdf(OBJ_PTR fmkr, FM *p, char *filename, bool quiet_mode, int *ierr)
177
+ {
178
+ int i;
179
+ if (writing_file) {
180
+ RAISE_ERROR("Sorry: cannot start a new output file until finish "
181
+ "current one.", ierr);
182
+ return;
183
+ }
184
+ Clear_Fonts_In_Use_Flags();
185
+ Free_Records(ierr);
186
+ if (*ierr != 0) return;
187
+ next_available_object_number = FIRST_OTHER_OBJ;
188
+ next_available_font_number = num_predefined_fonts + 1;
189
+ next_available_gs_number = 1;
190
+ next_available_xo_number = 1;
191
+ next_available_shade_number = 1;
192
+ writing_file = true;
193
+ time_t now = time(NULL);
194
+ char ofile[300], timestring[100];
195
+ Get_pdf_name(ofile, filename, 300);
196
+ if ((OF = fopen(ofile, "w")) == NULL) {
197
+ RAISE_ERROR_s("Sorry: can't open %s.\n", filename, ierr);
198
+ return;
199
+ }
200
+ if ((TF = tmpfile()) == NULL) {
201
+ RAISE_ERROR_s("Sorry: can't create temp file for writing PDF file %s.\n",
202
+ filename, ierr);
203
+ return;
204
+ }
205
+ /* open PDF file and write header */
206
+ fprintf(OF, "%%PDF-1.4\n");
207
+ strcpy(timestring, ctime(&now));
208
+ i = strlen(timestring);
209
+ if (i > 0) timestring[i-1] = '\0';
210
+ Record_Object_Offset(INFO_OBJ);
211
+ fprintf(OF,
212
+ "%i 0 obj <<\n/Creator (Tioga)\n/CreationDate (%s)\n>>\nendobj\n",
213
+ INFO_OBJ, timestring);
214
+ Record_Object_Offset(PAGES_OBJ);
215
+ fprintf(OF,
216
+ "%i 0 obj <<\n/Type /Pages\n/Kids [%i 0 R]\n/Count 1\n>> endobj\n",
217
+ PAGES_OBJ, PAGE_OBJ);
218
+ Record_Object_Offset(STREAM_OBJ);
219
+ if (FLATE_ENCODE)
220
+ fprintf(OF, "%i 0 obj <<\t/Filter /FlateDecode /Length ", STREAM_OBJ);
221
+ else
222
+ fprintf(OF, "%i 0 obj <<\t/Length ", STREAM_OBJ);
223
+ length_offset = ftell(OF);
224
+ fprintf(OF, " \n>>\nstream\n");
225
+ stream_start = ftell(OF);
226
+ fprintf(TF, "%.2f 0 0 %.2f %.2f %.2f cm\n", 1.0/ENLARGE, 1.0/ENLARGE,
227
+ Get_pdf_xoffset(), Get_pdf_yoffset());
228
+ /* set stroke and fill colors to black */
229
+ have_current_point = constructing_path = false;
230
+ c_line_width_set(fmkr, p, p->line_width, ierr);
231
+ c_line_cap_set(fmkr, p, p->line_cap, ierr);
232
+ c_line_join_set(fmkr, p, p->line_join, ierr);
233
+ c_miter_limit_set(fmkr, p, p->miter_limit, ierr);
234
+ c_line_type_set(fmkr, p, Get_line_type(fmkr, ierr), ierr);
235
+ c_stroke_color_set_RGB(fmkr, p, p->stroke_color_R, p->stroke_color_G,
236
+ p->stroke_color_B, ierr);
237
+ c_fill_color_set_RGB(fmkr, p, p->fill_color_R, p->fill_color_G,
238
+ p->fill_color_B, ierr);
239
+ // initialize clip region
240
+ bbox_llx = bbox_lly = 1e5;
241
+ bbox_urx = bbox_ury = -1e5;
242
+ }
243
+
244
+
245
+ void
246
+ Start_Axis_Standard_State(OBJ_PTR fmkr, FM *p, double r, double g, double b,
247
+ double line_width, int *ierr)
248
+ {
249
+ fprintf(TF, "q 2 J [] 0 d\n");
250
+ c_line_width_set(fmkr, p, line_width, ierr);
251
+ c_stroke_color_set_RGB(fmkr, p, r, g, b, ierr);
252
+ /* 2 J sets the line cap style to square cap */
253
+ /* set stroke and fill colors to black. set line type to solid */
254
+ }
255
+
256
+
257
+ void
258
+ End_Axis_Standard_State(void)
259
+ {
260
+ Write_grestore();
261
+ }
262
+
263
+
264
+ void
265
+ Write_gsave(void)
266
+ {
267
+ fprintf(TF, "q\n");
268
+ }
269
+
270
+
271
+ void
272
+ Write_grestore(void)
273
+ {
274
+ fprintf(TF, "Q\n");
275
+ }
276
+
277
+
278
+ void
279
+ c_pdf_gsave(OBJ_PTR fmkr, FM *p, int *ierr)
280
+ {
281
+ Write_gsave();
282
+ }
283
+
284
+
285
+ void
286
+ c_pdf_grestore(OBJ_PTR fmkr, FM *p, int *ierr)
287
+ {
288
+ Write_grestore();
289
+ }
290
+
291
+
292
+ static void
293
+ Print_Xref(long int offset)
294
+ {
295
+ char line[80];
296
+ int i, len;
297
+ snprintf(line,sizeof(line), "%li", offset);
298
+ len = strlen(line);
299
+ for (i=0; i < 10-len; i++) fputc('0', OF);
300
+ fprintf(OF, "%s 00000 n \n", line);
301
+ }
302
+
303
+
304
+ static void
305
+ Write_Stream(int *ierr)
306
+ {
307
+ long int len = ftell(TF);
308
+ unsigned long int new_len = (len * 11) / 10 + 100;
309
+ unsigned char *buffer, *dest_buffer;
310
+ rewind(TF);
311
+ buffer = ALLOC_N_unsigned_char(len+1);
312
+ dest_buffer = ALLOC_N_unsigned_char(new_len+1);
313
+ fread(buffer, 1, len, TF);
314
+ fclose(TF);
315
+ if (FLATE_ENCODE) {
316
+ if (do_flate_compress(dest_buffer, &new_len, buffer, len) != FLATE_OK) {
317
+ free(buffer); free(dest_buffer);
318
+ RAISE_ERROR("Error compressing PDF stream data", ierr);
319
+ return;
320
+ }
321
+ fwrite(dest_buffer, 1, new_len, OF);
322
+ }
323
+ else {
324
+ fwrite(buffer, 1, len, OF);
325
+ }
326
+ free(buffer);
327
+ free(dest_buffer);
328
+ }
329
+
330
+
331
+ void
332
+ Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
333
+ {
334
+ int i;
335
+ double llx, lly, urx, ury, xoff, yoff;
336
+ if (!writing_file) {
337
+ RAISE_ERROR("Sorry: cannot End_Output if not writing file.", ierr);
338
+ return;
339
+ }
340
+ writing_file = false;
341
+ if (constructing_path) {
342
+ RAISE_ERROR("Sorry: must finish with current path before ending file",
343
+ ierr);
344
+ return;
345
+ }
346
+ Write_Stream(ierr);
347
+ if (*ierr != 0) return;
348
+ stream_end = ftell(OF);
349
+ fprintf(OF, "endstream\nendobj\n");
350
+ Record_Object_Offset(PAGE_OBJ);
351
+ fprintf(OF, "%i 0 obj <<\n/Type /Page\n/Parent %i 0 R\n/MediaBox [ ",
352
+ PAGE_OBJ, PAGES_OBJ);
353
+ if (bbox_llx < p->page_left) bbox_llx = p->page_left;
354
+ if (bbox_lly < p->page_bottom) bbox_lly = p->page_bottom;
355
+ if (bbox_urx > p->page_left + p->page_width)
356
+ bbox_urx = p->page_left + p->page_width;
357
+ if (bbox_ury > p->page_bottom + p->page_height)
358
+ bbox_ury = p->page_bottom + p->page_height;
359
+ //#define MARGIN 3
360
+ #define MARGIN 0
361
+ xoff = Get_pdf_xoffset();
362
+ yoff = Get_pdf_yoffset();
363
+ llx = bbox_llx / ENLARGE + xoff - MARGIN; // convert back to points
364
+ lly = bbox_lly / ENLARGE + yoff - MARGIN;
365
+ urx = bbox_urx / ENLARGE + xoff + MARGIN;
366
+ ury = bbox_ury / ENLARGE + yoff + MARGIN;
367
+ if (urx < llx || ury < lly) {
368
+ RAISE_ERROR("Sorry: Empty plot!", ierr);
369
+ return;
370
+ }
371
+ fprintf(OF, "%d %d %d %d", ROUND(llx), ROUND(lly), ROUND(urx), ROUND(ury));
372
+ fprintf(OF, " ]\n/Contents %i 0 R\n/Resources << "
373
+ "/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n", STREAM_OBJ);
374
+ if (Used_Any_Fonts()) {
375
+ Font_Dictionary *f;
376
+ fprintf(OF, " /Font <<\n ");
377
+ for (f = font_dictionaries; f != NULL; f = f->next) {
378
+ if (!f->in_use) continue;
379
+ fprintf(OF, " /F%i %i 0 R\n", f->font_num, f->obj_num);
380
+ }
381
+ fprintf(OF, " >>\n"); // end of /Font
382
+ }
383
+ if (fill_opacities != NULL || stroke_opacities != NULL) {
384
+ // ExtGstate objects go here
385
+ Fill_Opacity_State *pf;
386
+ Stroke_Opacity_State *ps;
387
+ fprintf(OF, " /ExtGState <<\n");
388
+ for (ps = stroke_opacities; ps != NULL; ps = ps->next) {
389
+ fprintf(OF, " /GS%i %i 0 R\n", ps->gs_num, ps->obj_num);
390
+ }
391
+ for (pf = fill_opacities; pf != NULL; pf = pf->next) {
392
+ fprintf(OF, " /GS%i %i 0 R\n", pf->gs_num, pf->obj_num);
393
+ }
394
+ fprintf(OF, " >>\n"); // end of /ExtGState
395
+ }
396
+ if (xobj_list != NULL) {
397
+ // Xobjects go here
398
+ XObject_Info *xo;
399
+ fprintf(OF, " /XObject <<\n");
400
+ for (xo = xobj_list; xo != NULL; xo = xo->next) {
401
+ fprintf(OF, " /XObj%i %i 0 R\n", xo->xo_num, xo->obj_num);
402
+ }
403
+ fprintf(OF, " >>\n"); // end of /XObject
404
+ }
405
+ if (shades_list != NULL) {
406
+ // Shadings go here
407
+ Shading_Info *so;
408
+ fprintf(OF, " /Shading <<\n");
409
+ for (so = shades_list; so != NULL; so = so->next) {
410
+ fprintf(OF, " /Shade%i %i 0 R\n", so->shade_num, so->obj_num);
411
+ }
412
+ fprintf(OF, " >>\n"); // end of /Shading
413
+ }
414
+ fprintf(OF, " >>\n"); // end of /Resources
415
+ fprintf(OF, ">> endobj\n");
416
+ Record_Object_Offset(CATALOG_OBJ);
417
+ fprintf(OF, "%i 0 obj <<\n/Type /Catalog\n/Pages %i 0 R\n>> endobj\n",
418
+ CATALOG_OBJ, PAGES_OBJ);
419
+ Write_Font_Dictionaries();
420
+ Write_Font_Descriptors();
421
+ Write_Font_Widths();
422
+ Write_Stroke_Opacity_Objects();
423
+ Write_Fill_Opacity_Objects();
424
+ Write_XObjects(ierr);
425
+ if (*ierr != 0) return;
426
+ Write_Functions(ierr);
427
+ if (*ierr != 0) return;
428
+ Write_Shadings();
429
+ xref_offset = ftell(OF);
430
+ fprintf(OF, "xref\n0 %li\n0000000000 65535 f \n", num_objects);
431
+ for (i = 1; i < num_objects; i++)
432
+ Print_Xref(obj_offsets[i]); // NB: DONT USE OBJECT 0
433
+ fprintf(OF, "trailer\n<<\n/Size %li\n/Root %i 0 R\n/Info %i 0 "
434
+ "R\n>>\nstartxref\n%li\n%%%%EOF\n",
435
+ num_objects, CATALOG_OBJ, INFO_OBJ, xref_offset);
436
+ fseek(OF, length_offset, SEEK_SET);
437
+ fprintf(OF, "%li", stream_end - stream_start);
438
+ fclose(OF);
439
+ Free_Records(ierr);
440
+ }
441
+
442
+
443
+ void
444
+ Rename_pdf(char *oldname, char *newname)
445
+ {
446
+ char old_ofile[300], new_ofile[300];
447
+ Get_pdf_name(old_ofile, oldname, 300);
448
+ Get_pdf_name(new_ofile, newname, 300);
449
+ rename(old_ofile, new_ofile); // from stdio.h
450
+ }
451
+
@@ -0,0 +1,539 @@
1
+ /* pdfimage.c */
2
+ /*
3
+ Copyright (C) 2005 Bill Paxton
4
+
5
+ This file is part of Tioga.
6
+
7
+ Tioga is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Library Public License as published
9
+ by the Free Software Foundation; either version 2 of the License, or
10
+ (at your option) any later version.
11
+
12
+ Tioga is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU Library General Public License for more details.
16
+
17
+ You should have received a copy of the GNU Library General Public License
18
+ along with Tioga; if not, write to the Free Software
19
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
+ */
21
+
22
+ #include "figures.h"
23
+ #include "pdfs.h"
24
+
25
+ /* Images
26
+
27
+ invoke image by "/Image_name Do" in the content stream
28
+
29
+ the resources dictionary must have image object names in XObject dictionary
30
+ /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
31
+ /XObject <<
32
+ /Image_name 30 0 R
33
+ ...
34
+ >>
35
+
36
+ 30 0 obj <<
37
+ /Type /XObject
38
+ /Subtype /Image
39
+ /Width <integer> number of columns. required for all.
40
+ /Height <integer> number of rows. required for all.
41
+ /Length <integer> number of bytes in image data stream. required for all.
42
+ /Interpolate <boolean> optional for all.
43
+ /SMask <stream> optional for all.
44
+ ...
45
+ >>
46
+ stream
47
+ ...image data...
48
+ endstream
49
+ endobj
50
+
51
+ For JPEG2000 images:
52
+ /Filter /JPXDecode
53
+ /Mask <image_mask_name> for explicit masking. optional.
54
+
55
+ For JPEG images:
56
+ /Filter /DCTDecode
57
+ /ColorSpace <name or array>. required. /DeviceRGB ?
58
+ /BitsPerComponent 8
59
+ /Mask <image_mask_name> for explicit masking. optional.
60
+
61
+ For sampled images:
62
+ /Filter <name> whatever filter being used for the image data. optional.
63
+ /ColorSpace <name or array>. required.
64
+ /BitsPerComponent 8
65
+ /Mask <image_mask_name> for explicit masking. optional.
66
+ /Mask [min, max] for masking out specified sample values.
67
+ for example, you can use 0 to stand for "undefined", then setting /Mask [0 0] will cause all
68
+ 0 valued samples to be masked out of the image.
69
+
70
+ For image masks:
71
+ /ImageMask true
72
+ /BitsPerComponent 1
73
+ /Decode [0 1] means sample values of 0 are included in the output, values of 1 are excluded
74
+ /Decode [1 0] means sample values of 1 are included in the output, values of 0 are excluded
75
+
76
+ */
77
+
78
+
79
+ void
80
+ Free_JPG(JPG_Info *xo)
81
+ {
82
+ if (xo->filename != NULL) free(xo->filename);
83
+ }
84
+
85
+
86
+ void
87
+ Free_Sampled(Sampled_Info *xo)
88
+ {
89
+ if (xo->image_data != NULL) free(xo->image_data);
90
+ if (xo->lookup != NULL) free(xo->lookup);
91
+ }
92
+
93
+
94
+ static bool
95
+ Is_monochrome(int obj_num)
96
+ {
97
+ XObject_Info *xo;
98
+ for (xo = xobj_list; xo != NULL; xo = xo->next) {
99
+ if (xo->xobj_subtype == SAMPLED_SUBTYPE && xo->obj_num == obj_num) {
100
+ Sampled_Info *p = (Sampled_Info *)xo;
101
+ return (p->image_type == MONO_IMAGE);
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+
107
+
108
+ static void
109
+ Write_Image_From_File(char *filename, int width, int height, char *out_info,
110
+ int mask_obj_num, int *ierr)
111
+ {
112
+ FILE *jpg = fopen(filename, "r");
113
+ if (jpg == NULL) {
114
+ RAISE_ERROR_s("Sorry: cannot open file for showing image (%s)\n",
115
+ filename, ierr);
116
+ return;
117
+ }
118
+ unsigned char *buff;
119
+ int len, rd_len;
120
+ int buff_len = 256000;
121
+ buff = ALLOC_N_unsigned_char(buff_len);
122
+ len = 0;
123
+ while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len) {
124
+ len += buff_len;
125
+ }
126
+ len += rd_len;
127
+ fprintf(OF, "\t/Subtype /Image\n");
128
+ if (mask_obj_num > 0) {
129
+ if (!Is_monochrome(mask_obj_num))
130
+ fprintf(OF, "\t/SMask %i 0 R\n", mask_obj_num);
131
+ else
132
+ fprintf(OF, "\t/Mask %i 0 R\n", mask_obj_num);
133
+ }
134
+ fprintf(OF, "\t/Width %i\n", width);
135
+ fprintf(OF, "\t/Height %i\n", height);
136
+ fprintf(OF, "%s", out_info);
137
+ fprintf(OF, "\t/Length %i\n\t>>\nstream\n", len);
138
+ if (len < buff_len) fwrite(buff, 1, len, OF);
139
+ else {
140
+ rewind(jpg);
141
+ while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len) {
142
+ fwrite(buff, 1, buff_len, OF);
143
+ }
144
+ fwrite(buff, 1, rd_len, OF);
145
+ }
146
+ fprintf(OF, "\nendstream\n");
147
+ fclose(jpg);
148
+ }
149
+
150
+
151
+ void
152
+ Write_JPG(JPG_Info *xo, int *ierr)
153
+ {
154
+ Write_Image_From_File(xo->filename, xo->width, xo->height,
155
+ "\t/Filter /DCTDecode\n\t/ColorSpace "
156
+ "/DeviceRGB\n\t/BitsPerComponent 8\n",
157
+ xo->mask_obj_num, ierr);
158
+ }
159
+
160
+ extern void
161
+ str_hls_to_rgb_bang(unsigned char* str, long len);
162
+
163
+ void
164
+ Write_Sampled(Sampled_Info *xo, int *ierr)
165
+ {
166
+ fprintf(OF, "\n\t/Subtype /Image\n");
167
+ fprintf(OF, "\t/Filter /FlateDecode\n\t/Interpolate %s\n",
168
+ (xo->interpolate)? "true":"false");
169
+ fprintf(OF, "\t/Height %i\n", xo->height);
170
+ fprintf(OF, "\t/Width %i\n", xo->width);
171
+ int i, len;
172
+ unsigned long new_len;
173
+ unsigned char *image_data;
174
+ unsigned char *buffer;
175
+ switch (xo->image_type) {
176
+ case RGB_IMAGE:
177
+ case HLS_IMAGE:
178
+ fprintf(OF, "\t/ColorSpace /DeviceRGB\n");
179
+ fprintf(OF, "\t/BitsPerComponent 8\n");
180
+ break;
181
+ case CMYK_IMAGE:
182
+ fprintf(OF, "\t/ColorSpace /DeviceCMYK\n");
183
+ fprintf(OF, "\t/BitsPerComponent 8\n");
184
+ break;
185
+ case GRAY_IMAGE:
186
+ fprintf(OF, "\t/ColorSpace /DeviceGray\n");
187
+ fprintf(OF, "\t/BitsPerComponent 8\n");
188
+ break;
189
+ case MONO_IMAGE:
190
+ fprintf(OF, "\t/ImageMask true\n");
191
+ fprintf(OF, "\t/BitsPerComponent 1\n");
192
+ if (!xo->reversed) fprintf(OF, "\t/Decode [0 1]\n");
193
+ else fprintf(OF, "\t/Decode [1 0]\n");
194
+ break;
195
+ default:
196
+ len = xo->lookup_len;
197
+ fprintf(OF, "\t/ColorSpace [ /Indexed /DeviceRGB %i <", xo->hival);
198
+ for (i = 0; i < len; i++) {
199
+ unsigned char c = xo->lookup[i];
200
+ if (c == 0) fprintf(OF, "00");
201
+ else if (c < 16) fprintf(OF, "0%x", c);
202
+ else fprintf(OF, "%x", c);
203
+ }
204
+ fprintf(OF, "> ]\n");
205
+ fprintf(OF, "\t/BitsPerComponent 8\n");
206
+ }
207
+ if (xo->mask_obj_num > 0) {
208
+ if (xo->image_type == MONO_IMAGE) {
209
+ RAISE_ERROR("Sorry: monochrome images must not have masks", ierr);
210
+ return;
211
+ }
212
+ if (!Is_monochrome(xo->mask_obj_num))
213
+ fprintf(OF, "\t/SMask %i 0 R\n", xo->mask_obj_num);
214
+ else
215
+ fprintf(OF, "\t/Mask %i 0 R\n", xo->mask_obj_num);
216
+ }
217
+ if (xo->value_mask_min >= 0 && xo->value_mask_max >= 0
218
+ && xo->value_mask_min <= 255 && xo->value_mask_max <= 255
219
+ && xo->value_mask_min <= xo->value_mask_max)
220
+ fprintf(OF, "\t/Mask [%i %i]\n", xo->value_mask_min, xo->value_mask_max);
221
+
222
+ if (xo->image_type == HLS_IMAGE) {
223
+ image_data = ALLOC_N_unsigned_char(xo->length);
224
+ memcpy(image_data, xo->image_data, xo->length);
225
+ str_hls_to_rgb_bang(image_data, xo->length);
226
+ } else {
227
+ image_data = xo->image_data;
228
+ }
229
+
230
+ new_len = (xo->length * 11)/10 + 100;
231
+ buffer = ALLOC_N_unsigned_char(new_len);
232
+ if (do_flate_compress(buffer, &new_len, image_data, xo->length)
233
+ != FLATE_OK) {
234
+ free(buffer);
235
+ RAISE_ERROR("Error compressing image data", ierr);
236
+ return;
237
+ }
238
+ fprintf(OF, "\t/Length %li\n", new_len);
239
+ fprintf(OF, "\t>>\nstream\n");
240
+ if (fwrite(buffer, 1, new_len, OF) < new_len) {
241
+ RAISE_ERROR("Error writing image data", ierr);
242
+ return;
243
+ }
244
+ free(buffer);
245
+ if (xo->image_type == HLS_IMAGE) free(image_data);
246
+ fprintf(OF, "\nendstream\nendobj\n");
247
+ }
248
+
249
+
250
+ // transform maps (0,0), (1,0), and (0,1) to the given points
251
+ static void
252
+ Create_Transform_from_Points(double llx, double lly, double lrx, double lry,
253
+ double ulx, double uly, double *a, double *b,
254
+ double *c, double *d, double *e, double *f)
255
+ {
256
+ *e = llx; *f = lly; lrx -= llx; ulx -= llx; lry -= lly; uly -= lly;
257
+ *a = lrx; *b = lry; *c = ulx; *d = uly;
258
+ }
259
+
260
+
261
+ static void
262
+ Get_Image_Dest(FM *p, OBJ_PTR image_destination, double *dest, int *ierr)
263
+ {
264
+ int len = Array_Len(image_destination,ierr);
265
+ if (*ierr != 0) return;
266
+ if (len != 6) {
267
+ RAISE_ERROR("Sorry: invalid image destination array: "
268
+ "must have 6 entries", ierr);
269
+ return;
270
+ }
271
+ int i;
272
+ for (i = 0; i < 6; i++) {
273
+ OBJ_PTR entry = Array_Entry(image_destination, i, ierr);
274
+ if (*ierr != 0) return;
275
+ if (i % 2 == 0)
276
+ dest[i] = convert_figure_to_output_x(p,Number_to_double(entry, ierr));
277
+ else
278
+ dest[i] = convert_figure_to_output_y(p,Number_to_double(entry, ierr));
279
+ if (*ierr != 0) return;
280
+ }
281
+ }
282
+
283
+
284
+ static void
285
+ Show_JPEG(FM *p, char *filename, int width, int height, double *dest,
286
+ int subtype, int mask_obj_num)
287
+ {
288
+ JPG_Info *xo = (JPG_Info *)calloc(1,sizeof(JPG_Info));
289
+ xo->xobj_subtype = subtype;
290
+ double llx = dest[0], lly = dest[1], lrx = dest[2], lry = dest[3],
291
+ ulx = dest[4], uly = dest[5];
292
+ double a, b, c, d, e, f; // the transform to position the image
293
+ xo->next = xobj_list;
294
+ xobj_list = (XObject_Info *)xo;
295
+ xo->xo_num = next_available_xo_number++;
296
+ xo->obj_num = next_available_object_number++;
297
+ xo->filename = ALLOC_N_char(strlen(filename)+1);
298
+ strcpy(xo->filename, filename);
299
+ xo->width = width;
300
+ xo->height = height;
301
+ xo->mask_obj_num = mask_obj_num;
302
+ Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
303
+ &a, &b, &c, &d, &e, &f);
304
+ fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
305
+ a, b, c, d, e, f, xo->xo_num);
306
+ update_bbox(p, llx, lly);
307
+ update_bbox(p, lrx, lry);
308
+ update_bbox(p, ulx, uly);
309
+ update_bbox(p, lrx+ulx-llx, lry+uly-lly);
310
+ }
311
+
312
+
313
+ void
314
+ c_private_show_jpg(OBJ_PTR fmkr, FM *p, char *filename,
315
+ int width, int height, OBJ_PTR image_destination,
316
+ int mask_obj_num, int *ierr)
317
+ {
318
+ double dest[6];
319
+ if (constructing_path) {
320
+ RAISE_ERROR("Sorry: must finish with current path before "
321
+ "calling show_jpg", ierr);
322
+ return;
323
+ }
324
+ Get_Image_Dest(p, image_destination, dest, ierr);
325
+ if (*ierr != 0) return;
326
+ Show_JPEG(p, filename, width, height, dest, JPG_SUBTYPE, mask_obj_num);
327
+ }
328
+
329
+
330
+ OBJ_PTR
331
+ c_private_create_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR table,
332
+ int first_row, int last_row, int first_column,
333
+ int last_column, double min_val, double max_val,
334
+ int max_code, int if_below_range,
335
+ int if_above_range, int *ierr)
336
+ {
337
+ long num_cols, num_rows;
338
+ double **data = Table_Data_for_Read(table, &num_cols, &num_rows, ierr);
339
+ if (*ierr != 0) RETURN_NIL;
340
+ if (first_column < 0) first_column += num_cols;
341
+ if (first_column < 0 || first_column >= num_cols)
342
+ RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
343
+ first_column, ierr);
344
+ if (last_column < 0) last_column += num_cols;
345
+ if (last_column < 0 || last_column >= num_cols)
346
+ RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
347
+ last_column, ierr);
348
+ if (first_row < 0) first_row += num_rows;
349
+ if (first_row < 0 || first_row >= num_rows)
350
+ RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
351
+ first_row, ierr);
352
+ if (last_row < 0) last_row += num_rows;
353
+ if (last_row < 0 || last_row >= num_rows)
354
+ RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
355
+ last_row, ierr);
356
+ if (min_val >= max_val)
357
+ RAISE_ERROR_gg("Sorry: invalid range specification: min %g max %g",
358
+ min_val, max_val, ierr);
359
+ if (max_code <= 0 || max_code > 255)
360
+ RAISE_ERROR_i("Sorry: invalid max_code specification (%i)",
361
+ max_code, ierr);
362
+ if (if_below_range < 0 || if_below_range > 255)
363
+ RAISE_ERROR_i("Sorry: invalid if_below_range specification (%i)",
364
+ if_below_range, ierr);
365
+ if (if_above_range < 0 || if_above_range > 255)
366
+ RAISE_ERROR_i("Sorry: invalid if_above_range specification (%i)",
367
+ if_above_range, ierr);
368
+ int i, j, k;
369
+ int width = last_column - first_column + 1;
370
+ int height = last_row - first_row + 1;
371
+ int sz = width * height;
372
+ if (sz <= 0)
373
+ RAISE_ERROR_ii("Sorry: invalid data specification: width (%i) "
374
+ "height (%i)", width, height, ierr);
375
+ if (*ierr != 0) RETURN_NIL;
376
+ char *buff = ALLOC_N_char(sz);
377
+ for (k = 0, i = first_row; i <= last_row; i++) {
378
+ double *row = data[i];
379
+ for (j = first_column; j <= last_column; j++) {
380
+ double val = row[j];
381
+ if (val < min_val) buff[k++] = if_below_range;
382
+ else if (val > max_val) buff[k++] = if_above_range;
383
+ else {
384
+ val = max_code * (val - min_val)/(max_val - min_val);
385
+ buff[k++] = ROUND(val);
386
+ }
387
+ }
388
+ }
389
+ OBJ_PTR result = String_New(buff, sz);
390
+ free(buff);
391
+ return result;
392
+ }
393
+
394
+
395
+ OBJ_PTR
396
+ c_private_create_monochrome_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR table,
397
+ int first_row, int last_row,
398
+ int first_column, int last_column,
399
+ double boundary, bool reversed,
400
+ int *ierr)
401
+ {
402
+ long num_cols, num_rows;
403
+ double **data = Table_Data_for_Read(table, &num_cols, &num_rows, ierr);
404
+ if (*ierr != 0) RETURN_NIL;
405
+ if (first_column < 0) first_column += num_cols;
406
+ if (first_column < 0 || first_column >= num_cols)
407
+ RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
408
+ first_column, ierr);
409
+ if (last_column < 0) last_column += num_cols;
410
+ if (last_column < 0 || last_column >= num_cols)
411
+ RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
412
+ last_column, ierr);
413
+ if (first_row < 0) first_row += num_rows;
414
+ if (first_row < 0 || first_row >= num_rows)
415
+ RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
416
+ first_row, ierr);
417
+ if (last_row < 0) last_row += num_rows;
418
+ if (last_row < 0 || last_row >= num_rows)
419
+ RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
420
+ last_row, ierr);
421
+ int i, j, k;
422
+ int width = last_column - first_column + 1;
423
+ int height = last_row - first_row + 1;
424
+ int bytes_per_row = (width+7)/8;
425
+ int sz = bytes_per_row * 8 * height;
426
+ if (sz <= 0)
427
+ RAISE_ERROR_ii("Sorry: invalid data specification: width (%i) "
428
+ "height (%i)", width, height, ierr);
429
+ if (*ierr != 0) RETURN_NIL;
430
+ // to simplify the process, do it in two stages: first get the
431
+ // values and then pack the bits
432
+ char *buff = ALLOC_N_char(sz);
433
+ for (k = 0, i = first_row; i <= last_row; i++) {
434
+ double *row = data[i];
435
+ for (j = first_column; j <= last_column; j++) {
436
+ double val = row[j];
437
+ buff[k++] = (reversed)? (val <= boundary) : (val > boundary);
438
+ }
439
+ for (j = last_column+1; j < bytes_per_row * 8; j++) {
440
+ buff[k++] = 0;
441
+ }
442
+ }
443
+ int num_bytes = (sz+7) >> 3;
444
+ char *bits = ALLOC_N_char(num_bytes), c = 0;
445
+ int num_bits = num_bytes << 3;
446
+ for (i = 0, k = -1; i < num_bits; i++) {
447
+ int bit = (i < sz)? buff[i] : 0;
448
+ int which_bit = i & 7;
449
+ if (which_bit != 0) c |= bit << (7-which_bit);
450
+ else {
451
+ if (k >= 0) bits[k] = c;
452
+ k++; c = bit << 7;
453
+ }
454
+ }
455
+ bits[k] = c;
456
+ OBJ_PTR result = String_New(bits, num_bytes);
457
+ free(bits); free(buff);
458
+ return result;
459
+ }
460
+
461
+
462
+ OBJ_PTR
463
+ c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
464
+ double lly, double lrx, double lry, double ulx,
465
+ double uly, bool interpolate, bool reversed,
466
+ int w, int h, unsigned char* data, long len,
467
+ OBJ_PTR mask_min, OBJ_PTR mask_max, OBJ_PTR hivalue,
468
+ OBJ_PTR lookup_data, int mask_obj_num, int *ierr)
469
+ {
470
+ unsigned char *lookup = NULL;
471
+ int value_mask_min = 256, value_mask_max = 256, lookup_len = 0, hival = 0;
472
+ if (constructing_path) {
473
+ RAISE_ERROR("Sorry: must finish with current path before calling "
474
+ "show_image", ierr);
475
+ RETURN_NIL;
476
+ }
477
+ if (image_type == COLORMAP_IMAGE) {
478
+ value_mask_min = Number_to_int(mask_min, ierr);
479
+ value_mask_max = Number_to_int(mask_max, ierr);
480
+ hival = Number_to_int(hivalue, ierr);
481
+ lookup = (unsigned char *)(String_Ptr(lookup_data, ierr));
482
+ lookup_len = String_Len(lookup_data, ierr);
483
+ if (*ierr != 0) RETURN_NIL;
484
+ }
485
+
486
+ llx = convert_figure_to_output_x(p, llx);
487
+ lly = convert_figure_to_output_y(p, lly);
488
+ lrx = convert_figure_to_output_x(p, lrx);
489
+ lry = convert_figure_to_output_y(p, lry);
490
+ ulx = convert_figure_to_output_x(p, ulx);
491
+ uly = convert_figure_to_output_y(p, uly);
492
+
493
+ Sampled_Info *xo = (Sampled_Info *)calloc(1, sizeof(Sampled_Info));
494
+ xo->xobj_subtype = SAMPLED_SUBTYPE;
495
+ double a, b, c, d, e, f; // the transform to position the image
496
+ //int ir, ic, id;
497
+ xo->next = xobj_list;
498
+ xobj_list = (XObject_Info *)xo;
499
+ xo->xo_num = next_available_xo_number++;
500
+ xo->obj_num = next_available_object_number++;
501
+ xo->image_data = ALLOC_N_unsigned_char(len);
502
+ xo->length = len;
503
+ xo->interpolate = interpolate;
504
+ xo->reversed = reversed;
505
+ memcpy(xo->image_data, data, len);
506
+ xo->image_type = image_type;
507
+ if (image_type != COLORMAP_IMAGE) xo->lookup = NULL;
508
+ else {
509
+ if ((hival+1)*3 > lookup_len) {
510
+ RAISE_ERROR_ii("Sorry: color space hival (%i) is too large for "
511
+ "length of lookup table (%i)", hival, lookup_len,
512
+ ierr);
513
+ RETURN_NIL;
514
+ }
515
+ xo->hival = hival;
516
+ lookup_len = (hival+1) * 3;
517
+ xo->lookup = ALLOC_N_unsigned_char(lookup_len);
518
+ xo->lookup_len = lookup_len;
519
+ memcpy(xo->lookup, lookup, lookup_len);
520
+ }
521
+ xo->width = w;
522
+ xo->height = h;
523
+ xo->value_mask_min = value_mask_min;
524
+ xo->value_mask_max = value_mask_max;
525
+ xo->mask_obj_num = mask_obj_num;
526
+ if (mask_obj_num == -1)
527
+ return Integer_New(xo->obj_num); // this image is being used as
528
+ // an opacity mask
529
+ Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
530
+ &a, &b, &c, &d, &e, &f);
531
+ fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
532
+ a, b, c, d, e, f, xo->xo_num);
533
+ update_bbox(p, llx, lly);
534
+ update_bbox(p, lrx, lry);
535
+ update_bbox(p, ulx, uly);
536
+ update_bbox(p, lrx+ulx-llx, lry+uly-lly);
537
+ return Integer_New(xo->obj_num);
538
+ }
539
+