diff --git a/reactos/subsystems/win32/win32k/include/path.h b/reactos/subsystems/win32/win32k/include/path.h index d7e21171f11..f528d7d48ed 100644 --- a/reactos/subsystems/win32/win32k/include/path.h +++ b/reactos/subsystems/win32/win32k/include/path.h @@ -67,6 +67,7 @@ BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2); BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height); BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, HRGN *pHrgn); +BOOL FASTCALL PATH_ExtTextOut(PDC dc,INT x,INT y,UINT flags,const RECT *lprc,LPCWSTR str,UINT count,const INT *dx); VOID FASTCALL IntGdiCloseFigure(PPATH pPath); BOOL FASTCALL PATH_Delete(HPATH hPath); diff --git a/reactos/subsystems/win32/win32k/objects/freetype.c b/reactos/subsystems/win32/win32k/objects/freetype.c index cb8686c89c2..c6fdcaf7187 100644 --- a/reactos/subsystems/win32/win32k/objects/freetype.c +++ b/reactos/subsystems/win32/win32k/objects/freetype.c @@ -3162,24 +3162,11 @@ NtGdiExtTextOutW( Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR)); if (! NT_SUCCESS(Status)) { - goto fail; + goto fail; } } String = SafeString; - if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) - { - // At least one of the two flags were specified. Copy lprc. Once. - Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT)); - if (!NT_SUCCESS(Status)) - { - DC_UnlockDc(dc); - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return FALSE; - } - IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2); - } - if (NULL != UnsafeDx && Count > 0) { Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT); @@ -3188,12 +3175,40 @@ NtGdiExtTextOutW( goto fail; } Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT)); - if (! NT_SUCCESS(Status)) + if (!NT_SUCCESS(Status)) { goto fail; } } + if (lprc) + { + Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT)); + if (!NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + goto fail; + } + } + + if (PATH_IsPathOpen(dc->DcLevel)) + { + if (!PATH_ExtTextOut( dc, + XStart, + YStart, + fuOptions, + (const RECT *)&SpecifiedDestRect, + SafeString, + Count, + (const INT *)Dx)) goto fail; + goto good; + } + + if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) + { + IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2); + } + BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap); if ( !BitmapObj ) { @@ -3636,13 +3651,14 @@ NtGdiExtTextOutW( } BRUSHOBJ_UnlockBrush(BrushFg); NtGdiDeleteObject(hBrushFg); +good: if (NULL != SafeString) { - ExFreePool((void*)SafeString); + ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT); } if (NULL != Dx) { - ExFreePool(Dx); + ExFreePoolWithTag(Dx, TAG_GDITEXT); } DC_UnlockDc( dc ); @@ -3669,11 +3685,11 @@ fail: } if (NULL != SafeString) { - ExFreePool((void*)SafeString); + ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT); } if (NULL != Dx) { - ExFreePool(Dx); + ExFreePoolWithTag(Dx, TAG_GDITEXT); } DC_UnlockDc(dc); diff --git a/reactos/subsystems/win32/win32k/objects/path.c b/reactos/subsystems/win32/win32k/objects/path.c index 8337f92c31f..980041511f1 100644 --- a/reactos/subsystems/win32/win32k/objects/path.c +++ b/reactos/subsystems/win32/win32k/objects/path.c @@ -1854,6 +1854,239 @@ PATH_WidenPath(DC *dc) return ret; } +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 +FASTCALL +PATH_BezierTo(PPATH 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 +FASTCALL +PATH_add_outline(PDC dc, INT x, INT y, TTPOLYGONHEADER *header, DWORD size) +{ + PPATH pPath; + TTPOLYGONHEADER *start; + POINT pt; + + start = header; + + pPath = PATH_LockPath(dc->DcLevel.hPath); + { + return FALSE; + } + + while ((char *)header < (char *)start + size) + { + TTPOLYCURVE *curve; + + if (header->dwType != TT_POLYGON_TYPE) + { + DPRINT1("Unknown header type %d\n", header->dwType); + return FALSE; + } + + pt.x = x + int_from_fixed(header->pfxStart.x); + pt.y = y - int_from_fixed(header->pfxStart.y); + IntLPtoDP(dc, &pt, 1); + PATH_AddEntry(pPath, &pt, PT_MOVETO); + + curve = (TTPOLYCURVE *)(header + 1); + + while ((char *)curve < (char *)header + header->cb) + { + /*DPRINT1("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); + IntLPtoDP(dc, &pt, 1); + PATH_AddEntry(pPath, &pt, PT_LINETO); + } + break; + } + + case TT_PRIM_QSPLINE: + case TT_PRIM_CSPLINE: + { + WORD i; + POINTFX ptfx; + POINT *pts = ExAllocatePoolWithTag(PagedPool, (curve->cpfx + 1) * sizeof(POINT), TAG_PATH); + + 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); + IntLPtoDP(dc, &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); + IntLPtoDP(dc, &pts[i + 1], 1); + } + + PATH_BezierTo(pPath, pts, curve->cpfx + 1); + + ExFreePoolWithTag(pts, TAG_PATH); + break; + } + + default: + DPRINT1("Unknown curve type %04x\n", curve->wType); + return FALSE; + } + + curve = (TTPOLYCURVE *)&curve->apfx[curve->cpfx]; + } + header = (TTPOLYGONHEADER *)((char *)header + header->cb); + } + + IntGdiCloseFigure( pPath ); + PATH_UnlockPath( pPath ); + return TRUE; +} + +/********************************************************************** + * PATH_ExtTextOut + */ +BOOL +FASTCALL +PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECT *lprc, + LPCWSTR str, UINT count, const INT *dx) +{ + unsigned int idx; + double cosEsc, sinEsc; + PDC_ATTR Dc_Attr; + PTEXTOBJ TextObj; + LOGFONTW lf; + POINTL org; + INT offset = 0, xoff = 0, yoff = 0; + + if (!count) return TRUE; + + Dc_Attr = dc->pDc_Attr; + if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; + + TextObj = RealizeFontInit( Dc_Attr->hlfntNew); + if ( !TextObj ) return FALSE; + + FontGetObject( TextObj, 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; + } + + IntGdiGetDCOrg(dc, &org); + + for (idx = 0; idx < count; idx++) + { + GLYPHMETRICS gm; + DWORD dwSize; + void *outline; + + dwSize = ftGdiGetGlyphOutline( dc, + str[idx], + GGO_GLYPH_INDEX | GGO_NATIVE, + &gm, + 0, + NULL, + NULL, + TRUE); + if (!dwSize) return FALSE; + + outline = ExAllocatePoolWithTag(PagedPool, dwSize, TAG_PATH); + if (!outline) return FALSE; + + ftGdiGetGlyphOutline( dc, + str[idx], + GGO_GLYPH_INDEX | GGO_NATIVE, + &gm, + dwSize, + outline, + NULL, + TRUE); + + PATH_add_outline(dc, org.x + x + xoff, org.x + y + yoff, outline, dwSize); + + ExFreePoolWithTag(outline, TAG_PATH); + + if (dx) + { + offset += dx[idx]; + xoff = offset * cosEsc; + yoff = offset * -sinEsc; + } + else + { + xoff += gm.gmCellIncX; + yoff += gm.gmCellIncY; + } + } + return TRUE; +} /***********************************************************************