opengl32: Implement wglUseFontOutlines
Huw D M Davies
h.davies1 at physics.ox.ac.uk
Tue Mar 7 07:55:35 CST 2006
Huw Davies <huw at codeweavers.com>
opengl32: Implement wglUseFontOutlines.
--
Huw Davies
huw at codeweavers.com
---
configure.ac | 2
dlls/opengl32/opengl32.spec | 2
dlls/opengl32/wgl.c | 231 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 230 insertions(+), 5 deletions(-)
d820a39f15532515b2abef4f5aa4ff4dee2f3b37
diff --git a/configure.ac b/configure.ac
index f2f910d..2daecea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -373,7 +373,7 @@ then
dnl Check for the presence of OpenGL
if test "x$with_opengl" != "xno"
then
- AC_CHECK_HEADERS(GL/gl.h GL/glx.h GL/glext.h,,,
+ AC_CHECK_HEADERS(GL/gl.h GL/glx.h GL/glext.h GL/glu.h,,,
[#ifdef HAVE_GL_GLX_H
# include <GL/glx.h>
#endif])
diff --git a/dlls/opengl32/opengl32.spec b/dlls/opengl32/opengl32.spec
index 0215445..460045a 100644
--- a/dlls/opengl32/opengl32.spec
+++ b/dlls/opengl32/opengl32.spec
@@ -397,4 +397,4 @@
@ stdcall wglUseFontBitmapsA(long long long long)
@ stdcall wglUseFontBitmapsW(long long long long)
@ stdcall wglUseFontOutlinesA(long long long long long long long ptr)
-@ stub wglUseFontOutlinesW
+@ stdcall wglUseFontOutlinesW(long long long long long long long ptr)
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c
index 04eb40f..56c8ad1 100644
--- a/dlls/opengl32/wgl.c
+++ b/dlls/opengl32/wgl.c
@@ -34,6 +34,11 @@
#include "wgl_ext.h"
#include "opengl_ext.h"
+#ifdef HAVE_GL_GLU_H
+#undef far
+#undef near
+#include <GL/glu.h>
+#endif
#include "wine/library.h"
#include "wine/debug.h"
@@ -864,6 +869,212 @@ BOOL WINAPI wglUseFontBitmapsW(HDC hdc,
return TRUE;
}
+#ifdef HAVE_GL_GLU_H
+
+static void fixed_to_double(POINTFX fixed, UINT em_size, GLdouble vertex[3])
+{
+ vertex[0] = (fixed.x.value + (GLdouble)fixed.x.fract / (1 << 16)) / em_size;
+ vertex[1] = (fixed.y.value + (GLdouble)fixed.y.fract / (1 << 16)) / em_size;
+ vertex[2] = 0.0;
+}
+
+static void tess_callback_vertex(GLvoid *vertex)
+{
+ GLdouble *dbl = vertex;
+ TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
+ glVertex3dv(vertex);
+}
+
+static void tess_callback_begin(GLenum which)
+{
+ TRACE("%d\n", which);
+ glBegin(which);
+}
+
+static void tess_callback_end(void)
+{
+ TRACE("\n");
+ glEnd();
+}
+
+/***********************************************************************
+ * wglUseFontOutlines_common
+ */
+BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf,
+ BOOL unicode)
+{
+ UINT glyph;
+ const MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
+ GLUtesselator *tess;
+ LOGFONTW lf;
+ HFONT old_font, unscaled_font;
+ UINT em_size = 1024;
+ RECT rc;
+
+ TRACE("(%p, %ld, %ld, %ld, %f, %f, %d, %p, %s)\n", hdc, first, count,
+ listBase, deviation, extrusion, format, lpgmf, unicode ? "W" : "A");
+
+
+ ENTER_GL();
+ tess = gluNewTess();
+ if(tess)
+ {
+ gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
+ gluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
+ gluTessCallback(tess, GLU_TESS_END, tess_callback_end);
+ }
+ LEAVE_GL();
+
+ if(!tess) return FALSE;
+
+ GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
+ rc.left = rc.right = rc.bottom = 0;
+ rc.top = em_size;
+ DPtoLP(hdc, (POINT*)&rc, 2);
+ lf.lfHeight = -abs(rc.top - rc.bottom);
+ lf.lfOrientation = lf.lfEscapement = 0;
+ unscaled_font = CreateFontIndirectW(&lf);
+ old_font = SelectObject(hdc, unscaled_font);
+
+ for (glyph = first; glyph < first + count; glyph++)
+ {
+ DWORD needed;
+ GLYPHMETRICS gm;
+ BYTE *buf;
+ TTPOLYGONHEADER *pph;
+ TTPOLYCURVE *ppc;
+ GLdouble *vertices;
+
+ if(unicode)
+ needed = GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
+ else
+ needed = GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, 0, NULL, &identity);
+
+ if(needed == GDI_ERROR)
+ goto error;
+
+ buf = HeapAlloc(GetProcessHeap(), 0, needed);
+ vertices = HeapAlloc(GetProcessHeap(), 0, needed / sizeof(POINTFX) * 3 * sizeof(GLdouble));
+
+ if(unicode)
+ GetGlyphOutlineW(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
+ else
+ GetGlyphOutlineA(hdc, glyph, GGO_NATIVE, &gm, needed, buf, &identity);
+
+ TRACE("glyph %d\n", glyph);
+
+ if(lpgmf)
+ {
+ lpgmf->gmfBlackBoxX = gm.gmBlackBoxX / em_size;
+ lpgmf->gmfBlackBoxY = gm.gmBlackBoxY / em_size;
+ lpgmf->gmfptGlyphOrigin.x = gm.gmptGlyphOrigin.x / em_size;
+ lpgmf->gmfptGlyphOrigin.y = gm.gmptGlyphOrigin.y / em_size;
+ lpgmf->gmfCellIncX = gm.gmCellIncX / em_size;
+ lpgmf->gmfCellIncY = gm.gmCellIncY / em_size;
+ TRACE("%fx%f at %f,%f inc %f,%f\n", lpgmf->gmfBlackBoxX, lpgmf->gmfBlackBoxY,
+ lpgmf->gmfptGlyphOrigin.x, lpgmf->gmfptGlyphOrigin.y, lpgmf->gmfCellIncX, lpgmf->gmfCellIncY);
+ lpgmf++;
+ }
+
+ ENTER_GL();
+ glNewList(listBase++, GL_COMPILE);
+ gluTessBeginPolygon(tess, NULL);
+
+ pph = (TTPOLYGONHEADER*)buf;
+ while((BYTE*)pph < buf + needed)
+ {
+ TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value);
+
+ gluTessBeginContour(tess);
+
+ fixed_to_double(pph->pfxStart, em_size, vertices);
+ gluTessVertex(tess, vertices, vertices);
+ vertices += 3;
+
+ ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
+ while((char*)ppc < (char*)pph + pph->cb)
+ {
+ int i;
+
+ switch(ppc->wType) {
+ case TT_PRIM_LINE:
+ for(i = 0; i < ppc->cpfx; i++)
+ {
+ TRACE("\t\tline to %d, %d\n", ppc->apfx[i].x.value, ppc->apfx[i].y.value);
+ fixed_to_double(ppc->apfx[i], em_size, vertices);
+ gluTessVertex(tess, vertices, vertices);
+ vertices += 3;
+ }
+ break;
+
+ case TT_PRIM_QSPLINE:
+ for(i = 0; i < ppc->cpfx/2; i++)
+ {
+ /* FIXME just connecting the control points for now */
+ TRACE("\t\tcurve %d,%d %d,%d\n",
+ ppc->apfx[i * 2].x.value, ppc->apfx[i * 3].y.value,
+ ppc->apfx[i * 2 + 1].x.value, ppc->apfx[i * 3 + 1].y.value);
+ fixed_to_double(ppc->apfx[i * 2], em_size, vertices);
+ gluTessVertex(tess, vertices, vertices);
+ vertices += 3;
+ fixed_to_double(ppc->apfx[i * 2 + 1], em_size, vertices);
+ gluTessVertex(tess, vertices, vertices);
+ vertices += 3;
+ }
+ break;
+ default:
+ ERR("\t\tcurve type = %d\n", ppc->wType);
+ gluTessEndContour(tess);
+ goto error_in_list;
+ }
+
+ ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
+ (ppc->cpfx - 1) * sizeof(POINTFX));
+ }
+ gluTessEndContour(tess);
+ pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
+ }
+
+error_in_list:
+ gluTessEndPolygon(tess);
+ glEndList();
+ LEAVE_GL();
+ HeapFree(GetProcessHeap(), 0, buf);
+ HeapFree(GetProcessHeap(), 0, vertices);
+ }
+
+ error:
+ DeleteObject(SelectObject(hdc, old_font));
+ gluDeleteTess(tess);
+ return TRUE;
+
+}
+
+#else /* HAVE_GL_GLU_H */
+
+BOOL WINAPI wglUseFontOutlines_common(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf,
+ BOOL unicode)
+{
+ FIXME("Unable to compile in wglUseFontOutlines support without GL/glu.h\n");
+ return FALSE;
+}
+
+#endif /* HAVE_GL_GLU_H */
+
/***********************************************************************
* wglUseFontOutlinesA (OPENGL32.@)
*/
@@ -874,10 +1085,24 @@ BOOL WINAPI wglUseFontOutlinesA(HDC hdc,
FLOAT deviation,
FLOAT extrusion,
int format,
- LPGLYPHMETRICSFLOAT lpgmf) {
- FIXME("(): stub !\n");
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, FALSE);
+}
- return FALSE;
+/***********************************************************************
+ * wglUseFontOutlinesW (OPENGL32.@)
+ */
+BOOL WINAPI wglUseFontOutlinesW(HDC hdc,
+ DWORD first,
+ DWORD count,
+ DWORD listBase,
+ FLOAT deviation,
+ FLOAT extrusion,
+ int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return wglUseFontOutlines_common(hdc, first, count, listBase, deviation, extrusion, format, lpgmf, TRUE);
}
const GLubyte * internal_glGetString(GLenum name) {
More information about the wine-patches
mailing list