Commit e41ddd05 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

First draft of ExtTextOut on an open path.

parent de8f8334
......@@ -722,7 +722,8 @@ BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT);
TRACE("%s count %d nSize = %ld\n", debugstr_wn(str, count), count, nSize);
TRACE("%s %s count %d nSize = %ld\n", debugstr_wn(str, count),
wine_dbgstr_rect(lprect), count, nSize);
pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
pemr->emr.iType = EMR_EXTTEXTOUTW;
......
......@@ -1759,14 +1759,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
if(PATH_IsPathOpen(dc->path))
{
FIXME("called on an open path\n");
GDI_ReleaseObj( hdc );
return ret;
}
if(!dc->funcs->pExtTextOut)
if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
{
GDI_ReleaseObj( hdc );
return ret;
......@@ -1854,7 +1847,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
}
if(flags & ETO_OPAQUE)
if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
if(count == 0)
......@@ -1961,7 +1954,7 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
break;
}
if(GetBkMode(hdc) != TRANSPARENT)
if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
{
if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
{
......@@ -2012,7 +2005,12 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
}
if(span)
{
dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + i - span : NULL);
else
dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + i - span : NULL);
span = 0;
......@@ -2023,7 +2021,13 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
if(i == count - 1)
{
ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
y - (offsets ? offsets[count - span] * sinEsc : 0),
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + count - span : NULL);
else
ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
y - (offsets ? offsets[count - span] * sinEsc : 0),
(flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
glyphs, span, deltas ? deltas + count - span : NULL);
......@@ -2040,7 +2044,12 @@ BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
flags |= ETO_GLYPH_INDEX;
}
ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
if (PATH_IsPathOpen(dc->path))
ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
glyphs ? glyphs : reordered_str, count, deltas);
else
ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
glyphs ? glyphs : reordered_str, count, deltas);
}
......
......@@ -405,6 +405,8 @@ extern BOOL PATH_AssignGdiPath(GdiPath *pPathDest, const GdiPath *pPathSrc);
extern BOOL PATH_MoveTo(DC *dc);
extern BOOL PATH_LineTo(DC *dc, INT x, INT y);
extern BOOL PATH_Rectangle(DC *dc, INT x1, INT y1, INT x2, INT y2);
extern BOOL PATH_ExtTextOut(DC *dc, INT x, INT y, UINT flags, const RECT *lprc,
LPCWSTR str, UINT count, const INT *dx);
extern BOOL PATH_Ellipse(DC *dc, INT x1, INT y1, INT x2, INT y2);
extern BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
INT xStart, INT yStart, INT xEnd, INT yEnd, INT lines);
......
......@@ -3,6 +3,7 @@
*
* Copyright 1997, 1998 Martin Boehme
* 1999 Huw D M Davies
* Copyright 2005 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -26,6 +27,7 @@
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#if defined(HAVE_FLOAT_H)
#include <float.h>
#endif
......@@ -1212,6 +1214,208 @@ static BOOL PATH_PathToRegion(GdiPath *pPath, INT nPolyFillMode,
return TRUE;
}
static inline INT int_from_fixed(FIXED f)
{
return (f.fract >= 0x8000) ? (f.value + 1) : f.value;
}
/**********************************************************************
* PATH_BezierTo
*
* internally used by PATH_add_outline
*/
static void PATH_BezierTo(GdiPath *pPath, POINT *lppt, INT n)
{
if (n < 2) return;
if (n == 2)
{
PATH_AddEntry(pPath, &lppt[1], PT_LINETO);
}
else if (n == 3)
{
PATH_AddEntry(pPath, &lppt[0], PT_BEZIERTO);
PATH_AddEntry(pPath, &lppt[1], PT_BEZIERTO);
PATH_AddEntry(pPath, &lppt[2], PT_BEZIERTO);
}
else
{
POINT pt[3];
INT i = 0;
pt[2] = lppt[0];
n--;
while (n > 2)
{
pt[0] = pt[2];
pt[1] = lppt[i+1];
pt[2].x = (lppt[i+2].x + lppt[i+1].x) / 2;
pt[2].y = (lppt[i+2].y + lppt[i+1].y) / 2;
PATH_BezierTo(pPath, pt, 3);
n--;
i++;
}
pt[0] = pt[2];
pt[1] = lppt[i+1];
pt[2] = lppt[i+2];
PATH_BezierTo(pPath, pt, 3);
}
}
static BOOL PATH_add_outline(DC *dc, INT x, INT y, TTPOLYGONHEADER *header, DWORD size)
{
GdiPath *pPath = &dc->path;
TTPOLYGONHEADER *start;
POINT pt;
start = header;
while ((char *)header < (char *)start + size)
{
TTPOLYCURVE *curve;
if (header->dwType != TT_POLYGON_TYPE)
{
FIXME("Unknown header type %ld\n", header->dwType);
return FALSE;
}
pt.x = x + int_from_fixed(header->pfxStart.x);
pt.y = y - int_from_fixed(header->pfxStart.y);
LPtoDP(dc->hSelf, &pt, 1);
PATH_AddEntry(pPath, &pt, PT_MOVETO);
curve = (TTPOLYCURVE *)(header + 1);
while ((char *)curve < (char *)header + header->cb)
{
/*TRACE("curve->wType %d\n", curve->wType);*/
switch(curve->wType)
{
case TT_PRIM_LINE:
{
WORD i;
for (i = 0; i < curve->cpfx; i++)
{
pt.x = x + int_from_fixed(curve->apfx[i].x);
pt.y = y - int_from_fixed(curve->apfx[i].y);
LPtoDP(dc->hSelf, &pt, 1);
PATH_AddEntry(pPath, &pt, PT_LINETO);
}
break;
}
case TT_PRIM_QSPLINE:
case TT_PRIM_CSPLINE:
{
WORD i;
POINTFX ptfx;
POINT *pts = HeapAlloc(GetProcessHeap(), 0, (curve->cpfx + 1) * sizeof(POINT));
if (!pts) return FALSE;
ptfx = *(POINTFX *)((char *)curve - sizeof(POINTFX));
pts[0].x = x + int_from_fixed(ptfx.x);
pts[0].y = y - int_from_fixed(ptfx.y);
LPtoDP(dc->hSelf, &pts[0], 1);
for(i = 0; i < curve->cpfx; i++)
{
pts[i + 1].x = x + int_from_fixed(curve->apfx[i].x);
pts[i + 1].y = y - int_from_fixed(curve->apfx[i].y);
LPtoDP(dc->hSelf, &pts[i + 1], 1);
}
PATH_BezierTo(pPath, pts, curve->cpfx + 1);
HeapFree(GetProcessHeap(), 0, pts);
break;
}
default:
FIXME("Unknown curve type %04x\n", curve->wType);
return FALSE;
}
curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx];
}
header = (TTPOLYGONHEADER *)((char *)header + header->cb);
}
return CloseFigure(dc->hSelf);
}
/**********************************************************************
* PATH_ExtTextOut
*/
BOOL PATH_ExtTextOut(DC *dc, INT x, INT y, UINT flags, const RECT *lprc,
LPCWSTR str, UINT count, const INT *dx)
{
unsigned int idx;
double cosEsc, sinEsc;
LOGFONTW lf;
POINT org;
HDC hdc = dc->hSelf;
TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
wine_dbgstr_rect(lprc), debugstr_wn(str, count), count, dx);
if (!count) return TRUE;
GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
if (lf.lfEscapement != 0)
{
cosEsc = cos(lf.lfEscapement * M_PI / 1800);
sinEsc = sin(lf.lfEscapement * M_PI / 1800);
} else
{
cosEsc = 1;
sinEsc = 0;
}
GetDCOrgEx(hdc, &org);
for (idx = 0; idx < count; idx++)
{
INT offset = 0, xoff = 0, yoff = 0;
GLYPHMETRICS gm;
DWORD dwSize;
void *outline;
dwSize = GetGlyphOutlineW(hdc, str[idx], GGO_GLYPH_INDEX | GGO_NATIVE, &gm, 0, NULL, NULL);
if (!dwSize) return FALSE;
outline = HeapAlloc(GetProcessHeap(), 0, dwSize);
if (!outline) return FALSE;
GetGlyphOutlineW(hdc, str[idx], GGO_GLYPH_INDEX | GGO_NATIVE, &gm, dwSize, outline, NULL);
PATH_add_outline(dc, org.x + x + xoff, org.x + y + yoff, outline, dwSize);
HeapFree(GetProcessHeap(), 0, outline);
if (dx)
{
offset += dx[idx];
xoff = offset * cosEsc;
yoff = offset * -sinEsc;
}
else
{
xoff += gm.gmCellIncX;
yoff += gm.gmCellIncY;
}
}
return TRUE;
}
/* PATH_EmptyPath
*
* Removes all entries from the path and sets the path state to PATH_Null.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment