2 * X11 graphics driver text functions
4 * Copyright 1993,1994 Alexandre Julliard
13 /*#include "callback.h"*/
17 /* #define DEBUG_TEXT */
21 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
24 extern int CLIPPING_IntersectClipRect( DC
* dc
, short left
, short top
,
25 short right
, short bottom
, UINT16 flags
);
27 /***********************************************************************
31 X11DRV_ExtTextOut( DC
*dc
, INT32 x
, INT32 y
, UINT32 flags
,
32 const RECT32
*lprect
, LPCSTR str
, UINT32 count
,
36 int dir
, ascent
, descent
, i
;
41 char dfBreakChar
, lfUnderline
, lfStrikeOut
;
43 if (!DC_SetupGCForText( dc
)) return TRUE
;
45 pfo
= XFONT_GetFontObject( dc
->u
.x
.font
);
48 dfBreakChar
= (char)pfo
->fi
->df
.dfBreakChar
;
49 lfUnderline
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
) ? 1 : 0;
50 lfStrikeOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
) ? 1 : 0;
52 dprintf_text(stddeb
,"ExtTextOut: hdc=%04x df=%04x %d,%d '%.*s', %d flags=%d\n",
53 dc
->hSelf
, (UINT16
)(dc
->u
.x
.font
), x
, y
, (int)count
, str
, count
, flags
);
55 if (lprect
!= NULL
) dprintf_text(stddeb
, "\trect=(%d,%d- %d,%d)\n",
56 lprect
->left
, lprect
->top
,
57 lprect
->right
, lprect
->bottom
);
58 /* Setup coordinates */
60 if (dc
->w
.textAlign
& TA_UPDATECP
)
66 if (flags
& (ETO_OPAQUE
| ETO_CLIPPED
)) /* there's a rectangle */
68 if (!lprect
) /* not always */
71 if (flags
& ETO_CLIPPED
) /* Can't clip with no rectangle */
73 if (!X11DRV_GetTextExtentPoint( dc
, str
, count
, &sz
))
75 rect
.left
= XLPTODP( dc
, x
);
76 rect
.right
= XLPTODP( dc
, x
+sz
.cx
);
77 rect
.top
= YLPTODP( dc
, y
);
78 rect
.bottom
= YLPTODP( dc
, y
+sz
.cy
);
82 rect
.left
= XLPTODP( dc
, lprect
->left
);
83 rect
.right
= XLPTODP( dc
, lprect
->right
);
84 rect
.top
= YLPTODP( dc
, lprect
->top
);
85 rect
.bottom
= YLPTODP( dc
, lprect
->bottom
);
87 if (rect
.right
< rect
.left
) SWAP_INT( rect
.left
, rect
.right
);
88 if (rect
.bottom
< rect
.top
) SWAP_INT( rect
.top
, rect
.bottom
);
94 dprintf_text(stddeb
,"\treal coord: x=%i, y=%i, rect=(%d,%d-%d,%d)\n",
95 x
, y
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
97 /* Draw the rectangle */
99 if (flags
& ETO_OPAQUE
)
101 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
102 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
103 dc
->w
.DCOrgX
+ rect
.left
, dc
->w
.DCOrgY
+ rect
.top
,
104 rect
.right
-rect
.left
, rect
.bottom
-rect
.top
);
106 if (!count
) return TRUE
; /* Nothing more to do */
108 /* Compute text starting position */
110 if (lpDx
) /* have explicit character cell x offsets in logical coordinates */
112 int extra
= dc
->wndExtX
/ 2;
113 for (i
= info
.width
= 0; i
< count
; i
++) info
.width
+= lpDx
[i
];
114 info
.width
= (info
.width
* dc
->vportExtX
+ extra
) / dc
->wndExtX
;
118 XTextExtents( font
, str
, count
, &dir
, &ascent
, &descent
, &info
);
119 info
.width
+= count
*dc
->w
.charExtra
+ dc
->w
.breakExtra
*dc
->w
.breakCount
;
122 switch( dc
->w
.textAlign
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
125 if (dc
->w
.textAlign
& TA_UPDATECP
)
126 dc
->w
.CursPosX
= XDPTOLP( dc
, x
+ info
.width
);
130 if (dc
->w
.textAlign
& TA_UPDATECP
) dc
->w
.CursPosX
= XDPTOLP( dc
, x
);
137 switch( dc
->w
.textAlign
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
149 /* Set the clip region */
151 if (flags
& ETO_CLIPPED
)
153 hRgnClip
= dc
->w
.hClipRgn
;
154 CLIPPING_IntersectClipRect( dc
, rect
.left
, rect
.top
, rect
.right
,
155 rect
.bottom
, CLIP_INTERSECT
|CLIP_KEEPRGN
);
158 /* Draw the text background if necessary */
160 if (dc
->w
.backgroundMode
!= TRANSPARENT
)
162 /* If rectangle is opaque and clipped, do nothing */
163 if (!(flags
& ETO_CLIPPED
) || !(flags
& ETO_OPAQUE
))
165 /* Only draw if rectangle is not opaque or if some */
166 /* text is outside the rectangle */
167 if (!(flags
& ETO_OPAQUE
) ||
169 (x
+ info
.width
>= rect
.right
) ||
170 (y
-font
->ascent
< rect
.top
) ||
171 (y
+font
->descent
>= rect
.bottom
))
173 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
174 XFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
176 dc
->w
.DCOrgY
+ y
- font
->ascent
,
178 font
->ascent
+ font
->descent
);
183 /* Draw the text (count > 0 verified) */
185 XSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
186 if (!dc
->w
.charExtra
&& !dc
->w
.breakExtra
&& !lpDx
)
188 XDrawString( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
189 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
, str
, count
);
191 else /* Now the fun begins... */
193 XTextItem
*items
, *pitem
;
196 /* allocate max items */
198 pitem
= items
= xmalloc( count
* sizeof(XTextItem
) );
200 if( lpDx
) /* explicit character widths */
202 int extra
= dc
->wndExtX
/ 2;
206 /* initialize text item with accumulated delta */
208 pitem
->chars
= (char *)str
+ i
;
209 pitem
->delta
= delta
;
214 /* add characters to the same XTextItem until new delta
215 * becomes non-zero */
219 delta
+= (lpDx
[i
] * dc
->vportExtX
+ extra
) / dc
->wndExtX
220 - XTextWidth( font
, str
+ i
, 1);
222 } while ((++i
< count
) && !delta
);
226 else /* charExtra or breakExtra */
230 pitem
->chars
= (char *)str
+ i
;
231 pitem
->delta
= delta
;
238 delta
+= dc
->w
.charExtra
;
239 if (str
[i
] == (char)dfBreakChar
) delta
+= dc
->w
.breakExtra
;
241 } while ((++i
< count
) && !delta
);
246 XDrawText( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
247 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
, items
, pitem
- items
);
251 /* Draw underline and strike-out if needed */
255 long linePos
, lineWidth
;
257 if (!XGetFontProperty( font
, XA_UNDERLINE_POSITION
, &linePos
))
258 linePos
= font
->descent
-1;
259 if (!XGetFontProperty( font
, XA_UNDERLINE_THICKNESS
, &lineWidth
))
261 else if (lineWidth
== 1) lineWidth
= 0;
262 XSetLineAttributes( display
, dc
->u
.x
.gc
, lineWidth
,
263 LineSolid
, CapRound
, JoinBevel
);
264 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
265 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
+ linePos
,
266 dc
->w
.DCOrgX
+ x
+ info
.width
, dc
->w
.DCOrgY
+ y
+ linePos
);
270 long lineAscent
, lineDescent
;
271 if (!XGetFontProperty( font
, XA_STRIKEOUT_ASCENT
, &lineAscent
))
272 lineAscent
= font
->ascent
/ 3;
273 if (!XGetFontProperty( font
, XA_STRIKEOUT_DESCENT
, &lineDescent
))
274 lineDescent
= -lineAscent
;
275 XSetLineAttributes( display
, dc
->u
.x
.gc
, lineAscent
+ lineDescent
,
276 LineSolid
, CapRound
, JoinBevel
);
277 XDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
278 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
- lineAscent
,
279 dc
->w
.DCOrgX
+ x
+ info
.width
, dc
->w
.DCOrgY
+ y
- lineAscent
);
282 if (flags
& ETO_CLIPPED
) SelectClipRgn32( dc
->hSelf
, hRgnClip
);