📄 dglwgl.c
字号:
/* * 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 HFONTCreateHighResolutionFont(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 intMakeDisplayListFromGlyph( 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 intDrawGlyph( 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 BOOLLoadGLUTesselator(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, "gluTessEndContour")) == NULL) return FALSE; if ((gluTessEndPolygonProc = (gluTessEndPolygonProto) GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL) return FALSE; if ((gluTessPropertyProc = (gluTessPropertyProto) GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL) return FALSE; if ((gluTessNormalProc = (gluTessNormalProto) GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL) return FALSE; if ((gluTessCallbackProc = (gluTessCallbackProto) GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL) return FALSE; return TRUE; }/***************************************************************************** * UnloadGLUTesselator * * Unmaps the glu32.dll module. *****************************************************************************/static BOOLUnloadGLUTesselator(void) { if (gluModuleHandle != NULL) if (FreeLibrary(gluModuleHandle) == FALSE) return FALSE; gluModuleHandle = NULL; }/***************************************************************************** * TessVertexOut * * Used by tessellator to handle output vertexes. *****************************************************************************/ static void CALLBACKTessVertexOut(FLOAT p[3]) { GLfloat v[2]; v[0] = p[0] * ScaleFactor; v[1] = p[1] * ScaleFactor; _GLD_glVertex2fv(v); }static void CALLBACKTessVertexOutData(FLOAT p[3], GLfloat z){ GLfloat v[3]; v[0] = (GLfloat) p[0]; v[1] = (GLfloat) p[1]; v[2] = z; _GLD_glVertex3fv(v);}/***************************************************************************** * TessCombine * * Used by tessellator to handle self-intersecting contours and degenerate * geometry. *****************************************************************************/ static void CALLBACKTessCombine(double coords[3], void* vertex_data[4], FLOAT weight[4], void** outData) { if (!AppendToVertBuf((FLOAT) coords[0]) || !AppendToVertBuf((FLOAT) coords[1]) || !AppendToVertBuf((FLOAT) coords[2])) TessErrorOccurred = GL_OUT_OF_MEMORY; *outData = VertBuf + (VertBufIndex - 3); }/***************************************************************************** * TessError * * Saves the last tessellator error code in the global TessErrorOccurred. *****************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -