WindowsXP/windows/core/ntgdi/test/teff/te-textout.cpp
2025-04-27 07:49:33 -04:00

339 lines
7.8 KiB
C++

// te-textout.cpp: implementation of TE_TextOut() and related functions
// Stuff to eventually go in the DLL
#include <stdafx.h>
#include <te-globals.h>
#include <te-textout.h>
#include <te-effect.h>
#include <te-library.h>
#include <direct.h> // for chdir()
#include <te-outline.h>
#include <te-placement.h>
#include <te-image.h>
#define new DEBUG_NEW
//////////////////////////////////////////////////////////////////////////////
void
TE_MoveToLocation(void)
{
if (chdir(TE_Location))
TRACE("\nUnable to find directory %s.", TE_Location);
}
FIXED
DoubleToFIXED(double num)
{
long l = (long)(num * 65536L);
return *(FIXED *)&l;
}
// fixed_to_double - converts a fixed point number to a double
double
FIXEDToDouble(FIXED num)
{
long l = *(long *)&num;
return (double)(l / 65536.0);
}
//////////////////////////////////////////////////////////////////////////////
BOOL
ConvertSpline(DWORD buffer_size, LPTTPOLYGONHEADER poly, CTE_Outline& ol)
{
TRACE
(
"\nLPTTPOLYGONHEADER: size=%d, type=%d.",
poly->cb, poly->dwType
);
dxLPI = (double)xLPI;
dyLPI = (double)yLPI;
dxScale = (double)Scale;
dyScale = (double)Scale * dxLPI / dyLPI;
cbTotal = dwrc;
while( cbTotal > 0 )
{
HPEN hPenOld;
dprintf( "Polygon Header:" );
dprintf( " cb = %lu", lpph->cb );
dprintf( " dwType = %d", lpph->dwType );
PrintPointFX( " pfxStart = ", lpph->pfxStart );
DrawXMark( hdc, lpph->pfxStart );
nItem = 0;
lpb = (LPBYTE)lpph + sizeof(TTPOLYGONHEADER);
//---- Calculate size of data ----
cbOutline = (long)lpph->cb - sizeof(TTPOLYGONHEADER);
pptStart = (POINT *)&lpph->pfxStart; // Starting Point
pptStart->x = MapFX(lpph->pfxStart.x );
pptStart->y = MapFY(lpph->pfxStart.y );
while( cbOutline > 0 )
{
int n;
UINT u;
LPTTPOLYCURVE lpc;
dprintf( " cbOutline = %ld", cbOutline );
nItem++;
lpc = (LPTTPOLYCURVE)lpb;
switch( lpc->wType )
{
case TT_PRIM_LINE:
dprintf( " Item %d: Line", nItem );
break;
case TT_PRIM_CSPLINE:
dprintf( " Item %d: CSpline", nItem );
break;
default:
dprintf( " Item %d: unknown type %u", nItem, lpc->wType );
break;
}
dprintf( " # of points: %d", lpc->cpfx );
for( u = 0; u < lpc->cpfx; u++ )
{
PrintPointFX( " Point = ", lpc->apfx[u] );
DrawXMark( hdc, lpc->apfx[u] );
((POINT *)lpc->apfx)[u].x = MapFX( lpc->apfx[u].x );
((POINT *)lpc->apfx)[u].y = MapFY( lpc->apfx[u].y );
}
hPenOld = SelectObject( hdc, hPen );
MoveToEx( hdc, pptStart->x, pptStart->y , 0);
switch( lpc->wType )
{
case TT_PRIM_LINE:
PolylineTo(hdc, (POINT *)lpc->apfx, (DWORD)lpc->cpfx);
break;
case TT_PRIM_CSPLINE:
PolyBezierTo(hdc, (POINT *)lpc->apfx, (DWORD)lpc->cpfx);
break;
}
SelectObject( hdc, hPenOld );
pptStart = (POINT *)&lpc->apfx[lpc->cpfx - 1]; // Starting Point
n = sizeof(TTPOLYCURVE) + sizeof(POINTFX) * (lpc->cpfx - 1);
lpb += n;
cbOutline -= n;
}
hPenOld = SelectObject( hdc, hPen );
pptStart = (POINT *)&lpph->pfxStart; // Starting Point
LineTo( hdc, pptStart->x, pptStart->y);
SelectObject( hdc, hPenOld );
dprintf( "ended at cbOutline = %ld", cbOutline );
cbTotal -= lpph->cb;
lpph = (LPTTPOLYGONHEADER)lpb;
}
dprintf( "ended at cbTotal = %ld", cbTotal );
return TRUE;
}
BOOL
TE_TextOut
(
HDC hdc, // handle to device context
int nXStart, // x-coordinate of starting position
int nYStart, // y-coordinate of starting position
LPCTSTR lpString, // pointer to string
int cbString, // number of characters in string
LPCTSTR lpEffect // name of text effect
)
{
TRACE("\nTE_TextOut(): Applying effect %s to string %s.", lpEffect, lpString);
TextOut(hdc, nXStart, nYStart, lpString, cbString);
// Examine the currently loaded font
//TE_Height = ...
// Get a pointer to the nominated effect
CTE_Effect* pEffect = TE_Library.GetEffect(lpEffect);
if (pEffect == NULL)
{
TRACE("\nTE_TextOut(): Effect named %s not found in library or NULL effect.", lpString);
return FALSE;
}
if (pEffect->GetSpace() & (TE_SPACE_CHAR_BB_FLAG | TE_SPACE_CHAR_EM_FLAG))
{
// Character context: handle characters separately
TRACE("\nApplying effect in character context...");
for (int i = 0; i < cbString; i++)
{
char ch = lpString[i];
// (1) Determine placement
CTE_Placement pl;
// Bounding box
pl.SetBB(0.0, 0.0, 1.0, 1.0);
// Character cell
pl.SetInCell(0.0, 0.0, 1.0, 1.0);
// String context
pl.SetInString(0.0, 0.0, 1.0, 1.0);
pl.SetPosition(i);
// (2) Get outline
//UINT format = GGO_NATIVE;
UINT format = GGO_BEZIER;
GLYPHMETRICS gm;
MAT2 m2;
// Unit transform matrix
m2.eM11 = DoubleToFIXED(1.0);
m2.eM12 = DoubleToFIXED(0.0);
m2.eM21 = DoubleToFIXED(0.0);
m2.eM22 = DoubleToFIXED(1.0);
// Get the buffer size
DWORD buffer_size =
::GetGlyphOutlineW(hdc, UINT(ch), format, &gm, 0, NULL, &m2);
if (buffer_size == GDI_ERROR)
{
TRACE
(
"\nTE_TextOut() bad buffer size. Last error is %d.\n",
::GetLastError()
);
return FALSE;
}
TRACE
(
"\nGLYPHMETRICS for '%c': box=<%d,%d>, origin=<%d,%d>, cell inc=<%d,%d>.",
ch, gm.gmBlackBoxX, gm.gmBlackBoxY,
gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y,
gm.gmCellIncX, gm.gmCellIncY
);
// Get the outline curves
LPTTPOLYGONHEADER poly = (LPTTPOLYGONHEADER)malloc(buffer_size);
DWORD dwrc = ::GetGlyphOutlineW(hdc, UINT(ch), format, &gm, buffer_size, poly, &m2);
if (dwrc == -1L || dwrc == 0L)
{
TRACE
(
"\nTE_TextOut() error filling buffer. Last error is %d.\n",
::GetLastError()
);
return FALSE;
}
CTE_Outline ol;
// convert poly to ol...
ConvertSpline(buffer_size, poly, ol);
// (3) Prepare result image
CDC* pDC = new CDC;
CBitmap* pBitmap = new CBitmap;
pDC->CreateCompatibleDC(CDC::FromHandle(hdc));
int x = 1; // max width + margins?
int y = 1; // max height + margins?
pBitmap->CreateCompatibleBitmap(pDC, x, y);
pDC->SelectObject(pBitmap);
CTE_Image result(pDC);
// (4) Apply the effect, starting at the root
pEffect->Apply(ol, pl, result);
// (5) Draw result image to screen
/*
BitBlt
(
hdc, ?, ?, ?, ?,
result->GetDC()->GetSafeHdc(), ?, ?, SRCCOPY
);
*/
// (6) Clean up
//delete [] poly;
free(poly);
delete pBitmap;
delete pDC;
}
}
else
{
// String context: concatenate glyph outlines to single string outline
// if (pEffect->GetSpace() & TE_SPACE_STR_HOL_FLAG)
// handle differently?
for (int i = 0; i < cbString; i++)
{
char ch = lpString[i];
// (1) Determine placement
// (2) Get outline
}
// Determine bounding box for entire string
// (3) Prepare pdcResult
// (4) Apply effect
// (5) Draw resulting bmp
// (6) Clean up
}
return TRUE;
}