📄 font.c
字号:
static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int offset, const RECT *rect)
{
int prefix_x;
int prefix_end;
SIZE size;
HPEN hpen;
HPEN oldPen;
GetTextExtentPointW (hdc, str, offset, &size);
prefix_x = x + size.cx;
GetTextExtentPointW (hdc, str, offset+1, &size);
prefix_end = x + size.cx - 1;
/* The above method may eventually be slightly wrong due to kerning etc. */
/* Check for clipping */
if (rect)
{
if (prefix_x > rect->right || prefix_end < rect->left ||
y < rect->top || y > rect->bottom)
return; /* Completely outside */
/* Partially outside */
if (prefix_x < rect->left ) prefix_x = rect->left;
if (prefix_end > rect->right) prefix_end = rect->right;
}
hpen = CreatePen (PS_SOLID, 1, GetTextColor (hdc));
oldPen = SelectObject (hdc, hpen);
MoveToEx (hdc, prefix_x, y, NULL);
LineTo (hdc, prefix_end, y);
SelectObject (hdc, oldPen);
DeleteObject (hpen);
}
/***********************************************************************
* DrawTextExW (USER32.@)
*
* The documentation on the extra space required for DT_MODIFYSTRING at MSDN
* is not quite complete, especially with regard to \0. We will assume that
* the returned string could have a length of up to i_count+3 and also have
* a trailing \0 (which would be 4 more than a not-null-terminated string but
* 3 more than a null-terminated string). If this is not so then increase
* the allowance in DrawTextExA.
*/
#define MAX_BUFFER 1024
/* WINE synced 22-May-2006 */
/*
* @implemented
*/
int STDCALL
DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
{
SIZE size;
const WCHAR *strPtr;
WCHAR *retstr, *p_retstr;
size_t size_retstr;
WCHAR line[MAX_BUFFER];
int len, lh, count=i_count;
TEXTMETRICW tm;
int lmargin = 0, rmargin = 0;
int x = rect->left, y = rect->top;
int width = rect->right - rect->left;
int max_width = 0;
int last_line;
int tabwidth /* to keep gcc happy */ = 0;
int prefix_offset;
ellipsis_data ellip;
#if 0
TRACE("%s, %d, [%s] %08x\n", debugstr_wn (str, count), count,
wine_dbgstr_rect(rect), flags);
if (dtp) TRACE("Params: iTabLength=%d, iLeftMargin=%d, iRightMargin=%d\n",
dtp->iTabLength, dtp->iLeftMargin, dtp->iRightMargin);
#endif
if (!str || count == 0) return 0;
if (count == -1)
{
count = strlenW(str);
if (count == 0)
{
if( flags & DT_CALCRECT)
{
rect->right = rect->left;
rect->bottom = rect->top;
}
return 0;
}
}
strPtr = str;
if (flags & DT_SINGLELINE)
flags &= ~DT_WORDBREAK;
GetTextMetricsW(hdc, &tm);
if (flags & DT_EXTERNALLEADING)
lh = tm.tmHeight + tm.tmExternalLeading;
else
lh = tm.tmHeight;
if (dtp)
{
lmargin = dtp->iLeftMargin * tm.tmAveCharWidth;
rmargin = dtp->iRightMargin * tm.tmAveCharWidth;
if (!(flags & (DT_CENTER | DT_RIGHT)))
x += lmargin;
dtp->uiLengthDrawn = 0; /* This param RECEIVES number of chars processed */
}
if (flags & DT_EXPANDTABS)
{
int tabstop = ((flags & DT_TABSTOP) && dtp) ? dtp->iTabLength : 8;
tabwidth = tm.tmAveCharWidth * tabstop;
}
if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
if (flags & DT_MODIFYSTRING)
{
size_retstr = (count + 4) * sizeof (WCHAR);
retstr = HeapAlloc(GetProcessHeap(), 0, size_retstr);
if (!retstr) return 0;
memcpy (retstr, str, size_retstr);
}
else
{
size_retstr = 0;
retstr = NULL;
}
p_retstr = retstr;
do
{
len = sizeof(line)/sizeof(line[0]);
last_line = !(flags & DT_NOCLIP) && y + ((flags & DT_EDITCONTROL) ? 2*lh-1 : lh) > rect->bottom;
strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags, &size, last_line, &p_retstr, tabwidth, &prefix_offset, &ellip);
if (flags & DT_CENTER)
x = (rect->left + rect->right - size.cx) / 2;
else if (flags & DT_RIGHT) x = rect->right - size.cx;
if (flags & DT_SINGLELINE)
{
if (flags & DT_VCENTER) y = rect->top +
(rect->bottom - rect->top) / 2 - size.cy / 2;
else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
}
if (!(flags & DT_CALCRECT))
{
const WCHAR *str = line;
int xseg = x;
while (len)
{
int len_seg;
SIZE size;
if ((flags & DT_EXPANDTABS))
{
const WCHAR *p;
p = str; while (p < str+len && *p != TAB) p++;
len_seg = p - str;
if (len_seg != len && !GetTextExtentPointW(hdc, str, len_seg, &size))
return 0;
}
else
len_seg = len;
if (!ExtTextOutW( hdc, xseg, y,
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
rect, str, len_seg, NULL )) return 0;
if (prefix_offset != -1 && prefix_offset < len_seg)
{
TEXT_DrawUnderscore (hdc, xseg, y + tm.tmAscent + 1, str, prefix_offset, (flags & DT_NOCLIP) ? NULL : rect);
}
len -= len_seg;
str += len_seg;
if (len)
{
assert ((flags & DT_EXPANDTABS) && *str == TAB);
len--; str++;
xseg += ((size.cx/tabwidth)+1)*tabwidth;
if (prefix_offset != -1)
{
if (prefix_offset < len_seg)
{
/* We have just drawn an underscore; we ought to
* figure out where the next one is. I am going
* to leave it for now until I have a better model
* for the line, which will make reprefixing easier.
* This is where ellip would be used.
*/
prefix_offset = -1;
}
else
prefix_offset -= len_seg;
}
}
}
}
else if (size.cx > max_width)
max_width = size.cx;
y += lh;
if (dtp)
dtp->uiLengthDrawn += len;
}
while (strPtr && !last_line);
if (flags & DT_CALCRECT)
{
rect->right = rect->left + max_width;
rect->bottom = y;
if (dtp)
rect->right += lmargin + rmargin;
}
if (retstr)
{
memcpy (str, retstr, size_retstr);
HeapFree (GetProcessHeap(), 0, retstr);
}
return y - rect->top;
}
/***********************************************************************
* DrawTextExA (USER32.@)
*
* If DT_MODIFYSTRING is specified then there must be room for up to
* 4 extra characters. We take great care about just how much modified
* string we return.
*
* @implemented
*/
/* WINE synced 22-May-2006 */
int STDCALL
DrawTextExA( HDC hdc, LPSTR str, INT count,
LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
{
WCHAR *wstr;
WCHAR *p;
INT ret = 0;
int i;
DWORD wcount;
DWORD wmax;
DWORD amax;
if (!count) return 0;
if( !str || ((count == -1) && !(count = strlen(str))))
{
if( flags & DT_CALCRECT)
{
rect->right = rect->left;
rect->bottom = rect->top;
}
return 0;
}
wcount = MultiByteToWideChar( CP_ACP, 0, str, count, NULL, 0 );
wmax = wcount;
amax = count;
if (flags & DT_MODIFYSTRING)
{
wmax += 4;
amax += 4;
}
wstr = HeapAlloc(GetProcessHeap(), 0, wmax * sizeof(WCHAR));
if (wstr)
{
MultiByteToWideChar( CP_ACP, 0, str, count, wstr, wcount );
if (flags & DT_MODIFYSTRING)
for (i=4, p=wstr+wcount; i--; p++) *p=0xFFFE;
/* Initialise the extra characters so that we can see which ones
* change. U+FFFE is guaranteed to be not a unicode character and
* so will not be generated by DrawTextEx itself.
*/
ret = DrawTextExW( hdc, wstr, wcount, rect, flags, dtp );
if (flags & DT_MODIFYSTRING)
{
/* Unfortunately the returned string may contain multiple \0s
* and so we need to measure it ourselves.
*/
for (i=4, p=wstr+wcount; i-- && *p != 0xFFFE; p++) wcount++;
WideCharToMultiByte( CP_ACP, 0, wstr, wcount, str, amax, NULL, NULL );
}
HeapFree(GetProcessHeap(), 0, wstr);
}
return ret;
}
/***********************************************************************
* DrawTextW (USER32.@)
*
* @implemented
*/
int STDCALL
DrawTextW( HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags )
{
DRAWTEXTPARAMS dtp;
memset (&dtp, 0, sizeof(dtp));
if (flags & DT_TABSTOP)
{
dtp.iTabLength = (flags >> 8) && 0xff;
flags &= 0xffff00ff;
}
return DrawTextExW(hdc, (LPWSTR)str, count, rect, flags, &dtp);
}
/***********************************************************************
* DrawTextA (USER32.@)
*
* @implemented
*/
int STDCALL
DrawTextA( HDC hdc, LPCSTR str, INT count, LPRECT rect, UINT flags )
{
DRAWTEXTPARAMS dtp;
memset (&dtp, 0, sizeof(dtp));
if (flags & DT_TABSTOP)
{
dtp.iTabLength = (flags >> 8) && 0xff;
flags &= 0xffff00ff;
}
return DrawTextExA( hdc, (LPSTR)str, count, rect, flags, &dtp );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -