📄 text.c
字号:
{
DPRINT1("WARNING: Could not set the charmap!\n");
}
}
Render = IntIsFontRenderingEnabled();
if (Render)
RenderMode = IntGetFontRenderMode(&TextObj->logfont.elfEnumLogfontEx.elfLogFont);
else
RenderMode = FT_RENDER_MODE_MONO;
error = FT_Set_Pixel_Sizes(
face,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
/* FIXME should set character height if neg */
(TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ?
- TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight :
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight == 0 ? 11 : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight));
if (error)
{
DPRINT1("Error in setting pixel sizes: %u\n", error);
IntUnLockFreeType;
goto fail;
}
/*
* Process the vertical alignment and determine the yoff.
*/
if (dc->Dc_Attr.lTextAlign & TA_BASELINE)
yoff = 0;
else if (dc->Dc_Attr.lTextAlign & TA_BOTTOM)
yoff = -face->size->metrics.descender >> 6;
else /* TA_TOP */
yoff = face->size->metrics.ascender >> 6;
use_kerning = FT_HAS_KERNING(face);
previous = 0;
/*
* Process the horizontal alignment and modify XStart accordingly.
*/
if (dc->Dc_Attr.lTextAlign & (TA_RIGHT | TA_CENTER))
{
ULONGLONG TextWidth = 0;
LPCWSTR TempText = String;
int Start;
/*
* Calculate width of the text.
*/
if (NULL != Dx)
{
Start = Count < 2 ? 0 : Count - 2;
TextWidth = Count < 2 ? 0 : (Dx[Count - 2] << 6);
}
else
{
Start = 0;
}
TempText = String + Start;
for (i = Start; i < Count; i++)
{
if (fuOptions & ETO_GLYPH_INDEX)
glyph_index = *TempText;
else
glyph_index = FT_Get_Char_Index(face, *TempText);
if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
{
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index);
}
glyph = face->glyph;
realglyph = NtGdiGlyphCacheSet(face, glyph_index,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight, glyph, RenderMode);
if (!realglyph)
{
DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
IntUnLockFreeType;
goto fail;
}
}
/* retrieve kerning distance */
if (use_kerning && previous && glyph_index)
{
FT_Vector delta;
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
TextWidth += delta.x;
}
TextWidth += realglyph->advance.x >> 10;
previous = glyph_index;
TempText++;
}
previous = 0;
if (dc->Dc_Attr.lTextAlign & TA_RIGHT)
{
RealXStart -= TextWidth;
}
else
{
RealXStart -= TextWidth / 2;
}
}
TextLeft = RealXStart;
TextTop = YStart;
BackgroundLeft = (RealXStart + 32) >> 6;
/*
* The main rendering loop.
*/
for (i = 0; i < Count; i++)
{
if (fuOptions & ETO_GLYPH_INDEX)
glyph_index = *String;
else
glyph_index = FT_Get_Char_Index(face, *String);
if (!(realglyph = NtGdiGlyphCacheGet(face, glyph_index,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight)))
{
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
{
DPRINT1("Failed to load and render glyph! [index: %u]\n", glyph_index);
IntUnLockFreeType;
goto fail;
}
glyph = face->glyph;
realglyph = NtGdiGlyphCacheSet(face,
glyph_index,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight,
glyph,
RenderMode);
if (!realglyph)
{
DPRINT1("Failed to render glyph! [index: %u]\n", glyph_index);
IntUnLockFreeType;
goto fail;
}
}
// DbgPrint("realglyph: %x\n", realglyph);
// DbgPrint("TextLeft: %d\n", TextLeft);
/* retrieve kerning distance and move pen position */
if (use_kerning && previous && glyph_index && NULL == Dx)
{
FT_Vector delta;
FT_Get_Kerning(face, previous, glyph_index, 0, &delta);
TextLeft += delta.x;
}
// DPRINT1("TextLeft: %d\n", TextLeft);
// DPRINT1("TextTop: %d\n", TextTop);
if (realglyph->format == ft_glyph_format_outline)
{
DbgPrint("Should already be done\n");
// error = FT_Render_Glyph(glyph, RenderMode);
error = FT_Glyph_To_Bitmap(&realglyph, RenderMode, 0, 0);
if (error)
{
DPRINT1("WARNING: Failed to render glyph!\n");
goto fail;
}
}
realglyph2 = (FT_BitmapGlyph)realglyph;
// DPRINT1("Pitch: %d\n", pitch);
// DPRINT1("Advance: %d\n", realglyph->advance.x);
if (fuOptions & ETO_OPAQUE)
{
DestRect.left = BackgroundLeft;
DestRect.right = (TextLeft + (realglyph->advance.x >> 10) + 32) >> 6;
DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
IntEngBitBlt(
&BitmapObj->SurfObj,
NULL,
NULL,
dc->CombinedClip,
NULL,
&DestRect,
&SourcePoint,
&SourcePoint,
&BrushBgInst.BrushObject,
&BrushOrigin,
ROP3_TO_ROP4(PATCOPY));
BackgroundLeft = DestRect.right;
}
DestRect.left = ((TextLeft + 32) >> 6) + realglyph2->left;
DestRect.right = DestRect.left + realglyph2->bitmap.width;
DestRect.top = TextTop + yoff - realglyph2->top;
DestRect.bottom = DestRect.top + realglyph2->bitmap.rows;
// DbgPrint("lrtb %d %d %d %d\n", DestRect.left, DestRect.right,
// DestRect.top, DestRect.bottom);
// DbgPrint("specified lrtb %d %d %d %d\n", SpecifiedDestRect.left, SpecifiedDestRect.right,
// SpecifiedDestRect.top, SpecifiedDestRect.bottom);
// DbgPrint ("dc->w.DCOrgX: %d\n", dc->w.DCOrgX);
bitSize.cx = realglyph2->bitmap.width;
bitSize.cy = realglyph2->bitmap.rows;
MaskRect.right = realglyph2->bitmap.width;
MaskRect.bottom = realglyph2->bitmap.rows;
/*
* We should create the bitmap out of the loop at the biggest possible
* glyph size. Then use memset with 0 to clear it and sourcerect to
* limit the work of the transbitblt.
*
* FIXME: DIB bitmaps should have an lDelta which is a multiple of 4.
* Here we pass in the pitch from the FreeType bitmap, which is not
* guaranteed to be a multiple of 4. If it's not, we should expand
* the FreeType bitmap to a temporary bitmap.
*/
HSourceGlyph = EngCreateBitmap(bitSize, realglyph2->bitmap.pitch,
(realglyph2->bitmap.pixel_mode == ft_pixel_mode_grays) ?
BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
realglyph2->bitmap.buffer);
if ( !HSourceGlyph )
{
DPRINT1("WARNING: EngLockSurface() failed!\n");
// FT_Done_Glyph(realglyph);
IntUnLockFreeType;
goto fail;
}
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
if ( !SourceGlyphSurf )
{
EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
goto fail;
}
/*
* Use the font data as a mask to paint onto the DCs surface using a
* brush.
*/
if (lprc &&
(fuOptions & ETO_CLIPPED) &&
DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX)
{
// We do the check '>=' instead of '>' to possibly save an iteration
// through this loop, since it's breaking after the drawing is done,
// and x is always incremented.
DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX;
DoBreak = TRUE;
}
IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
dc->CombinedClip,
XlateObj,
XlateObj2,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
&BrushFgInst.BrushObject,
&BrushOrigin);
EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
if (DoBreak)
{
break;
}
if (NULL == Dx)
{
TextLeft += realglyph->advance.x >> 10;
// DbgPrint("new TextLeft: %d\n", TextLeft);
}
else
{
TextLeft += Dx[i] << 6;
// DbgPrint("new TextLeft2: %d\n", TextLeft);
}
previous = glyph_index;
String++;
}
IntUnLockFreeType;
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
BITMAPOBJ_UnlockBitmap(BitmapObj);
if(TextObj != NULL)
TEXTOBJ_UnlockText(TextObj);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
if (NULL != SafeString)
{
ExFreePool((void*)SafeString);
}
if (NULL != Dx)
{
ExFreePool(Dx);
}
DC_UnlockDc( dc );
return TRUE;
fail:
if ( XlateObj2 != NULL )
EngDeleteXlate(XlateObj2);
if ( XlateObj != NULL )
EngDeleteXlate(XlateObj);
if(TextObj != NULL)
TEXTOBJ_UnlockText(TextObj);
BITMAPOBJ_UnlockBitmap(BitmapObj);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
if (hBrushFg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
}
if (NULL != SafeString)
{
ExFreePool((void*)SafeString);
}
if (NULL != Dx)
{
ExFreePool(Dx);
}
DC_UnlockDc(dc);
return FALSE;
}
BOOL
STDCALL
NtGdiGetAspectRatioFilterEx(HDC hDC,
LPSIZE AspectRatio)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL
STDCALL
NtGdiGetCharABCWidths(HDC hDC,
UINT FirstChar,
UINT LastChar,
LPABC abc)
{
LPABC SafeBuffer;
PDC dc;
PTEXTOBJ TextObj;
PFONTGDI FontGDI;
FT_Face face;
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
NTSTATUS Status;
if (LastChar < FirstChar)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
BufferSize = (LastChar - FirstChar + 1) * sizeof(ABC);
SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
if (SafeBuffer == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
dc = DC_LockDc(hDC);
if (dc == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
hFont = dc->Dc_Attr.hlfntNew;
TextObj = TEXTOBJ_LockText(hFont);
DC_UnlockDc(dc);
if (TextObj == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
FontGDI = ObjToGDI(TextObj->Font, FONT);
face = FontGDI->face;
if (face->charmap == NULL)
{
for (i = 0; i < face->num_charmaps; i++)
{
charmap = face->charmaps[i];
if (charmap->encoding != 0)
{
found = charmap;
break;
}
}
if (!found)
{
DPRINT1("WARNING: Could not find desired charmap!\n");
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
IntLockFreeType;
FT_Set_Charmap(face, found);
IntUnLockFreeType;
}
IntLockFreeType;
FT_Set_Pixel_Sizes(face,
TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfWidth,
/* FIXME should set charac
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -