4 * accept dvi function calls and translate to X
11 #include <X11/IntrinsicP.h>
12 #include <X11/StringDefs.h>
17 /* math.h on a Sequent doesn't define M_PI, apparently */
19 #define M_PI 3.14159265358979323846
26 #define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
27 #define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
28 (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
29 #define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
31 /* forward reference */
32 static int FakeCharacter(DviWidget, char *, int);
34 /* shadowed by a macro definition in parse.c, and unused elsewhere */
37 HorizontalMove(DviWidget dw, int delta)
39 dw->dvi.state->x += delta;
44 HorizontalGoto(DviWidget dw, int NewPosition)
46 dw->dvi.state->x = NewPosition;
50 VerticalMove(DviWidget dw, int delta)
52 dw->dvi.state->y += delta;
56 VerticalGoto(DviWidget dw, int NewPosition)
58 dw->dvi.state->y = NewPosition;
62 AdjustCacheDeltas (DviWidget dw)
69 extra = DeviceToX(dw, dw->dvi.text_device_width)
70 - dw->dvi.text_x_width;
73 for (i = 0; i <= dw->dvi.cache.index; i++)
74 if (dw->dvi.cache.adjustable[i])
76 dw->dvi.text_x_width += extra;
79 for (i = 0; i <= dw->dvi.cache.index; i++)
80 if (dw->dvi.cache.adjustable[i]) {
85 deltap = &dw->dvi.cache.cache[i].delta;
87 if (*deltap > 0 && x + *deltap < MIN_DELTA) {
88 x = MIN_DELTA - *deltap;
98 dw->dvi.cache.adjustable[i] = 0;
103 FlushCharCache (DviWidget dw)
105 if (dw->dvi.cache.char_index != 0) {
106 AdjustCacheDeltas (dw);
107 XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
108 dw->dvi.cache.start_x, dw->dvi.cache.start_y,
109 dw->dvi.cache.cache, dw->dvi.cache.index + 1);
111 dw->dvi.cache.index = 0;
112 dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
114 if (dw->dvi.noPolyText)
115 dw->dvi.cache.max = 1;
117 dw->dvi.cache.char_index = 0;
118 dw->dvi.cache.cache[0].nchars = 0;
119 dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
120 dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
124 Newline (DviWidget dw)
127 dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
128 dw->dvi.word_flag = 0;
134 dw->dvi.word_flag = 1;
137 #define charWidth(fi,c) (\
139 (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
141 (fi)->max_bounds.width\
146 int charExists (XFontStruct *fi, int c)
150 /* 'c' is always >= 0 */
151 if (fi->per_char == NULL
152 || (unsigned int)c < fi->min_char_or_byte2
153 || (unsigned int)c > fi->max_char_or_byte2)
155 p = fi->per_char + (c - fi->min_char_or_byte2);
156 return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
157 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
160 /* 'wid' is in device units */
162 DoCharacter (DviWidget dw, int c, int wid)
164 register XFontStruct *font;
165 register XTextItem *text;
172 * quick and dirty extents calculation:
174 if (!(y + 24 >= dw->dvi.extents.y1
175 && y - 24 <= dw->dvi.extents.y2
177 && x + 24 >= dw->dvi.extents.x1
178 && x - 24 <= dw->dvi.extents.x2
183 if (y != dw->dvi.cache.y
184 || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
187 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
190 * load a new font, if the current block is not empty,
193 if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
194 dw->dvi.cache.font_number != dw->dvi.state->font_number)
198 dw->dvi.cache.font_size = dw->dvi.state->font_size;
199 dw->dvi.cache.font_number = dw->dvi.state->font_number;
200 dw->dvi.cache.font = QueryFont (dw,
201 dw->dvi.cache.font_number,
202 dw->dvi.cache.font_size);
203 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
204 ++dw->dvi.cache.index;
205 if (dw->dvi.cache.index >= dw->dvi.cache.max)
207 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
208 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
211 if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
212 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
213 ++dw->dvi.cache.index;
214 if (dw->dvi.cache.index >= dw->dvi.cache.max)
216 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
217 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
219 dw->dvi.cache.adjustable[dw->dvi.cache.index]
221 dw->dvi.word_flag = 0;
223 font = dw->dvi.cache.font;
224 text = &dw->dvi.cache.cache[dw->dvi.cache.index];
225 if (text->nchars == 0) {
226 text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
227 text->delta = x - dw->dvi.cache.x;
228 if (font != dw->dvi.font) {
229 text->font = font->fid;
233 dw->dvi.cache.x += text->delta;
235 if (charExists(font, c)) {
237 dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
239 w = charWidth(font, c);
240 dw->dvi.cache.x += w;
242 dw->dvi.text_x_width += w;
243 dw->dvi.text_device_width += wid;
249 int FindCharWidth (DviWidget dw, char *buf, int *widp)
254 if (dw->dvi.device_font == 0
255 || dw->dvi.state->font_number != dw->dvi.device_font_number) {
256 dw->dvi.device_font_number = dw->dvi.state->font_number;
258 = QueryDeviceFont (dw, dw->dvi.device_font_number);
260 if (dw->dvi.device_font
261 && device_char_width (dw->dvi.device_font,
262 dw->dvi.state->font_size, buf, widp))
265 maxpos = MaxFontPosition (dw);
266 for (i = 1; i <= maxpos; i++) {
267 DeviceFont *f = QueryDeviceFont (dw, i);
268 if (f && device_font_special (f)
269 && device_char_width (f, dw->dvi.state->font_size,
271 dw->dvi.state->font_number = i;
278 /* Return the width of the character in device units. */
281 PutCharacter (DviWidget dw, char *buf)
288 if (!dw->dvi.display_enable)
289 return 0; /* The width doesn't matter in this case. */
290 prevFont = dw->dvi.state->font_number;
291 if (!FindCharWidth (dw, buf, &wid))
293 map = QueryFontMap (dw, dw->dvi.state->font_number);
295 c = DviCharIndex (map, buf);
297 DoCharacter (dw, c, wid);
299 (void) FakeCharacter (dw, buf, wid);
300 dw->dvi.state->font_number = prevFont;
304 /* Return 1 if we can fake it; 0 otherwise. */
307 int FakeCharacter (DviWidget dw, char *buf, int wid)
311 const char *chars = 0;
313 if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
315 #define pack2(c1, c2) (((c1) << 8) | (c2))
317 switch (pack2(buf[0], buf[1])) {
318 case pack2('f', 'i'):
321 case pack2('f', 'l'):
324 case pack2('f', 'f'):
327 case pack2('F', 'i'):
330 case pack2('F', 'l'):
336 oldx = dw->dvi.state->x;
337 oldw = dw->dvi.text_device_width;
339 for (; *chars; chars++) {
341 dw->dvi.state->x += PutCharacter (dw, ch);
343 dw->dvi.state->x = oldx;
344 dw->dvi.text_device_width = oldw + wid;
349 PutNumberedCharacter (DviWidget dw, int c)
355 if (!dw->dvi.display_enable)
358 if (dw->dvi.device_font == 0
359 || dw->dvi.state->font_number != dw->dvi.device_font_number) {
360 dw->dvi.device_font_number = dw->dvi.state->font_number;
362 = QueryDeviceFont (dw, dw->dvi.device_font_number);
365 if (dw->dvi.device_font == 0
366 || !device_code_width (dw->dvi.device_font,
367 dw->dvi.state->font_size, c, &wid))
369 if (dw->dvi.native) {
370 DoCharacter (dw, c, wid);
373 map = QueryFontMap (dw, dw->dvi.state->font_number);
376 for (name = device_name_for_code (dw->dvi.device_font, c);
378 name = device_name_for_code ((DeviceFont *)0, c)) {
379 int code = DviCharIndex (map, name);
381 DoCharacter (dw, code, wid);
384 if (FakeCharacter (dw, name, wid))
392 ClearPage (DviWidget dw)
394 XClearWindow (XtDisplay (dw), XtWindow (dw));
401 int desired_line_width;
403 if (dw->dvi.line_thickness < 0)
404 desired_line_width = (int)(((double)dw->dvi.device_resolution
405 * dw->dvi.state->font_size)
406 / (10.0*72.0*dw->dvi.sizescale));
408 desired_line_width = dw->dvi.line_thickness;
410 if (desired_line_width != dw->dvi.line_width) {
412 values.line_width = DeviceToX(dw, desired_line_width);
413 if (values.line_width == 0)
414 values.line_width = 1;
415 XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
416 GCLineWidth, &values);
417 dw->dvi.line_width = desired_line_width;
422 setFillGC (DviWidget dw)
425 unsigned long mask = GCFillStyle | GCForeground;
427 fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1);
428 if (dw->dvi.fill_type != fill_type) {
430 if (fill_type <= 0) {
431 values.foreground = dw->dvi.background;
432 values.fill_style = FillSolid;
433 } else if (fill_type >= 9) {
434 values.foreground = dw->dvi.foreground;
435 values.fill_style = FillSolid;
437 values.foreground = dw->dvi.foreground;
438 values.fill_style = FillOpaqueStippled;
439 values.stipple = dw->dvi.gray[fill_type - 1];
442 XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values);
443 dw->dvi.fill_type = fill_type;
448 DrawLine (DviWidget dw, int x, int y)
452 AdjustCacheDeltas (dw);
456 XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
458 xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
462 DrawCircle (DviWidget dw, int diam)
466 AdjustCacheDeltas (dw);
468 d = DeviceToX (dw, diam);
469 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
470 XPos (dw), YPos (dw) - d/2,
475 DrawFilledCircle (DviWidget dw, int diam)
479 AdjustCacheDeltas (dw);
481 d = DeviceToX (dw, diam);
482 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
483 XPos (dw), YPos (dw) - d/2,
485 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
486 XPos (dw), YPos (dw) - d/2,
491 DrawEllipse (DviWidget dw, int a, int b)
493 AdjustCacheDeltas (dw);
495 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
496 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
497 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
501 DrawFilledEllipse (DviWidget dw, int a, int b)
503 AdjustCacheDeltas (dw);
505 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
506 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
507 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
508 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
509 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
510 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
514 DrawArc (DviWidget dw, int x_0, int y_0, int x_1, int y_1)
517 int rad = (int)((sqrt ((double)x_0*x_0 + (double)y_0*y_0)
518 + sqrt ((double)x_1*x_1 + (double)y_1*y_1)
520 if ((x_0 == 0 && y_0 == 0) || (x_1 == 0 && y_1 == 0))
522 angle1 = (int)(atan2 ((double)y_0, (double)-x_0)*180.0*64.0/M_PI);
523 angle2 = (int)(atan2 ((double)-y_1, (double)x_1)*180.0*64.0/M_PI);
529 AdjustCacheDeltas (dw);
532 rad = DeviceToX (dw, rad);
533 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
534 XPos (dw) + DeviceToX (dw, x_0) - rad,
535 YPos (dw) + DeviceToX (dw, y_0) - rad,
536 rad*2, rad*2, angle1, angle2);
540 DrawPolygon (DviWidget dw, int *v, int n)
548 AdjustCacheDeltas (dw);
550 p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
555 for (i = 0; i < n; i++) {
557 p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
559 p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
563 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
564 p, n + 2, CoordModeOrigin);
569 DrawFilledPolygon (DviWidget dw, int *v, int n)
579 AdjustCacheDeltas (dw);
581 p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
582 p[0].x = p[n+1].x = XPos (dw);
583 p[0].y = p[n+1].y = YPos (dw);
586 for (i = 0; i < n; i++) {
588 p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
590 p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
592 XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
593 p, n + 1, Complex, CoordModeOrigin);
594 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
595 p, n + 2, CoordModeOrigin);
599 #define POINTS_MAX 10000
602 appendPoint(XPoint *points, int *pointi, int x, int y)
604 if (*pointi < POINTS_MAX) {
605 points[*pointi].x = x;
606 points[*pointi].y = y;
614 flattenCurve(XPoint *points, int *pointi,
615 int x_2, int y_2, int x_3, int y_3, int x_4, int y_4)
617 int x_1, y_1, dx, dy, n1, n2, n;
619 x_1 = points[*pointi - 1].x;
620 y_1 = points[*pointi - 1].y;
625 n1 = dy*(x_2 - x_1) - dx*(y_2 - y_1);
626 n2 = dy*(x_3 - x_1) - dx*(y_3 - y_1);
631 n = n1 > n2 ? n1 : n2;
633 if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
634 appendPoint (points, pointi, x_4, y_4);
636 flattenCurve (points, pointi,
639 (x_1 + x_2*2 + x_3)/4,
640 (y_1 + y_2*2 + y_3)/4,
641 (x_1 + 3*x_2 + 3*x_3 + x_4)/8,
642 (y_1 + 3*y_2 + 3*y_3 + y_4)/8);
643 flattenCurve (points, pointi,
644 (x_2 + x_3*2 + x_4)/4,
645 (y_2 + y_3*2 + y_4)/4,
654 DrawSpline (DviWidget dw, int *v, int n)
660 XPoint points[POINTS_MAX];
662 if (n == 0 || (n & 1) != 0)
664 AdjustCacheDeltas (dw);
672 tx = sx + DeviceToX (dw, dx);
673 ty = sy + DeviceToX (dw, dy);
677 appendPoint (points, &pointi, sx, sy);
678 appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
680 for (i = 2; i < n; i += 2) {
681 int ux = ox + DeviceToX (dw, dx += v[i]);
682 int uy = oy + DeviceToX (dw, dy += v[i+1]);
683 flattenCurve (points, &pointi,
684 (sx + tx*5)/6, (sy + ty*5)/6,
685 (tx*5 + ux)/6, (ty*5 + uy)/6,
686 (tx + ux)/2, (ty + uy)/2);
693 appendPoint (points, &pointi, tx, ty);
695 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
696 points, pointi, CoordModeOrigin);
703 c-continued-statement-offset: 8
707 c-tab-always-indent: nil