2 * X11 graphics driver text functions
4 * Copyright 1993,1994 Alexandre Julliard
13 /*#include "callback.h"*/
18 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
21 /***********************************************************************
25 X11DRV_ExtTextOut( DC
*dc
, INT32 x
, INT32 y
, UINT32 flags
,
26 const RECT32
*lprect
, LPCSTR str
, UINT32 count
,
30 int dir
, ascent
, descent
, i
;
35 char dfBreakChar
, lfUnderline
, lfStrikeOut
;
37 if (!DC_SetupGCForText( dc
)) return TRUE
;
39 pfo
= XFONT_GetFontObject( dc
->u
.x
.font
);
42 dfBreakChar
= (char)pfo
->fi
->df
.dfBreakChar
;
43 lfUnderline
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
) ? 1 : 0;
44 lfStrikeOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
) ? 1 : 0;
46 TRACE(text
,"hdc=%04x df=%04x %d,%d '%.*s', %d flags=%d\n",
47 dc
->hSelf
, (UINT16
)(dc
->u
.x
.font
), x
, y
, (int)count
, str
, count
, flags
);
49 if (lprect
!= NULL
) TRACE(text
, "\trect=(%d,%d- %d,%d)\n",
50 lprect
->left
, lprect
->top
,
51 lprect
->right
, lprect
->bottom
);
52 /* Setup coordinates */
54 if (dc
->w
.textAlign
& TA_UPDATECP
)
60 if (flags
& (ETO_OPAQUE
| ETO_CLIPPED
)) /* there's a rectangle */
62 if (!lprect
) /* not always */
65 if (flags
& ETO_CLIPPED
) /* Can't clip with no rectangle */
67 if (!X11DRV_GetTextExtentPoint( dc
, str
, count
, &sz
))
69 rect
.left
= XLPTODP( dc
, x
);
70 rect
.right
= XLPTODP( dc
, x
+sz
.cx
);
71 rect
.top
= YLPTODP( dc
, y
);
72 rect
.bottom
= YLPTODP( dc
, y
+sz
.cy
);
76 rect
.left
= XLPTODP( dc
, lprect
->left
);
77 rect
.right
= XLPTODP( dc
, lprect
->right
);
78 rect
.top
= YLPTODP( dc
, lprect
->top
);
79 rect
.bottom
= YLPTODP( dc
, lprect
->bottom
);
81 if (rect
.right
< rect
.left
) SWAP_INT( rect
.left
, rect
.right
);
82 if (rect
.bottom
< rect
.top
) SWAP_INT( rect
.top
, rect
.bottom
);
88 TRACE(text
,"\treal coord: x=%i, y=%i, rect=(%d,%d-%d,%d)\n",
89 x
, y
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
91 /* Draw the rectangle */
93 if (flags
& ETO_OPAQUE
)
95 TSXSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
96 TSXFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
97 dc
->w
.DCOrgX
+ rect
.left
, dc
->w
.DCOrgY
+ rect
.top
,
98 rect
.right
-rect
.left
, rect
.bottom
-rect
.top
);
100 if (!count
) return TRUE
; /* Nothing more to do */
102 /* Compute text starting position */
104 if (lpDx
) /* have explicit character cell x offsets in logical coordinates */
106 int extra
= dc
->wndExtX
/ 2;
107 for (i
= info
.width
= 0; i
< count
; i
++) info
.width
+= lpDx
[i
];
108 info
.width
= (info
.width
* dc
->vportExtX
+ extra
) / dc
->wndExtX
;
112 TSXTextExtents( font
, str
, count
, &dir
, &ascent
, &descent
, &info
);
113 info
.width
+= count
*dc
->w
.charExtra
+ dc
->w
.breakExtra
*dc
->w
.breakCount
;
116 switch( dc
->w
.textAlign
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
119 if (dc
->w
.textAlign
& TA_UPDATECP
)
120 dc
->w
.CursPosX
= XDPTOLP( dc
, x
+ info
.width
);
124 if (dc
->w
.textAlign
& TA_UPDATECP
) dc
->w
.CursPosX
= XDPTOLP( dc
, x
);
131 switch( dc
->w
.textAlign
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
143 /* Set the clip region */
145 if (flags
& ETO_CLIPPED
)
147 hRgnClip
= dc
->w
.hClipRgn
;
148 CLIPPING_IntersectClipRect( dc
, rect
.left
, rect
.top
, rect
.right
,
149 rect
.bottom
, CLIP_INTERSECT
|CLIP_KEEPRGN
);
152 /* Draw the text background if necessary */
154 if (dc
->w
.backgroundMode
!= TRANSPARENT
)
156 /* If rectangle is opaque and clipped, do nothing */
157 if (!(flags
& ETO_CLIPPED
) || !(flags
& ETO_OPAQUE
))
159 /* Only draw if rectangle is not opaque or if some */
160 /* text is outside the rectangle */
161 if (!(flags
& ETO_OPAQUE
) ||
163 (x
+ info
.width
>= rect
.right
) ||
164 (y
-font
->ascent
< rect
.top
) ||
165 (y
+font
->descent
>= rect
.bottom
))
167 TSXSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.backgroundPixel
);
168 TSXFillRectangle( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
170 dc
->w
.DCOrgY
+ y
- font
->ascent
,
172 font
->ascent
+ font
->descent
);
177 /* Draw the text (count > 0 verified) */
179 TSXSetForeground( display
, dc
->u
.x
.gc
, dc
->w
.textPixel
);
180 if (!dc
->w
.charExtra
&& !dc
->w
.breakExtra
&& !lpDx
)
182 TSXDrawString( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
183 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
, str
, count
);
185 else /* Now the fun begins... */
187 XTextItem
*items
, *pitem
;
190 /* allocate max items */
192 pitem
= items
= HEAP_xalloc( GetProcessHeap(), 0,
193 count
* sizeof(XTextItem
) );
195 if( lpDx
) /* explicit character widths */
197 int extra
= dc
->wndExtX
/ 2;
201 /* initialize text item with accumulated delta */
203 pitem
->chars
= (char *)str
+ i
;
204 pitem
->delta
= delta
;
209 /* add characters to the same XTextItem until new delta
210 * becomes non-zero */
214 delta
+= (lpDx
[i
] * dc
->vportExtX
+ extra
) / dc
->wndExtX
215 - TSXTextWidth( font
, str
+ i
, 1);
217 } while ((++i
< count
) && !delta
);
221 else /* charExtra or breakExtra */
225 pitem
->chars
= (char *)str
+ i
;
226 pitem
->delta
= delta
;
233 delta
+= dc
->w
.charExtra
;
234 if (str
[i
] == (char)dfBreakChar
) delta
+= dc
->w
.breakExtra
;
236 } while ((++i
< count
) && !delta
);
241 TSXDrawText( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
242 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
, items
, pitem
- items
);
243 HeapFree( GetProcessHeap(), 0, items
);
246 /* Draw underline and strike-out if needed */
250 long linePos
, lineWidth
;
252 if (!TSXGetFontProperty( font
, XA_UNDERLINE_POSITION
, &linePos
))
253 linePos
= font
->descent
-1;
254 if (!TSXGetFontProperty( font
, XA_UNDERLINE_THICKNESS
, &lineWidth
))
256 else if (lineWidth
== 1) lineWidth
= 0;
257 TSXSetLineAttributes( display
, dc
->u
.x
.gc
, lineWidth
,
258 LineSolid
, CapRound
, JoinBevel
);
259 TSXDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
260 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
+ linePos
,
261 dc
->w
.DCOrgX
+ x
+ info
.width
, dc
->w
.DCOrgY
+ y
+ linePos
);
265 long lineAscent
, lineDescent
;
266 if (!TSXGetFontProperty( font
, XA_STRIKEOUT_ASCENT
, &lineAscent
))
267 lineAscent
= font
->ascent
/ 2;
268 if (!TSXGetFontProperty( font
, XA_STRIKEOUT_DESCENT
, &lineDescent
))
269 lineDescent
= -lineAscent
* 2 / 3;
270 TSXSetLineAttributes( display
, dc
->u
.x
.gc
, lineAscent
+ lineDescent
,
271 LineSolid
, CapRound
, JoinBevel
);
272 TSXDrawLine( display
, dc
->u
.x
.drawable
, dc
->u
.x
.gc
,
273 dc
->w
.DCOrgX
+ x
, dc
->w
.DCOrgY
+ y
- lineAscent
,
274 dc
->w
.DCOrgX
+ x
+ info
.width
, dc
->w
.DCOrgY
+ y
- lineAscent
);
277 if (flags
& ETO_CLIPPED
)
279 SelectClipRgn32( dc
->hSelf
, hRgnClip
);
280 DeleteObject32( hRgnClip
);