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();
28 HorizontalMove(dw
, delta
)
32 dw
->dvi
.state
->x
+= delta
;
35 HorizontalGoto(dw
, NewPosition
)
39 dw
->dvi
.state
->x
= NewPosition
;
42 VerticalMove(dw
, delta
)
46 dw
->dvi
.state
->y
+= delta
;
49 VerticalGoto(dw
, NewPosition
)
53 dw
->dvi
.state
->y
= NewPosition
;
56 AdjustCacheDeltas (dw
)
64 extra
= DeviceToX(dw
, dw
->dvi
.text_device_width
)
65 - dw
->dvi
.text_x_width
;
68 for (i
= 0; i
<= dw
->dvi
.cache
.index
; i
++)
69 if (dw
->dvi
.cache
.adjustable
[i
])
73 dw
->dvi
.text_x_width
+= extra
;
74 for (i
= 0; i
<= dw
->dvi
.cache
.index
; i
++)
75 if (dw
->dvi
.cache
.adjustable
[i
]) {
80 deltap
= &dw
->dvi
.cache
.cache
[i
].delta
;
82 if (*deltap
> 0 && x
+ *deltap
< MIN_DELTA
) {
83 x
= MIN_DELTA
- *deltap
;
93 dw
->dvi
.cache
.adjustable
[i
] = 0;
100 if (dw
->dvi
.cache
.char_index
!= 0) {
101 AdjustCacheDeltas (dw
);
102 XDrawText (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
103 dw
->dvi
.cache
.start_x
, dw
->dvi
.cache
.start_y
,
104 dw
->dvi
.cache
.cache
, dw
->dvi
.cache
.index
+ 1);
106 dw
->dvi
.cache
.index
= 0;
107 dw
->dvi
.cache
.max
= DVI_TEXT_CACHE_SIZE
;
109 if (dw
->dvi
.noPolyText
)
110 dw
->dvi
.cache
.max
= 1;
112 dw
->dvi
.cache
.char_index
= 0;
113 dw
->dvi
.cache
.cache
[0].nchars
= 0;
114 dw
->dvi
.cache
.start_x
= dw
->dvi
.cache
.x
= XPos (dw
);
115 dw
->dvi
.cache
.start_y
= dw
->dvi
.cache
.y
= YPos (dw
);
122 dw
->dvi
.text_x_width
= dw
->dvi
.text_device_width
= 0;
123 dw
->dvi
.word_flag
= 0;
129 dw
->dvi
.word_flag
= 1;
132 #define charWidth(fi,c) (\
134 (fi)->per_char[(c) - (fi)->min_char_or_byte2].width\
136 (fi)->max_bounds.width\
141 int charExists (fi
, c
)
147 if (fi
->per_char
== NULL
||
148 c
< fi
->min_char_or_byte2
|| c
> fi
->max_char_or_byte2
)
150 p
= fi
->per_char
+ (c
- fi
->min_char_or_byte2
);
151 return (p
->lbearing
!= 0 || p
->rbearing
!= 0 || p
->width
!= 0
152 || p
->ascent
!= 0 || p
->descent
!= 0 || p
->attributes
!= 0);
156 DoCharacter (dw
, c
, wid
)
159 int wid
; /* width in device units */
161 register XFontStruct
*font
;
162 register XTextItem
*text
;
169 * quick and dirty extents calculation:
171 if (!(y
+ 24 >= dw
->dvi
.extents
.y1
172 && y
- 24 <= dw
->dvi
.extents
.y2
174 && x
+ 24 >= dw
->dvi
.extents
.x1
175 && x
- 24 <= dw
->dvi
.extents
.x2
180 if (y
!= dw
->dvi
.cache
.y
181 || dw
->dvi
.cache
.char_index
>= DVI_CHAR_CACHE_SIZE
) {
186 * load a new font, if the current block is not empty,
189 if (dw
->dvi
.cache
.font_size
!= dw
->dvi
.state
->font_size
||
190 dw
->dvi
.cache
.font_number
!= dw
->dvi
.state
->font_number
)
192 dw
->dvi
.cache
.font_size
= dw
->dvi
.state
->font_size
;
193 dw
->dvi
.cache
.font_number
= dw
->dvi
.state
->font_number
;
194 dw
->dvi
.cache
.font
= QueryFont (dw
,
195 dw
->dvi
.cache
.font_number
,
196 dw
->dvi
.cache
.font_size
);
197 if (dw
->dvi
.cache
.cache
[dw
->dvi
.cache
.index
].nchars
!= 0) {
198 ++dw
->dvi
.cache
.index
;
199 if (dw
->dvi
.cache
.index
>= dw
->dvi
.cache
.max
)
201 dw
->dvi
.cache
.cache
[dw
->dvi
.cache
.index
].nchars
= 0;
202 dw
->dvi
.cache
.adjustable
[dw
->dvi
.cache
.index
] = 0;
205 if (x
!= dw
->dvi
.cache
.x
|| dw
->dvi
.word_flag
) {
206 if (dw
->dvi
.cache
.cache
[dw
->dvi
.cache
.index
].nchars
!= 0) {
207 ++dw
->dvi
.cache
.index
;
208 if (dw
->dvi
.cache
.index
>= dw
->dvi
.cache
.max
)
210 dw
->dvi
.cache
.cache
[dw
->dvi
.cache
.index
].nchars
= 0;
212 dw
->dvi
.cache
.adjustable
[dw
->dvi
.cache
.index
]
214 dw
->dvi
.word_flag
= 0;
216 font
= dw
->dvi
.cache
.font
;
217 text
= &dw
->dvi
.cache
.cache
[dw
->dvi
.cache
.index
];
218 if (text
->nchars
== 0) {
219 text
->chars
= &dw
->dvi
.cache
.char_cache
[dw
->dvi
.cache
.char_index
];
220 text
->delta
= x
- dw
->dvi
.cache
.x
;
221 if (font
!= dw
->dvi
.font
) {
222 text
->font
= font
->fid
;
226 dw
->dvi
.cache
.x
+= text
->delta
;
228 if (charExists(font
, c
)) {
230 dw
->dvi
.cache
.char_cache
[dw
->dvi
.cache
.char_index
++] = (char) c
;
232 w
= charWidth(font
, c
);
233 dw
->dvi
.cache
.x
+= w
;
235 dw
->dvi
.text_x_width
+= w
;
236 dw
->dvi
.text_device_width
+= wid
;
242 int FindCharWidth (dw
, buf
, widp
)
250 if (dw
->dvi
.device_font
== 0
251 || dw
->dvi
.state
->font_number
!= dw
->dvi
.device_font_number
) {
252 dw
->dvi
.device_font_number
= dw
->dvi
.state
->font_number
;
254 = QueryDeviceFont (dw
, dw
->dvi
.device_font_number
);
256 if (dw
->dvi
.device_font
257 && device_char_width (dw
->dvi
.device_font
,
258 dw
->dvi
.state
->font_size
, buf
, widp
))
261 maxpos
= MaxFontPosition (dw
);
262 for (i
= 1; i
<= maxpos
; i
++) {
263 DeviceFont
*f
= QueryDeviceFont (dw
, i
);
264 if (f
&& device_font_special (f
)
265 && device_char_width (f
, dw
->dvi
.state
->font_size
,
267 dw
->dvi
.state
->font_number
= i
;
274 /* Return the width of the character in device units. */
276 int PutCharacter (dw
, buf
)
285 if (!dw
->dvi
.display_enable
)
286 return 0; /* The width doesn't matter in this case. */
287 prevFont
= dw
->dvi
.state
->font_number
;
288 if (!FindCharWidth (dw
, buf
, &wid
))
290 map
= QueryFontMap (dw
, dw
->dvi
.state
->font_number
);
292 c
= DviCharIndex (map
, buf
);
294 DoCharacter (dw
, c
, wid
);
296 (void) FakeCharacter (dw
, buf
, wid
);
297 dw
->dvi
.state
->font_number
= prevFont
;
301 /* Return 1 if we can fake it; 0 otherwise. */
304 int FakeCharacter (dw
, buf
, wid
)
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
;
348 PutNumberedCharacter (dw
, c
)
356 if (!dw
->dvi
.display_enable
)
359 if (dw
->dvi
.device_font
== 0
360 || dw
->dvi
.state
->font_number
!= dw
->dvi
.device_font_number
) {
361 dw
->dvi
.device_font_number
= dw
->dvi
.state
->font_number
;
363 = QueryDeviceFont (dw
, dw
->dvi
.device_font_number
);
366 if (dw
->dvi
.device_font
== 0
367 || !device_code_width (dw
->dvi
.device_font
,
368 dw
->dvi
.state
->font_size
, c
, &wid
))
370 if (dw
->dvi
.native
) {
371 DoCharacter (dw
, c
, wid
);
374 map
= QueryFontMap (dw
, dw
->dvi
.state
->font_number
);
377 for (name
= device_name_for_code (dw
->dvi
.device_font
, c
);
379 name
= device_name_for_code ((DeviceFont
*)0, c
)) {
380 int code
= DviCharIndex (map
, name
);
382 DoCharacter (dw
, code
, wid
);
385 if (FakeCharacter (dw
, name
, wid
))
393 XClearWindow (XtDisplay (dw
), XtWindow (dw
));
400 int desired_line_width
;
402 if (dw
->dvi
.line_thickness
< 0)
403 desired_line_width
= (int)(((double)dw
->dvi
.device_resolution
404 * dw
->dvi
.state
->font_size
)
405 / (10.0*72.0*dw
->dvi
.sizescale
));
407 desired_line_width
= dw
->dvi
.line_thickness
;
409 if (desired_line_width
!= dw
->dvi
.line_width
) {
411 values
.line_width
= DeviceToX(dw
, desired_line_width
);
412 if (values
.line_width
== 0)
413 values
.line_width
= 1;
414 XChangeGC(XtDisplay (dw
), dw
->dvi
.normal_GC
,
415 GCLineWidth
, &values
);
416 dw
->dvi
.line_width
= desired_line_width
;
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
;
453 AdjustCacheDeltas (dw
);
457 XDrawLine (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
459 xp
+ DeviceToX (dw
, x
), yp
+ DeviceToX (dw
, y
));
462 DrawCircle (dw
, diam
)
468 AdjustCacheDeltas (dw
);
470 d
= DeviceToX (dw
, diam
);
471 XDrawArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
472 XPos (dw
), YPos (dw
) - d
/2,
476 DrawFilledCircle (dw
, diam
)
482 AdjustCacheDeltas (dw
);
484 d
= DeviceToX (dw
, diam
);
485 XFillArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
486 XPos (dw
), YPos (dw
) - d
/2,
488 XDrawArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
489 XPos (dw
), YPos (dw
) - d
/2,
493 DrawEllipse (dw
, a
, b
)
497 AdjustCacheDeltas (dw
);
499 XDrawArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
500 XPos (dw
), YPos (dw
) - DeviceToX (dw
, b
/2),
501 DeviceToX (dw
, a
), DeviceToX (dw
, b
), 0, 64*360);
504 DrawFilledEllipse (dw
, a
, b
)
508 AdjustCacheDeltas (dw
);
510 XFillArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
511 XPos (dw
), YPos (dw
) - DeviceToX (dw
, b
/2),
512 DeviceToX (dw
, a
), DeviceToX (dw
, b
), 0, 64*360);
513 XDrawArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
514 XPos (dw
), YPos (dw
) - DeviceToX (dw
, b
/2),
515 DeviceToX (dw
, a
), DeviceToX (dw
, b
), 0, 64*360);
518 DrawArc (dw
, x0
, y0
, x1
, y1
)
523 int rad
= (int)((sqrt ((double)x0
*x0
+ (double)y0
*y0
)
524 + sqrt ((double)x1
*x1
+ (double)y1
*y1
) + 1.0)/2.0);
525 if ((x0
== 0 && y0
== 0) || (x1
== 0 && y1
== 0))
527 angle1
= (int)(atan2 ((double)y0
, (double)-x0
)*180.0*64.0/M_PI
);
528 angle2
= (int)(atan2 ((double)-y1
, (double)x1
)*180.0*64.0/M_PI
);
534 AdjustCacheDeltas (dw
);
537 rad
= DeviceToX (dw
, rad
);
538 XDrawArc (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
539 XPos (dw
) + DeviceToX (dw
, x0
) - rad
,
540 YPos (dw
) + DeviceToX (dw
, y0
) - rad
,
541 rad
*2, rad
*2, angle1
, angle2
);
544 DrawPolygon (dw
, v
, n
)
555 AdjustCacheDeltas (dw
);
557 p
= (XPoint
*)XtMalloc((n
+ 2)*sizeof(XPoint
));
562 for (i
= 0; i
< n
; i
++) {
564 p
[i
+ 1].x
= DeviceToX (dw
, dx
) + p
[0].x
;
566 p
[i
+ 1].y
= DeviceToX (dw
, dy
) + p
[0].y
;
570 XDrawLines (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
571 p
, n
+ 2, CoordModeOrigin
);
576 DrawFilledPolygon (dw
, v
, n
)
589 AdjustCacheDeltas (dw
);
591 p
= (XPoint
*)XtMalloc((n
+ 2)*sizeof(XPoint
));
592 p
[0].x
= p
[n
+1].x
= XPos (dw
);
593 p
[0].y
= p
[n
+1].y
= YPos (dw
);
596 for (i
= 0; i
< n
; i
++) {
598 p
[i
+ 1].x
= DeviceToX (dw
, dx
) + p
[0].x
;
600 p
[i
+ 1].y
= DeviceToX (dw
, dy
) + p
[0].y
;
602 XFillPolygon (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
603 p
, n
+ 1, Complex
, CoordModeOrigin
);
604 XDrawLines (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.fill_GC
,
605 p
, n
+ 2, CoordModeOrigin
);
609 #define POINTS_MAX 10000
612 appendPoint(points
, pointi
, x
, y
)
617 if (*pointi
< POINTS_MAX
) {
618 points
[*pointi
].x
= x
;
619 points
[*pointi
].y
= y
;
627 flattenCurve(points
, pointi
, x2
, y2
, x3
, y3
, x4
, y4
)
630 int x2
, y2
, x3
, y3
, x4
, y4
;
632 int x1
, y1
, dx
, dy
, n1
, n2
, n
;
634 x1
= points
[*pointi
- 1].x
;
635 y1
= points
[*pointi
- 1].y
;
640 n1
= dy
*(x2
- x1
) - dx
*(y2
- y1
);
641 n2
= dy
*(x3
- x1
) - dx
*(y3
- y1
);
646 n
= n1
> n2
? n1
: n2
;
648 if (n
*n
/ (dy
*dy
+ dx
*dx
) <= FLATNESS
*FLATNESS
)
649 appendPoint (points
, pointi
, x4
, y4
);
651 flattenCurve (points
, pointi
,
652 (x1
+ x2
)/2, (y1
+ y2
)/2,
653 (x1
+ x2
*2 + x3
)/4, (y1
+ y2
*2 + y3
)/4,
654 (x1
+3*x2
+ 3*x3
+ x4
)/8, (y1
+3*y2
+ 3*y3
+ y4
)/8);
655 flattenCurve (points
, pointi
,
656 (x2
+ x3
*2 + x4
)/4, (y2
+ y3
*2 + y4
)/4,
657 (x3
+ x4
)/2, (y3
+ y4
)/2,
663 DrawSpline (dw
, v
, n
)
672 XPoint points
[POINTS_MAX
];
674 if (n
== 0 || (n
& 1) != 0)
676 AdjustCacheDeltas (dw
);
684 tx
= sx
+ DeviceToX (dw
, dx
);
685 ty
= sy
+ DeviceToX (dw
, dy
);
689 appendPoint (points
, &pointi
, sx
, sy
);
690 appendPoint (points
, &pointi
, (sx
+ tx
)/2, (sy
+ ty
)/2);
692 for (i
= 2; i
< n
; i
+= 2) {
693 int ux
= ox
+ DeviceToX (dw
, dx
+= v
[i
]);
694 int uy
= oy
+ DeviceToX (dw
, dy
+= v
[i
+1]);
695 flattenCurve (points
, &pointi
,
696 (sx
+ tx
*5)/6, (sy
+ ty
*5)/6,
697 (tx
*5 + ux
)/6, (ty
*5 + uy
)/6,
698 (tx
+ ux
)/2, (ty
+ uy
)/2);
705 appendPoint (points
, &pointi
, tx
, ty
);
707 XDrawLines (XtDisplay (dw
), XtWindow (dw
), dw
->dvi
.normal_GC
,
708 points
, pointi
, CoordModeOrigin
);
715 c-continued-statement-offset: 8
719 c-tab-always-indent: nil