Stubs for EnumServiceStatus32, small changes.
[wine/multimedia.git] / graphics / x11drv / text.c
blob8f09124ee45718ea6b25df0cd92002f28664ae5b
1 /*
2 * X11 graphics driver text functions
4 * Copyright 1993,1994 Alexandre Julliard
5 */
7 #include <stdlib.h>
8 #include "ts_xlib.h"
9 #include <X11/Xatom.h>
10 #include "windows.h"
11 #include <math.h>
12 #include "dc.h"
13 #include "gdi.h"
14 /*#include "callback.h"*/
15 #include "heap.h"
16 #include "x11font.h"
17 #include "debugstr.h"
18 #include "debug.h"
20 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
21 #define IROUND(x) (int)((x)>0? (x)+0.5 : (x) - 0.5)
23 /***********************************************************************
24 * X11DRV_ExtTextOut
26 BOOL32
27 X11DRV_ExtTextOut( DC *dc, INT32 x, INT32 y, UINT32 flags,
28 const RECT32 *lprect, LPCSTR str, UINT32 count,
29 const INT32 *lpDx )
31 int i;
32 fontObject* pfo;
33 INT32 width, ascent, descent, xwidth, ywidth;
34 XFontStruct* font;
35 RECT32 rect;
36 char dfBreakChar, lfUnderline, lfStrikeOut;
37 BOOL32 rotated = FALSE;
38 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
40 if (!X11DRV_SetupGCForText( dc )) return TRUE;
42 pfo = XFONT_GetFontObject( physDev->font );
43 font = pfo->fs;
45 if (pfo->lf.lfEscapement && pfo->lpX11Trans)
46 rotated = TRUE;
47 dfBreakChar = (char)pfo->fi->df.dfBreakChar;
48 lfUnderline = (pfo->fo_flags & FO_SYNTH_UNDERLINE) ? 1 : 0;
49 lfStrikeOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT) ? 1 : 0;
51 TRACE(text,"hdc=%04x df=%04x %d,%d %s, %d flags=%d lpDx=%p\n",
52 dc->hSelf, (UINT16)(physDev->font), x, y,
53 debugstr_an (str, count), count, flags, lpDx);
55 /* some strings sent here end in a newline for whatever reason. I have no
56 clue what the right treatment should be in general, but ignoring
57 terminating newlines seems ok. MW, April 1998. */
58 if (count > 0 && str[count - 1] == '\n') count--;
60 if (lprect != NULL) TRACE(text, "\trect=(%d,%d - %d,%d)\n",
61 lprect->left, lprect->top,
62 lprect->right, lprect->bottom );
63 /* Setup coordinates */
65 if (dc->w.textAlign & TA_UPDATECP)
67 x = dc->w.CursPosX;
68 y = dc->w.CursPosY;
71 if (flags & (ETO_OPAQUE | ETO_CLIPPED)) /* there's a rectangle */
73 if (!lprect) /* not always */
75 SIZE32 sz;
76 if (flags & ETO_CLIPPED) /* Can't clip with no rectangle */
77 return FALSE;
78 if (!X11DRV_GetTextExtentPoint( dc, str, count, &sz ))
79 return FALSE;
80 rect.left = XLPTODP( dc, x );
81 rect.right = XLPTODP( dc, x+sz.cx );
82 rect.top = YLPTODP( dc, y );
83 rect.bottom = YLPTODP( dc, y+sz.cy );
85 else
87 rect.left = XLPTODP( dc, lprect->left );
88 rect.right = XLPTODP( dc, lprect->right );
89 rect.top = YLPTODP( dc, lprect->top );
90 rect.bottom = YLPTODP( dc, lprect->bottom );
92 if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
93 if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
96 x = XLPTODP( dc, x );
97 y = YLPTODP( dc, y );
99 TRACE(text,"\treal coord: x=%i, y=%i, rect=(%d,%d - %d,%d)\n",
100 x, y, rect.left, rect.top, rect.right, rect.bottom);
102 /* Draw the rectangle */
104 if (flags & ETO_OPAQUE)
106 TSXSetForeground( display, physDev->gc, physDev->backgroundPixel );
107 TSXFillRectangle( display, physDev->drawable, physDev->gc,
108 dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
109 rect.right-rect.left, rect.bottom-rect.top );
111 if (!count) return TRUE; /* Nothing more to do */
113 /* Compute text starting position */
115 if (lpDx) /* have explicit character cell x offsets in logical coordinates */
117 int extra = dc->wndExtX / 2;
118 for (i = width = 0; i < count; i++) width += lpDx[i];
119 width = (width * dc->vportExtX + extra ) / dc->wndExtX;
121 else
123 SIZE32 sz;
124 if (!X11DRV_GetTextExtentPoint( dc, str, count, &sz ))
125 return FALSE;
126 width = XLSTODS(dc, sz.cx);
128 ascent = pfo->lpX11Trans ? pfo->lpX11Trans->ascent : font->ascent;
129 descent = pfo->lpX11Trans ? pfo->lpX11Trans->descent : font->descent;
130 xwidth = pfo->lpX11Trans ? width * pfo->lpX11Trans->a /
131 pfo->lpX11Trans->pixelsize : width;
132 ywidth = pfo->lpX11Trans ? width * pfo->lpX11Trans->b /
133 pfo->lpX11Trans->pixelsize : 0;
135 switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
137 case TA_LEFT:
138 if (dc->w.textAlign & TA_UPDATECP) {
139 dc->w.CursPosX = XDPTOLP( dc, x + xwidth );
140 dc->w.CursPosY = YDPTOLP( dc, y - ywidth );
142 break;
143 case TA_RIGHT:
144 x -= xwidth;
145 y += ywidth;
146 if (dc->w.textAlign & TA_UPDATECP) {
147 dc->w.CursPosX = XDPTOLP( dc, x );
148 dc->w.CursPosY = YDPTOLP( dc, y );
150 break;
151 case TA_CENTER:
152 x -= xwidth / 2;
153 y += ywidth / 2;
154 break;
157 switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
159 case TA_TOP:
160 x -= pfo->lpX11Trans ? ascent * pfo->lpX11Trans->c /
161 pfo->lpX11Trans->pixelsize : 0;
162 y += pfo->lpX11Trans ? ascent * pfo->lpX11Trans->d /
163 pfo->lpX11Trans->pixelsize : ascent;
164 break;
165 case TA_BOTTOM:
166 x += pfo->lpX11Trans ? descent * pfo->lpX11Trans->c /
167 pfo->lpX11Trans->pixelsize : 0;
168 y -= pfo->lpX11Trans ? descent * pfo->lpX11Trans->d /
169 pfo->lpX11Trans->pixelsize : descent;
170 break;
171 case TA_BASELINE:
172 break;
175 /* Set the clip region */
177 if (flags & ETO_CLIPPED)
179 SaveVisRgn( dc->hSelf );
180 CLIPPING_IntersectVisRect( dc, rect.left, rect.top, rect.right,
181 rect.bottom, FALSE );
184 /* Draw the text background if necessary */
186 if (dc->w.backgroundMode != TRANSPARENT)
188 /* If rectangle is opaque and clipped, do nothing */
189 if (!(flags & ETO_CLIPPED) || !(flags & ETO_OPAQUE))
191 /* Only draw if rectangle is not opaque or if some */
192 /* text is outside the rectangle */
193 if (!(flags & ETO_OPAQUE) ||
194 (x < rect.left) ||
195 (x + width >= rect.right) ||
196 (y - ascent < rect.top) ||
197 (y + descent >= rect.bottom))
199 TSXSetForeground( display, physDev->gc,
200 physDev->backgroundPixel );
201 TSXFillRectangle( display, physDev->drawable, physDev->gc,
202 dc->w.DCOrgX + x,
203 dc->w.DCOrgY + y - ascent,
204 width,
205 ascent + descent );
210 /* Draw the text (count > 0 verified) */
212 TSXSetForeground( display, physDev->gc, physDev->textPixel );
213 if (!dc->w.charExtra && !dc->w.breakExtra && !lpDx)
215 if(!rotated)
217 TSXDrawString( display, physDev->drawable, physDev->gc,
218 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
220 else
222 /* have to render character by character. */
223 double offset = 0.0;
224 int i;
226 for(i=0; i<count; i++) {
227 int char_metric_offset = (unsigned char) str[i]
228 - font->min_char_or_byte2;
229 int x_i = IROUND((double) (dc->w.DCOrgX + x) + offset *
230 pfo->lpX11Trans->a / 1000.0 );
231 int y_i = IROUND((double) (dc->w.DCOrgY + y) - offset *
232 pfo->lpX11Trans->b / 1000.0 );
234 TSXDrawString( display, physDev->drawable, physDev->gc,
235 x_i, y_i, &str[i], 1);
236 offset += (double) (font->per_char ?
237 font->per_char[char_metric_offset].attributes:
238 font->min_bounds.attributes);
242 else /* Now the fun begins... */
244 XTextItem *items, *pitem;
245 int delta;
247 /* allocate max items */
249 pitem = items = HEAP_xalloc( GetProcessHeap(), 0,
250 count * sizeof(XTextItem) );
251 delta = i = 0;
252 if( lpDx ) /* explicit character widths */
254 int extra = dc->wndExtX / 2;
256 while (i < count)
258 /* initialize text item with accumulated delta */
260 pitem->chars = (char *)str + i;
261 pitem->delta = delta;
262 pitem->nchars = 0;
263 pitem->font = None;
264 delta = 0;
266 /* add characters to the same XTextItem until new delta
267 * becomes non-zero */
271 delta += (lpDx[i] * dc->vportExtX + extra) / dc->wndExtX
272 - TSXTextWidth( font, str + i, 1);
273 pitem->nchars++;
274 } while ((++i < count) && !delta);
275 pitem++;
278 else /* charExtra or breakExtra */
280 while (i < count)
282 pitem->chars = (char *)str + i;
283 pitem->delta = delta;
284 pitem->nchars = 0;
285 pitem->font = None;
286 delta = 0;
290 delta += dc->w.charExtra;
291 if (str[i] == (char)dfBreakChar) delta += dc->w.breakExtra;
292 pitem->nchars++;
293 } while ((++i < count) && !delta);
294 pitem++;
298 TSXDrawText( display, physDev->drawable, physDev->gc,
299 dc->w.DCOrgX + x, dc->w.DCOrgY + y, items, pitem - items );
300 HeapFree( GetProcessHeap(), 0, items );
303 /* Draw underline and strike-out if needed */
305 if (lfUnderline)
307 long linePos, lineWidth;
309 if (!TSXGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
310 linePos = descent - 1;
311 if (!TSXGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
312 lineWidth = 0;
313 else if (lineWidth == 1) lineWidth = 0;
314 TSXSetLineAttributes( display, physDev->gc, lineWidth,
315 LineSolid, CapRound, JoinBevel );
316 TSXDrawLine( display, physDev->drawable, physDev->gc,
317 dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
318 dc->w.DCOrgX + x + width, dc->w.DCOrgY + y + linePos );
320 if (lfStrikeOut)
322 long lineAscent, lineDescent;
323 if (!TSXGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
324 lineAscent = ascent / 2;
325 if (!TSXGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
326 lineDescent = -lineAscent * 2 / 3;
327 TSXSetLineAttributes( display, physDev->gc, lineAscent + lineDescent,
328 LineSolid, CapRound, JoinBevel );
329 TSXDrawLine( display, physDev->drawable, physDev->gc,
330 dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
331 dc->w.DCOrgX + x + width, dc->w.DCOrgY + y - lineAscent );
334 if (flags & ETO_CLIPPED)
335 RestoreVisRgn( dc->hSelf );
337 return TRUE;