mirror of https://github.com/lianthony/NT4.0
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
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);
|
|
|
|
|
|
}
|