📄 dglwgl.c
字号:
{0, 0}, {0, 1}
};
LPGLYPHMETRICSFLOAT glyphMetricsFloat =
&glyphMetricsFloatArray[glyphIndex - first];
/*
* Determine how much space is needed to store the glyph's
* outlines. If our glyph buffer isn't large enough,
* resize it.
*/
glyphSize = GetGlyphOutline( hDC,
glyphIndex,
GGO_NATIVE,
&glyphMetrics,
0,
NULL,
&matrix
);
if (glyphSize < 0)
return FALSE; /*WGL_STATUS_FAILURE*/
if (glyphSize > glyphBufSize)
{
__wglFree(glyphBuf);
glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
if (!glyphBuf)
return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
}
/*
* Get the glyph's outlines.
*/
if (GetGlyphOutline( hDC,
glyphIndex,
GGO_NATIVE,
&glyphMetrics,
glyphBufSize,
glyphBuf,
&matrix
) < 0)
{
__wglFree(glyphBuf);
return FALSE; /*WGL_STATUS_FAILURE*/
}
glyphMetricsFloat->gmfBlackBoxX =
(FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
glyphMetricsFloat->gmfBlackBoxY =
(FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
glyphMetricsFloat->gmfptGlyphOrigin.x =
(FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
glyphMetricsFloat->gmfptGlyphOrigin.y =
(FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
glyphMetricsFloat->gmfCellIncX =
(FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
glyphMetricsFloat->gmfCellIncY =
(FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
/*
* Turn the glyph into a display list:
*/
if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
glyphBuf,
glyphSize,
glyphMetricsFloat,
chordalDeviation + ScaleFactor,
extrusion,
format))
{
__wglFree(glyphBuf);
return FALSE; /*WGL_STATUS_FAILURE*/
}
}
/*
* Clean up temporary storage and return. If an error occurred,
* clear all OpenGL error flags and return FAILURE status;
* otherwise just return SUCCESS.
*/
__wglFree(glyphBuf);
SelectObject(hDC, hOldFont);
if (_GLD_glGetError() == GL_NO_ERROR)
return TRUE; /*WGL_STATUS_SUCCESS*/
else
{
while (_GLD_glGetError() != GL_NO_ERROR)
;
return FALSE; /*WGL_STATUS_FAILURE*/
}
}
/*****************************************************************************
* CreateHighResolutionFont
*
* Gets metrics for the current font and creates an equivalent font
* scaled to the design units of the font.
*
*****************************************************************************/
static HFONT
CreateHighResolutionFont(HDC hDC)
{
UINT otmSize;
OUTLINETEXTMETRIC *otm;
LONG fontHeight, fontWidth, fontUnits;
LOGFONT logFont;
otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
if (otmSize == 0)
return NULL;
otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
if (otm == NULL)
return NULL;
otm->otmSize = otmSize;
if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
return NULL;
fontHeight = otm->otmTextMetrics.tmHeight -
otm->otmTextMetrics.tmInternalLeading;
fontWidth = otm->otmTextMetrics.tmAveCharWidth;
fontUnits = (LONG) otm->otmEMSquare;
ScaleFactor = 1.0F / (FLOAT) fontUnits;
logFont.lfHeight = - ((LONG) fontUnits);
logFont.lfWidth = (LONG)
((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
logFont.lfEscapement = 0;
logFont.lfOrientation = 0;
logFont.lfWeight = otm->otmTextMetrics.tmWeight;
logFont.lfItalic = otm->otmTextMetrics.tmItalic;
logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily =
otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
strcpy(logFont.lfFaceName,
(char *)otm + (int)otm->otmpFaceName);
hNewFont = CreateFontIndirect(&logFont);
if (hNewFont == NULL)
return NULL;
__wglFree(otm);
return hNewFont;
}
/*****************************************************************************
* MakeDisplayListFromGlyph
*
* Converts the outline of a glyph to an OpenGL display list.
*
* Return value is nonzero for success, zero for failure.
*
* Does not check for OpenGL errors, so if the caller needs to know about them,
* it should call glGetError().
*****************************************************************************/
static int
MakeDisplayListFromGlyph( IN DWORD listName,
IN UCHAR* glyphBuf,
IN DWORD glyphSize,
IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
IN FLOAT chordalDeviation,
IN FLOAT extrusion,
IN INT format)
{
int status;
_GLD_glNewList(listName, GL_COMPILE);
status = DrawGlyph( glyphBuf,
glyphSize,
chordalDeviation,
extrusion,
format);
_GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
glyphMetricsFloat->gmfCellIncY,
0.0F);
_GLD_glEndList();
return status;
}
/*****************************************************************************
* DrawGlyph
*
* Converts the outline of a glyph to OpenGL drawing primitives, tessellating
* as needed, and then draws the glyph. Tessellation of the quadratic splines
* in the outline is controlled by "chordalDeviation", and the drawing
* primitives (lines or polygons) are selected by "format".
*
* Return value is nonzero for success, zero for failure.
*
* Does not check for OpenGL errors, so if the caller needs to know about them,
* it should call glGetError().
*****************************************************************************/
static int
DrawGlyph( IN UCHAR* glyphBuf,
IN DWORD glyphSize,
IN FLOAT chordalDeviation,
IN FLOAT extrusion,
IN INT format)
{
INT status = 0;
FLOAT* p;
DWORD loop;
DWORD point;
GLUtesselator* tess = NULL;
/*
* Initialize the global buffer into which we place the outlines:
*/
if (!InitLineBuf())
goto exit;
/*
* Convert the glyph outlines to a set of polyline loops.
* (See MakeLinesFromGlyph() for the format of the loop data
* structure.)
*/
if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
goto exit;
p = LineBuf;
/*
* Now draw the loops in the appropriate format:
*/
if (format == WGL_FONT_LINES)
{
/*
* This is the easy case. Just draw the outlines.
*/
for (loop = (DWORD) *p++; loop; --loop)
{
_GLD_glBegin(GL_LINE_LOOP);
for (point = (DWORD) *p++; point; --point)
{
_GLD_glVertex2fv(p);
p += 2;
}
_GLD_glEnd();
}
status = 1;
}
else if (format == WGL_FONT_POLYGONS)
{
double v[3];
FLOAT *save_p = p;
GLfloat z_value;
/*
* This is the hard case. We have to set up a tessellator
* to convert the outlines into a set of polygonal
* primitives, which the tessellator passes to some
* auxiliary routines for drawing.
*/
if (!LoadGLUTesselator())
goto exit;
if (!InitVertBuf())
goto exit;
if (!(tess = gluNewTessProc()))
goto exit;
gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
(void(CALLBACK *)()) TessVertexOutData);
gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
TessErrorOccurred = 0;
_GLD_glNormal3f(0.0f, 0.0f, 1.0f);
v[2] = 0.0;
z_value = 0.0f;
gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
for (loop = (DWORD) *p++; loop; --loop)
{
gluTessBeginContourProc(tess);
for (point = (DWORD) *p++; point; --point)
{
v[0] = p[0];
v[1] = p[1];
gluTessVertexProc(tess, v, p);
p += 2;
}
gluTessEndContourProc(tess);
}
gluTessEndPolygonProc(tess);
status = !TessErrorOccurred;
/* Extrusion code */
if (extrusion) {
DWORD loops;
GLfloat thickness = (GLfloat) -extrusion;
FLOAT *vert, *vert2;
DWORD count;
p = save_p;
loops = (DWORD) *p++;
for (loop = 0; loop < loops; loop++) {
GLfloat dx, dy, len;
DWORD last;
count = (DWORD) *p++;
_GLD_glBegin(GL_QUAD_STRIP);
/* Check if the first and last vertex are identical
* so we don't draw the same quad twice.
*/
vert = p + (count-1)*2;
last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
for (point = 0; point <= last; point++) {
vert = p + 2 * (point % last);
vert2 = p + 2 * ((point+1) % last);
dx = vert[0] - vert2[0];
dy = vert[1] - vert2[1];
len = (GLfloat)sqrt(dx * dx + dy * dy);
_GLD_glNormal3f(dy / len, -dx / len, 0.0f);
_GLD_glVertex3f((GLfloat) vert[0],
(GLfloat) vert[1], thickness);
_GLD_glVertex3f((GLfloat) vert[0],
(GLfloat) vert[1], 0.0f);
}
_GLD_glEnd();
p += count*2;
}
/* Draw the back face */
p = save_p;
v[2] = thickness;
_GLD_glNormal3f(0.0f, 0.0f, -1.0f);
gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
for (loop = (DWORD) *p++; loop; --loop)
{
count = (DWORD) *p++;
gluTessBeginContourProc(tess);
for (point = 0; point < count; point++)
{
vert = p + ((count-point-1)<<1);
v[0] = vert[0];
v[1] = vert[1];
gluTessVertexProc(tess, v, vert);
}
p += count*2;
gluTessEndContourProc(tess);
}
gluTessEndPolygonProc(tess);
}
#if DEBUG
if (TessErrorOccurred)
printf("Tessellation error %s\n",
gluErrorString(TessErrorOccurred));
#endif
}
exit:
FreeLineBuf();
if (tess)
gluDeleteTessProc(tess);
// UnloadGLUTesselator();
FreeVertBuf();
return status;
}
/*****************************************************************************
* LoadGLUTesselator
*
* Maps the glu32.dll module and gets function pointers for the
* tesselator functions.
*****************************************************************************/
static BOOL
LoadGLUTesselator(void)
{
if (gluModuleHandle != NULL)
return TRUE;
{
extern HINSTANCE hInstanceOpenGL;
char *gluName = "GLU32.DLL";
// char name[256];
// char *ptr;
// int len;
/*
len = GetModuleFileName(hInstanceOpenGL, name, 255);
if (len != 0)
{
ptr = name+len-1;
while (ptr > name && *ptr != '\\')
ptr--;
if (*ptr == '\\')
ptr++;
if (!stricmp(ptr, "cosmogl.dll"))
{
gluName = "COSMOGLU.DLL";
}
else if (!stricmp(ptr, "opengl32.dll"))
{
gluName = "GLU32.DLL";
}
}
*/
if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
return FALSE;
}
if ((gluNewTessProc = (gluNewTessProto)
GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
return FALSE;
if ((gluDeleteTessProc = (gluDeleteTessProto)
GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
return FALSE;
if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
return FALSE;
if ((gluTessBeginContourProc = (gluTessBeginContourProto)
GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
return FALSE;
if ((gluTessVertexProc = (gluTessVertexProto)
GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
return FALSE;
if ((gluTessEndContourProc = (gluTessEndContourProto)
GetProcAddress(gluModuleHandle, "gl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -