18
36
/* When this is called in g_alabel.c, the X font has already been
19
37
retrieved, in whole or in part (by calling "_set_font()", which in turn
20
38
calls "_plotter->retrieve_font()", which is bound to the
21
_x_retrieve_font() routine in x_retrieve.c). I.e., whatever portion of
39
_pl_x_retrieve_font() routine in x_retrieve.c). I.e., whatever portion of
22
40
the X font was required to be retrieved in order to return font metrics,
23
41
has previously been retrieved.
25
To retrieve a larger part, we call _x_retrieve_font() again. But this
26
time, we pass the label to be rendered to _x_retrieve_font() as a
27
"hint", i.e., as a data member of (the driver-specific part of) the
28
drawing state. That tells _x_retrieve_font how much more of the font to
29
retrieve. This scheme is a hack, but it works (and doesn't violate
43
To retrieve a larger part, we call _pl_x_retrieve_font() again. But this
44
time, we pass the label to be rendered to _pl_x_retrieve_font() as a
45
"hint", i.e., as the x_label data member of (the driver-specific part
46
of) the drawing state. That tells _pl_x_retrieve_font how much more of the
47
font to retrieve. This scheme is a hack, but it works (and doesn't
32
The original retrieval may well have mapped the font name to something
33
else (in the case of an unavailable X font, a default X font may have
34
been substituted). So we're careful to use drawstate->true_font_name as
35
drawstate->font_name, for the duration of the second retrieval. Note:
36
this requires a strcpy, since _x_retrieve_font() may free the
37
true_font_name member. */
50
#include "x_afftext.h"
41
_x_paint_text_string (R___(Plotter *_plotter) const unsigned char *s, int h_just, int v_just)
43
_x_paint_text_string (R___(_plotter) s, h_just, v_just)
44
S___(Plotter *_plotter;)
45
const unsigned char *s;
53
_pl_x_paint_text_string (R___(Plotter *_plotter) const unsigned char *s, int h_just, int v_just)
50
55
const char *saved_font_name;
51
56
char *temp_font_name;
59
double width = 0.0; /* width of string in user units */
60
double rot[4]; /* user-frame rotation matrix */
61
double a[4]; /* transformation matrix for XAffDrawString() */
56
64
/* sanity check; this routine supports only baseline positioning */
57
if (v_just != JUST_BASE)
65
if (v_just != PL_JUST_BASE)
60
68
/* similarly for horizontal justification */
61
if (h_just != JUST_LEFT)
69
if (h_just != PL_JUST_LEFT)
64
72
if (*s == (unsigned char)'\0')
67
/* Do retrieval, but use current `true_font_name' as our font name (see
68
above; we've previously retrieved a subset of it). */
75
/* Do retrieval, fill in the X-specific field x_font_struct of the
76
drawing state. (We've previously retrieved a small subset of the
77
font, to obtain metrics used for text positioning, as mentioned above;
78
so retrieving a larger portion should go smoothly.)
80
We retrieve not `font_name' but rather `true_font_name', because the
81
latter may have been what was retrieved, if a default X font had to be
82
substituted; see g_retrieve.c. */
70
84
if (_plotter->drawstate->true_font_name == NULL) /* shouldn't happen */
73
87
saved_font_name = _plotter->drawstate->font_name;
75
(char *)_plot_xmalloc (strlen (_plotter->drawstate->true_font_name) + 1);
89
(char *)_pl_xmalloc (strlen (_plotter->drawstate->true_font_name) + 1);
76
90
strcpy (temp_font_name, _plotter->drawstate->true_font_name);
77
91
_plotter->drawstate->font_name = temp_font_name;
79
93
_plotter->drawstate->x_label = s; /* pass label hint */
80
ok = _x_retrieve_font (S___(_plotter));
94
ok = _pl_x_retrieve_font (S___(_plotter));
81
95
_plotter->drawstate->x_label = NULL; /* restore label hint to default */
83
97
_plotter->drawstate->font_name = saved_font_name;
86
100
if (!ok) /* shouldn't happen */
89
/* Set font in GC used for drawing (the other GC, used for filling, is
90
left alone). _x_retrieve_font() does not do this. */
103
/* set font in GC used for drawing (the other GC, used for filling, is
91
105
XSetFont (_plotter->x_dpy, _plotter->drawstate->x_gc_fg,
92
106
_plotter->drawstate->x_font_struct->fid);
94
108
/* select our pen color as foreground color in X GC used for drawing */
95
_x_set_pen_color (S___(_plotter));
109
_pl_x_set_pen_color (S___(_plotter));
97
111
/* compute position in device coordinates */
98
112
x = XD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y);
99
113
y = YD(_plotter->drawstate->pos.x, _plotter->drawstate->pos.y);
101
if (_plotter->drawstate->x_native_positioning)
102
/* a special case: the font name did not include a pixel matrix, or it
103
did but the text rotation angle is zero; so move the easy way, i.e.,
104
use native repositioning */
106
int label_len = strlen ((char *)s);
110
/* X11 protocol OOB check */
111
if (XOOB_INT(ix) || XOOB_INT(iy))
113
_plotter->warning (R___(_plotter)
114
"not drawing a text string that is positioned too far for X11");
118
if (_plotter->x_double_buffering != DBL_NONE)
119
/* double buffering, have a `x_drawable3' to draw into */
120
XDrawString (_plotter->x_dpy, _plotter->x_drawable3,
121
_plotter->drawstate->x_gc_fg,
122
ix, iy, (char *)s, label_len);
125
/* not double buffering, have no `x_drawable3' */
126
if (_plotter->x_drawable1)
127
XDrawString (_plotter->x_dpy, _plotter->x_drawable1,
128
_plotter->drawstate->x_gc_fg,
129
ix, iy, (char *)s, label_len);
130
if (_plotter->x_drawable2)
131
XDrawString (_plotter->x_dpy, _plotter->x_drawable2,
132
_plotter->drawstate->x_gc_fg,
133
ix, iy, (char *)s, label_len);
136
/* compute width of string in normalized units (font size = 1000) */
137
offset = IROUND(1000.0 * XTextWidth (_plotter->drawstate->x_font_struct,
139
(int)(strlen((char *)s))) /
140
_plotter->drawstate->x_font_pixmatrix[0]);
143
/* general case: due to nonzero text rotation and/or a non-uniform
144
transformation from user to device coordinates, a pixel matrix
145
appeared explicitly in the font name (and hence the font name was an
146
XLFD font name); must move the cursor and plot each character
149
const unsigned char *stringptr = s;
151
/* loop over characters */
154
int charno = *stringptr;
156
charno - _plotter->drawstate->x_font_struct->min_char_or_byte2;
160
offset * _plotter->drawstate->x_font_pixmatrix[0]/1000.0);
162
-offset * _plotter->drawstate->x_font_pixmatrix[1]/1000.0);
164
/* X11 protocol OOB check */
165
if (XOOB_INT(ix) || XOOB_INT(iy))
167
_plotter->warning (R___(_plotter)
168
"truncating a text string that extends too far for X11");
172
if (_plotter->x_double_buffering != DBL_NONE)
173
/* double buffering, have a `x_drawable3' to draw into */
174
XDrawString (_plotter->x_dpy, _plotter->x_drawable3,
175
_plotter->drawstate->x_gc_fg,
176
ix, iy, (char *)stringptr, 1);
178
/* not double buffering, have no `x_drawable3' */
180
if (_plotter->x_drawable1)
181
XDrawString (_plotter->x_dpy, _plotter->x_drawable1,
182
_plotter->drawstate->x_gc_fg,
183
ix, iy, (char *)stringptr, 1);
184
if (_plotter->x_drawable2)
185
XDrawString (_plotter->x_dpy, _plotter->x_drawable2,
186
_plotter->drawstate->x_gc_fg,
187
ix, iy, (char *)stringptr, 1);
190
/* add this glyph's contribution to the width of the string, in
191
normalized units (font size = 1000) */
192
offset += (_plotter->drawstate->x_font_struct->per_char ?
193
_plotter->drawstate->x_font_struct->per_char[char_offset].attributes :
194
_plotter->drawstate->x_font_struct->min_bounds.attributes);
200
/* convert normalized string width to width in user coors */
201
width = _plotter->drawstate->true_font_size * (double)offset / 1000.0;
115
/* X11 protocol OOB check */
118
if (X_OOB_INT(ix) || X_OOB_INT(iy))
120
_plotter->warning (R___(_plotter)
121
"not drawing a text string that is positioned too far for X11");
125
/* Draw the text string by calling XAffDrawString() in x_afftext.c, which
126
operates by affinely transform a bitmap generated by XDrawString() in
127
the following way: it pulls it back from the server as an image,
128
transforms the image, and then sends the image back to the server. */
130
/* First, compute a 2x2 matrix a[] that would, in the jargon of the
131
matrix extension to the XLFD (X Logical Font Description) scheme, be
132
called a `pixel matrix'. It specifies how XAffDrawAffString should
133
`anamorphically transform' the text bitmap produced by XDrawString(),
134
to yield the bitmap we want. It's essentially the product of (i) the
135
user-frame text rotation matrix, and (ii) the user_space->device_space
136
transformation matrix. But see additional comments below. */
138
/* user-frame rotation matrix */
139
rot[0] = cos (M_PI * _plotter->drawstate->text_rotation / 180.0);
140
rot[1] = sin (M_PI * _plotter->drawstate->text_rotation / 180.0);
141
rot[2] = - sin (M_PI * _plotter->drawstate->text_rotation / 180.0);
142
rot[3] = cos (M_PI * _plotter->drawstate->text_rotation / 180.0);
144
/* Compute matrix product. But note flipped-y convention affecting a[1]
145
and a[3]. Sign flipping is because the pixel matrix (as used in the
146
XLFD matrix extension and hence, for consistency, by our code by
147
XAffDrawAffString()) is expressed with respect to a right-handed
148
coordinate system, in which y grows upward, rather than X11's default
149
left-handed coordinate system, in which y grows downward. */
151
a[0] = (rot[0] * _plotter->drawstate->transform.m[0]
152
+ rot[1] * _plotter->drawstate->transform.m[2]);
153
a[1] = - (rot[0] * _plotter->drawstate->transform.m[1]
154
+ rot[1] * _plotter->drawstate->transform.m[3]);
155
a[2] = (rot[2] * _plotter->drawstate->transform.m[0]
156
+ rot[3] * _plotter->drawstate->transform.m[2]);
157
a[3] = - (rot[2] * _plotter->drawstate->transform.m[1]
158
+ rot[3] * _plotter->drawstate->transform.m[3]);
160
/* Apply an overall scaling. We want the text string to appear at a
161
certain font size in the user frame; and the font that XDrawString
162
will use was retrieved at a certain pixel size in the device frame.
163
So we compensate on both sides, so to speak. We multiply by
164
true_font_size / x_font_pixel_size, where the numerator refers to the
165
user frame, and the denominator to the device frame. */
167
for (i = 0; i < 4; i++)
169
* (_plotter->drawstate->true_font_size / _plotter->drawstate->x_font_pixel_size);
171
if (_plotter->x_double_buffering != X_DBL_BUF_NONE)
172
/* double buffering, have a `x_drawable3' to draw into */
173
XAffDrawAffString (_plotter->x_dpy, _plotter->x_drawable3,
174
_plotter->drawstate->x_gc_fg,
175
_plotter->drawstate->x_font_struct,
176
ix, iy, a, (char *)s);
179
/* not double buffering, have no `x_drawable3' */
180
if (_plotter->x_drawable1)
181
XAffDrawAffString (_plotter->x_dpy, _plotter->x_drawable1,
182
_plotter->drawstate->x_gc_fg,
183
_plotter->drawstate->x_font_struct,
184
ix, iy, a, (char *)s);
185
if (_plotter->x_drawable2)
186
XAffDrawAffString (_plotter->x_dpy, _plotter->x_drawable2,
187
_plotter->drawstate->x_gc_fg,
188
_plotter->drawstate->x_font_struct,
189
ix, iy, a, (char *)s);
192
/* compute width of just-drawn string in user units */
193
width = (((XTextWidth (_plotter->drawstate->x_font_struct,
195
(int)(strlen((char *)s)))
196
*_plotter->drawstate->true_font_size))
197
/ _plotter->drawstate->x_font_pixel_size);
203
199
/* maybe flush X output buffer and handle X events (a no-op for
204
200
XDrawablePlotters, which is overridden for XPlotters) */
205
201
_maybe_handle_x_events (S___(_plotter));
217
213
/* When this is called in g_alabel.c, the X font has already been
218
214
retrieved, in whole or in part (by calling "_set_font()", which in turn
219
215
calls "_plotter->retrieve_font()", i.e., which calls the
220
_x_retrieve_font() routine in x_retrieve.c). I.e., whatever portion of
216
_pl_x_retrieve_font() routine in x_retrieve.c). I.e., whatever portion of
221
217
the X font was required to be retrieved in order to return font metrics,
222
218
has previously been retrieved.
224
To retrieve a larger part, we call _x_retrieve_font() again. But this
225
time, we pass the label to be rendered to _x_retrieve_font() as a
220
To retrieve a larger part, we call _pl_x_retrieve_font() again. But this
221
time, we pass the label to be rendered to _pl_x_retrieve_font() as a
226
222
"hint", i.e., as a data member of (the driver-specific part of) the
227
drawing state. That tells _x_retrieve_font how much more of the font to
223
drawing state. That tells _pl_x_retrieve_font how much more of the font to
228
224
retrieve. This scheme is an ugly hack, but it works (and doesn't
231
The original retrieval may well have mapped the font name to something
232
else (in the case of an unavailable X font, a default X font may have
233
been substituted). So we're careful to use drawstate->true_font_name as
234
drawstate->font_name, for the duration of the second retrieval. Note:
235
this requires a strcpy, since _x_retrieve_font() may free the
236
true_font_name member. */
225
violate layering). */
240
_x_get_text_width (R___(Plotter *_plotter) const unsigned char *s)
242
_x_get_text_width (R___(_plotter) s)
243
S___(Plotter *_plotter;)
244
const unsigned char *s;
228
_pl_x_get_text_width (R___(Plotter *_plotter) const unsigned char *s)
247
230
const char *saved_font_name;
248
231
char *temp_font_name;
253
235
/* Do retrieval, but use current `true_font_name' as our font name (see
254
236
above; we've previously retrieved a subset of it). */