tioga 1.7 → 1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Tioga_README +45 -29
- data/split/Dvector/dvector.c +1 -1
- data/split/Tioga/{shared/axes.c → axes.c} +360 -36
- data/split/Tioga/figures.c +2 -1
- data/split/Tioga/figures.h +6 -2
- data/split/Tioga/generic.h +0 -1
- data/split/Tioga/lib/FigMkr.rb +3 -1
- data/split/Tioga/lib/X_and_Y_Axes.rb +74 -4
- data/split/Tioga/makers.c +1303 -0
- data/split/Tioga/{shared/pdf_font_dicts.c → pdf_font_dicts.c} +0 -0
- data/split/Tioga/{shared/pdfcolor.c → pdfcolor.c} +304 -145
- data/split/Tioga/pdfcoords.c +534 -0
- data/split/Tioga/{shared/pdffile.c → pdffile.c} +161 -56
- data/split/Tioga/{shared/pdfimage.c → pdfimage.c} +171 -74
- data/split/Tioga/{shared/pdfpath.c → pdfpath.c} +0 -0
- data/split/Tioga/{shared/pdftext.c → pdftext.c} +245 -138
- data/split/Tioga/{shared/texout.c → texout.c} +18 -9
- data/split/Tioga/wrappers.c +23 -7
- data/split/Tioga/wrappers.h +5 -3
- data/split/extconf.rb +1 -1
- metadata +25 -25
- data/split/Tioga/shared/makers.c +0 -1220
- data/split/Tioga/shared/pdfcoords.c +0 -443
@@ -28,7 +28,9 @@
|
|
28
28
|
#define Get_pdf_xoffset() 5.0
|
29
29
|
#define Get_pdf_yoffset() 5.0
|
30
30
|
|
31
|
-
|
31
|
+
|
32
|
+
/* must match the font numbers in FigureConstants.rb */
|
33
|
+
char *predefined_Fonts[] = {
|
32
34
|
NULL,
|
33
35
|
"Times-Roman",
|
34
36
|
"Times-Italic", // 2
|
@@ -44,12 +46,14 @@ char *predefined_Fonts[] = { /* must match the font numbers in FigureConstants.r
|
|
44
46
|
"Courier-BoldOblique",
|
45
47
|
"Symbol",
|
46
48
|
"ZapfDingbats" // 14
|
47
|
-
|
49
|
+
};
|
48
50
|
int num_predefined_fonts = 14;
|
49
51
|
int num_pdf_standard_fonts = 14;
|
50
52
|
|
51
|
-
long *obj_offsets, capacity_obj_offsets, stream_start, stream_end
|
52
|
-
long
|
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;
|
53
57
|
long next_available_shade_number, next_available_font_number;
|
54
58
|
Stroke_Opacity_State *stroke_opacities = NULL;
|
55
59
|
Fill_Opacity_State *fill_opacities = NULL;
|
@@ -61,24 +65,35 @@ Old_Font_Dictionary *old_font_dictionaries = NULL;
|
|
61
65
|
FILE *OF = NULL; // for the PDF file
|
62
66
|
FILE *TF = NULL; // for the temp file
|
63
67
|
|
68
|
+
|
64
69
|
/* PDF File Management */
|
65
70
|
|
66
|
-
static void
|
71
|
+
static void
|
72
|
+
Free_XObjects(int *ierr)
|
67
73
|
{
|
68
74
|
XObject_Info *xo;
|
69
75
|
while (xobj_list != NULL) {
|
70
76
|
xo = xobj_list;
|
71
77
|
xobj_list = xo->next;
|
72
78
|
switch (xo->xobj_subtype) {
|
73
|
-
|
74
|
-
|
75
|
-
|
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;
|
76
89
|
}
|
77
90
|
free(xo);
|
78
91
|
}
|
79
92
|
}
|
80
93
|
|
81
|
-
|
94
|
+
|
95
|
+
void
|
96
|
+
Init_pdf(int *ierr)
|
82
97
|
{
|
83
98
|
int i;
|
84
99
|
writing_file = false;
|
@@ -88,7 +103,9 @@ void Init_pdf(int *ierr)
|
|
88
103
|
for (i=0; i < capacity_obj_offsets; i++) obj_offsets[i] = 0;
|
89
104
|
}
|
90
105
|
|
91
|
-
|
106
|
+
|
107
|
+
void
|
108
|
+
Record_Object_Offset(int obj_number)
|
92
109
|
{
|
93
110
|
long int offset = ftell(OF);
|
94
111
|
if (obj_number >= capacity_obj_offsets) {
|
@@ -101,22 +118,30 @@ void Record_Object_Offset(int obj_number)
|
|
101
118
|
if (obj_number >= num_objects) num_objects = obj_number + 1;
|
102
119
|
}
|
103
120
|
|
104
|
-
|
121
|
+
|
122
|
+
static void
|
123
|
+
Write_XObjects(int *ierr)
|
105
124
|
{
|
106
125
|
XObject_Info *xo;
|
107
126
|
for (xo = xobj_list; xo != NULL; xo = xo->next) {
|
108
127
|
Record_Object_Offset(xo->obj_num);
|
109
128
|
fprintf(OF, "%i 0 obj << /Type /XObject ", xo->obj_num);
|
110
129
|
switch (xo->xobj_subtype) {
|
111
|
-
|
112
|
-
|
113
|
-
|
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);
|
114
138
|
}
|
115
139
|
if (*ierr != 0) return;
|
116
140
|
fprintf(OF, ">> endobj\n");
|
117
141
|
}
|
118
142
|
}
|
119
143
|
|
144
|
+
|
120
145
|
#define INFO_OBJ 1
|
121
146
|
#define PAGES_OBJ 2
|
122
147
|
#define STREAM_OBJ 3
|
@@ -124,24 +149,38 @@ static void Write_XObjects(int *ierr)
|
|
124
149
|
#define CATALOG_OBJ 5
|
125
150
|
#define FIRST_OTHER_OBJ 6
|
126
151
|
|
127
|
-
|
152
|
+
|
153
|
+
static void
|
154
|
+
Free_Records(int *ierr)
|
128
155
|
{
|
129
|
-
Free_Stroke_Opacities();
|
156
|
+
Free_Stroke_Opacities();
|
157
|
+
Free_Fill_Opacities();
|
158
|
+
Free_XObjects(ierr);
|
159
|
+
Free_Shadings();
|
160
|
+
Free_Functions();
|
130
161
|
}
|
131
162
|
|
132
|
-
|
163
|
+
|
164
|
+
static void
|
165
|
+
Get_pdf_name(char *ofile, char *filename, int maxlen)
|
133
166
|
{
|
134
167
|
char *dot;
|
135
168
|
strncpy(ofile, filename, maxlen);
|
136
|
-
dot = strrchr(ofile,'.');
|
169
|
+
dot = strrchr(ofile, '.');
|
137
170
|
if (dot != NULL) dot[0] = '\0';
|
138
171
|
strcat(ofile, "_figure.pdf");
|
139
172
|
}
|
140
173
|
|
141
|
-
|
174
|
+
|
175
|
+
void
|
176
|
+
Open_pdf(OBJ_PTR fmkr, FM *p, char *filename, bool quiet_mode, int *ierr)
|
177
|
+
{
|
142
178
|
int i;
|
143
179
|
if (writing_file) {
|
144
|
-
RAISE_ERROR("Sorry: cannot start a new output file until finish
|
180
|
+
RAISE_ERROR("Sorry: cannot start a new output file until finish "
|
181
|
+
"current one.", ierr);
|
182
|
+
return;
|
183
|
+
}
|
145
184
|
Clear_Fonts_In_Use_Flags();
|
146
185
|
Free_Records(ierr);
|
147
186
|
if (*ierr != 0) return;
|
@@ -155,18 +194,27 @@ void Open_pdf(OBJ_PTR fmkr, FM *p, char *filename, bool quiet_mode, int *ierr) {
|
|
155
194
|
char ofile[300], timestring[100];
|
156
195
|
Get_pdf_name(ofile, filename, 300);
|
157
196
|
if ((OF = fopen(ofile, "w")) == NULL) {
|
158
|
-
|
197
|
+
RAISE_ERROR_s("Sorry: can't open %s.\n", filename, ierr);
|
198
|
+
return;
|
199
|
+
}
|
159
200
|
if ((TF = tmpfile()) == NULL) {
|
160
|
-
|
201
|
+
RAISE_ERROR_s("Sorry: can't create temp file for writing PDF file %s.\n",
|
202
|
+
filename, ierr);
|
203
|
+
return;
|
204
|
+
}
|
161
205
|
/* open PDF file and write header */
|
162
206
|
fprintf(OF, "%%PDF-1.4\n");
|
163
207
|
strcpy(timestring, ctime(&now));
|
164
208
|
i = strlen(timestring);
|
165
209
|
if (i > 0) timestring[i-1] = '\0';
|
166
210
|
Record_Object_Offset(INFO_OBJ);
|
167
|
-
fprintf(OF,
|
211
|
+
fprintf(OF,
|
212
|
+
"%i 0 obj <<\n/Creator (Tioga)\n/CreationDate (%s)\n>>\nendobj\n",
|
213
|
+
INFO_OBJ, timestring);
|
168
214
|
Record_Object_Offset(PAGES_OBJ);
|
169
|
-
fprintf(OF,
|
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);
|
170
218
|
Record_Object_Offset(STREAM_OBJ);
|
171
219
|
if (FLATE_ENCODE)
|
172
220
|
fprintf(OF, "%i 0 obj <<\t/Filter /FlateDecode /Length ", STREAM_OBJ);
|
@@ -176,7 +224,7 @@ void Open_pdf(OBJ_PTR fmkr, FM *p, char *filename, bool quiet_mode, int *ierr) {
|
|
176
224
|
fprintf(OF, " \n>>\nstream\n");
|
177
225
|
stream_start = ftell(OF);
|
178
226
|
fprintf(TF, "%.2f 0 0 %.2f %.2f %.2f cm\n", 1.0/ENLARGE, 1.0/ENLARGE,
|
179
|
-
|
227
|
+
Get_pdf_xoffset(), Get_pdf_yoffset());
|
180
228
|
/* set stroke and fill colors to black */
|
181
229
|
have_current_point = constructing_path = false;
|
182
230
|
c_line_width_set(fmkr, p, p->line_width, ierr);
|
@@ -184,14 +232,20 @@ void Open_pdf(OBJ_PTR fmkr, FM *p, char *filename, bool quiet_mode, int *ierr) {
|
|
184
232
|
c_line_join_set(fmkr, p, p->line_join, ierr);
|
185
233
|
c_miter_limit_set(fmkr, p, p->miter_limit, ierr);
|
186
234
|
c_line_type_set(fmkr, p, Get_line_type(fmkr, ierr), ierr);
|
187
|
-
c_stroke_color_set_RGB(fmkr, p, p->stroke_color_R, p->stroke_color_G,
|
188
|
-
|
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);
|
189
239
|
// initialize clip region
|
190
240
|
bbox_llx = bbox_lly = 1e5;
|
191
241
|
bbox_urx = bbox_ury = -1e5;
|
192
242
|
}
|
193
243
|
|
194
|
-
|
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
|
+
{
|
195
249
|
fprintf(TF, "q 2 J [] 0 d\n");
|
196
250
|
c_line_width_set(fmkr, p, line_width, ierr);
|
197
251
|
c_stroke_color_set_RGB(fmkr, p, r, g, b, ierr);
|
@@ -199,31 +253,56 @@ void Start_Axis_Standard_State(OBJ_PTR fmkr, FM *p, double r, double g, double b
|
|
199
253
|
/* set stroke and fill colors to black. set line type to solid */
|
200
254
|
}
|
201
255
|
|
202
|
-
void End_Axis_Standard_State(void) { Write_grestore(); }
|
203
256
|
|
204
|
-
void
|
257
|
+
void
|
258
|
+
End_Axis_Standard_State(void)
|
259
|
+
{
|
260
|
+
Write_grestore();
|
261
|
+
}
|
262
|
+
|
263
|
+
|
264
|
+
void
|
265
|
+
Write_gsave(void)
|
205
266
|
{
|
206
267
|
fprintf(TF, "q\n");
|
207
268
|
}
|
208
269
|
|
209
|
-
|
270
|
+
|
271
|
+
void
|
272
|
+
Write_grestore(void)
|
210
273
|
{
|
211
274
|
fprintf(TF, "Q\n");
|
212
275
|
}
|
213
276
|
|
214
|
-
void c_pdf_gsave(OBJ_PTR fmkr, FM *p, int *ierr) { Write_gsave(); }
|
215
|
-
void c_pdf_grestore(OBJ_PTR fmkr, FM *p, int *ierr) { Write_grestore(); }
|
216
277
|
|
217
|
-
|
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
|
+
{
|
218
295
|
char line[80];
|
219
296
|
int i, len;
|
220
297
|
snprintf(line,sizeof(line), "%li", offset);
|
221
298
|
len = strlen(line);
|
222
299
|
for (i=0; i < 10-len; i++) fputc('0', OF);
|
223
300
|
fprintf(OF, "%s 00000 n \n", line);
|
224
|
-
|
301
|
+
}
|
302
|
+
|
225
303
|
|
226
|
-
static void
|
304
|
+
static void
|
305
|
+
Write_Stream(int *ierr)
|
227
306
|
{
|
228
307
|
long int len = ftell(TF);
|
229
308
|
unsigned long int new_len = (len * 11) / 10 + 100;
|
@@ -240,29 +319,43 @@ static void Write_Stream(int *ierr)
|
|
240
319
|
return;
|
241
320
|
}
|
242
321
|
fwrite(dest_buffer, 1, new_len, OF);
|
243
|
-
}
|
322
|
+
}
|
323
|
+
else {
|
244
324
|
fwrite(buffer, 1, len, OF);
|
245
|
-
}
|
246
|
-
free(buffer);
|
325
|
+
}
|
326
|
+
free(buffer);
|
327
|
+
free(dest_buffer);
|
247
328
|
}
|
248
329
|
|
249
|
-
|
330
|
+
|
331
|
+
void
|
332
|
+
Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
250
333
|
{
|
251
334
|
int i;
|
252
335
|
double llx, lly, urx, ury, xoff, yoff;
|
253
|
-
if (!writing_file) {
|
336
|
+
if (!writing_file) {
|
337
|
+
RAISE_ERROR("Sorry: cannot End_Output if not writing file.", ierr);
|
338
|
+
return;
|
339
|
+
}
|
254
340
|
writing_file = false;
|
255
|
-
if (constructing_path) {
|
341
|
+
if (constructing_path) {
|
342
|
+
RAISE_ERROR("Sorry: must finish with current path before ending file",
|
343
|
+
ierr);
|
344
|
+
return;
|
345
|
+
}
|
256
346
|
Write_Stream(ierr);
|
257
347
|
if (*ierr != 0) return;
|
258
348
|
stream_end = ftell(OF);
|
259
349
|
fprintf(OF, "endstream\nendobj\n");
|
260
350
|
Record_Object_Offset(PAGE_OBJ);
|
261
|
-
fprintf(OF, "%i 0 obj <<\n/Type /Page\n/Parent %i 0 R\n/MediaBox [ ",
|
351
|
+
fprintf(OF, "%i 0 obj <<\n/Type /Page\n/Parent %i 0 R\n/MediaBox [ ",
|
352
|
+
PAGE_OBJ, PAGES_OBJ);
|
262
353
|
if (bbox_llx < p->page_left) bbox_llx = p->page_left;
|
263
354
|
if (bbox_lly < p->page_bottom) bbox_lly = p->page_bottom;
|
264
|
-
if (bbox_urx > p->page_left + p->page_width)
|
265
|
-
|
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;
|
266
359
|
//#define MARGIN 3
|
267
360
|
#define MARGIN 0
|
268
361
|
xoff = Get_pdf_xoffset();
|
@@ -271,9 +364,13 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
271
364
|
lly = bbox_lly / ENLARGE + yoff - MARGIN;
|
272
365
|
urx = bbox_urx / ENLARGE + xoff + MARGIN;
|
273
366
|
ury = bbox_ury / ENLARGE + yoff + MARGIN;
|
274
|
-
if (urx < llx || ury < lly) {
|
367
|
+
if (urx < llx || ury < lly) {
|
368
|
+
RAISE_ERROR("Sorry: Empty plot!", ierr);
|
369
|
+
return;
|
370
|
+
}
|
275
371
|
fprintf(OF, "%d %d %d %d", ROUND(llx), ROUND(lly), ROUND(urx), ROUND(ury));
|
276
|
-
fprintf(OF, " ]\n/Contents %i 0 R\n/Resources <<
|
372
|
+
fprintf(OF, " ]\n/Contents %i 0 R\n/Resources << "
|
373
|
+
"/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n", STREAM_OBJ);
|
277
374
|
if (Used_Any_Fonts()) {
|
278
375
|
Font_Dictionary *f;
|
279
376
|
fprintf(OF, " /Font <<\n ");
|
@@ -283,7 +380,8 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
283
380
|
}
|
284
381
|
fprintf(OF, " >>\n"); // end of /Font
|
285
382
|
}
|
286
|
-
if (fill_opacities != NULL || stroke_opacities != NULL) {
|
383
|
+
if (fill_opacities != NULL || stroke_opacities != NULL) {
|
384
|
+
// ExtGstate objects go here
|
287
385
|
Fill_Opacity_State *pf;
|
288
386
|
Stroke_Opacity_State *ps;
|
289
387
|
fprintf(OF, " /ExtGState <<\n");
|
@@ -295,7 +393,8 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
295
393
|
}
|
296
394
|
fprintf(OF, " >>\n"); // end of /ExtGState
|
297
395
|
}
|
298
|
-
if (xobj_list != NULL) {
|
396
|
+
if (xobj_list != NULL) {
|
397
|
+
// Xobjects go here
|
299
398
|
XObject_Info *xo;
|
300
399
|
fprintf(OF, " /XObject <<\n");
|
301
400
|
for (xo = xobj_list; xo != NULL; xo = xo->next) {
|
@@ -303,7 +402,8 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
303
402
|
}
|
304
403
|
fprintf(OF, " >>\n"); // end of /XObject
|
305
404
|
}
|
306
|
-
if (shades_list != NULL) {
|
405
|
+
if (shades_list != NULL) {
|
406
|
+
// Shadings go here
|
307
407
|
Shading_Info *so;
|
308
408
|
fprintf(OF, " /Shading <<\n");
|
309
409
|
for (so = shades_list; so != NULL; so = so->next) {
|
@@ -314,7 +414,8 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
314
414
|
fprintf(OF, " >>\n"); // end of /Resources
|
315
415
|
fprintf(OF, ">> endobj\n");
|
316
416
|
Record_Object_Offset(CATALOG_OBJ);
|
317
|
-
fprintf(OF, "%i 0 obj <<\n/Type /Catalog\n/Pages %i 0 R\n>> endobj\n",
|
417
|
+
fprintf(OF, "%i 0 obj <<\n/Type /Catalog\n/Pages %i 0 R\n>> endobj\n",
|
418
|
+
CATALOG_OBJ, PAGES_OBJ);
|
318
419
|
Write_Font_Dictionaries();
|
319
420
|
Write_Font_Descriptors();
|
320
421
|
Write_Font_Widths();
|
@@ -326,17 +427,21 @@ void Close_pdf(OBJ_PTR fmkr, FM *p, bool quiet_mode, int *ierr)
|
|
326
427
|
if (*ierr != 0) return;
|
327
428
|
Write_Shadings();
|
328
429
|
xref_offset = ftell(OF);
|
329
|
-
fprintf(OF, "xref\n0 %
|
330
|
-
for (i = 1; i < num_objects; i++)
|
331
|
-
|
332
|
-
|
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);
|
333
436
|
fseek(OF, length_offset, SEEK_SET);
|
334
437
|
fprintf(OF, "%li", stream_end - stream_start);
|
335
438
|
fclose(OF);
|
336
439
|
Free_Records(ierr);
|
337
440
|
}
|
338
441
|
|
339
|
-
|
442
|
+
|
443
|
+
void
|
444
|
+
Rename_pdf(char *oldname, char *newname)
|
340
445
|
{
|
341
446
|
char old_ofile[300], new_ofile[300];
|
342
447
|
Get_pdf_name(old_ofile, oldname, 300);
|
@@ -76,18 +76,23 @@
|
|
76
76
|
*/
|
77
77
|
|
78
78
|
|
79
|
-
void
|
79
|
+
void
|
80
|
+
Free_JPG(JPG_Info *xo)
|
80
81
|
{
|
81
82
|
if (xo->filename != NULL) free(xo->filename);
|
82
83
|
}
|
83
84
|
|
84
|
-
|
85
|
+
|
86
|
+
void
|
87
|
+
Free_Sampled(Sampled_Info *xo)
|
85
88
|
{
|
86
89
|
if (xo->image_data != NULL) free(xo->image_data);
|
87
90
|
if (xo->lookup != NULL) free(xo->lookup);
|
88
91
|
}
|
89
92
|
|
90
|
-
|
93
|
+
|
94
|
+
static bool
|
95
|
+
Is_monochrome(int obj_num)
|
91
96
|
{
|
92
97
|
XObject_Info *xo;
|
93
98
|
for (xo = xobj_list; xo != NULL; xo = xo->next) {
|
@@ -99,21 +104,32 @@ static bool Is_monochrome(int obj_num)
|
|
99
104
|
return false;
|
100
105
|
}
|
101
106
|
|
102
|
-
|
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)
|
103
111
|
{
|
104
112
|
FILE *jpg = fopen(filename, "r");
|
105
|
-
if (jpg == NULL) {
|
113
|
+
if (jpg == NULL) {
|
114
|
+
RAISE_ERROR_s("Sorry: cannot open file for showing image (%s)\n",
|
115
|
+
filename, ierr);
|
116
|
+
return;
|
117
|
+
}
|
106
118
|
unsigned char *buff;
|
107
119
|
int len, rd_len;
|
108
120
|
int buff_len = 256000;
|
109
121
|
buff = ALLOC_N_unsigned_char(buff_len);
|
110
122
|
len = 0;
|
111
|
-
while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len)
|
123
|
+
while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len) {
|
124
|
+
len += buff_len;
|
125
|
+
}
|
112
126
|
len += rd_len;
|
113
127
|
fprintf(OF, "\t/Subtype /Image\n");
|
114
128
|
if (mask_obj_num > 0) {
|
115
|
-
if (!Is_monochrome(mask_obj_num))
|
116
|
-
|
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);
|
117
133
|
}
|
118
134
|
fprintf(OF, "\t/Width %i\n", width);
|
119
135
|
fprintf(OF, "\t/Height %i\n", height);
|
@@ -122,23 +138,32 @@ static void Write_Image_From_File(char *filename, int width, int height, char *o
|
|
122
138
|
if (len < buff_len) fwrite(buff, 1, len, OF);
|
123
139
|
else {
|
124
140
|
rewind(jpg);
|
125
|
-
while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len)
|
141
|
+
while ((rd_len = fread(buff, 1, buff_len, jpg)) == buff_len) {
|
142
|
+
fwrite(buff, 1, buff_len, OF);
|
143
|
+
}
|
126
144
|
fwrite(buff, 1, rd_len, OF);
|
127
145
|
}
|
128
146
|
fprintf(OF, "\nendstream\n");
|
129
147
|
fclose(jpg);
|
130
148
|
}
|
131
149
|
|
132
|
-
|
150
|
+
|
151
|
+
void
|
152
|
+
Write_JPG(JPG_Info *xo, int *ierr)
|
133
153
|
{
|
134
154
|
Write_Image_From_File(xo->filename, xo->width, xo->height,
|
135
|
-
|
155
|
+
"\t/Filter /DCTDecode\n\t/ColorSpace "
|
156
|
+
"/DeviceRGB\n\t/BitsPerComponent 8\n",
|
157
|
+
xo->mask_obj_num, ierr);
|
136
158
|
}
|
137
159
|
|
138
|
-
|
160
|
+
|
161
|
+
void
|
162
|
+
Write_Sampled(Sampled_Info *xo, int *ierr)
|
139
163
|
{
|
140
164
|
fprintf(OF, "\n\t/Subtype /Image\n");
|
141
|
-
fprintf(OF, "\t/Filter /FlateDecode\n\t/Interpolate %s\n",
|
165
|
+
fprintf(OF, "\t/Filter /FlateDecode\n\t/Interpolate %s\n",
|
166
|
+
(xo->interpolate)? "true":"false");
|
142
167
|
fprintf(OF, "\t/Height %i\n", xo->height);
|
143
168
|
fprintf(OF, "\t/Width %i\n", xo->width);
|
144
169
|
int i, len;
|
@@ -177,16 +202,22 @@ void Write_Sampled(Sampled_Info *xo, int *ierr)
|
|
177
202
|
}
|
178
203
|
if (xo->mask_obj_num > 0) {
|
179
204
|
if (xo->image_type == MONO_IMAGE) {
|
180
|
-
RAISE_ERROR("Sorry: monochrome images must not have masks", ierr);
|
181
|
-
|
182
|
-
|
205
|
+
RAISE_ERROR("Sorry: monochrome images must not have masks", ierr);
|
206
|
+
return;
|
207
|
+
}
|
208
|
+
if (!Is_monochrome(xo->mask_obj_num))
|
209
|
+
fprintf(OF, "\t/SMask %i 0 R\n", xo->mask_obj_num);
|
210
|
+
else
|
211
|
+
fprintf(OF, "\t/Mask %i 0 R\n", xo->mask_obj_num);
|
183
212
|
}
|
184
|
-
if (xo->value_mask_min >= 0 && xo->value_mask_max >= 0
|
185
|
-
|
213
|
+
if (xo->value_mask_min >= 0 && xo->value_mask_max >= 0
|
214
|
+
&& xo->value_mask_min <= 255 && xo->value_mask_max <= 255
|
215
|
+
&& xo->value_mask_min <= xo->value_mask_max)
|
186
216
|
fprintf(OF, "\t/Mask [%i %i]\n", xo->value_mask_min, xo->value_mask_max);
|
187
217
|
new_len = (xo->length * 11)/10 + 100;
|
188
218
|
buffer = ALLOC_N_unsigned_char(new_len);
|
189
|
-
if (do_flate_compress(buffer, &new_len, xo->image_data, xo->length)
|
219
|
+
if (do_flate_compress(buffer, &new_len, xo->image_data, xo->length)
|
220
|
+
!= FLATE_OK) {
|
190
221
|
free(buffer);
|
191
222
|
RAISE_ERROR("Error compressing image data", ierr);
|
192
223
|
return;
|
@@ -194,25 +225,35 @@ void Write_Sampled(Sampled_Info *xo, int *ierr)
|
|
194
225
|
fprintf(OF, "\t/Length %li\n", new_len);
|
195
226
|
fprintf(OF, "\t>>\nstream\n");
|
196
227
|
if (fwrite(buffer, 1, new_len, OF) < new_len) {
|
197
|
-
RAISE_ERROR("Error writing image data", ierr);
|
228
|
+
RAISE_ERROR("Error writing image data", ierr);
|
229
|
+
return;
|
230
|
+
}
|
198
231
|
free(buffer);
|
199
232
|
fprintf(OF, "\nendstream\nendobj\n");
|
200
233
|
}
|
201
234
|
|
202
|
-
|
203
|
-
|
204
|
-
|
235
|
+
|
236
|
+
// transform maps (0,0), (1,0), and (0,1) to the given points
|
237
|
+
static void
|
238
|
+
Create_Transform_from_Points(double llx, double lly, double lrx, double lry,
|
239
|
+
double ulx, double uly, double *a, double *b,
|
240
|
+
double *c, double *d, double *e, double *f)
|
205
241
|
{
|
206
242
|
*e = llx; *f = lly; lrx -= llx; ulx -= llx; lry -= lly; uly -= lly;
|
207
243
|
*a = lrx; *b = lry; *c = ulx; *d = uly;
|
208
244
|
}
|
209
245
|
|
210
|
-
|
246
|
+
|
247
|
+
static void
|
248
|
+
Get_Image_Dest(FM *p, OBJ_PTR image_destination, double *dest, int *ierr)
|
211
249
|
{
|
212
250
|
int len = Array_Len(image_destination,ierr);
|
213
251
|
if (*ierr != 0) return;
|
214
252
|
if (len != 6) {
|
215
|
-
RAISE_ERROR("Sorry: invalid image destination array:
|
253
|
+
RAISE_ERROR("Sorry: invalid image destination array: "
|
254
|
+
"must have 6 entries", ierr);
|
255
|
+
return;
|
256
|
+
}
|
216
257
|
int i;
|
217
258
|
for (i = 0; i < 6; i++) {
|
218
259
|
OBJ_PTR entry = Array_Entry(image_destination, i, ierr);
|
@@ -225,11 +266,15 @@ static void Get_Image_Dest(FM *p, OBJ_PTR image_destination, double *dest, int *
|
|
225
266
|
}
|
226
267
|
}
|
227
268
|
|
228
|
-
|
269
|
+
|
270
|
+
static void
|
271
|
+
Show_JPEG(FM *p, char *filename, int width, int height, double *dest,
|
272
|
+
int subtype, int mask_obj_num)
|
229
273
|
{
|
230
274
|
JPG_Info *xo = (JPG_Info *)calloc(1,sizeof(JPG_Info));
|
231
275
|
xo->xobj_subtype = subtype;
|
232
|
-
double llx = dest[0], lly = dest[1], lrx = dest[2], lry = dest[3],
|
276
|
+
double llx = dest[0], lly = dest[1], lrx = dest[2], lry = dest[3],
|
277
|
+
ulx = dest[4], uly = dest[5];
|
233
278
|
double a, b, c, d, e, f; // the transform to position the image
|
234
279
|
xo->next = xobj_list;
|
235
280
|
xobj_list = (XObject_Info *)xo;
|
@@ -240,54 +285,79 @@ static void Show_JPEG(FM *p, char *filename, int width, int height, double *dest
|
|
240
285
|
xo->width = width;
|
241
286
|
xo->height = height;
|
242
287
|
xo->mask_obj_num = mask_obj_num;
|
243
|
-
Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
|
244
|
-
|
288
|
+
Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
|
289
|
+
&a, &b, &c, &d, &e, &f);
|
290
|
+
fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
|
291
|
+
a, b, c, d, e, f, xo->xo_num);
|
245
292
|
update_bbox(p, llx, lly);
|
246
293
|
update_bbox(p, lrx, lry);
|
247
294
|
update_bbox(p, ulx, uly);
|
248
295
|
update_bbox(p, lrx+ulx-llx, lry+uly-lly);
|
249
296
|
}
|
250
297
|
|
251
|
-
|
252
|
-
|
298
|
+
|
299
|
+
void
|
300
|
+
c_private_show_jpg(OBJ_PTR fmkr, FM *p, char *filename,
|
301
|
+
int width, int height, OBJ_PTR image_destination,
|
302
|
+
int mask_obj_num, int *ierr)
|
303
|
+
{
|
253
304
|
double dest[6];
|
254
305
|
if (constructing_path) {
|
255
|
-
RAISE_ERROR("Sorry: must finish with current path before
|
306
|
+
RAISE_ERROR("Sorry: must finish with current path before "
|
307
|
+
"calling show_jpg", ierr);
|
308
|
+
return;
|
309
|
+
}
|
256
310
|
Get_Image_Dest(p, image_destination, dest, ierr);
|
257
311
|
if (*ierr != 0) return;
|
258
312
|
Show_JPEG(p, filename, width, height, dest, JPG_SUBTYPE, mask_obj_num);
|
259
313
|
}
|
260
314
|
|
261
|
-
|
262
|
-
|
263
|
-
|
315
|
+
|
316
|
+
OBJ_PTR
|
317
|
+
c_private_create_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR table,
|
318
|
+
int first_row, int last_row, int first_column,
|
319
|
+
int last_column, double min_val, double max_val,
|
320
|
+
int max_code, int if_below_range,
|
321
|
+
int if_above_range, int *ierr)
|
264
322
|
{
|
265
323
|
long num_cols, num_rows;
|
266
324
|
double **data = Table_Data_for_Read(table, &num_cols, &num_rows, ierr);
|
267
325
|
if (*ierr != 0) RETURN_NIL;
|
268
326
|
if (first_column < 0) first_column += num_cols;
|
269
327
|
if (first_column < 0 || first_column >= num_cols)
|
270
|
-
RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
|
328
|
+
RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
|
329
|
+
first_column, ierr);
|
271
330
|
if (last_column < 0) last_column += num_cols;
|
272
331
|
if (last_column < 0 || last_column >= num_cols)
|
273
|
-
RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
|
332
|
+
RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
|
333
|
+
last_column, ierr);
|
274
334
|
if (first_row < 0) first_row += num_rows;
|
275
335
|
if (first_row < 0 || first_row >= num_rows)
|
276
|
-
RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
|
336
|
+
RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
|
337
|
+
first_row, ierr);
|
277
338
|
if (last_row < 0) last_row += num_rows;
|
278
339
|
if (last_row < 0 || last_row >= num_rows)
|
279
|
-
RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
|
340
|
+
RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
|
341
|
+
last_row, ierr);
|
280
342
|
if (min_val >= max_val)
|
281
|
-
RAISE_ERROR_gg("Sorry: invalid range specification: min %g max %g",
|
343
|
+
RAISE_ERROR_gg("Sorry: invalid range specification: min %g max %g",
|
344
|
+
min_val, max_val, ierr);
|
282
345
|
if (max_code <= 0 || max_code > 255)
|
283
|
-
RAISE_ERROR_i("Sorry: invalid max_code specification (%i)",
|
346
|
+
RAISE_ERROR_i("Sorry: invalid max_code specification (%i)",
|
347
|
+
max_code, ierr);
|
284
348
|
if (if_below_range < 0 || if_below_range > 255)
|
285
|
-
RAISE_ERROR_i("Sorry: invalid if_below_range specification (%i)",
|
349
|
+
RAISE_ERROR_i("Sorry: invalid if_below_range specification (%i)",
|
350
|
+
if_below_range, ierr);
|
286
351
|
if (if_above_range < 0 || if_above_range > 255)
|
287
|
-
RAISE_ERROR_i("Sorry: invalid if_above_range specification (%i)",
|
288
|
-
|
352
|
+
RAISE_ERROR_i("Sorry: invalid if_above_range specification (%i)",
|
353
|
+
if_above_range, ierr);
|
354
|
+
int i, j, k;
|
355
|
+
int width = last_column - first_column + 1;
|
356
|
+
int height = last_row - first_row + 1;
|
289
357
|
int sz = width * height;
|
290
|
-
if (sz <= 0)
|
358
|
+
if (sz <= 0)
|
359
|
+
RAISE_ERROR_ii("Sorry: invalid data specification: width (%i) "
|
360
|
+
"height (%i)", width, height, ierr);
|
291
361
|
if (*ierr != 0) RETURN_NIL;
|
292
362
|
char *buff = ALLOC_N_char(sz);
|
293
363
|
for (k = 0, i = first_row; i <= last_row; i++) {
|
@@ -308,30 +378,43 @@ OBJ_PTR c_private_create_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR table,
|
|
308
378
|
}
|
309
379
|
|
310
380
|
|
311
|
-
OBJ_PTR
|
312
|
-
|
313
|
-
|
381
|
+
OBJ_PTR
|
382
|
+
c_private_create_monochrome_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR table,
|
383
|
+
int first_row, int last_row,
|
384
|
+
int first_column, int last_column,
|
385
|
+
double boundary, bool reversed,
|
386
|
+
int *ierr)
|
314
387
|
{
|
315
388
|
long num_cols, num_rows;
|
316
389
|
double **data = Table_Data_for_Read(table, &num_cols, &num_rows, ierr);
|
317
390
|
if (*ierr != 0) RETURN_NIL;
|
318
391
|
if (first_column < 0) first_column += num_cols;
|
319
392
|
if (first_column < 0 || first_column >= num_cols)
|
320
|
-
RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
|
393
|
+
RAISE_ERROR_i("Sorry: invalid first_column specification (%i)",
|
394
|
+
first_column, ierr);
|
321
395
|
if (last_column < 0) last_column += num_cols;
|
322
396
|
if (last_column < 0 || last_column >= num_cols)
|
323
|
-
RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
|
397
|
+
RAISE_ERROR_i("Sorry: invalid last_column specification (%i)",
|
398
|
+
last_column, ierr);
|
324
399
|
if (first_row < 0) first_row += num_rows;
|
325
400
|
if (first_row < 0 || first_row >= num_rows)
|
326
|
-
RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
|
401
|
+
RAISE_ERROR_i("Sorry: invalid first_row specification (%i)",
|
402
|
+
first_row, ierr);
|
327
403
|
if (last_row < 0) last_row += num_rows;
|
328
404
|
if (last_row < 0 || last_row >= num_rows)
|
329
|
-
RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
|
330
|
-
|
405
|
+
RAISE_ERROR_i("Sorry: invalid last_row specification (%i)",
|
406
|
+
last_row, ierr);
|
407
|
+
int i, j, k;
|
408
|
+
int width = last_column - first_column + 1;
|
409
|
+
int height = last_row - first_row + 1;
|
410
|
+
int bytes_per_row = (width+7)/8;
|
331
411
|
int sz = bytes_per_row * 8 * height;
|
332
|
-
if (sz <= 0)
|
412
|
+
if (sz <= 0)
|
413
|
+
RAISE_ERROR_ii("Sorry: invalid data specification: width (%i) "
|
414
|
+
"height (%i)", width, height, ierr);
|
333
415
|
if (*ierr != 0) RETURN_NIL;
|
334
|
-
// to simplify the process, do it in two stages: first get the
|
416
|
+
// to simplify the process, do it in two stages: first get the
|
417
|
+
// values and then pack the bits
|
335
418
|
char *buff = ALLOC_N_char(sz);
|
336
419
|
for (k = 0, i = first_row; i <= last_row; i++) {
|
337
420
|
double *row = data[i];
|
@@ -362,13 +445,21 @@ OBJ_PTR c_private_create_monochrome_image_data(OBJ_PTR fmkr, FM *p, OBJ_PTR tabl
|
|
362
445
|
}
|
363
446
|
|
364
447
|
|
365
|
-
OBJ_PTR
|
366
|
-
|
367
|
-
|
448
|
+
OBJ_PTR
|
449
|
+
c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx,
|
450
|
+
double lly, double lrx, double lry, double ulx,
|
451
|
+
double uly, bool interpolate, bool reversed,
|
452
|
+
int w, int h, unsigned char* data, long len,
|
453
|
+
OBJ_PTR mask_min, OBJ_PTR mask_max, OBJ_PTR hivalue,
|
454
|
+
OBJ_PTR lookup_data, int mask_obj_num, int *ierr)
|
368
455
|
{
|
369
|
-
unsigned char *lookup=NULL;
|
370
|
-
int value_mask_min = 256, value_mask_max = 256, lookup_len=0, hival=0;
|
371
|
-
if (constructing_path) {
|
456
|
+
unsigned char *lookup = NULL;
|
457
|
+
int value_mask_min = 256, value_mask_max = 256, lookup_len = 0, hival = 0;
|
458
|
+
if (constructing_path) {
|
459
|
+
RAISE_ERROR("Sorry: must finish with current path before calling "
|
460
|
+
"show_image", ierr);
|
461
|
+
RETURN_NIL;
|
462
|
+
}
|
372
463
|
if (image_type == COLORMAP_IMAGE) {
|
373
464
|
value_mask_min = Number_to_int(mask_min, ierr);
|
374
465
|
value_mask_max = Number_to_int(mask_max, ierr);
|
@@ -378,17 +469,17 @@ OBJ_PTR c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx, do
|
|
378
469
|
if (*ierr != 0) RETURN_NIL;
|
379
470
|
}
|
380
471
|
|
381
|
-
llx = convert_figure_to_output_x(p,llx);
|
382
|
-
lly = convert_figure_to_output_y(p,lly);
|
383
|
-
lrx = convert_figure_to_output_x(p,lrx);
|
384
|
-
lry = convert_figure_to_output_y(p,lry);
|
385
|
-
ulx = convert_figure_to_output_x(p,ulx);
|
386
|
-
uly = convert_figure_to_output_y(p,uly);
|
387
|
-
|
388
|
-
Sampled_Info *xo = (Sampled_Info *)calloc(1,sizeof(Sampled_Info));
|
472
|
+
llx = convert_figure_to_output_x(p, llx);
|
473
|
+
lly = convert_figure_to_output_y(p, lly);
|
474
|
+
lrx = convert_figure_to_output_x(p, lrx);
|
475
|
+
lry = convert_figure_to_output_y(p, lry);
|
476
|
+
ulx = convert_figure_to_output_x(p, ulx);
|
477
|
+
uly = convert_figure_to_output_y(p, uly);
|
478
|
+
|
479
|
+
Sampled_Info *xo = (Sampled_Info *)calloc(1, sizeof(Sampled_Info));
|
389
480
|
xo->xobj_subtype = SAMPLED_SUBTYPE;
|
390
481
|
double a, b, c, d, e, f; // the transform to position the image
|
391
|
-
int ir, ic, id;
|
482
|
+
//int ir, ic, id;
|
392
483
|
xo->next = xobj_list;
|
393
484
|
xobj_list = (XObject_Info *)xo;
|
394
485
|
xo->xo_num = next_available_xo_number++;
|
@@ -402,7 +493,9 @@ OBJ_PTR c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx, do
|
|
402
493
|
if (image_type != COLORMAP_IMAGE) xo->lookup = NULL;
|
403
494
|
else {
|
404
495
|
if ((hival+1)*3 > lookup_len) {
|
405
|
-
RAISE_ERROR_ii("Sorry: color space hival (%i) is too large for
|
496
|
+
RAISE_ERROR_ii("Sorry: color space hival (%i) is too large for "
|
497
|
+
"length of lookup table (%i)", hival, lookup_len,
|
498
|
+
ierr);
|
406
499
|
RETURN_NIL;
|
407
500
|
}
|
408
501
|
xo->hival = hival;
|
@@ -416,9 +509,13 @@ OBJ_PTR c_private_show_image(OBJ_PTR fmkr, FM *p, int image_type, double llx, do
|
|
416
509
|
xo->value_mask_min = value_mask_min;
|
417
510
|
xo->value_mask_max = value_mask_max;
|
418
511
|
xo->mask_obj_num = mask_obj_num;
|
419
|
-
if (mask_obj_num == -1)
|
420
|
-
|
421
|
-
|
512
|
+
if (mask_obj_num == -1)
|
513
|
+
return Integer_New(xo->obj_num); // this image is being used as
|
514
|
+
// an opacity mask
|
515
|
+
Create_Transform_from_Points(llx, lly, lrx, lry, ulx, uly,
|
516
|
+
&a, &b, &c, &d, &e, &f);
|
517
|
+
fprintf(TF, "q %0.2f %0.2f %0.2f %0.2f %0.2f %0.2f cm /XObj%i Do Q\n",
|
518
|
+
a, b, c, d, e, f, xo->xo_num);
|
422
519
|
update_bbox(p, llx, lly);
|
423
520
|
update_bbox(p, lrx, lry);
|
424
521
|
update_bbox(p, ulx, uly);
|