4 * accept dvi function calls and translate to X
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
14 /* math.h on a Sequent doesn't define M_PI, apparently */
16 #define M_PI 3.14159265358979323846
21 #define DeviceToX(dw, n) ((int)((n) * (dw)->dvi.scale_factor + .5))
22 #define XPos(dw) (DeviceToX((dw), (dw)->dvi.state->x - \
23 (dw)->dvi.text_device_width) + (dw)->dvi.text_x_width)
24 #define YPos(dw) (DeviceToX((dw), (dw)->dvi.state->y))
26 static int FakeCharacter();
29 extern int MaxFontPosition();
32 HorizontalMove(dw, delta)
36 dw->dvi.state->x += delta;
40 HorizontalGoto(dw, NewPosition)
44 dw->dvi.state->x = NewPosition;
48 VerticalMove(dw, delta)
52 dw->dvi.state->y += delta;
56 VerticalGoto(dw, NewPosition)
60 dw->dvi.state->y = NewPosition;
64 AdjustCacheDeltas (dw)
72 extra = DeviceToX(dw, dw->dvi.text_device_width)
73 - dw->dvi.text_x_width;
76 for (i = 0; i <= dw->dvi.cache.index; i++)
77 if (dw->dvi.cache.adjustable[i])
79 dw->dvi.text_x_width += extra;
82 for (i = 0; i <= dw->dvi.cache.index; i++)
83 if (dw->dvi.cache.adjustable[i]) {
88 deltap = &dw->dvi.cache.cache[i].delta;
90 if (*deltap > 0 && x + *deltap < MIN_DELTA) {
91 x = MIN_DELTA - *deltap;
101 dw->dvi.cache.adjustable[i] = 0;
109 if (dw->dvi.cache.char_index != 0) {
110 AdjustCacheDeltas (dw);
111 XDrawText (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
112 dw->dvi.cache.start_x, dw->dvi.cache.start_y,
113 dw->dvi.cache.cache, dw->dvi.cache.index + 1);
115 dw->dvi.cache.index = 0;
116 dw->dvi.cache.max = DVI_TEXT_CACHE_SIZE;
118 if (dw->dvi.noPolyText)
119 dw->dvi.cache.max = 1;
121 dw->dvi.cache.char_index = 0;
122 dw->dvi.cache.cache[0].nchars = 0;
123 dw->dvi.cache.start_x = dw->dvi.cache.x = XPos (dw);
124 dw->dvi.cache.start_y = dw->dvi.cache.y = YPos (dw);
132 dw->dvi.text_x_width = dw->dvi.text_device_width = 0;
133 dw->dvi.word_flag = 0;
140 dw->dvi.word_flag = 1;
143 #define charWidth(fi,c) (\
145 (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
147 (fi)->max_bounds.width\
152 int charExists (fi, c)
158 if (fi->per_char == NULL ||
159 c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
161 p = fi->per_char + (c - fi->min_char_or_byte2);
162 return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
163 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
167 DoCharacter (dw, c, wid)
170 int wid; /* width in device units */
172 register XFontStruct *font;
173 register XTextItem *text;
180 * quick and dirty extents calculation:
182 if (!(y + 24 >= dw->dvi.extents.y1
183 && y - 24 <= dw->dvi.extents.y2
185 && x + 24 >= dw->dvi.extents.x1
186 && x - 24 <= dw->dvi.extents.x2
191 if (y != dw->dvi.cache.y
192 || dw->dvi.cache.char_index >= DVI_CHAR_CACHE_SIZE) {
195 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
198 * load a new font, if the current block is not empty,
201 if (dw->dvi.cache.font_size != dw->dvi.state->font_size ||
202 dw->dvi.cache.font_number != dw->dvi.state->font_number)
206 dw->dvi.cache.font_size = dw->dvi.state->font_size;
207 dw->dvi.cache.font_number = dw->dvi.state->font_number;
208 dw->dvi.cache.font = QueryFont (dw,
209 dw->dvi.cache.font_number,
210 dw->dvi.cache.font_size);
211 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
212 ++dw->dvi.cache.index;
213 if (dw->dvi.cache.index >= dw->dvi.cache.max)
215 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
216 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
219 if (x != dw->dvi.cache.x || dw->dvi.word_flag) {
220 if (dw->dvi.cache.cache[dw->dvi.cache.index].nchars != 0) {
221 ++dw->dvi.cache.index;
222 if (dw->dvi.cache.index >= dw->dvi.cache.max)
224 dw->dvi.cache.cache[dw->dvi.cache.index].nchars = 0;
225 dw->dvi.cache.adjustable[dw->dvi.cache.index] = 0;
227 dw->dvi.cache.adjustable[dw->dvi.cache.index]
229 dw->dvi.word_flag = 0;
231 font = dw->dvi.cache.font;
232 text = &dw->dvi.cache.cache[dw->dvi.cache.index];
233 if (text->nchars == 0) {
234 text->chars = &dw->dvi.cache.char_cache[dw->dvi.cache.char_index];
235 text->delta = x - dw->dvi.cache.x;
236 if (font != dw->dvi.font) {
237 text->font = font->fid;
241 dw->dvi.cache.x += text->delta;
243 if (charExists(font, c)) {
245 dw->dvi.cache.char_cache[dw->dvi.cache.char_index++] = (char) c;
247 w = charWidth(font, c);
248 dw->dvi.cache.x += w;
250 dw->dvi.text_x_width += w;
251 dw->dvi.text_device_width += wid;
257 int FindCharWidth (dw, buf, widp)
265 if (dw->dvi.device_font == 0
266 || dw->dvi.state->font_number != dw->dvi.device_font_number) {
267 dw->dvi.device_font_number = dw->dvi.state->font_number;
269 = QueryDeviceFont (dw, dw->dvi.device_font_number);
271 if (dw->dvi.device_font
272 && device_char_width (dw->dvi.device_font,
273 dw->dvi.state->font_size, buf, widp))
276 maxpos = MaxFontPosition (dw);
277 for (i = 1; i <= maxpos; i++) {
278 DeviceFont *f = QueryDeviceFont (dw, i);
279 if (f && device_font_special (f)
280 && device_char_width (f, dw->dvi.state->font_size,
282 dw->dvi.state->font_number = i;
289 /* Return the width of the character in device units. */
291 int PutCharacter (dw, buf)
300 if (!dw->dvi.display_enable)
301 return 0; /* The width doesn't matter in this case. */
302 prevFont = dw->dvi.state->font_number;
303 if (!FindCharWidth (dw, buf, &wid))
305 map = QueryFontMap (dw, dw->dvi.state->font_number);
307 c = DviCharIndex (map, buf);
309 DoCharacter (dw, c, wid);
311 (void) FakeCharacter (dw, buf, wid);
312 dw->dvi.state->font_number = prevFont;
316 /* Return 1 if we can fake it; 0 otherwise. */
319 int FakeCharacter (dw, buf, wid)
328 if (buf[0] == '\0' || buf[1] == '\0' || buf[2] != '\0')
330 #define pack2(c1, c2) (((c1) << 8) | (c2))
332 switch (pack2(buf[0], buf[1])) {
333 case pack2('f', 'i'):
336 case pack2('f', 'l'):
339 case pack2('f', 'f'):
342 case pack2('F', 'i'):
345 case pack2('F', 'l'):
351 oldx = dw->dvi.state->x;
352 oldw = dw->dvi.text_device_width;
354 for (; *chars; chars++) {
356 dw->dvi.state->x += PutCharacter (dw, ch);
358 dw->dvi.state->x = oldx;
359 dw->dvi.text_device_width = oldw + wid;
364 PutNumberedCharacter (dw, c)
372 if (!dw->dvi.display_enable)
375 if (dw->dvi.device_font == 0
376 || dw->dvi.state->font_number != dw->dvi.device_font_number) {
377 dw->dvi.device_font_number = dw->dvi.state->font_number;
379 = QueryDeviceFont (dw, dw->dvi.device_font_number);
382 if (dw->dvi.device_font == 0
383 || !device_code_width (dw->dvi.device_font,
384 dw->dvi.state->font_size, c, &wid))
386 if (dw->dvi.native) {
387 DoCharacter (dw, c, wid);
390 map = QueryFontMap (dw, dw->dvi.state->font_number);
393 for (name = device_name_for_code (dw->dvi.device_font, c);
395 name = device_name_for_code ((DeviceFont *)0, c)) {
396 int code = DviCharIndex (map, name);
398 DoCharacter (dw, code, wid);
401 if (FakeCharacter (dw, name, wid))
410 XClearWindow (XtDisplay (dw), XtWindow (dw));
417 int desired_line_width;
419 if (dw->dvi.line_thickness < 0)
420 desired_line_width = (int)(((double)dw->dvi.device_resolution
421 * dw->dvi.state->font_size)
422 / (10.0*72.0*dw->dvi.sizescale));
424 desired_line_width = dw->dvi.line_thickness;
426 if (desired_line_width != dw->dvi.line_width) {
428 values.line_width = DeviceToX(dw, desired_line_width);
429 if (values.line_width == 0)
430 values.line_width = 1;
431 XChangeGC(XtDisplay (dw), dw->dvi.normal_GC,
432 GCLineWidth, &values);
433 dw->dvi.line_width = desired_line_width;
442 unsigned long mask = GCFillStyle | GCForeground;
444 fill_type = (dw->dvi.fill * 10) / (DVI_FILL_MAX + 1);
445 if (dw->dvi.fill_type != fill_type) {
447 if (fill_type <= 0) {
448 values.foreground = dw->dvi.background;
449 values.fill_style = FillSolid;
450 } else if (fill_type >= 9) {
451 values.foreground = dw->dvi.foreground;
452 values.fill_style = FillSolid;
454 values.foreground = dw->dvi.foreground;
455 values.fill_style = FillOpaqueStippled;
456 values.stipple = dw->dvi.gray[fill_type - 1];
459 XChangeGC(XtDisplay (dw), dw->dvi.fill_GC, mask, &values);
460 dw->dvi.fill_type = fill_type;
471 AdjustCacheDeltas (dw);
475 XDrawLine (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
477 xp + DeviceToX (dw, x), yp + DeviceToX (dw, y));
481 DrawCircle (dw, diam)
487 AdjustCacheDeltas (dw);
489 d = DeviceToX (dw, diam);
490 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
491 XPos (dw), YPos (dw) - d/2,
496 DrawFilledCircle (dw, diam)
502 AdjustCacheDeltas (dw);
504 d = DeviceToX (dw, diam);
505 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
506 XPos (dw), YPos (dw) - d/2,
508 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
509 XPos (dw), YPos (dw) - d/2,
514 DrawEllipse (dw, a, b)
518 AdjustCacheDeltas (dw);
520 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
521 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
522 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
526 DrawFilledEllipse (dw, a, b)
530 AdjustCacheDeltas (dw);
532 XFillArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
533 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
534 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
535 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
536 XPos (dw), YPos (dw) - DeviceToX (dw, b/2),
537 DeviceToX (dw, a), DeviceToX (dw, b), 0, 64*360);
541 DrawArc (dw, x0, y0, x1, y1)
546 int rad = (int)((sqrt ((double)x0*x0 + (double)y0*y0)
547 + sqrt ((double)x1*x1 + (double)y1*y1) + 1.0)/2.0);
548 if ((x0 == 0 && y0 == 0) || (x1 == 0 && y1 == 0))
550 angle1 = (int)(atan2 ((double)y0, (double)-x0)*180.0*64.0/M_PI);
551 angle2 = (int)(atan2 ((double)-y1, (double)x1)*180.0*64.0/M_PI);
557 AdjustCacheDeltas (dw);
560 rad = DeviceToX (dw, rad);
561 XDrawArc (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
562 XPos (dw) + DeviceToX (dw, x0) - rad,
563 YPos (dw) + DeviceToX (dw, y0) - rad,
564 rad*2, rad*2, angle1, angle2);
568 DrawPolygon (dw, v, n)
579 AdjustCacheDeltas (dw);
581 p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
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;
594 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
595 p, n + 2, CoordModeOrigin);
600 DrawFilledPolygon (dw, v, n)
613 AdjustCacheDeltas (dw);
615 p = (XPoint *)XtMalloc((n + 2)*sizeof(XPoint));
616 p[0].x = p[n+1].x = XPos (dw);
617 p[0].y = p[n+1].y = YPos (dw);
620 for (i = 0; i < n; i++) {
622 p[i + 1].x = DeviceToX (dw, dx) + p[0].x;
624 p[i + 1].y = DeviceToX (dw, dy) + p[0].y;
626 XFillPolygon (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
627 p, n + 1, Complex, CoordModeOrigin);
628 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.fill_GC,
629 p, n + 2, CoordModeOrigin);
633 #define POINTS_MAX 10000
636 appendPoint(points, pointi, x, y)
641 if (*pointi < POINTS_MAX) {
642 points[*pointi].x = x;
643 points[*pointi].y = y;
651 flattenCurve(points, pointi, x2, y2, x3, y3, x4, y4)
654 int x2, y2, x3, y3, x4, y4;
656 int x1, y1, dx, dy, n1, n2, n;
658 x1 = points[*pointi - 1].x;
659 y1 = points[*pointi - 1].y;
664 n1 = dy*(x2 - x1) - dx*(y2 - y1);
665 n2 = dy*(x3 - x1) - dx*(y3 - y1);
670 n = n1 > n2 ? n1 : n2;
672 if (n*n / (dy*dy + dx*dx) <= FLATNESS*FLATNESS)
673 appendPoint (points, pointi, x4, y4);
675 flattenCurve (points, pointi,
676 (x1 + x2)/2, (y1 + y2)/2,
677 (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
678 (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
679 flattenCurve (points, pointi,
680 (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
681 (x3 + x4)/2, (y3 + y4)/2,
687 DrawSpline (dw, v, n)
696 XPoint points[POINTS_MAX];
698 if (n == 0 || (n & 1) != 0)
700 AdjustCacheDeltas (dw);
708 tx = sx + DeviceToX (dw, dx);
709 ty = sy + DeviceToX (dw, dy);
713 appendPoint (points, &pointi, sx, sy);
714 appendPoint (points, &pointi, (sx + tx)/2, (sy + ty)/2);
716 for (i = 2; i < n; i += 2) {
717 int ux = ox + DeviceToX (dw, dx += v[i]);
718 int uy = oy + DeviceToX (dw, dy += v[i+1]);
719 flattenCurve (points, &pointi,
720 (sx + tx*5)/6, (sy + ty*5)/6,
721 (tx*5 + ux)/6, (ty*5 + uy)/6,
722 (tx + ux)/2, (ty + uy)/2);
729 appendPoint (points, &pointi, tx, ty);
731 XDrawLines (XtDisplay (dw), XtWindow (dw), dw->dvi.normal_GC,
732 points, pointi, CoordModeOrigin);
739 c-continued-statement-offset: 8
743 c-tab-always-indent: nil