chgrfont.cpp
来自「Windows上的MUD客户端程序」· C++ 代码 · 共 545 行
CPP
545 行
// COPYRIGHT:
//
// (C) Copyright Microsoft Corp. 1993. All rights reserved.
//
// You have a royalty-free right to use, modify, reproduce and
// distribute the Sample Files (and/or any modified version) in
// any way you find useful, provided that you agree that
// Microsoft has no warranty obligations or liability for any
// Sample Application Files which are modified.
//
#include "grheader.h"
#undef HUGE
#include <math.h>
#include "ChGrFont.h"
#include "GxTypes.h"
#include "TrBasic.h"
FIXED FixedFromDouble(double);
template <class aType>
void swap(aType& a, aType& b)
{
aType tmp;
tmp = a;
a = b;
b = tmp;
}
int ChPolyPolygonGx3::Convexify(ChPolyPolygonGx3* pPoly, int polyIndex)
{
#if defined(CH_USE_GGEMS_TRI_VERSION)
int n;
double vertices[100][2];
int triangles[200][3];
int i;
int nmonopoly;
TRACE("In Convexify.\n");
vertices[0][0] = 0.0;
vertices[0][1] = 0.0;
vertices[1][0] = 10.0;
vertices[1][1] = 0.0;
vertices[2][0] = 20.0;
vertices[2][1] = 0.0;
vertices[3][0] = 20.0;
vertices[3][1] = 5.0;
vertices[4][0] = 20.0;
vertices[4][1] = 20.0;
vertices[5][0] = 0.0;
vertices[5][1] = 20.0;
vertices[6][0] = 5.0;
vertices[6][1] = 10.0;
//#define FAKEPOLY 1
#ifdef FAKEPOLY
n = 7; // GetPointCount(polyIndex);
#else
n = GetPointCount(polyIndex);
#endif
// triangles = new int[n][3];
memset((void *)seg, 0, sizeof(seg));
for (i = 1; i <= n; i++) {
GxVec3f ip = GetPoint(polyIndex, i-1);
seg[i].is_inserted = FALSE;
#ifndef FAKEPOLY
seg[i].v0.x = ip.x();
seg[i].v0.y = ip.y();
#else
seg[i].v0.x = vertices[i-1][0];
seg[i].v0.y = vertices[i-1][1];
#endif
if (i == 1) {
seg[n].v1.x = seg[i].v0.x;
seg[n].v1.y = seg[i].v0.y;
} else {
seg[i - 1].v1.x = seg[i].v0.x;
seg[i - 1].v1.y = seg[i].v0.y;
}
}
global.nseg = n;
generate_random_ordering(n);
construct_trapezoids(n, seg);
nmonopoly = monotonate_trapezoids(n);
triangulate_monotone_polygons(nmonopoly, triangles);
// Add the triangles to the end of pPoly
for (i = 0; i < n - 2; i++) {
pPoly->NewPoly();
pPoly->Append(GetPoint(polyIndex, triangles[i][0]));
pPoly->Append(GetPoint(polyIndex, triangles[i][1]));
pPoly->Append(GetPoint(polyIndex, triangles[i][2]));
pPoly->EndPoly();
}
#endif // disabled for now
return 0;
}
ChPolyPolygonI *ChPolyPolygonI::EndPoly()
{
// Check the order, and force to match flag
if(m_direction == dontCare) return this;
GxVec3f pt0, pt1, fn(0,0,0);
int polyIndex = GetPolyCount()-1;
int num = GetPointCount(polyIndex);
if(num < 3) return this;
for ( int j = 0; j < num - 1; j++ )
{
CPoint q0 = GetPoint(polyIndex, j);
CPoint q1 = GetPoint(polyIndex, j + 1);
pt0.set(q0.x, q0.y, 0);
pt1.set(q1.x, q1.y, 0);
fn += pt0.cross( pt1 ) ;
}
CPoint q0 = GetPoint(polyIndex, j);
CPoint q1 = GetPoint(polyIndex, 0);
pt0.set(q0.x, q0.y, 0);
pt1.set(q1.x, q1.y, 0);
fn += pt0.cross( pt1 ) ;
bool boolClockWise = fn.z() < 0.0;
if(boolClockWise ^ (m_direction == clockwise))
{
// Flip the poly
int start = m_pAccumCounts[polyIndex];
for( j = 0; j < num / 2; j++ )
{
swap(m_pPts[start + j], m_pPts[start + num - 1 - j]);
}
}
return this;
}
ChPolyPolygonGx3 *ChPolyPolygonGx3::EndPoly()
{
// Check the order, and force to match flag
if(m_direction == dontCare) return this;
GxVec3f pt0, pt1, fn(0,0,0);
int polyIndex = GetPolyCount()-1;
int num = GetPointCount(polyIndex);
if(num < 3) return this;
for ( int j = 0; j < num - 1; j++ )
{
GxVec3f q0 = GetPoint(polyIndex, j);
GxVec3f q1 = GetPoint(polyIndex, j + 1);
pt0.set(q0.x(), q0.y(), 0);
pt1.set(q1.x(), q1.y(), 0);
fn += pt0.cross( pt1 ) ;
}
GxVec3f q0 = GetPoint(polyIndex, j);
GxVec3f q1 = GetPoint(polyIndex, 0);
pt0.set(q0.x(), q0.y(), 0);
pt1.set(q1.x(), q1.y(), 0);
fn += pt0.cross( pt1 ) ;
bool boolClockWise = fn.z() < 0.0;
if(boolClockWise ^ (m_direction == clockwise))
{
// Flip the poly
int start = m_pAccumCounts[polyIndex];
for( j = 0; j < num / 2; j++ )
{
swap(m_pPts[start + j], m_pPts[start + num - 1 - j]);
}
}
return this;
}
// Convert degrees to radians for math functions.
#define RAD(x) ((x) * 3.1415927 / 180)
/****************************************************************************
* FUNCTION : FixedFromDouble
* RETURNS : FIXED value representing the given double.
****************************************************************************/
FIXED
FixedFromDouble (double d)
{
long l;
l = (long) (d * 65536L);
return *(FIXED *) & l;
}
/****************************************************************************
* FUNCTION : FixedFromDouble
* RETURNS : FIXED value representing the given double.
****************************************************************************/
double
DoubleFromFixed (FIXED f)
{
double d = f.value;
d += (f.fract / 65536.);
return d;
}
/****************************************************************************
* FUNCTION : IntFromFixed
* RETURNS : int value approximating the FIXED value.
****************************************************************************/
int
IntFromFixed (FIXED f)
{
if (f.fract >= 0x8000)
return (f.value + 1);
else
return (f.value);
}
/****************************************************************************
* FUNCTION : fxDiv2
* RETURNS : (val1 + val2)/2 for FIXED values
****************************************************************************/
FIXED
fxDiv2 (FIXED fxVal1, FIXED fxVal2)
{
long l;
l = (*((long *) &(fxVal1)) + *((long *) &(fxVal2))) / 2;
return (*(FIXED *) & l);
}
/****************************************************************************
* FUNCTION : MakeRotationMat
* PURPOSE : Fill in a rotation matrix based on the given angle.
* RETURNS : none.
****************************************************************************/
void
MakeRotationMat (LPMAT2 lpMat, double dAngle)
{
lpMat->eM11 = FixedFromDouble (cos (RAD (dAngle)));
lpMat->eM12 = FixedFromDouble (sin (RAD (dAngle)));
lpMat->eM21 = FixedFromDouble (-sin (RAD (dAngle)));
lpMat->eM22 = FixedFromDouble (cos (RAD (dAngle)));
}
/****************************************************************************
* FUNCTION : ShearMat
* PURPOSE : Fill in a 0.25 horizontal shear matrix.
* RETURNS : none.
****************************************************************************/
void
ShearMat (LPMAT2 lpMat)
{
lpMat->eM11 = FixedFromDouble (1);
lpMat->eM12 = FixedFromDouble (0);
lpMat->eM21 = FixedFromDouble (0.25);
lpMat->eM22 = FixedFromDouble (1);
}
/****************************************************************************
* FUNCTION : IdentityMat
* PURPOSE : Fill in matrix to be the identity matrix.
* RETURNS : none.
****************************************************************************/
void
IdentityMat (LPMAT2 lpMat)
{
lpMat->eM11 = FixedFromDouble (1);
lpMat->eM12 = FixedFromDouble (0);
lpMat->eM21 = FixedFromDouble (0);
lpMat->eM22 = FixedFromDouble (1);
}
/****************************************************************************
* FUNCTION : DrawT2Outline
*
* PURPOSE : Decode the GGO_NATIVE outline, create a polypolygon from it,
* and draw it using PolyPolygon.
*
* Polygon is not actually returned as would be more common
* in real usage. Also, an arbitrary size for the polygon
* is specified instead of actually expanding on a need-to-
* grow basis.
*
* Error conditions are not handled.
*
* RETURNS : none.
****************************************************************************/
void
CreateT2Outline (LPTTPOLYGONHEADER lpHeader, DWORD size, int nAscent, ChPolyPolygonGx3& poly)
{
// Append each polygon and segment to 'poly'
LPTTPOLYGONHEADER lpStart;
LPTTPOLYCURVE lpCurve;
GxVec3f pt[500]; // big enough for one spline
//WORD cTotal = 0; // Total number of points in polypolygon.
WORD cInCurve; // Number of points in current curve.
WORD cCurves = 0; // Number of curves in polypolygon.
unsigned int cInSpline; // Number of points in digitized spline curve.
//WORD iFirstCurve; // Index to start point of first curve.
WORD i;
QS spline;
GxVec3f cpt, firstPoint;
lpStart = lpHeader;
poly.Init();
while ((DWORD)lpHeader < (DWORD)(((LPSTR)lpStart) + size))
{
if (lpHeader->dwType == TT_POLYGON_TYPE)
{
poly.NewPoly();
bool boolFirst = true;
cInCurve = 0; // obs
// Get to first curve.
lpCurve = (LPTTPOLYCURVE) (lpHeader + 1);
//iFirstCurve = cTotal;
while ((DWORD)lpCurve < (DWORD)(((LPSTR)lpHeader) + lpHeader->cb))
{
if (lpCurve->wType == TT_PRIM_LINE)
{
if(boolFirst)
{
firstPoint.x() = DoubleFromFixed(lpCurve->apfx[0].x);
firstPoint.y() = DoubleFromFixed(lpCurve->apfx[0].y);
firstPoint.z() = 0;
boolFirst = false;
}
for (i = 0; i < lpCurve->cpfx; i++)
{
cpt.x() = DoubleFromFixed(lpCurve->apfx[i].x);
cpt.y() = DoubleFromFixed(lpCurve->apfx[i].y);
cpt.z() = 0;
poly.Append(cpt);
//cTotal++; // obs
cInCurve++; // obs
}
}
else if (lpCurve->wType == TT_PRIM_QSPLINE)
{
//**********************************************
// Format assumption:
// The bytes immediately preceding a POLYCURVE
// structure contain a valid POINTFX.
//
// If this is first curve, this points to the
// pfxStart of the POLYGONHEADER.
// Otherwise, this points to the last point of
// the previous POLYCURVE.
//
// In either case, this is representative of the
// previous curve's last point.
//**********************************************
spline.ptfxStartPt = *(LPPOINTFX)((LPSTR)lpCurve - sizeof(POINTFX));
for (i = 0; i < lpCurve->cpfx;)
{
// The B point.
spline.ptfxCntlPt = lpCurve->apfx[i++];
// Calculate the C point.
if (i == (lpCurve->cpfx - 1))
{
spline.ptfxEndPt = lpCurve->apfx[i++];
}
else
{
// C is midpoint between B and next point.
spline.ptfxEndPt.x = fxDiv2(lpCurve->apfx[i-1].x,
lpCurve->apfx[i].x);
spline.ptfxEndPt.y = fxDiv2(lpCurve->apfx[i-1].y,
lpCurve->apfx[i].y);
}
cInSpline = 0;
QSpline2Polyline(pt, &spline, -1, &cInSpline, nAscent);
if(boolFirst)
{
firstPoint = pt[0];
boolFirst = false;
}
// Copy the spline pts to our array; brute force
for( unsigned int k = 0; k < cInSpline; k++)
{
poly.Append(pt[k]);
}
//cTotal += cInSpline; // obs
//cInCurve += cInSpline; // obs
// New A point for next slice of spline.
spline.ptfxStartPt = spline.ptfxEndPt;
}
}
else
; // error, error, error
// Move on to next curve.
lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[i]);
}
// Add points to close curve.
// Depending on the specific font and glyph being used, these
// may not always be needed, but it never hurts.
#if 0
pt[cTotal].x = lpHeader->pfxStart.x.value;
pt[cTotal].y = lpHeader->pfxStart.y.value;
cInCurve++;
cTotal++;
pt[cTotal].x = pt[iFirstCurve].x;
pt[cTotal].y = pt[iFirstCurve].y;
cInCurve++;
cTotal++;
count[cCurves++] = cInCurve;
#endif
#if 0
cpt.x() = lpHeader->pfxStart.x.value;
cpt.y() = lpHeader->pfxStart.y.value;
#endif
cpt.x() = DoubleFromFixed(lpHeader->pfxStart.x);
cpt.y() = DoubleFromFixed(lpHeader->pfxStart.y);
cpt.z() = 0;
poly.Append(cpt);
//cpt.x() = firstPoint.x();
//cpt.y() = firstPoint.y();
//cpt.z() = 0;
poly.Append(firstPoint);
poly.EndPoly();
// Move on to next polygon.
lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb);
}
else
; // error, error, error
}
}
/****************************************************************************
* FUNCTION : CreateGlyphPolyPoly
*
* PURPOSE : Create a polypoly for a glyph.
*
* Caller must delete returned pointer.
*
* RETURNS : polypoly, or 0 if error.
****************************************************************************/
ChPolyPolygonGx3* CreateGlyphPolyPoly (HFONT hFont, unsigned int letter, int ascent, int& xAdvance, int &yAdvance)
{
GLYPHMETRICS gm;
MAT2 mat;
DWORD size;
LPSTR lpBits;
WORD flag;
//ChPolyPolygonGx3 *pPoly = new ChPolyPolygonGx3(ChPolyPolygonGx3::counterClockwise);
ChPolyPolygonGx3 *pPoly = new ChPolyPolygonGx3(ChPolyPolygonGx3::dontCare);
HDC hdc = ::GetDC(NULL);
HFONT oldFont = HFONT(::SelectObject(hdc, hFont));
/* make the 2x2 matrix */
IdentityMat(&mat);
// these are simply hardcoded examples
#if 0
if (wEffect == IDM_IDENTITY)
IdentityMat(&mat);
else if (wEffect == IDM_ROTATE60)
MakeRotationMat(&mat, 60);
else if (wEffect == IDM_SHEAR)
ShearMat(&mat);
#endif
flag = GGO_NATIVE;
// allocate space for the outline
size = GetGlyphOutline(hdc, letter, flag, &gm, 0, NULL, &mat);
if(GDI_ERROR == size)
{
delete pPoly;
return 0;
}
if(!size)
{
if(letter == ' ')
{
SIZE size;
GetTextExtentPoint32(hdc, " ", 1, &size);
xAdvance = size.cx;
yAdvance = 0;
}
else
{
xAdvance = 0;
yAdvance = 0;
}
return pPoly; // empty
}
lpBits = new char[size];
if ((GetGlyphOutline(hdc, letter, flag, &gm, size, lpBits, &mat)) != size)
{
//MessageBox(hMyWnd, "Won't get it", "foo", MB_OK);
delete pPoly;
return 0;
}
xAdvance = gm.gmCellIncX;
yAdvance = gm.gmCellIncY;
::SelectObject(hdc, oldFont);
ReleaseDC(NULL, hdc);
// Glyph is in outline format. Set up viewport origin to align the
// glyph and draw it. Actual decoding is done in
// CreateT2Outline.
{
// Align based on cell origin. ??
//OffsetViewportOrg(hDC, x, y + ascent);
//ChPolyPolygonI poly;
CreateT2Outline((LPTTPOLYGONHEADER)lpBits, size, ascent, *pPoly);
}
delete(lpBits);
return pPoly;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?