Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

631 lines
16 KiB

/******************************Module*Header*******************************\
* Module Name: ftuni.c
*
* the tests for simple unicode extended functions
*
* Created: 06-Aug-1991 16:05:32
* Author: Bodin Dresevic [BodinD]
*
* Copyright (c) 1990 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define C_CHAR 150
static CHAR szOutText[256];
#define RET_FALSE(x) {DbgPrint((x)); return(FALSE);}
#define RIP(x) {DbgPrint(x); DbgBreakPoint();}
#define ASSERTGDI(x,y) if(!(x)) RIP(y)
// This is to create a bitmapinfo structure
VOID vTestGetGlyphOutline(HDC hdc);
VOID vTestGlyphOutline(HWND hwnd, HDC hdcScreen, RECT* prcl)
{
SIZE ptl;
HFONT hfont;
HFONT hfontOriginal;
LOGFONT lfnt;
// Get a font.
memset(&lfnt, 0, sizeof(lfnt));
lstrcpy(lfnt.lfFaceName, "Lucida Blackletter");
lfnt.lfHeight = 24;
lfnt.lfWeight = 400;
lfnt.lfOutPrecision = OUT_TT_ONLY_PRECIS;
if ((hfont = CreateFontIndirect(&lfnt)) == NULL)
{
// DbgPrint("ft!bTestGetGlyphOutline(): Logical font creation failed.\n");
return;
}
hfontOriginal = SelectObject(hdcScreen, hfont);
ModifyWorldTransform (hdcScreen, NULL, MWT_IDENTITY);
SetMapMode (hdcScreen, MM_ANISOTROPIC);
SetViewportExtEx (hdcScreen, 2, 1, &ptl);
// do the experiment once in the compatible mode
SetGraphicsMode(hdcScreen,GM_COMPATIBLE);
vTestGetGlyphOutline(hdcScreen);
// do the experiment once in the advmode mode
SetGraphicsMode(hdcScreen,GM_ADVANCED);
vTestGetGlyphOutline(hdcScreen);
// restore the state
SetViewportExtEx (hdcScreen, ptl.cx, ptl.cy, NULL);
SetMapMode (hdcScreen, MM_TEXT);
SetGraphicsMode (hdcScreen,GM_COMPATIBLE);
SelectObject(hdcScreen, hfontOriginal);
DeleteObject(hfont);
prcl; hwnd;
}
/******************************Public*Routine******************************\
*
* vQsplineToPolyBezier, stolen from ttfd
*
* Effects:
*
* Warnings:
*
* History:
* 20-Feb-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#define ONE_HALF_28_4 0x0000000
#define THREE_HALVES_28_4 (ONE_HALF_28_4 * 3)
#define DIV_BY_2(x) (((x) + 1) / 2)
#define DIV_BY_3(x) (((x) + 1) / 3)
#ifdef LATER
VOID vQsplineToPolyBezier
(
ULONG cBez, //IN count of curves to convert to beziers format
POINTFIX * pptfixStart, //IN starting point on the first curve
POINTFIX * pptfixSpline, //IN array of (cBez+1) points that, together with the starting point *pptfixStart define the spline
POINTFIX * pptfixBez //OUT buffer to be filled with 3 * cBez poly bezier control points
)
{
ULONG iBez,cMidBez;
POINTFIX ptfixA;
// cMidBez == # of beziers for whom the last point on the bezier is computed
// as a mid point of the two consecutive points in the input array. Only the
// last bezier is not a mid bezier, the last point for that bezier is equal
// to the last point in the input array
ASSERTGDI(cBez > 0, "TTFD!_cBez == 0\n");
cMidBez = cBez - 1;
ptfixA = *pptfixStart;
for (iBez = 0; iBez < cMidBez; iBez++, pptfixSpline++)
{
// let us call the three spline points
// A,B,C;
// B = *pptfix;
// C = (pptfix[0] + pptfix[1]) / 2; // mid point, unless at the end
//
// if we decide to call the two intermediate control points for the
// bezier M,N (i.e. full set of control points for the bezier is
// A,M,N,C), the points M,N are determined by following formulas:
//
// M = (2*B + A) / 3 ; two thirds along the segment AB
// N = (2*B + C) / 3 ; two thirds along the segment CB
//
// this is the computation we are doing in this loop:
// M point for this bezier
pptfixBez->x = DIV_BY_3((pptfixSpline->x * 2) + ptfixA.x);
pptfixBez->y = DIV_BY_3((pptfixSpline->y * 2) + ptfixA.y);
pptfixBez++;
// compute C point for this bezier, which is also the A point for the next
// bezier
if (iBez == (cBez - 1))
{
// this is the last bezier, its end point is the last point
// in the input array
ptfixA = pptfixSpline[1];
}
else // take midpoint
{
ptfixA.x = DIV_BY_2(pptfixSpline[0].x + pptfixSpline[1].x);
ptfixA.y = DIV_BY_2(pptfixSpline[0].y + pptfixSpline[1].y);
}
// now compute N point for this bezier:
pptfixBez->x = DIV_BY_3((pptfixSpline->x * 2) + ptfixA.x);
pptfixBez->y = DIV_BY_3((pptfixSpline->y * 2) + ptfixA.y);
pptfixBez++;
// finally record the C point for this curve
*pptfixBez++ = ptfixA;
}
// finally do the last bezier. If the last bezier is the only one, the loop
// above has been skipped
// M point for this bezier
pptfixBez->x = DIV_BY_3((pptfixSpline->x * 2) + ptfixA.x);
pptfixBez->y = DIV_BY_3((pptfixSpline->y * 2) + ptfixA.y);
pptfixBez++;
// compute C point for this bezier, its end point is the last point
// in the input array
ptfixA = pptfixSpline[1];
// now compute N point for this bezier:
pptfixBez->x = DIV_BY_3((pptfixSpline->x * 2) + ptfixA.x);
pptfixBez->y = DIV_BY_3((pptfixSpline->y * 2) + ptfixA.y);
pptfixBez++;
// finally record the C point for this curve, no need to increment pptfixBez
*pptfixBez = ptfixA;
}
#endif
// reasonable guess that in most cases a contour will not consist of more
// that this many beziers
#define C_BEZIER 6
/******************************Public*Routine******************************\
*
*
*
* Effects:
*
* Warnings:
*
* History:
* 09-Mar-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
#define X_OFF (340/2)
#define Y_OFF 240
#define SHIFT 16
VOID vShiftPoint(POINTL * pptl, PSZ psz)
{
POINTL ptlTmp = *pptl;
pptl->x >>= SHIFT;
pptl->x += X_OFF;
pptl->y = - pptl->y;
pptl->y >>= SHIFT;
pptl->y += Y_OFF;
/*
DbgPrint(" %s : bef. (0x%lx, 0x%lx) aft. (0x%lx, 0x%lx) \n",
psz,
ptlTmp.x,
ptlTmp.y,
pptl->x,
pptl->y
);
*/
}
VOID vShiftCrv(TTPOLYCURVE *pcrv, ULONG * pcjCrv)
{
INT i;
*pcjCrv = offsetof(TTPOLYCURVE,apfx) + pcrv->cpfx * sizeof(POINTFX);
/*
DbgPrint("New curve, type = 0x%x, cpt = %d, cjCrv = %ld\n",
pcrv->wType, pcrv->cpfx, *pcjCrv);
*/
for (i = 0; i < (INT)pcrv->cpfx; i++)
vShiftPoint((POINTL *)&pcrv->apfx[i]," ");
}
VOID vShiftPoly(TTPOLYGONHEADER *ppoly, ULONG cjTotal)
{
ULONG cjCrv;
TTPOLYCURVE * pcrv;
ULONG cjPoly;
// DbgPrint("New Polygon: dwType = %d, ppoly->cb = %d, cjTotal = %ld \n",
// ppoly->dwType, ppoly->cb, cjTotal);
vShiftPoint((POINTL *)&ppoly->pfxStart, "pfxStart");
for (
cjPoly = sizeof(TTPOLYGONHEADER),pcrv = (TTPOLYCURVE *)(ppoly + 1);
cjPoly < ppoly->cb;
cjPoly += cjCrv
)
{
vShiftCrv(pcrv, &cjCrv);
// get to the next curve in this polygon
pcrv = (TTPOLYCURVE *)((PBYTE)pcrv + cjCrv);
}
// DbgPrint("cjPoly final = %ld, ppoly->cb = %d \n", cjPoly, ppoly->cb);
}
VOID vShiftOutline
(
TTPOLYGONHEADER * ppolyStart, // IN OUT pointer to the buffer with outline data
ULONG cjTotal // IN size of the buffer
)
{
ULONG cjSoFar = 0;
TTPOLYGONHEADER * ppoly;
for (
cjSoFar = 0, ppoly = ppolyStart;
cjSoFar < cjTotal;
cjSoFar += ppoly->cb, ppoly = (TTPOLYGONHEADER *)((PBYTE)ppoly + ppoly->cb)
)
{
vShiftPoly(ppoly, cjTotal);
}
}
#ifdef LATER
BOOL bDrawOutline
(
HDC hdc, // IN OUT pointer to the path object to be generated
TTPOLYGONHEADER * ppolyStart, // IN OUT pointer to the buffer with outline data
ULONG cjTotal // IN size of the buffer
)
{
ULONG cjPoly, cjSoFar = 0;
TTPOLYGONHEADER * ppoly;
TTPOLYCURVE * pcrv;
POINTFIX aptfixBez[3 * C_BEZIER]; // 3 points per bezier
POINTFIX * pptfixBez;
ULONG cBez;
ULONG cjCrv;
POINTFIX * pptfixStart;
for (ppoly = ppolyStart; cjSoFar < cjTotal; )
{
// DbgPrint("Starting new polygon\n");
ASSERTGDI(ppoly->dwType == TT_POLYGON_TYPE, "TTFD!_ TT_POLYGON_TYPE\n");
MoveToEx(hdc, ((LPPOINT)&ppoly->pfxStart)->x, ((LPPOINT)&ppoly->pfxStart)->y, NULL); // begin new closed contour
pptfixStart = (POINTFIX *)&ppoly->pfxStart;
for (cjPoly = sizeof(TTPOLYGONHEADER), pcrv = (TTPOLYCURVE *)(ppoly + 1);cjPoly < ppoly->cb;)
{
if (pcrv->wType == TT_PRIM_LINE)
{
if (!PolylineTo(hdc,(LPPOINT)pcrv->apfx, pcrv->cpfx))
RET_FALSE("TTFD!_bPolyLineTo()\n");
}
else // qspline
{
ASSERTGDI(pcrv->wType == TT_PRIM_QSPLINE, "TTFD!_TT_PRIM_QSPLINE\n");
ASSERTGDI(pcrv->cpfx > 1, "TTFD!_TT_PRIM_QSPLINE, cpfx <= 1\n");
cBez = pcrv->cpfx - 1;
pptfixBez = aptfixBez;
if (cBez <= C_BEZIER)
{
vQsplineToPolyBezier (
cBez, // count of curves to convert to beziers format
pptfixStart, // starting point on the first curve
(POINTFIX *)pcrv->apfx, // array of (cBez+1) points that, together with the starting point *pptfixStart define the spline
pptfixBez); // buffer to be filled with 3 * cBez poly bezier control points
if (!PolyBezierTo(hdc, (LPPOINT)pptfixBez, 3 * cBez))
RET_FALSE("TTFD!_bPolyBezierTo() failed\n");
}
else
{
// DbgPrint("ft, to many beziers, cBez = %ld\n", cBez);
}
}
// get to the next curve in this polygon
pptfixStart = (POINTFIX *) &pcrv->apfx[pcrv->cpfx - 1];
cjCrv = offsetof(TTPOLYCURVE,apfx) + pcrv->cpfx * sizeof(POINTFX);
cjPoly += cjCrv;
pcrv = (TTPOLYCURVE *)((PBYTE)pcrv + cjCrv);
}
// close contour
LineTo(hdc, ((LPPOINT)&ppoly->pfxStart)->x, ((LPPOINT)&ppoly->pfxStart)->y);
// get to the next polygon header
cjSoFar += ppoly->cb;
ppoly = (TTPOLYGONHEADER *)((PBYTE)ppoly + ppoly->cb);
}
return (TRUE);
}
#endif
/******************************Public*Routine******************************\
*
* Stolen from gilman and modified
*
* Effects:
*
* Warnings:
*
* History:
* 09-Mar-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
BOOL bTestGetGlyphOutline (
HDC hdc,
ULONG uch,
LPMAT2 lpmat2
)
{
ULONG row = 0; // screen row coordinate to print at
ULONG rowIncr;
TEXTMETRIC tm;
ULONG cjBuffer;
PBYTE pjBuffer;
GLYPHMETRICS gm;
uch = (ULONG)(BYTE)uch;
// Get textmetrics.
if ( !GetTextMetrics(hdc, &tm) )
{
DbgPrint("ft!bTestGetGlyphOutline(): GetTextMetrics failed\n");
return FALSE;
}
rowIncr = tm.tmHeight + tm.tmExternalLeading;
sprintf(szOutText, "tmMaxCharWidth : %ld", tm.tmMaxCharWidth);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += (2 * rowIncr);
// Determine buffer size needed by GetGlyphOutline.
if ( (cjBuffer = (ULONG) GetGlyphOutline(hdc, uch, GGO_NATIVE, &gm, 0, (PVOID) NULL, lpmat2)) == (ULONG) -1 )
{
DbgPrint("ft!bTestGetGlyphOutline(): could not get buffer size from API\n");
return FALSE;
}
// Allocate memory.
if ( (pjBuffer = (PBYTE) LocalAlloc(LPTR, cjBuffer)) == (PBYTE) NULL )
{
DbgPrint("ft!bTestGetGlyphOutline(): LocalAlloc(LPTR, 0x%lx) failed\n", cjBuffer);
return FALSE;
}
// Get the bitmap.
if ( GetGlyphOutline(hdc, uch, GGO_NATIVE, &gm, cjBuffer, (PVOID) pjBuffer, lpmat2) == (DWORD) -1 )
{
LocalFree(pjBuffer);
return FALSE;
}
// Print out GLYPHMETRIC data.
sprintf(szOutText, "gmBlackBoxX: %ld", gm.gmBlackBoxX);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += rowIncr;
sprintf(szOutText, "gmBlackBoxY: %ld", gm.gmBlackBoxY);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += rowIncr;
sprintf(szOutText, "gmptGlyphOrigin: (%ld, %ld)", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += rowIncr;
sprintf(szOutText, "gmCellIncX: %ld", gm.gmCellIncX);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += rowIncr;
sprintf(szOutText, "gmCellIncY: %ld", gm.gmCellIncY);
TextOut(hdc, 0, row, szOutText, strlen(szOutText));
row += rowIncr;
// draw outline
// DbgPrint("ft! bDrawOutline begin \n");
// converting 16.16 to POINTL's
vShiftOutline((TTPOLYGONHEADER *)pjBuffer, cjBuffer);
#ifdef LATER
if (!bDrawOutline(hdc, (TTPOLYGONHEADER *)pjBuffer, cjBuffer))
DbgPrint("bDrawOutline screwed up\n");
// DbgPrint("ft! bDrawOutline end \n");
#endif
// Allow an opportunity to examine the contents.
// DbgPrint("ft!bTestGetGlyphOutline(): call to GetGlyphOutline succeeded\n");
// DbgPrint("\tbitmap is at 0x%lx, size is 0x%lx (%ld)\n", pjBuffer, cjBuffer, cjBuffer);
// DbgBreakPoint();
return TRUE;
}
/******************************Public*Routine******************************\
*
*
*
* Effects:
*
* Warnings:
*
* History:
* 09-Mar-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID vTestGetGlyphOutline(HDC hdc)
{
MAT2 mat2;
ULONG ul = 'T';
// Fill in MAT2 structure. Identity matrix.
mat2.eM11.value = 3;
mat2.eM11.fract = 0;
mat2.eM12.value = 0;
mat2.eM12.fract = 0;
mat2.eM21.value = 0;
mat2.eM21.fract = 0;
mat2.eM22.value = 3;
mat2.eM22.fract = 0;
// Clear the screen to white
PatBlt(hdc, 0, 0, 2000, 2000, WHITENESS);
DbgPrint("ft!vTestGGO(): use identity matrix\n");
for (ul = (ULONG)'a'; ul < (ULONG)'z'; ul++)
{
if ( !bTestGetGlyphOutline(hdc, ul, &mat2))
DbgPrint("ft!vTestGGO(): call to bTestGetGlyphOutline failed\n");
vDoPause(1);
// Clear the screen to white
PatBlt(hdc, 0, 0, 2000, 2000, WHITENESS);
}
vDoPause(0);
// Fill in MAT2 structure. Rotate 45 deg CCW, scale
mat2.eM11.value = 3;
mat2.eM11.fract = 0;
mat2.eM12.value = 3;
mat2.eM12.fract = 0;
mat2.eM21.value = -3;
mat2.eM21.fract = 0;
mat2.eM22.value = 3;
mat2.eM22.fract = 0;
DbgPrint("ft!vTestGGO(): rotate 45 deg CCW and scale by sqrt(2)\n");
if ( !bTestGetGlyphOutline(hdc, ul,&mat2) )
DbgPrint("ft!vTestGGO(): call to bTestGetGlyphOutline failed\n");
vDoPause(0);
// Clear the screen to white
PatBlt(hdc, 0, 0, 2000, 2000, WHITENESS);
// Fill in MAT2 structure. general values
mat2.eM11.value = 5;
mat2.eM11.fract = 0;
mat2.eM12.value = 6;
mat2.eM12.fract = 0;
mat2.eM21.value = -3;
mat2.eM21.fract = 0;
mat2.eM22.value = 3;
mat2.eM22.fract = 0;
DbgPrint("ft!vTestGGO(): rotate 45 deg CCW and scale by sqrt(2)\n");
if ( !bTestGetGlyphOutline(hdc, ul,&mat2) )
DbgPrint("ft!vTestGGO(): call to bTestGetGlyphOutline failed\n");
vDoPause(0);
}