tioga 1.6 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +35 -10
- data/split/Dvector/dvector.c +264 -22
- data/split/Dvector/lib/Dvector_extras.rb +30 -2
- data/split/Flate/extconf.rb +1 -1
- data/split/Function/function.c +112 -2
- data/split/Tioga/figures.c +76 -77
- data/split/Tioga/figures.h +375 -490
- data/split/Tioga/generic.c +254 -0
- data/split/Tioga/generic.h +236 -0
- data/split/Tioga/init.c +434 -320
- data/split/Tioga/lib/Creating_Paths.rb +11 -1
- data/split/Tioga/lib/FigMkr.rb +263 -65
- data/split/Tioga/lib/Legends.rb +4 -2
- data/split/Tioga/lib/Markers.rb +3 -2
- data/split/Tioga/lib/Special_Paths.rb +22 -23
- data/split/Tioga/lib/TeX_Text.rb +79 -1
- data/split/Tioga/lib/TexPreamble.rb +14 -0
- data/split/Tioga/lib/Utils.rb +5 -1
- data/split/Tioga/pdfs.h +7 -45
- data/split/Tioga/{axes.c → shared/axes.c} +210 -197
- data/split/Tioga/{makers.c → shared/makers.c} +442 -211
- data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
- data/split/Tioga/shared/pdfcolor.c +628 -0
- data/split/Tioga/shared/pdfcoords.c +443 -0
- data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
- data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
- data/split/Tioga/shared/pdfpath.c +766 -0
- data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
- data/split/Tioga/shared/texout.c +524 -0
- data/split/Tioga/wrappers.c +489 -0
- data/split/Tioga/wrappers.h +259 -0
- data/split/extconf.rb +4 -0
- data/split/mkmf2.rb +12 -1
- data/tests/benchmark_dvector_reads.rb +112 -0
- data/tests/tc_Dvector.rb +35 -3
- data/tests/tc_Function.rb +32 -0
- metadata +65 -52
- data/split/Tioga/pdfcolor.c +0 -486
- data/split/Tioga/pdfcoords.c +0 -523
- data/split/Tioga/pdfpath.c +0 -913
- data/split/Tioga/texout.c +0 -380
@@ -26,7 +26,7 @@ void Init_Font_Dictionary(void) {
|
|
26
26
|
int i, num_fonts = num_pdf_standard_fonts;
|
27
27
|
Font_Dictionary *font_info;
|
28
28
|
for (i = 0; i < num_fonts; i++) {
|
29
|
-
font_info =
|
29
|
+
font_info = (Font_Dictionary *)calloc(1,sizeof(Font_Dictionary));
|
30
30
|
font_info->afm = &afm_array[i];
|
31
31
|
font_info->font_num = font_info->afm->font_num;
|
32
32
|
font_info->in_use = false;
|
@@ -104,7 +104,7 @@ static void Record_Font_In_Use(Font_Dictionary *font_info, int font_number)
|
|
104
104
|
|
105
105
|
#define DEBUG 0
|
106
106
|
#define MAXSTR 100
|
107
|
-
static Font_Dictionary *GetFontDict(char *font_name, int font_number) {
|
107
|
+
static Font_Dictionary *GetFontDict(char *font_name, int font_number, int *ierr) {
|
108
108
|
Font_Dictionary *font_info;
|
109
109
|
for (font_info = font_dictionaries; font_info != NULL; font_info = font_info->next) {
|
110
110
|
if (strcmp(font_name, font_info->afm->font_name) == 0) {
|
@@ -112,23 +112,22 @@ static Font_Dictionary *GetFontDict(char *font_name, int font_number) {
|
|
112
112
|
return font_info;
|
113
113
|
}
|
114
114
|
}
|
115
|
-
|
115
|
+
RAISE_ERROR_s("Sorry: invalid font name (%s)", font_name, ierr);
|
116
116
|
return NULL;
|
117
117
|
}
|
118
118
|
|
119
|
-
static Font_Dictionary *GetFontInfo(int font_number)
|
119
|
+
static Font_Dictionary *GetFontInfo(int font_number, int *ierr)
|
120
120
|
{
|
121
121
|
Font_Dictionary *f;
|
122
122
|
for (f = font_dictionaries; f != NULL; f = f->next) {
|
123
123
|
if (f->font_num == font_number) { Record_Font_In_Use(f, font_number); return f; }
|
124
124
|
}
|
125
125
|
if (font_number > 0 && font_number <= num_predefined_fonts)
|
126
|
-
return GetFontDict(predefined_Fonts[font_number], font_number);
|
126
|
+
return GetFontDict(predefined_Fonts[font_number], font_number, ierr);
|
127
127
|
return NULL;
|
128
128
|
}
|
129
129
|
|
130
|
-
|
131
|
-
{
|
130
|
+
OBJ_PTR c_register_font(OBJ_PTR fmkr, FM *p, char *font_name, int *ierr) {
|
132
131
|
Font_Dictionary *f;
|
133
132
|
int i;
|
134
133
|
for (f = font_dictionaries; f != NULL; f = f->next) {
|
@@ -136,22 +135,17 @@ static int c_register_font(char *font_name)
|
|
136
135
|
}
|
137
136
|
for (i = 1; i <= num_predefined_fonts; i++) {
|
138
137
|
if (strcmp(predefined_Fonts[i], font_name)==0) {
|
139
|
-
f = GetFontDict(font_name, i);
|
140
|
-
if (f == NULL)
|
138
|
+
f = GetFontDict(font_name, i, ierr);
|
139
|
+
if (f == NULL) RAISE_ERROR_s("Error in reading font metrics for %s", font_name, ierr);
|
141
140
|
return i;
|
142
141
|
}
|
143
142
|
}
|
144
|
-
f = GetFontDict(font_name, next_available_font_number);
|
145
|
-
if (f == NULL)
|
146
|
-
|
143
|
+
f = GetFontDict(font_name, next_available_font_number, ierr);
|
144
|
+
if (f == NULL) RAISE_ERROR_s("Error in reading font metrics for %s", font_name, ierr);
|
145
|
+
next_available_font_number++;
|
146
|
+
return Integer_New(next_available_font_number);
|
147
147
|
}
|
148
148
|
|
149
|
-
VALUE FM_register_font(VALUE fmkr, VALUE font_name)
|
150
|
-
{
|
151
|
-
font_name = rb_String(font_name);
|
152
|
-
int font_num = c_register_font(RSTRING_PTR(font_name));
|
153
|
-
return INT2FIX(font_num);
|
154
|
-
}
|
155
149
|
|
156
150
|
bool Used_Any_Fonts(void)
|
157
151
|
{
|
@@ -221,10 +215,11 @@ void Write_Font_Dictionaries(void)
|
|
221
215
|
}
|
222
216
|
|
223
217
|
static void GetStringInfo(FM *p, int font_number, unsigned char *text, double ft_ht,
|
224
|
-
double *llx_ptr, double *lly_ptr, double *urx_ptr, double *ury_ptr, double *width_ptr) {
|
225
|
-
Font_Dictionary *fontinfo = GetFontInfo(font_number);
|
226
|
-
if (
|
227
|
-
|
218
|
+
double *llx_ptr, double *lly_ptr, double *urx_ptr, double *ury_ptr, double *width_ptr, int *ierr) {
|
219
|
+
Font_Dictionary *fontinfo = GetFontInfo(font_number, ierr);
|
220
|
+
if (*ierr != 0) return;
|
221
|
+
if (fontinfo == NULL) {
|
222
|
+
RAISE_ERROR_i("Sorry: invalid font number (%i): must register font before use it.", font_number, ierr); return; }
|
228
223
|
unsigned char *c_ptr = text, c;
|
229
224
|
double width = 0, llx, lly, urx, ury;
|
230
225
|
if (fontinfo == NULL || text == NULL || text[0] == '\0') {
|
@@ -242,52 +237,50 @@ static void GetStringInfo(FM *p, int font_number, unsigned char *text, double ft
|
|
242
237
|
}
|
243
238
|
urx = llx + width;
|
244
239
|
*width_ptr = width * ft_ht * 1e-3;
|
245
|
-
*llx_ptr =
|
246
|
-
*lly_ptr =
|
247
|
-
*
|
248
|
-
*
|
240
|
+
*llx_ptr = ft_ht * 1e-3 * llx;
|
241
|
+
*lly_ptr = ft_ht * 1e-3 * lly;
|
242
|
+
*ury_ptr = ft_ht * 1e-3 * ury;
|
243
|
+
*urx_ptr = ft_ht * 1e-3 * (urx-70.0); // adjust for extra white space on right
|
249
244
|
}
|
250
245
|
|
251
|
-
|
252
|
-
|
253
|
-
FM *p = Get_FM(fmkr);
|
254
|
-
font_number = rb_Integer(font_number);
|
255
|
-
string = rb_String(string);
|
256
|
-
unsigned char *text = (unsigned char *)(RSTRING_PTR(string));
|
257
|
-
scale = rb_Float(scale);
|
258
|
-
double ft_ht = p->default_text_scale * NUM2DBL(scale) * p->default_font_size * ENLARGE;
|
246
|
+
OBJ_PTR c_marker_string_info(OBJ_PTR fmkr, FM *p, int fnt, unsigned char *text, double scale, int *ierr) {
|
247
|
+
double ft_ht = p->default_text_scale * scale * p->default_font_size * ENLARGE;
|
259
248
|
int ft_height = ROUND(ft_ht);
|
260
249
|
ft_ht = ft_height;
|
261
250
|
double llx, lly, urx, ury, width;
|
262
|
-
|
263
|
-
|
264
|
-
|
251
|
+
GetStringInfo(p, fnt, text, ft_ht, &llx, &lly, &urx, &ury, &width, ierr);
|
252
|
+
if (*ierr != 0) RETURN_NIL;
|
253
|
+
OBJ_PTR result = Array_New(5);
|
265
254
|
width = convert_output_to_figure_dx(p,width);
|
266
255
|
llx = convert_output_to_figure_dx(p,llx);
|
267
256
|
urx = convert_output_to_figure_dx(p,urx);
|
268
257
|
lly = convert_output_to_figure_dy(p,lly);
|
269
258
|
ury = convert_output_to_figure_dy(p,ury);
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
259
|
+
Array_Store(result, 0, Float_New(width), ierr);
|
260
|
+
Array_Store(result, 1, Float_New(llx), ierr);
|
261
|
+
Array_Store(result, 2, Float_New(lly), ierr);
|
262
|
+
Array_Store(result, 3, Float_New(urx), ierr);
|
263
|
+
Array_Store(result, 4, Float_New(ury), ierr);
|
264
|
+
|
275
265
|
return result;
|
276
266
|
}
|
277
267
|
|
278
268
|
#define TRANSFORM_VEC(dx,dy) tmp = dx; dx = (dx) * a + (dy) * c; dy = tmp * b + (dy) * d;
|
279
269
|
|
280
|
-
void c_rotated_string_at_points(
|
281
|
-
|
282
|
-
double
|
270
|
+
static void c_rotated_string_at_points(
|
271
|
+
OBJ_PTR fmkr, FM *p, double rotation, int font_number, unsigned char *text, double scale,
|
272
|
+
int n, double *xs, double *ys, int alignment, int just,
|
273
|
+
double horizontal_scaling, double vertical_scaling,
|
274
|
+
double italic_angle, double ascent_angle, int *ierr)
|
283
275
|
{
|
284
276
|
double ft_ht = p->default_text_scale * scale * p->default_font_size * ENLARGE;
|
285
|
-
int i, ft_height = ROUND(ft_ht);
|
277
|
+
int i, ft_height = ROUND(ft_ht), justification = just-1;
|
286
278
|
ft_ht = ft_height;
|
287
|
-
if (constructing_path)
|
279
|
+
if (constructing_path) { RAISE_ERROR("Sorry: must not be constructing a path when show marker", ierr); return; }
|
288
280
|
double llx, lly, urx, ury, width, shiftx, shifty, tmp;
|
289
281
|
double a=horizontal_scaling, b=0.0, c=0.0, d=vertical_scaling; // the initial transform
|
290
|
-
GetStringInfo(p, font_number, text, ft_ht, &llx, &lly, &urx, &ury, &width);
|
282
|
+
GetStringInfo(p, font_number, text, ft_ht, &llx, &lly, &urx, &ury, &width, ierr);
|
283
|
+
if (*ierr != 0) return;
|
291
284
|
// translate according to justification and alignment
|
292
285
|
// note that we use the bbox to calculate shifts so 'center' means center of bbox
|
293
286
|
if (italic_angle != 0) {
|
@@ -315,14 +308,18 @@ void c_rotated_string_at_points(FM *p, double rotation, int font_number, unsigne
|
|
315
308
|
shiftx *= 0.9;
|
316
309
|
}
|
317
310
|
break;
|
318
|
-
default:
|
311
|
+
default:
|
312
|
+
RAISE_ERROR_i("Sorry: invalid setting for marker justification (%i)", justification, ierr);
|
313
|
+
return;
|
319
314
|
}
|
320
315
|
switch (alignment) {
|
321
316
|
case ALIGNED_AT_TOP: shifty = -ury; break;
|
322
317
|
case ALIGNED_AT_MIDHEIGHT: shifty = -(ury+lly)/2; break;
|
323
318
|
case ALIGNED_AT_BASELINE: shifty = 0; break;
|
324
319
|
case ALIGNED_AT_BOTTOM: shifty = -lly; break;
|
325
|
-
default:
|
320
|
+
default:
|
321
|
+
RAISE_ERROR_i("Sorry: invalid setting for marker alignment (%i)", alignment, ierr);
|
322
|
+
return;
|
326
323
|
}
|
327
324
|
// transform the bbox
|
328
325
|
double llx2 = llx, lly2 = lly, urx2 = urx, ury2 = ury; // if we're rotated we'll need all 4 corners of bbox
|
@@ -350,12 +347,14 @@ void c_rotated_string_at_points(FM *p, double rotation, int font_number, unsigne
|
|
350
347
|
update_bbox(p,x+llx2, y+ury2);
|
351
348
|
update_bbox(p,x+urx2, y+lly2);
|
352
349
|
dx = x - prev_x; dy = y - prev_y;
|
353
|
-
idx = ROUND(dx); idy = ROUND(dy);
|
354
|
-
prev_x = prev_x + idx; prev_y = prev_y + idy;
|
350
|
+
//idx = ROUND(dx); idy = ROUND(dy);
|
351
|
+
//prev_x = prev_x + idx; prev_y = prev_y + idy;
|
352
|
+
prev_x = prev_x + dx; prev_y = prev_y + dy;
|
355
353
|
if (b == 0 && c == 0 && a == 1 && d == 1) {
|
356
|
-
fprintf(TF, "%i %i Td (", idx, idy);
|
354
|
+
//fprintf(TF, "%i %i Td (", idx, idy);
|
355
|
+
fprintf(TF, "%0.6f %0.6f Td (", dx, dy);
|
357
356
|
} else { // need high precision when doing rotations
|
358
|
-
fprintf(TF, "%0.6f %0.6f %0.6f %0.6f %0.6f %0.6f Tm (", a, b, c, d,
|
357
|
+
fprintf(TF, "%0.6f %0.6f %0.6f %0.6f %0.6f %0.6f Tm (", a, b, c, d, x, y);
|
359
358
|
}
|
360
359
|
while ((char_code = *cp++) != '\0') {
|
361
360
|
if (char_code == '\\')
|
@@ -370,71 +369,94 @@ void c_rotated_string_at_points(FM *p, double rotation, int font_number, unsigne
|
|
370
369
|
fprintf(TF, "ET\n");
|
371
370
|
}
|
372
371
|
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
{
|
378
|
-
|
379
|
-
int int_args, c, alignment, justification, fnt_num, n, mode;
|
372
|
+
void c_private_show_marker(
|
373
|
+
OBJ_PTR fmkr, FM *p, int int_args, OBJ_PTR stroke_width, OBJ_PTR string,
|
374
|
+
OBJ_PTR x, OBJ_PTR y, OBJ_PTR x_vec, OBJ_PTR y_vec,
|
375
|
+
double h_scale, double v_scale, double scale, double it_angle, double ascent_angle, double angle,
|
376
|
+
OBJ_PTR fill_color, OBJ_PTR stroke_color, int *ierr) {
|
377
|
+
int c, alignment, justification, fnt_num, n, mode;
|
380
378
|
unsigned char *text = NULL, buff[2];
|
381
379
|
double *xs, *ys, xloc, yloc, prev_line_width = -1;
|
382
380
|
bool restore_fill_color = false, restore_stroke_color = false;
|
383
|
-
|
384
|
-
|
385
|
-
|
381
|
+
double stroke_color_R=0.0, stroke_color_G=0.0, stroke_color_B=0.0;
|
382
|
+
double prev_stroke_color_R, prev_stroke_color_G, prev_stroke_color_B;
|
383
|
+
double fill_color_R=0.0, fill_color_G=0.0, fill_color_B=0.0;
|
384
|
+
double prev_fill_color_R, prev_fill_color_G, prev_fill_color_B;
|
386
385
|
c = int_args / 100000; int_args -= c * 100000;
|
387
386
|
fnt_num = int_args / 1000; int_args -= fnt_num * 1000;
|
388
387
|
mode = int_args / 100; int_args -= mode * 100;
|
389
388
|
alignment = int_args / 10; int_args -= alignment * 10;
|
390
389
|
justification = int_args;
|
391
|
-
if (string ==
|
392
|
-
if (c < 0 || c > 255)
|
393
|
-
|
390
|
+
if (string == OBJ_NIL) {
|
391
|
+
if (c < 0 || c > 255) {
|
392
|
+
RAISE_ERROR_i("Sorry: invalid character code (%i) : must be between 0 and 255", c, ierr);
|
393
|
+
return;
|
394
|
+
}
|
394
395
|
text = buff; text[0] = c; text[1] = '\0';
|
395
|
-
if (stroke_width !=
|
396
|
-
|
397
|
-
|
396
|
+
if (stroke_width != OBJ_NIL) {
|
397
|
+
double width = Number_to_double(stroke_width, ierr);
|
398
|
+
if (*ierr != 0) return;
|
398
399
|
prev_line_width = p->line_width; // restore it later
|
399
400
|
fprintf(TF, "%0.6f w\n", width * ENLARGE);
|
400
401
|
}
|
401
402
|
} else {
|
402
|
-
|
403
|
-
|
403
|
+
text = (unsigned char *)(String_Ptr(string,ierr));
|
404
|
+
if (*ierr != 0) return;
|
404
405
|
}
|
405
406
|
fprintf(TF, "%d Tr\n", mode);
|
406
|
-
if (stroke_color !=
|
407
|
-
(mode == STROKE || mode == FILL_AND_STROKE ||
|
408
|
-
|
409
|
-
|
407
|
+
if (stroke_color != OBJ_NIL &&
|
408
|
+
(mode == STROKE || mode == FILL_AND_STROKE ||
|
409
|
+
mode == STROKE_AND_CLIP || mode == FILL_STROKE_AND_CLIP)) {
|
410
|
+
Unpack_RGB(stroke_color, &stroke_color_R, &stroke_color_G, &stroke_color_B, ierr);
|
411
|
+
if (*ierr != 0) return;
|
412
|
+
if (stroke_color_R != p->stroke_color_R ||
|
413
|
+
stroke_color_G != p->stroke_color_G ||
|
414
|
+
stroke_color_B != p->stroke_color_B) {
|
415
|
+
prev_stroke_color_R = p->stroke_color_R;
|
416
|
+
prev_stroke_color_G = p->stroke_color_G;
|
417
|
+
prev_stroke_color_B = p->stroke_color_B;
|
418
|
+
restore_stroke_color = true;
|
419
|
+
c_stroke_color_set_RGB(fmkr, p, stroke_color_R, stroke_color_G, stroke_color_B, ierr);
|
420
|
+
if (*ierr != 0) return;
|
421
|
+
}
|
410
422
|
}
|
411
|
-
if (fill_color !=
|
412
|
-
(mode == FILL || mode == FILL_AND_STROKE ||
|
413
|
-
|
414
|
-
|
423
|
+
if (fill_color != OBJ_NIL &&
|
424
|
+
(mode == FILL || mode == FILL_AND_STROKE ||
|
425
|
+
mode == FILL_AND_CLIP || mode == FILL_STROKE_AND_CLIP)) {
|
426
|
+
Unpack_RGB(fill_color, &fill_color_R, &fill_color_G, &fill_color_B, ierr);
|
427
|
+
if (*ierr != 0) return;
|
428
|
+
if (fill_color_R != p->fill_color_R ||
|
429
|
+
fill_color_G != p->fill_color_G ||
|
430
|
+
fill_color_B != p->fill_color_B) {
|
431
|
+
prev_fill_color_R = p->fill_color_R;
|
432
|
+
prev_fill_color_G = p->fill_color_G;
|
433
|
+
prev_fill_color_B = p->fill_color_B;
|
434
|
+
restore_fill_color = true;
|
435
|
+
c_fill_color_set_RGB(fmkr, p, fill_color_R, fill_color_G, fill_color_B, ierr);
|
436
|
+
if (*ierr != 0) return;
|
437
|
+
}
|
415
438
|
}
|
416
|
-
|
417
|
-
v_scale = rb_Float(v_scale);
|
418
|
-
scale = rb_Float(scale);
|
419
|
-
it_angle = rb_Float(it_angle);
|
420
|
-
ascent_angle = rb_Float(ascent_angle);
|
421
|
-
angle = rb_Float(angle);
|
422
|
-
if (x == Qnil) {
|
439
|
+
if (x == OBJ_NIL) {
|
423
440
|
long xlen, ylen;
|
424
|
-
xs =
|
425
|
-
|
426
|
-
|
427
|
-
if (
|
441
|
+
xs = Vector_Data_for_Read(x_vec, &xlen, ierr);
|
442
|
+
if (*ierr != 0) return;
|
443
|
+
ys = Vector_Data_for_Read(y_vec, &ylen, ierr);
|
444
|
+
if (*ierr != 0) return;
|
445
|
+
if (xlen != ylen) {
|
446
|
+
RAISE_ERROR("Sorry: must have same number xs and ys for showing markers", ierr); return; }
|
447
|
+
if (xlen <= 0) return;
|
428
448
|
n = xlen;
|
429
449
|
} else {
|
430
|
-
|
431
|
-
|
450
|
+
xloc = Number_to_double(x, ierr); xs = &xloc;
|
451
|
+
yloc = Number_to_double(y, ierr); ys = &yloc;
|
452
|
+
if (*ierr != 0) return;
|
432
453
|
n = 1;
|
433
454
|
}
|
434
|
-
c_rotated_string_at_points(p,
|
435
|
-
alignment, justification,
|
436
|
-
if (prev_line_width >= 0) c_line_width_set(p, prev_line_width);
|
437
|
-
if (restore_fill_color)
|
438
|
-
|
439
|
-
|
455
|
+
c_rotated_string_at_points(fmkr, p, angle, fnt_num, text, scale, n, xs, ys,
|
456
|
+
alignment, justification, h_scale, v_scale, it_angle, ascent_angle, ierr);
|
457
|
+
if (prev_line_width >= 0) c_line_width_set(fmkr, p, prev_line_width, ierr);
|
458
|
+
if (restore_fill_color)
|
459
|
+
c_fill_color_set_RGB(fmkr, p, prev_fill_color_R, prev_fill_color_G, prev_fill_color_B, ierr);
|
460
|
+
if (restore_stroke_color)
|
461
|
+
c_stroke_color_set_RGB(fmkr, p, prev_stroke_color_R, prev_stroke_color_G, prev_stroke_color_B, ierr);
|
440
462
|
}
|
@@ -0,0 +1,524 @@
|
|
1
|
+
/* texout.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
|
+
|
24
|
+
#define RADIANS_TO_DEGREES (180.0 / PI)
|
25
|
+
|
26
|
+
static FILE *fp; // for the TeX file
|
27
|
+
|
28
|
+
/* TeX text */
|
29
|
+
|
30
|
+
void c_rescale_text(OBJ_PTR fmkr, FM *p, double scaling_factor, int *ierr) {
|
31
|
+
double scale = scaling_factor * p->default_text_scale;
|
32
|
+
if (scaling_factor <= 0) { RAISE_ERROR("Sorry: text scaling must be positive", ierr); return; }
|
33
|
+
p->default_text_height_dx *= scaling_factor;
|
34
|
+
p->default_text_height_dy *= scaling_factor;
|
35
|
+
p->default_text_scale = scale;
|
36
|
+
}
|
37
|
+
|
38
|
+
static int String_Is_Blank(char *str) {
|
39
|
+
char c;
|
40
|
+
if (str == NULL) return 1;
|
41
|
+
while (1) {
|
42
|
+
c = *str++;
|
43
|
+
if (c == '\0') return 1;
|
44
|
+
if (!isspace(c)) break;
|
45
|
+
}
|
46
|
+
return 0;
|
47
|
+
}
|
48
|
+
|
49
|
+
static OBJ_PTR Get_Measure_Hash(OBJ_PTR fmkr, OBJ_PTR measure_name)
|
50
|
+
{
|
51
|
+
OBJ_PTR value;
|
52
|
+
int i;
|
53
|
+
OBJ_PTR measures_info = Obj_Attr_Get(fmkr, measures_info_ID, &i);
|
54
|
+
if(measure_name == OBJ_NIL) {
|
55
|
+
return OBJ_NIL;
|
56
|
+
}
|
57
|
+
if(! Hash_Has_Key_Obj(measures_info, measure_name)) {
|
58
|
+
value = Hash_New();
|
59
|
+
Hash_Set_Obj_Obj(measures_info, measure_name, value);
|
60
|
+
}
|
61
|
+
else
|
62
|
+
value = Hash_Get_Obj_Obj(measures_info, measure_name);
|
63
|
+
return value;
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
static void tex_show_rotated_text(OBJ_PTR fmkr, FM *p, char *text,
|
68
|
+
double x, double y, double scale,
|
69
|
+
double angle, int justification,
|
70
|
+
int alignment, OBJ_PTR measure_name)
|
71
|
+
{ // x and y are the device coords for the reference point of the text
|
72
|
+
char ref, jst;
|
73
|
+
double ft_ht, sz;
|
74
|
+
int dummy;
|
75
|
+
OBJ_PTR measures = Get_Measure_Hash(fmkr, measure_name);
|
76
|
+
if (String_Is_Blank(text)) return; /* blank strings break TeX! */
|
77
|
+
scale *= p->default_text_scale;
|
78
|
+
ft_ht = scale * p->default_font_size;
|
79
|
+
sz = ft_ht * ENLARGE;
|
80
|
+
ref = (alignment == ALIGNED_AT_BASELINE)? 'B' :
|
81
|
+
(alignment == ALIGNED_AT_BOTTOM)? 'b' :
|
82
|
+
(alignment == ALIGNED_AT_TOP)? 't' : 'c';
|
83
|
+
if (justification == 0) jst = 'c';
|
84
|
+
else if (justification > 0) jst = 'r';
|
85
|
+
else jst = 'l';
|
86
|
+
bbox_llx = MIN(bbox_llx, x - sz);
|
87
|
+
bbox_lly = MIN(bbox_lly, y - sz);
|
88
|
+
bbox_urx = MAX(bbox_urx, x + sz);
|
89
|
+
bbox_ury = MAX(bbox_ury, y + sz);
|
90
|
+
if (angle != 0.0)
|
91
|
+
fprintf(fp,"\\put(%d,%d){\\rotatebox{%.1f}{\\scalebox{%.2f}{\\makebox(0,0)[%c%c]{",
|
92
|
+
ROUND(x), ROUND(y), angle, scale, jst, ref);
|
93
|
+
else
|
94
|
+
fprintf(fp,"\\put(%d,%d){\\scalebox{%.2f}{\\makebox(0,0)[%c%c]{",
|
95
|
+
ROUND(x), ROUND(y), scale, jst, ref);
|
96
|
+
if(measure_name != OBJ_NIL)
|
97
|
+
fprintf(fp, "{\\tiogameasure{%s}{\\tiogasetfont{}",
|
98
|
+
CString_Ptr(measure_name,&dummy));
|
99
|
+
else
|
100
|
+
fprintf(fp, "{{\\tiogasetfont{}");
|
101
|
+
|
102
|
+
/* Moving the \BS out of the potential \tiogameasure input, so it does
|
103
|
+
not disturb the measure.
|
104
|
+
*/
|
105
|
+
fprintf(fp, (alignment == ALIGNED_AT_BASELINE)? "%s}\\BS" : "%s}", text);
|
106
|
+
fprintf(fp, angle != 0? "}}}}}\n" : "}}}}\n");
|
107
|
+
|
108
|
+
/* Now, we save measures informations if applicable*/
|
109
|
+
if(measures != OBJ_NIL) {
|
110
|
+
Hash_Set_Double(measures, "scale", scale);
|
111
|
+
/* [xy]anchor are saved in postscript points */
|
112
|
+
Hash_Set_Double(measures, "xanchor", ROUND(x) / ENLARGE);
|
113
|
+
Hash_Set_Double(measures, "yanchor", ROUND(y) / ENLARGE);
|
114
|
+
Hash_Set_Double(measures, "angle", angle);
|
115
|
+
Hash_Set_Double(measures, "just", justification);
|
116
|
+
Hash_Set_Double(measures, "align", alignment);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
static void Convert_Frame_Text_Position_To_Output_Location(FM *p, int frame_side, double offset,
|
121
|
+
double fraction, double *xp, double *yp, double *base_angle, char *text, int *ierr)
|
122
|
+
{
|
123
|
+
double page_x, page_y;
|
124
|
+
switch (frame_side) {
|
125
|
+
case LEFT:
|
126
|
+
page_x = p->page_width * p->frame_left - offset;
|
127
|
+
page_y = p->page_height * (p->frame_bottom + fraction * p->frame_height);
|
128
|
+
*base_angle = 90;
|
129
|
+
break;
|
130
|
+
case RIGHT:
|
131
|
+
page_x = p->page_width * p->frame_right + offset;
|
132
|
+
page_y = p->page_height * (p->frame_bottom + fraction * p->frame_height);
|
133
|
+
*base_angle = 90;
|
134
|
+
break;
|
135
|
+
case AT_X_ORIGIN:
|
136
|
+
if (0.0 > p->bounds_xmax || 0.0 < p->bounds_xmin) {
|
137
|
+
RAISE_ERROR_s("Sorry: x origin is not part of plot for (%s)", text, ierr); return; }
|
138
|
+
page_x = convert_figure_to_output_x(p, 0.0);
|
139
|
+
if (p->xaxis_reversed) offset = -offset;
|
140
|
+
page_x += offset;
|
141
|
+
page_y = p->page_height * (p->frame_bottom + fraction * p->frame_height);
|
142
|
+
*base_angle = 90;
|
143
|
+
break;
|
144
|
+
case TOP:
|
145
|
+
page_y = p->page_height * p->frame_top + offset;
|
146
|
+
page_x = p->page_width * (p->frame_left + fraction * p->frame_width);
|
147
|
+
*base_angle = 0;
|
148
|
+
break;
|
149
|
+
case BOTTOM:
|
150
|
+
page_y = p->page_height * p->frame_bottom - offset;
|
151
|
+
page_x = p->page_width * (p->frame_left + fraction * p->frame_width);
|
152
|
+
*base_angle = 0;
|
153
|
+
break;
|
154
|
+
case AT_Y_ORIGIN:
|
155
|
+
if (0.0 > p->bounds_ymax || 0.0 < p->bounds_ymin) {
|
156
|
+
RAISE_ERROR_s("Sorry: y origin is not part of plot for (%s)", text, ierr); return; }
|
157
|
+
page_y = convert_figure_to_output_y(p, 0.0);
|
158
|
+
if (p->yaxis_reversed) offset = -offset;
|
159
|
+
page_y += offset;
|
160
|
+
page_x = p->page_width * (p->frame_left + fraction * p->frame_width);
|
161
|
+
*base_angle = 0;
|
162
|
+
break;
|
163
|
+
default:
|
164
|
+
RAISE_ERROR_s("Sorry: invalid parameter for frame side in show text (%s)", text, ierr);
|
165
|
+
return;
|
166
|
+
}
|
167
|
+
*xp = p->page_left + page_x; *yp = p->page_bottom + page_y;
|
168
|
+
}
|
169
|
+
|
170
|
+
void c_show_rotated_text(OBJ_PTR fmkr, FM *p, char *text, int frame_side, double shift, double fraction,
|
171
|
+
double scale, double angle, int justification, int alignment, OBJ_PTR measure_name, int *ierr) {
|
172
|
+
double x, y, base_angle, ft_ht = p->default_text_scale * scale * p->default_font_size;
|
173
|
+
Convert_Frame_Text_Position_To_Output_Location(p, frame_side, shift*ft_ht*ENLARGE, fraction, &x, &y, &base_angle, text, ierr);
|
174
|
+
tex_show_rotated_text(fmkr, p, text, x, y, scale, angle + base_angle, justification, alignment, measure_name);
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
void c_show_rotated_label(OBJ_PTR fmkr, FM *p, char *text,
|
179
|
+
double xloc, double yloc, double scale, double angle, int justification, int alignment, OBJ_PTR measure_name, int *ierr) {
|
180
|
+
tex_show_rotated_text(fmkr, p, text, convert_figure_to_output_x(p, xloc), convert_figure_to_output_y(p, yloc),
|
181
|
+
scale, angle, justification, alignment, measure_name);
|
182
|
+
}
|
183
|
+
|
184
|
+
OBJ_PTR c_check_label_clip(OBJ_PTR fmkr, FM *p, double x, double y, int *ierr) {
|
185
|
+
x = convert_figure_to_frame_x(p,x);
|
186
|
+
y = convert_figure_to_frame_y(p,y);
|
187
|
+
if (x < p->label_left_margin || y < p->label_bottom_margin ||
|
188
|
+
1.0 - x < p->label_right_margin || 1.0 - y < p->label_top_margin) RETURN_FALSE;
|
189
|
+
RETURN_TRUE;
|
190
|
+
}
|
191
|
+
|
192
|
+
/* TeX File Management */
|
193
|
+
|
194
|
+
static long cur_pos;
|
195
|
+
|
196
|
+
static void Get_tex_name(char *ofile, char *filename, int maxlen)
|
197
|
+
{
|
198
|
+
char *dot;
|
199
|
+
strncpy(ofile, filename, maxlen);
|
200
|
+
dot = strrchr(ofile,'.');
|
201
|
+
if (dot != NULL) dot[0] = '\0';
|
202
|
+
strcat(ofile, "_figure.txt");
|
203
|
+
}
|
204
|
+
|
205
|
+
void Open_tex(OBJ_PTR fmkr, char *filename, bool quiet_mode, int *ierr)
|
206
|
+
{
|
207
|
+
char ofile[300];
|
208
|
+
Get_tex_name(ofile, filename, 300);
|
209
|
+
fp = fopen(ofile, "w");
|
210
|
+
fprintf(fp,"\\setlength{\\unitlength}{%fbp}%%\n", 1.0/ENLARGE);
|
211
|
+
cur_pos = ftell(fp);
|
212
|
+
fprintf(fp,"\\begin{picture}(xxxxxx,xxxxxx) %% (width,height)(xoffset,yoffset) -- Adjust the 2nd pair for registration adjustments\n"); /* this line is rewritten at the end */
|
213
|
+
fprintf(fp,"\\def\\BS{\\phantom{\\Huge\\scalebox{0}[2]{\\hbox{\\rotatebox{180}{O}O}}}}\n");
|
214
|
+
// graphicx seems to vertically align baseline (B) like center (c),
|
215
|
+
// so we add BS (Big Strut) to make them look the same
|
216
|
+
}
|
217
|
+
|
218
|
+
void Close_tex(OBJ_PTR fmkr, bool quiet_mode, int *ierr)
|
219
|
+
{
|
220
|
+
double x, y, xoff, yoff;
|
221
|
+
x = bbox_urx - bbox_llx; if (x < 0) x = bbox_urx = bbox_llx = 0;
|
222
|
+
y = bbox_ury - bbox_lly; if (y < 0) y = bbox_ury = bbox_lly = 0;
|
223
|
+
xoff = bbox_llx + Get_tex_xoffset(fmkr,ierr)*ENLARGE;
|
224
|
+
yoff = bbox_lly + Get_tex_yoffset(fmkr,ierr)*ENLARGE;
|
225
|
+
fprintf(fp,"\\end{picture}");
|
226
|
+
fseek(fp, cur_pos, SEEK_SET);
|
227
|
+
fprintf(fp,"\\begin{picture}(%03d,%03d)(%02d,%d)", ROUND(x), ROUND(y), ROUND(xoff), ROUND(yoff));
|
228
|
+
fclose(fp);
|
229
|
+
}
|
230
|
+
|
231
|
+
|
232
|
+
static void Write_preview_header(OBJ_PTR fmkr, FILE *file, int *ierr) {
|
233
|
+
fprintf(file, "\\documentclass{%s}\n\n", Get_tex_preview_documentclass(fmkr,ierr));
|
234
|
+
/* we print out the preamble generated from tioga.sty.in */
|
235
|
+
fprintf(file, "%% Tioga preamble generated from tioga.sty.in\n");
|
236
|
+
fprintf(file, "%s\n", Get_tex_preview_generated_preamble(fmkr,ierr));
|
237
|
+
fprintf(file, "%% User-specified preamble\n");
|
238
|
+
fprintf(file, "%s\n\n", Get_tex_preamble(fmkr,ierr));
|
239
|
+
fprintf(file, "%% Command to format numeric labels on xaxis\n");
|
240
|
+
fprintf(file, "\\newcommand{\\tiogaxaxisnumericlabel}[1]{%s}\n\n", Get_xaxis_numeric_label_tex(fmkr,ierr));
|
241
|
+
fprintf(file, "%% Command to format numeric labels on yaxis\n");
|
242
|
+
fprintf(file, "\\newcommand{\\tiogayaxisnumericlabel}[1]{%s}\n\n", Get_yaxis_numeric_label_tex(fmkr,ierr));
|
243
|
+
fprintf(file, "%% Color constants definitions\n");
|
244
|
+
fprintf(file, "%s\n\n", CString_Ptr(COLOR_PREAMBLE(fmkr,ierr),ierr));
|
245
|
+
fprintf(file, "%% Set page margins, page size and orientation.\n");
|
246
|
+
fprintf(file, "\t\\usepackage[pdftex,tmargin=0pt,lmargin=0pt,"
|
247
|
+
"rmargin=0pt,bmargin=0pt,\n");
|
248
|
+
fprintf(file, "\tpaperwidth=%s,paperheight=%s,\n",
|
249
|
+
Get_tex_preview_paper_width(fmkr,ierr),
|
250
|
+
Get_tex_preview_paper_height(fmkr,ierr));
|
251
|
+
fprintf(file, "\thoffset=%s,voffset=%s\n",
|
252
|
+
Get_tex_preview_hoffset(fmkr,ierr),
|
253
|
+
Get_tex_preview_voffset(fmkr,ierr));
|
254
|
+
fprintf(file, "\t]{geometry}\n");
|
255
|
+
|
256
|
+
fprintf(file, "\n%% We need the graphicx package and the calc package.\n");
|
257
|
+
fprintf(file, "\t\\usepackage{graphicx}\n");
|
258
|
+
fprintf(file, "\t\\usepackage{calc}\n\n");
|
259
|
+
fprintf(file, "\t%% This is necessary to avoid getting the picture on the second page\n");
|
260
|
+
fprintf(file, "\t\\topskip=0pt\n\n");
|
261
|
+
|
262
|
+
/* now, the commands to customize the font used */
|
263
|
+
fprintf(file, "\\settiogafontsize[10pt]{%s}\n", Get_tex_fontsize(fmkr,ierr));
|
264
|
+
fprintf(file, "\\settiogafontfamily{\\%s}\n", Get_tex_fontfamily(fmkr,ierr));
|
265
|
+
fprintf(file, "\\settiogafontseries{\\%s}\n", Get_tex_fontseries(fmkr,ierr));
|
266
|
+
fprintf(file, "\\settiogafontshape{\\%s}\n", Get_tex_fontshape(fmkr,ierr));
|
267
|
+
}
|
268
|
+
|
269
|
+
|
270
|
+
static void Write_figure_command(OBJ_PTR fmkr, char *simple_name, FILE *file, int *ierr) {
|
271
|
+
char *minwhitespace;
|
272
|
+
|
273
|
+
if (Get_tex_preview_fullpage(fmkr,ierr)) {
|
274
|
+
minwhitespace = Get_tex_preview_minwhitespace(fmkr,ierr);
|
275
|
+
if (minwhitespace == NULL) {
|
276
|
+
fprintf(file, "\\tiogafigurefullpage{%s}\n", simple_name);
|
277
|
+
} else {
|
278
|
+
fprintf(file, "\\tiogafigurefullpage[%s]{%s}\n", minwhitespace, simple_name);
|
279
|
+
}
|
280
|
+
} else {
|
281
|
+
const char * command = Get_tex_preview_tiogafigure_command(fmkr,ierr);
|
282
|
+
if(strcmp(command, "tiogafigureshow")) {
|
283
|
+
fprintf(file, "\\%s{%s}{%s}{%s}\n", Get_tex_preview_tiogafigure_command(fmkr,ierr), simple_name,
|
284
|
+
Get_tex_preview_figure_width(fmkr,ierr), Get_tex_preview_figure_height(fmkr,ierr));
|
285
|
+
} else { /* no need for extra arguments for tiogafigureshow */
|
286
|
+
fprintf(file, "\\%s{%s}\n", Get_tex_preview_tiogafigure_command(fmkr,ierr), simple_name);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
|
292
|
+
void Create_wrapper(OBJ_PTR fmkr, char *fname, bool quiet_mode, int *ierr)
|
293
|
+
{ // create the wrapper TeX file to combine the text and graphics to make a figure
|
294
|
+
char *dot;
|
295
|
+
char tex_fname[100], base_name[100], simple_name[100];
|
296
|
+
FILE *file;
|
297
|
+
if ((dot=strrchr(fname,'.')) != NULL) {
|
298
|
+
strncpy(base_name, fname, dot-fname); base_name[dot-fname] = '\0';
|
299
|
+
snprintf(tex_fname, sizeof(tex_fname), "%s.tex", base_name);
|
300
|
+
}
|
301
|
+
else {
|
302
|
+
strcpy(base_name, fname);
|
303
|
+
snprintf(tex_fname, sizeof(tex_fname), "%s.tex", fname);
|
304
|
+
}
|
305
|
+
if ((dot=strrchr(base_name,'/')) != NULL) {
|
306
|
+
strcpy(simple_name, dot+1);
|
307
|
+
}
|
308
|
+
else {
|
309
|
+
strcpy(simple_name, base_name);
|
310
|
+
}
|
311
|
+
file = fopen(tex_fname, "w");
|
312
|
+
fprintf(file, "%% Tioga preview LaTeX file for %s_figure.pdf and %s_figure.txt\n\n", base_name, base_name);
|
313
|
+
|
314
|
+
Write_preview_header(fmkr, file, ierr);
|
315
|
+
|
316
|
+
fprintf(file, "\n%% Here's the page with the figure.\n");
|
317
|
+
fprintf(file, "\\begin{document}\n");
|
318
|
+
fprintf(file, "\\pagestyle{%s}\n", Get_tex_preview_pagestyle(fmkr,ierr));
|
319
|
+
/* necessary to get the position right */
|
320
|
+
fprintf(file, "\\noindent");
|
321
|
+
Write_figure_command(fmkr, simple_name, file, ierr);
|
322
|
+
fprintf(file, "\\end{document}\n");
|
323
|
+
fclose(file);
|
324
|
+
}
|
325
|
+
|
326
|
+
void Init_tex(int *ierr)
|
327
|
+
{
|
328
|
+
}
|
329
|
+
|
330
|
+
void Rename_tex(char *oldname, char *newname, int *ierr)
|
331
|
+
{
|
332
|
+
char old_ofile[300], new_ofile[300];
|
333
|
+
Get_tex_name(old_ofile, oldname, 300);
|
334
|
+
Get_tex_name(new_ofile, newname, 300);
|
335
|
+
rename(old_ofile, new_ofile); // from stdio.h
|
336
|
+
}
|
337
|
+
|
338
|
+
void private_make_portfolio(char *name, OBJ_PTR fignums, OBJ_PTR fignames, int *ierr)
|
339
|
+
{
|
340
|
+
FILE *file;
|
341
|
+
int i, len, numfigs, j;
|
342
|
+
char tex_fname[256];
|
343
|
+
snprintf(tex_fname, sizeof(tex_fname), "%s.tex", name);
|
344
|
+
file = fopen(tex_fname, "w");
|
345
|
+
if (file == NULL) {
|
346
|
+
RAISE_ERROR_s("Sorry: can't open %s.\n", tex_fname, ierr); return; }
|
347
|
+
fprintf(file, "%% Tioga Portfolio %s\n\n", name);
|
348
|
+
fprintf(file, "\\documentclass{article}\n");
|
349
|
+
fprintf(file, "\\usepackage{pdfpages}\n");
|
350
|
+
fprintf(file, "\\begin{document}\n");
|
351
|
+
fprintf(file, "%% Start of figures, one per page\n\n");
|
352
|
+
len = Array_Len(fignames,ierr);
|
353
|
+
if (fignums == OBJ_NIL) {
|
354
|
+
for (i=0; i < len; i++) {
|
355
|
+
fprintf(file, "\\includepdf{%s.pdf}\n", Get_String(fignames, i, ierr));
|
356
|
+
if (*ierr != 0) return;
|
357
|
+
}
|
358
|
+
} else {
|
359
|
+
numfigs = Array_Len(fignums,ierr);
|
360
|
+
if (*ierr != 0) return;
|
361
|
+
for (i=0; i < numfigs; i++) {
|
362
|
+
OBJ_PTR n = Array_Entry(fignums,i,ierr);
|
363
|
+
if (*ierr != 0) return;
|
364
|
+
j = Number_to_int(n,ierr);
|
365
|
+
if (j >= 0 && j < len) {
|
366
|
+
fprintf(file, "\\includepdf{%s.pdf}\n", Get_String(fignames, j, ierr));
|
367
|
+
if (*ierr != 0) return;
|
368
|
+
}
|
369
|
+
else {
|
370
|
+
fclose(file);
|
371
|
+
RAISE_ERROR("Requested figure numbers must be >= 0 and < num_figures.", ierr);
|
372
|
+
return;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
}
|
376
|
+
fprintf(file, "\n\\end{document}\n");
|
377
|
+
fclose(file);
|
378
|
+
}
|
379
|
+
|
380
|
+
|
381
|
+
/*
|
382
|
+
Stores and transforms measures as printed by pdflatex.
|
383
|
+
|
384
|
+
Takes sizes in bp.
|
385
|
+
|
386
|
+
*/
|
387
|
+
void c_save_measure(OBJ_PTR fmkr, OBJ_PTR measure_name,
|
388
|
+
double width, double height, double depth)
|
389
|
+
{
|
390
|
+
double angle, scale;
|
391
|
+
int just, align;
|
392
|
+
/* Page coordinates in bp before applying rotation ! */
|
393
|
+
double xl,xr,yt,yb;
|
394
|
+
double xa,ya;
|
395
|
+
OBJ_PTR measures = Get_Measure_Hash(fmkr, measure_name);
|
396
|
+
int dummy;
|
397
|
+
|
398
|
+
/* The following really should not happen */
|
399
|
+
if(measures == OBJ_NIL) {
|
400
|
+
fprintf(stderr, "Warning: got hash = OBJ_NIL in %s, line %d\n",
|
401
|
+
__FILE__, __LINE__);
|
402
|
+
return;
|
403
|
+
}
|
404
|
+
|
405
|
+
/* Storing measured sizes */
|
406
|
+
Hash_Set_Double(measures, "tex_measured_width", width);
|
407
|
+
Hash_Set_Double(measures, "tex_measured_height", height);
|
408
|
+
Hash_Set_Double(measures, "tex_measured_depth", depth);
|
409
|
+
|
410
|
+
angle = Hash_Get_Double(measures, "angle");
|
411
|
+
scale = Hash_Get_Double(measures, "scale");
|
412
|
+
just = Hash_Get_Double(measures, "just");
|
413
|
+
align = Hash_Get_Double(measures, "align");
|
414
|
+
|
415
|
+
/* Setting the appropriate scale */
|
416
|
+
width *= scale;
|
417
|
+
height *= scale;
|
418
|
+
depth *= scale;
|
419
|
+
/* Now setting the width and height in */
|
420
|
+
Hash_Set_Double(measures, "width", width);
|
421
|
+
Hash_Set_Double(measures, "height", height);
|
422
|
+
Hash_Set_Double(measures, "depth", depth);
|
423
|
+
|
424
|
+
xa = Hash_Get_Double(measures, "xanchor");
|
425
|
+
ya = Hash_Get_Double(measures, "yanchor");
|
426
|
+
|
427
|
+
/* Now, we try to compute the precise position of
|
428
|
+
the points of the box surrounding the text.
|
429
|
+
*/
|
430
|
+
|
431
|
+
/* First, before rotation: */
|
432
|
+
switch(just) {
|
433
|
+
case 1: /* Right-justified */
|
434
|
+
xr = xa;
|
435
|
+
xl = xa - width;
|
436
|
+
break;
|
437
|
+
case 0: /* Centered */
|
438
|
+
xr = xa + width/2;
|
439
|
+
xl = xa - width/2;
|
440
|
+
break;
|
441
|
+
case -1: /* Left-justified */
|
442
|
+
xl = xa;
|
443
|
+
xr = xa + width;
|
444
|
+
break;
|
445
|
+
default:
|
446
|
+
fprintf(stderr, "Invalid justification = %d at %s, line %d\n",
|
447
|
+
just, __FILE__, __LINE__);
|
448
|
+
xl = xa;
|
449
|
+
xr = xa + width/2;
|
450
|
+
}
|
451
|
+
|
452
|
+
/* First, before rotation: */
|
453
|
+
switch(align) {
|
454
|
+
case ALIGNED_AT_BASELINE:
|
455
|
+
yt = ya + height;
|
456
|
+
yb = ya - depth;
|
457
|
+
break;
|
458
|
+
case ALIGNED_AT_BOTTOM:
|
459
|
+
yt = ya + height + depth;
|
460
|
+
yb = ya;
|
461
|
+
break;
|
462
|
+
case ALIGNED_AT_TOP:
|
463
|
+
yb = ya - height - depth;
|
464
|
+
yt = ya;
|
465
|
+
break;
|
466
|
+
default: /* Centered */
|
467
|
+
yb = ya - 0.5*(height + depth);
|
468
|
+
yt = ya + 0.5*(height + depth);
|
469
|
+
}
|
470
|
+
|
471
|
+
/* Now, rotation */
|
472
|
+
if(angle == 0.0) {
|
473
|
+
/* xbl = x of 'bottom left' */
|
474
|
+
Hash_Set_Double(measures, "xbl", xl);
|
475
|
+
Hash_Set_Double(measures, "ybl", yb);
|
476
|
+
Hash_Set_Double(measures, "xtl", xl);
|
477
|
+
Hash_Set_Double(measures, "ytl", yt);
|
478
|
+
Hash_Set_Double(measures, "xbr", xr);
|
479
|
+
Hash_Set_Double(measures, "ybr", yb);
|
480
|
+
Hash_Set_Double(measures, "xtr", xr);
|
481
|
+
Hash_Set_Double(measures, "ytr", yt);
|
482
|
+
}
|
483
|
+
else {
|
484
|
+
double s = - sin(angle * PI/180);
|
485
|
+
double c = cos(angle * PI/180);
|
486
|
+
Hash_Set_Double(measures, "xbl",
|
487
|
+
xa + (xl-xa)*c + (yb - ya) * s);
|
488
|
+
Hash_Set_Double(measures, "ybl",
|
489
|
+
ya - (xl-xa)*s + (yb - ya) * c);
|
490
|
+
Hash_Set_Double(measures, "xtl",
|
491
|
+
xa + (xl-xa)*c + (yt - ya) * s);
|
492
|
+
Hash_Set_Double(measures, "ytl",
|
493
|
+
ya - (xl-xa)*s + (yt - ya) * c);
|
494
|
+
Hash_Set_Double(measures, "xbr",
|
495
|
+
xa + (xr-xa)*c + (yb - ya) * s);
|
496
|
+
Hash_Set_Double(measures, "ybr",
|
497
|
+
ya - (xr-xa)*s + (yb - ya) * c);
|
498
|
+
Hash_Set_Double(measures, "xtr",
|
499
|
+
xa + (xr-xa)*c + (yt - ya) * s);
|
500
|
+
Hash_Set_Double(measures, "ytr",
|
501
|
+
ya - (xr-xa)*s + (yt - ya) * c);
|
502
|
+
}
|
503
|
+
|
504
|
+
/* We transform coordinates into an array
|
505
|
+
(topleft, topright, botright, botleft)
|
506
|
+
of arrays (xy) of doubles
|
507
|
+
*/
|
508
|
+
OBJ_PTR points = Array_New(0);
|
509
|
+
OBJ_PTR current_point;
|
510
|
+
int i;
|
511
|
+
for(i = 0; i < 8; i++) {
|
512
|
+
char buf[4];
|
513
|
+
if(! (i % 2)) {
|
514
|
+
current_point = Array_New(0);
|
515
|
+
Array_Push(points, current_point, &dummy);
|
516
|
+
}
|
517
|
+
snprintf(buf, sizeof(buf), "%c%c%c",
|
518
|
+
(i%2 ? 'y' : 'x'),
|
519
|
+
(i/4 ? 't' : 'b'),
|
520
|
+
((i >= 2) && (i < 6) ? 'r' : 'l'));
|
521
|
+
Array_Push(current_point, Hash_Get_Obj(measures, buf), &dummy);
|
522
|
+
}
|
523
|
+
Hash_Set_Obj(measures, "points", points);
|
524
|
+
}
|