[NtGDI] Change TextOut

Separate TextOut for internal use.
Use flTextAlign internally.
Not sure why GetDeviceCap was used for determining rendering. SVN commit
logs are unavailable. Include code from wine that might make more sense.
This commit is contained in:
James Tabor 2019-03-05 16:03:15 -06:00
parent f5f6ea2965
commit 3377fe184e
2 changed files with 97 additions and 30 deletions

View file

@ -410,7 +410,7 @@ IntGetFontLanguageInfo(PDC Dc)
pdcattr = Dc->pdcattr; pdcattr = Dc->pdcattr;
/* This might need a test for a HEBREW- or ARABIC_CHARSET as well */ /* This might need a test for a HEBREW- or ARABIC_CHARSET as well */
if ( pdcattr->lTextAlign & TA_RTLREADING ) if ( pdcattr->flTextAlign & TA_RTLREADING )
if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 ) if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
result|=GCP_REORDER; result|=GCP_REORDER;

View file

@ -50,6 +50,16 @@ static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
FT_Library g_FreeTypeLibrary; FT_Library g_FreeTypeLibrary;
typedef struct
{
FT_Int major;
FT_Int minor;
FT_Int patch;
} FT_Version_t;
static FT_Version_t FT_Version;
static DWORD FT_SimpleVersion;
#define FT_VERSION_VALUE(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch))
/* special font names */ /* special font names */
static const UNICODE_STRING g_MarlettW = RTL_CONSTANT_STRING(L"Marlett"); static const UNICODE_STRING g_MarlettW = RTL_CONSTANT_STRING(L"Marlett");
@ -641,6 +651,13 @@ InitFontSupport(VOID)
return FALSE; return FALSE;
} }
FT_Library_Version(g_FreeTypeLibrary,&FT_Version.major,&FT_Version.minor,&FT_Version.patch);
DPRINT1("FreeType version is %d.%d.%d\n",FT_Version.major,FT_Version.minor,FT_Version.patch);
FT_SimpleVersion = ((FT_Version.major << 16) & 0xff0000) |
((FT_Version.minor << 8) & 0x00ff00) |
((FT_Version.patch ) & 0x0000ff);
IntLoadSystemFonts(); IntLoadSystemFonts();
IntLoadFontSubstList(&g_FontSubstListHead); IntLoadFontSubstList(&g_FontSubstListHead);
@ -1638,17 +1655,40 @@ IntGdiCleanupPrivateFontsForProcess(VOID)
} while (Entry); } while (Entry);
} }
static BOOL is_hinting_enabled(void)
{
static int enabled = -1;
if (enabled == -1)
{
/* Use the >= 2.2.0 function if available */
FT_TrueTypeEngineType type = FT_Get_TrueType_Engine_Type(g_FreeTypeLibrary);
enabled = (type == FT_TRUETYPE_ENGINE_TYPE_PATENTED);
DPRINT1("hinting is %senabled\n", enabled ? "" : "NOT ");
}
return enabled;
}
static BOOL is_subpixel_rendering_enabled( void )
{
static int enabled = -1;
if (enabled == -1)
{
/* FreeType >= 2.8.1 offers LCD-optimezed rendering without lcd filters. */
if (FT_SimpleVersion >= FT_VERSION_VALUE(2, 8, 1))
enabled = TRUE;
else enabled = FALSE;
DPRINT1("subpixel rendering is %senabled\n", enabled ? "" : "NOT ");
}
return enabled;
}
BOOL FASTCALL BOOL FASTCALL
IntIsFontRenderingEnabled(VOID) IntIsFontRenderingEnabled(VOID)
{ {
BOOL Ret = g_RenderingEnabled; return is_hinting_enabled() && is_subpixel_rendering_enabled() && g_RenderingEnabled;
HDC hDC;
hDC = IntGetScreenDC();
if (hDC)
Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && g_RenderingEnabled;
return Ret;
} }
VOID FASTCALL VOID FASTCALL
@ -5506,8 +5546,8 @@ IntNormalizeAngle(LONG nTenthAngle)
BOOL BOOL
APIENTRY APIENTRY
GreExtTextOutW( IntExtTextOutW(
IN HDC hDC, IN PDC dc,
IN INT XStart, IN INT XStart,
IN INT YStart, IN INT YStart,
IN UINT fuOptions, IN UINT fuOptions,
@ -5523,7 +5563,6 @@ GreExtTextOutW(
* appropriate) * appropriate)
*/ */
DC *dc;
PDC_ATTR pdcattr; PDC_ATTR pdcattr;
SURFOBJ *SurfObj; SURFOBJ *SurfObj;
SURFACE *psurf = NULL; SURFACE *psurf = NULL;
@ -5565,19 +5604,8 @@ GreExtTextOutW(
return FALSE; return FALSE;
} }
/* NOTE: This function locks the screen DC, so it must never be called
with a DC already locked */
Render = IntIsFontRenderingEnabled(); Render = IntIsFontRenderingEnabled();
// TODO: Write test-cases to exactly match real Windows in different
// bad parameters (e.g. does Windows check the DC or the RECT first?).
dc = DC_LockDc(hDC);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if (PATH_IsPathOpen(dc->dclevel)) if (PATH_IsPathOpen(dc->dclevel))
{ {
bResult = PATH_ExtTextOut(dc, bResult = PATH_ExtTextOut(dc,
@ -5608,7 +5636,7 @@ GreExtTextOutW(
IntLPtoDP(dc, (POINT *)lprc, 2); IntLPtoDP(dc, (POINT *)lprc, 2);
} }
if (pdcattr->lTextAlign & TA_UPDATECP) if (pdcattr->flTextAlign & TA_UPDATECP)
{ {
Start.x = pdcattr->ptlCurrent.x; Start.x = pdcattr->ptlCurrent.x;
Start.y = pdcattr->ptlCurrent.y; Start.y = pdcattr->ptlCurrent.y;
@ -5743,7 +5771,7 @@ GreExtTextOutW(
use_kerning = FT_HAS_KERNING(face); use_kerning = FT_HAS_KERNING(face);
previous = 0; previous = 0;
if ((fuOptions & ETO_OPAQUE) || if ((fuOptions & ETO_OPAQUE) ||
(pdcattr->lTextAlign & (TA_CENTER | TA_RIGHT)) || (pdcattr->flTextAlign & (TA_CENTER | TA_RIGHT)) ||
memcmp(&mat, &identityMat, sizeof(mat)) != 0 || memcmp(&mat, &identityMat, sizeof(mat)) != 0 ||
plf->lfUnderline || plf->lfStrikeOut) plf->lfUnderline || plf->lfStrikeOut)
{ {
@ -5813,12 +5841,12 @@ GreExtTextOutW(
} }
// Process the X and Y alignments. // Process the X and Y alignments.
if ((pdcattr->lTextAlign & TA_CENTER) == TA_CENTER) if ((pdcattr->flTextAlign & TA_CENTER) == TA_CENTER)
{ {
XStart64 = -DeltaX64 / 2; XStart64 = -DeltaX64 / 2;
YStart64 = -DeltaY64 / 2; YStart64 = -DeltaY64 / 2;
} }
else if ((pdcattr->lTextAlign & TA_RIGHT) == TA_RIGHT) else if ((pdcattr->flTextAlign & TA_RIGHT) == TA_RIGHT)
{ {
XStart64 = -DeltaX64; XStart64 = -DeltaX64;
YStart64 = -DeltaY64; YStart64 = -DeltaY64;
@ -5849,13 +5877,13 @@ GreExtTextOutW(
/* Process the vertical alignment */ /* Process the vertical alignment */
#define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM) #define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM)
RtlZeroMemory(vecs, sizeof(vecs)); RtlZeroMemory(vecs, sizeof(vecs));
if ((pdcattr->lTextAlign & VALIGN_MASK) == TA_BASELINE) if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BASELINE)
{ {
vecs[1].y = -FontGDI->tmAscent << 16; // upper left vecs[1].y = -FontGDI->tmAscent << 16; // upper left
vecs[4].y = 0; // baseline vecs[4].y = 0; // baseline
vecs[0].y = FontGDI->tmDescent << 16; // lower left vecs[0].y = FontGDI->tmDescent << 16; // lower left
} }
else if ((pdcattr->lTextAlign & VALIGN_MASK) == TA_BOTTOM) else if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BOTTOM)
{ {
vecs[1].y = -FontGDI->tmHeight << 16; // upper left vecs[1].y = -FontGDI->tmHeight << 16; // upper left
vecs[4].y = -FontGDI->tmDescent << 16; // baseline vecs[4].y = -FontGDI->tmDescent << 16; // baseline
@ -6236,7 +6264,7 @@ GreExtTextOutW(
MouseSafetyOnDrawEnd(dc->ppdev); MouseSafetyOnDrawEnd(dc->ppdev);
} }
if (pdcattr->lTextAlign & TA_UPDATECP) { if (pdcattr->flTextAlign & TA_UPDATECP) {
pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x; pdcattr->ptlCurrent.x = DestRect.right - dc->ptlDCOrig.x;
} }
@ -6252,6 +6280,45 @@ Cleanup:
if (TextObj != NULL) if (TextObj != NULL)
TEXTOBJ_UnlockText(TextObj); TEXTOBJ_UnlockText(TextObj);
return bResult;
}
BOOL
APIENTRY
GreExtTextOutW(
IN HDC hDC,
IN INT XStart,
IN INT YStart,
IN UINT fuOptions,
IN OPTIONAL PRECTL lprc,
IN LPCWSTR String,
IN INT Count,
IN OPTIONAL LPINT Dx,
IN DWORD dwCodePage)
{
BOOL bResult;
DC *dc;
// TODO: Write test-cases to exactly match real Windows in different
// bad parameters (e.g. does Windows check the DC or the RECT first?).
dc = DC_LockDc(hDC);
if (!dc)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
bResult = IntExtTextOutW( dc,
XStart,
YStart,
fuOptions,
lprc,
String,
Count,
Dx,
dwCodePage );
DC_UnlockDc(dc); DC_UnlockDc(dc);
return bResult; return bResult;