Author: jgardou
Date: Fri Mar 22 15:10:46 2013
New Revision: 58571
URL:
http://svn.reactos.org/svn/reactos?rev=58571&view=rev
Log:
[OPENGL32]
* Sync implementation of wglUseFontBitmaps and wglUseFontOutlines with WINE 1.5.26
Modified:
trunk/reactos/dll/opengl/opengl32/font.c
trunk/reactos/dll/opengl/opengl32/opengl32.spec
Modified: trunk/reactos/dll/opengl/opengl32/font.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/font.c…
==============================================================================
--- trunk/reactos/dll/opengl/opengl32/font.c [iso-8859-1] (original)
+++ trunk/reactos/dll/opengl/opengl32/font.c [iso-8859-1] Fri Mar 22 15:10:46 2013
@@ -1,1155 +1,565 @@
-/****************************************************************************
-* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and associated documentation files (the "Software"),
-* to deal in the Software without restriction, including without limitation
-* the rights to use, copy, modify, merge, publish, distribute, sublicense,
-* and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included
-* in all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-****************************************************************************/
-
-#include "opengl32.h"
+/* Window-specific OpenGL functions implementation.
+ *
+ * Copyright (c) 1999 Lionel Ulmer
+ * Copyright (c) 2005 Raphael Junqueira
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
#include <math.h>
-
-#define LINE_BUF_QUANT 4000
-#define VERT_BUF_QUANT 4000
-
-static HFONT hNewFont, hOldFont;
-static FLOAT ScaleFactor;
-static FLOAT* LineBuf;
-static DWORD LineBufSize;
-static DWORD LineBufIndex;
-static FLOAT* VertBuf;
-static DWORD VertBufSize;
-static DWORD VertBufIndex;
-static GLenum TessErrorOccurred;
-
-/*****************************************************************************
-* AppendToLineBuf
-*
-* Appends one floating-point value to the global LineBuf array. Return value
-* is non-zero for success, zero for failure.
-*****************************************************************************/
-
-INT AppendToLineBuf(FLOAT value)
-{
- if (LineBufIndex >= LineBufSize)
- {
- FLOAT* f;
- LineBufSize += LINE_BUF_QUANT;
-
- f = (FLOAT*) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, LineBuf,
(LineBufSize) * sizeof(FLOAT));
- if (!f)
- return 0;
- LineBuf = f;
- }
- LineBuf[LineBufIndex++] = value;
- return 1;
-}
-
-/*****************************************************************************
-* AppendToVertBuf
-*
-* Appends one floating-point value to the global VertBuf array. Return value
-* is non-zero for success, zero for failure.
-*
-* Note that we can't realloc this one, because the tessellator is using
-* pointers into it.
-*****************************************************************************/
-
-INT AppendToVertBuf(FLOAT value)
-{
- if (VertBufIndex >= VertBufSize)
- return 0;
- VertBuf[VertBufIndex++] = value;
- return 1;
-}
-
-/*****************************************************************************
-* GetWord
-*
-* Fetch the next 16-bit word from a little-endian byte stream, and increment
-* the stream pointer to the next unscanned byte.
-*****************************************************************************/
-
-LONG GetWord(UCHAR** p)
-{
- LONG value;
-
- value = ((*p)[1] << 8) + (*p)[0];
- *p += 2;
- return value;
-}
-
-/*****************************************************************************
-* GetDWord
-*
-* Fetch the next 32-bit word from a little-endian byte stream, and increment
-* the stream pointer to the next unscanned byte.
-*****************************************************************************/
-
-LONG GetDWord(UCHAR** p)
-{
- LONG value;
-
- value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) +
(*p)[0];
- *p += 4;
- return value;
-}
-
-/*****************************************************************************
-* GetFixed
-*
-* Fetch the next 32-bit fixed-point value from a little-endian byte stream,
-* convert it to floating-point, and increment the stream pointer to the next
-* unscanned byte.
-*****************************************************************************/
-double GetFixed(UCHAR** p)
-{
- LONG hiBits, loBits;
- double value;
-
- loBits = GetWord(p);
- hiBits = GetWord(p);
- value = (double) ((hiBits << 16) | loBits) / 65536.0;
-
- return value * ScaleFactor;
-}
-
-
-/*****************************************************************************
-**
-** InvertGlyphBitmap.
-**
-** Invert the bitmap so that it suits OpenGL's representation.
-** Each row starts on a double word boundary.
-**
-*****************************************************************************/
-
-VOID InvertGlyphBitmap(INT w, INT h, DWORD *fptr, DWORD *tptr)
-{
- INT dWordsInRow = (w+31)/32;
- INT i, j;
-
- if (w <= 0 || h <= 0) {
- return;
- }
-
- tptr += ((h-1)*dWordsInRow);
- for (i = 0; i < h; i++) {
- for (j = 0; j < dWordsInRow; j++) {
- *(tptr + j) = *(fptr + j);
- }
- tptr -= dWordsInRow;
- fptr += dWordsInRow;
- }
-}
-
-/*****************************************************************************
-* CreateHighResolutionFont
-*
-* Gets metrics for the current font and creates an equivalent font
-* scaled to the design units of the font.
-*
-*****************************************************************************/
-
-HFONT CreateHighResolutionFont(HDC hDC)
-{
- UINT otmSize;
- OUTLINETEXTMETRIC *otm;
- LONG fontHeight, fontWidth, fontUnits;
- LOGFONTW logFont, logFontFaceName;
-
- otmSize = GetOutlineTextMetricsW(hDC, 0, NULL);
- if (!otmSize)
- return NULL;
-
- otm = (OUTLINETEXTMETRIC *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, otmSize);
- if (!otm)
- return NULL;
-
- otm->otmSize = otmSize;
- if (!GetOutlineTextMetricsW(hDC, otmSize, otm))
- return NULL;
-
- GetObjectW(GetCurrentObject(hDC, OBJ_FONT), sizeof(logFontFaceName),
&logFontFaceName);
-
- 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;
- wcscpy(logFont.lfFaceName, logFontFaceName.lfFaceName);
-
- hNewFont = CreateFontIndirectW(&logFont);
-
- HeapFree(GetProcessHeap(), 0, otm);
-
- return hNewFont;
-}
-
-/*****************************************************************************
-* MakeLinesFromArc
-*
-* Subdivides one arc of a quadratic spline until the chordal deviation
-* tolerance requirement is met, then places the resulting set of line
-* segments in the global LineBuf.
-*****************************************************************************/
-INT MakeLinesFromArc(FLOAT x0, FLOAT y0, FLOAT x1, FLOAT y1, FLOAT x2, FLOAT y2,
- DWORD vertexCountIndex, FLOAT chordalDeviationSquared)
-{
- FLOAT x01;
- FLOAT y01;
- FLOAT x12;
- FLOAT y12;
- FLOAT midPointX;
- FLOAT midPointY;
- FLOAT deltaX;
- FLOAT deltaY;
-
- /*
- * Calculate midpoint of the curve by de Casteljau:
- */
- x01 = 0.5F * (x0 + x1);
- y01 = 0.5F * (y0 + y1);
- x12 = 0.5F * (x1 + x2);
- y12 = 0.5F * (y1 + y2);
- midPointX = 0.5F * (x01 + x12);
- midPointY = 0.5F * (y01 + y12);
-
-
- /*
- * Estimate chordal deviation by the distance from the midpoint
- * of the curve to its non-pointpolated control point. If this
- * distance is greater than the specified chordal deviation
- * constraint, then subdivide. Otherwise, generate polylines
- * from the three control points.
- */
- deltaX = midPointX - x1;
- deltaY = midPointY - y1;
-
- if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
- {
- MakeLinesFromArc( x0, y0,
- x01, y01,
- midPointX, midPointY,
- vertexCountIndex,
- chordalDeviationSquared);
-
- MakeLinesFromArc( midPointX, midPointY,
- x12, y12,
- x2, y2,
- vertexCountIndex,
- chordalDeviationSquared);
- }
- else
- {
- /*
- * The "pen" is already at (x0, y0), so we don't need to
- * add that point to the LineBuf.
+#include <GL/gl.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(wgl);
+
+/***********************************************************************
+ * wglUseFontBitmaps_common
+ */
+static BOOL wglUseFontBitmaps_common( HDC hdc, DWORD first, DWORD count, DWORD listBase,
BOOL unicode )
+{
+ GLYPHMETRICS gm;
+ unsigned int glyph, size = 0;
+ void *bitmap = NULL, *gl_bitmap = NULL;
+ int org_alignment;
+ BOOL ret = TRUE;
+
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &org_alignment);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+ for (glyph = first; glyph < first + count; glyph++) {
+ static const MAT2 identity = { {0,1},{0,0},{0,0},{0,1} };
+ unsigned int needed_size, height, width, width_int;
+
+ if (unicode)
+ needed_size = GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, 0, NULL,
&identity);
+ else
+ needed_size = GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, 0, NULL,
&identity);
+
+ TRACE("Glyph: %3d / List: %d size %d\n", glyph, listBase,
needed_size);
+ if (needed_size == GDI_ERROR) {
+ ret = FALSE;
+ break;
+ }
+
+ if (needed_size > size) {
+ size = needed_size;
+ HeapFree(GetProcessHeap(), 0, bitmap);
+ HeapFree(GetProcessHeap(), 0, gl_bitmap);
+ bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+ gl_bitmap = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+ }
+ if (unicode)
+ ret = (GetGlyphOutlineW(hdc, glyph, GGO_BITMAP, &gm, size, bitmap,
&identity) != GDI_ERROR);
+ else
+ ret = (GetGlyphOutlineA(hdc, glyph, GGO_BITMAP, &gm, size, bitmap,
&identity) != GDI_ERROR);
+ if (!ret) break;
+
+ if (TRACE_ON(wgl)) {
+ unsigned int bitmask;
+ unsigned char *bitmap_ = bitmap;
+
+ TRACE(" - bbox: %d x %d\n", gm.gmBlackBoxX, gm.gmBlackBoxY);
+ TRACE(" - origin: (%d, %d)\n", gm.gmptGlyphOrigin.x,
gm.gmptGlyphOrigin.y);
+ TRACE(" - increment: %d - %d\n", gm.gmCellIncX, gm.gmCellIncY);
+ if (needed_size != 0) {
+ TRACE(" - bitmap:\n");
+ for (height = 0; height < gm.gmBlackBoxY; height++) {
+ TRACE(" ");
+ for (width = 0, bitmask = 0x80; width < gm.gmBlackBoxX; width++,
bitmask >>= 1) {
+ if (bitmask == 0) {
+ bitmap_ += 1;
+ bitmask = 0x80;
+ }
+ if (*bitmap_ & bitmask)
+ TRACE("*");
+ else
+ TRACE(" ");
+ }
+ bitmap_ += (4 - ((UINT_PTR)bitmap_ & 0x03));
+ TRACE("\n");
+ }
+ }
+ }
+
+ /* In OpenGL, the bitmap is drawn from the bottom to the top... So we need to
invert the
+ * glyph for it to be drawn properly.
*/
- if (!AppendToLineBuf(x1)
- || !AppendToLineBuf(y1)
- || !AppendToLineBuf(x2)
- || !AppendToLineBuf(y2))
- return 0;
- LineBuf[vertexCountIndex] += 2.0F;
- }
-
- return 1;
-}
-
-/*****************************************************************************
-* MakeLinesFromTTQSpline
-*
-* Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
-* structure to polyline points in the global LineBuf.
-*****************************************************************************/
-
-INT MakeLinesFromTTQSpline( UCHAR** pp, DWORD vertexCountIndex, WORD pointCount, FLOAT
chordalDeviation)
-{
- FLOAT x0, y0, x1, y1, x2, y2;
- WORD point;
-
- /*
- * Process each of the non-pointpolated points in the outline.
- * To do this, we need to generate two pointpolated points (the
- * start and end of the arc) for each non-pointpolated point.
- * The first pointpolated point is always the one most recently
- * stored in LineBuf, so we just extract it from there. The
- * second pointpolated point is either the average of the next
- * two points in the QSpline, or the last point in the QSpline
- * if only one remains.
- */
- for (point = 0; point < pointCount - 1; ++point)
- {
- x0 = LineBuf[LineBufIndex - 2];
- y0 = LineBuf[LineBufIndex - 1];
-
- x1 = (FLOAT) GetFixed(pp);
- y1 = (FLOAT) GetFixed(pp);
-
- if (point == pointCount - 2)
- {
- /*
- * This is the last arc in the QSpline. The final
- * point is the end of the arc.
- */
- x2 = (FLOAT) GetFixed(pp);
- y2 = (FLOAT) GetFixed(pp);
- }
- else
- {
- /*
- * Peek at the next point in the input to compute
- * the end of the arc:
- */
- x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
- y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
- /*
- * Push the point back onto the input so it will
- * be reused as the next off-curve point:
- */
- *pp -= 8;
- }
-
- if (!MakeLinesFromArc( x0, y0,
- x1, y1,
- x2, y2,
- vertexCountIndex,
- chordalDeviation * chordalDeviation))
- return 0;
- }
-
- return 1;
-}
-
-/*****************************************************************************
-* MakeLinesFromTTLine
-*
-* Converts points from the polyline in a TT_PRIM_LINE structure to
-* equivalent points in the global LineBuf.
-*****************************************************************************/
-INT MakeLinesFromTTLine(UCHAR** pp, DWORD vertexCountIndex, WORD pointCount)
-{
- /*
- * Just copy the line segments into the line buffer (converting
- * type as we go):
- */
- LineBuf[vertexCountIndex] += pointCount;
- while (pointCount--)
- {
- if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
- || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
- return 0;
- }
-
- return 1;
-}
-
-/*****************************************************************************
-* MakeLinesFromTTPolyCurve
-*
-* Converts the lines and splines in a single TTPOLYCURVE structure to points
-* in the global LineBuf.
-*****************************************************************************/
-
-INT MakeLinesFromTTPolycurve(UCHAR** pp, DWORD vertexCountIndex, FLOAT chordalDeviation)
-{
- WORD type;
- WORD pointCount;
-
- /*
- * Pick up the relevant fields of the TTPOLYCURVE structure:
- */
- type = (WORD) GetWord(pp);
- pointCount = (WORD) GetWord(pp);
-
- /*
- * Convert the "curve" to line segments:
- */
- if (type == TT_PRIM_LINE)
- return MakeLinesFromTTLine( pp,
- vertexCountIndex,
- pointCount);
- else if (type == TT_PRIM_QSPLINE)
- return MakeLinesFromTTQSpline( pp,
- vertexCountIndex,
- pointCount,
- chordalDeviation);
- else
- return 0;
-}
-
-/*****************************************************************************
-* MakeLinesFromTTPolygon
-*
-* Converts a TTPOLYGONHEADER and its associated curve structures into a
-* single polyline loop in the global LineBuf.
-*****************************************************************************/
-
-INT MakeLinesFromTTPolygon(UCHAR** pp, FLOAT chordalDeviation)
-{
- DWORD polySize;
- UCHAR* polyStart;
- DWORD vertexCountIndex;
-
- /*
- * Record where the polygon data begins, and where the loop's
- * vertex count resides:
- */
- polyStart = *pp;
- vertexCountIndex = LineBufIndex;
- if (!AppendToLineBuf(0.0F))
- return 0;
-
- /*
- * Extract relevant data from the TTPOLYGONHEADER:
- */
- polySize = GetDWord(pp);
- if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
- return 0;
- if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
- return 0;
- if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
- return 0;
- LineBuf[vertexCountIndex] += 1.0F;
-
- /*
- * Process each of the TTPOLYCURVE structures in the polygon:
- */
- while (*pp < polyStart + polySize)
- if (!MakeLinesFromTTPolycurve( pp,
- vertexCountIndex,
- chordalDeviation))
- return 0;
-
- return 1;
-}
-
-/*****************************************************************************
-* TessVertexOut
-*
-* Used by tessellator to handle output vertexes.
-*****************************************************************************/
-
-VOID CALLBACK TessVertexOutData(FLOAT p[3], GLfloat *pz)
-{
- GLfloat v[3];
- v[0] = (GLfloat) p[0];
- v[1] = (GLfloat) p[1];
- v[2] = *pz;
- glVertex3fv(v);
-}
-
-/*****************************************************************************
-* TessCombine
-*
-* Used by tessellator to handle self-pointsecting contours and degenerate
-* geometry.
-*****************************************************************************/
-VOID CALLBACK TessCombine(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.
-*****************************************************************************/
-
-VOID CALLBACK TessError(GLenum error)
-{
- TessErrorOccurred = error;
-}
-
-/*****************************************************************************
-* MakeLinesFromGlyph
-*
-* Converts the outline of a glyph from the TTPOLYGON format to a simple
-* array of floating-point values containing one or more loops.
-*
-* The first element of the output array is a count of the number of loops.
-* The loop data follows this count. Each loop consists of a count of the
-* number of vertices it contains, followed by the vertices. Each vertex
-* is an X and Y coordinate. For example, a single triangle might be
-* described by this array:
-*
-* 1., 3., 0., 0., 1., 0., 0., 1.
-* ^ ^ ^ ^ ^ ^ ^ ^
-* #loops #verts x1 y1 x2 y2 x3 y3
-*
-* A two-loop glyph would look like this:
-*
-* 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
-*
-* Line segments from the TTPOLYGON are transferred to the output array in
-* the obvious way. Quadratic splines in the TTPOLYGON are converted to
-* collections of line segments
-*****************************************************************************/
-
-INT MakeLinesFromGlyph(UCHAR* glyphBuf, DWORD glyphSize, FLOAT chordalDeviation)
-{
- UCHAR* p;
- INT status = 0;
-
- /*
- * Pick up all the polygons (aka loops) that make up the glyph:
- */
- if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
- goto exit;
-
- p = glyphBuf;
- while (p < glyphBuf + glyphSize)
- {
- if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
- goto exit;
- LineBuf[0] += 1.0F; /* increment loop count */
- }
-
- status = 1;
-
-exit:
- 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().
-*****************************************************************************/
-
-INT DrawGlyph(UCHAR* glyphBuf, DWORD glyphSize, FLOAT chordalDeviation, FLOAT extrusion,
INT format)
-{
- INT status = 0;
- FLOAT* p;
- DWORD loop;
- DWORD point;
- GLUtesselator* tess = NULL;
-
- /*
- * Initialize the global buffer into which we place the outlines:
- */
- LineBuf = (FLOAT*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (LINE_BUF_QUANT) *
sizeof(FLOAT));
-
- if(!LineBuf)
- goto exit;
-
- LineBufSize = LINE_BUF_QUANT;
- LineBufIndex = 0;
-
- /*
- * 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)
- {
- glBegin(GL_LINE_LOOP);
- for (point = (DWORD) *p++; point; --point)
- {
- glVertex2fv(p);
- p += 2;
+ if (needed_size != 0) {
+ width_int = (gm.gmBlackBoxX + 31) / 32;
+ for (height = 0; height < gm.gmBlackBoxY; height++) {
+ for (width = 0; width < width_int; width++) {
+ ((int *) gl_bitmap)[(gm.gmBlackBoxY - height - 1) * width_int +
width] =
+ ((int *) bitmap)[height * width_int + width];
+ }
}
- 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.
- */
-
- VertBuf = (FLOAT*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (VERT_BUF_QUANT)
* sizeof(FLOAT));
-
- if (!VertBuf)
- goto exit;
-
- VertBufSize = VERT_BUF_QUANT;
- VertBufIndex = 0;
-
- if (!(tess = gluNewTess()))
- goto exit;
-
- gluTessCallback(tess, GLU_BEGIN, (VOID(CALLBACK *)()) glBegin);
- gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (VOID(CALLBACK *)())
TessVertexOutData);
- gluTessCallback(tess, GLU_END, (VOID(CALLBACK *)()) glEnd);
- gluTessCallback(tess, GLU_ERROR, (VOID(CALLBACK *)()) TessError);
- gluTessCallback(tess, GLU_TESS_COMBINE, (VOID(CALLBACK *)()) TessCombine);
- gluTessNormal(tess, 0.0F, 0.0F, 1.0F);
-
- TessErrorOccurred = 0;
- glNormal3f(0.0f, 0.0f, 1.0f);
- v[2] = 0.0;
- z_value = 0.0f;
-
- gluTessBeginPolygon(tess, &z_value);
-
- for (loop = (DWORD) *p++; loop; --loop)
- {
- gluTessBeginContour(tess);
-
- for (point = (DWORD) *p++; point; --point)
- {
- v[0] = p[0];
- v[1] = p[1];
- gluTessVertex(tess, v, p);
- p += 2;
- }
-
- gluTessEndContour(tess);
- }
- gluTessEndPolygon(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++;
- 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);
-
- glNormal3f(dy / len, -dx / len, 0.0f);
- glVertex3f((GLfloat) vert[0],
- (GLfloat) vert[1], thickness);
- glVertex3f((GLfloat) vert[0],
- (GLfloat) vert[1], 0.0f);
- }
-
- glEnd();
- p += count*2;
- }
-
- /* Draw the back face */
- p = save_p;
- v[2] = thickness;
- glNormal3f(0.0f, 0.0f, -1.0f);
- gluTessNormal(tess, 0.0F, 0.0F, -1.0F);
-
- gluTessBeginPolygon(tess, &thickness);
-
- for (loop = (DWORD) *p++; loop; --loop)
- {
- count = (DWORD) *p++;
-
- gluTessBeginContour(tess);
-
- for (point = 0; point < count; point++)
- {
- vert = p + ((count-point-1)<<1);
- v[0] = vert[0];
- v[1] = vert[1];
- gluTessVertex(tess, v, vert);
- }
- p += count*2;
-
- gluTessEndContour(tess);
- }
- gluTessEndPolygon(tess);
- }
-
-#if !defined(NDEBUG)
- if (TessErrorOccurred)
- DBGPRINT("Tessellation error %s\n",
gluErrorString(TessErrorOccurred));
-#endif
- }
-
-
-exit:
-
- if(LineBuf)
- HeapFree(GetProcessHeap(), 0, LineBuf);
-
- if(VertBuf)
- HeapFree(GetProcessHeap(), 0, VertBuf);
-
- if (tess)
- gluDeleteTess(tess);
-
- return status;
-}
-
-
-/*****************************************************************************
-* 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().
-*****************************************************************************/
-
-INT MakeDisplayListFromGlyph(DWORD listName, UCHAR* glyphBuf, DWORD glyphSize,
LPGLYPHMETRICSFLOAT glyphMetricsFloat,
- FLOAT chordalDeviation, FLOAT extrusion, INT format)
-{
- INT status;
-
- glNewList(listName, GL_COMPILE);
- status = DrawGlyph(glyphBuf, glyphSize, chordalDeviation, extrusion, format);
- glTranslatef(glyphMetricsFloat->gmfCellIncX,
glyphMetricsFloat->gmfCellIncY, 0.0F);
- glEndList();
-
- return status;
-}
-
-// ***********************************************************************
-
-/*****************************************************************************
-* IntUseFontBitmaps
-*
-* Converts a subrange of the glyphs in a GDI font to OpenGL display
-* lists.
-*
-* Extended to support any GDI font, not just TrueType fonts. (DaveM)
-*
-*****************************************************************************/
-
-BOOL APIENTRY IntUseFontBitmapsW(HDC hDC, DWORD first, DWORD count, DWORD listBase)
-{
- INT i, ox, oy, ix, iy;
- INT w = 0, h = 0;
- INT iBufSize, iCurBufSize = 0;
- DWORD *bitmapBuffer = NULL;
- DWORD *invertedBitmapBuffer = NULL;
- BOOL bSuccessOrFail = TRUE;
- BOOL bTrueType = FALSE;
- TEXTMETRIC tm;
- GLYPHMETRICS gm;
- RASTERIZER_STATUS rs;
- MAT2 mat;
- SIZE size;
- RECT rect;
- HDC hDCMem;
- HBITMAP hBitmap;
- BITMAPINFO bmi;
- HFONT hFont;
-
- // Set up a unity matrix.
- ZeroMemory(&mat, sizeof(mat));
- mat.eM11.value = 1;
- mat.eM22.value = 1;
-
- // Test to see if selected font is TrueType or not
- ZeroMemory(&tm, sizeof(tm));
- if (!GetTextMetrics(hDC, &tm))
- {
- DBGPRINT("Font metrics error\n");
- return FALSE;
- }
- bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
-
- // Test to see if TRUE-TYPE capabilities are installed
- // (only necessary if TrueType font selected)
- ZeroMemory(&rs, sizeof(rs));
-
- if (bTrueType)
- {
- if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS)) || !(rs.wFlags &
TT_ENABLED))
- {
- DBGPRINT("No TrueType caps\n");
- bTrueType = FALSE;
- }
- }
-
- // Trick to get the current font handle
- hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
- SelectObject(hDC, hFont);
-
- // Have memory device context available for holding bitmaps of font glyphs
- hDCMem = CreateCompatibleDC(hDC);
- SelectObject(hDCMem, hFont);
- SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
- SetBkColor(hDCMem, 0);
-
- for (i = first; (DWORD) i < (first + count); i++)
- {
- // Find out how much space is needed for the bitmap so we can
- // Set the buffer size correctly.
- if (bTrueType)
- {
- // Use TrueType support to get bitmap size of glyph
- iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, 0, NULL, &mat);
- if (iBufSize == GDI_ERROR)
- {
- bSuccessOrFail = FALSE;
- break;
- }
- }
- else
- {
- // Use generic GDI support to compute bitmap size of glyph
- w = tm.tmMaxCharWidth;
- h = tm.tmHeight;
- if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size))
- {
- w = size.cx;
- h = size.cy;
- }
- iBufSize = w * h;
- // Use DWORD multiple for compatibility
- iBufSize += 3;
- iBufSize /= 4;
- iBufSize *= 4;
- }
-
- // If we need to allocate Larger Buffers, then do so - but allocate
- // An extra 50 % so that we don't do too many mallocs !
- if (iBufSize > iCurBufSize)
- {
- if (bitmapBuffer)
- {
- HeapFree(GetProcessHeap(), 0, bitmapBuffer);
- }
- if (invertedBitmapBuffer)
- {
- HeapFree(GetProcessHeap(), 0, invertedBitmapBuffer);
- }
-
- iCurBufSize = iBufSize * 2;
- bitmapBuffer = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
iCurBufSize);
- invertedBitmapBuffer = (DWORD *) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, iCurBufSize);
-
- if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL)
- {
- bSuccessOrFail = FALSE;
- break;
- }
- }
-
- // If we fail to get the Glyph data, delete the display lists
- // Created so far and return FALSE.
- if (bTrueType)
- {
- // Use TrueType support to get bitmap of glyph
- if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, iBufSize, bitmapBuffer,
&mat) == GDI_ERROR)
- {
- bSuccessOrFail = FALSE;
- break;
- }
-
- // Setup glBitmap parameters for current font glyph
- w = gm.gmBlackBoxX;
- h = gm.gmBlackBoxY;
- ox = gm.gmptGlyphOrigin.x;
- oy = gm.gmptGlyphOrigin.y;
- ix = gm.gmCellIncX;
- iy = gm.gmCellIncY;
- }
- else
- {
- // Use generic GDI support to create bitmap of glyph
- ZeroMemory(bitmapBuffer, iBufSize);
-
- if (i >= tm.tmFirstChar && i <= tm.tmLastChar)
- {
- // Only create bitmaps for actual font glyphs
- hBitmap = CreateBitmap(w, h, 1, 1, NULL);
- SelectObject(hDCMem, hBitmap);
- // Make bitmap of current font glyph
- SetRect(&rect, 0, 0, w, h);
- DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
- DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
- // Make copy of bitmap in our local buffer
- ZeroMemory(&bmi, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = w;
- bmi.bmiHeader.biHeight = -h;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 1;
- bmi.bmiHeader.biCompression = BI_RGB;
- GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
- DeleteObject(hBitmap);
- }
- else
- {
- // Otherwise use empty display list for non-existing glyph
- iBufSize = 0;
- }
-
- // Setup glBitmap parameters for current font glyph
- ox = 0;
- oy = tm.tmDescent;
- ix = w;
- iy = 0;
- }
-
- // Create an OpenGL display list.
- glNewList((listBase + i), GL_COMPILE);
-
- // Some fonts have no data for the space character, yet advertise
- // a non-zero size.
- if (0 == iBufSize)
- {
- glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
- }
- else
- {
- // Invert the Glyph data.
- InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
-
- // Render an OpenGL bitmap and invert the origin.
- glBitmap(w, h,
- (GLfloat) ox, (GLfloat) (h-oy),
- (GLfloat) ix, (GLfloat) iy,
- (GLubyte *) invertedBitmapBuffer);
- }
-
- // Close this display list.
+ }
+
+ glNewList(listBase++, GL_COMPILE);
+ if (needed_size != 0) {
+ glBitmap(gm.gmBlackBoxX, gm.gmBlackBoxY,
+ 0 - gm.gmptGlyphOrigin.x, (int) gm.gmBlackBoxY - gm.gmptGlyphOrigin.y,
+ gm.gmCellIncX, gm.gmCellIncY,
+ gl_bitmap);
+ } else {
+ /* This is the case of 'empty' glyphs like the space character */
+ glBitmap(0, 0, 0, 0, gm.gmCellIncX, gm.gmCellIncY, NULL);
+ }
glEndList();
}
- if (bSuccessOrFail == FALSE)
+ glPixelStorei(GL_UNPACK_ALIGNMENT, org_alignment);
+ HeapFree(GetProcessHeap(), 0, bitmap);
+ HeapFree(GetProcessHeap(), 0, gl_bitmap);
+ return ret;
+}
+
+/***********************************************************************
+ * wglUseFontBitmapsA (OPENGL32.@)
+ */
+BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ return wglUseFontBitmaps_common( hdc, first, count, listBase, FALSE );
+}
+
+/***********************************************************************
+ * wglUseFontBitmapsW (OPENGL32.@)
+ */
+BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
+{
+ return wglUseFontBitmaps_common( hdc, first, count, listBase, TRUE );
+}
+
+/* FIXME: should probably have a glu.h header */
+
+typedef struct GLUtesselator GLUtesselator;
+typedef void (WINAPI *_GLUfuncptr)(void);
+
+#define GLU_TESS_BEGIN 100100
+#define GLU_TESS_VERTEX 100101
+#define GLU_TESS_END 100102
+
+static GLUtesselator * (WINAPI *pgluNewTess)(void);
+static void (WINAPI *pgluDeleteTess)(GLUtesselator *tess);
+static void (WINAPI *pgluTessNormal)(GLUtesselator *tess, GLdouble x, GLdouble y,
GLdouble z);
+static void (WINAPI *pgluTessBeginPolygon)(GLUtesselator *tess, void *polygon_data);
+static void (WINAPI *pgluTessEndPolygon)(GLUtesselator *tess);
+static void (WINAPI *pgluTessCallback)(GLUtesselator *tess, GLenum which, _GLUfuncptr
fn);
+static void (WINAPI *pgluTessBeginContour)(GLUtesselator *tess);
+static void (WINAPI *pgluTessEndContour)(GLUtesselator *tess);
+static void (WINAPI *pgluTessVertex)(GLUtesselator *tess, GLdouble *location, GLvoid*
data);
+
+static HMODULE load_libglu(void)
+{
+ static const WCHAR glu32W[] =
{'g','l','u','3','2','.','d','l','l',0};
+ static int already_loaded;
+ static HMODULE module;
+
+ if (already_loaded) return module;
+ already_loaded = 1;
+
+ TRACE("Trying to load GLU library\n");
+ module = LoadLibraryW( glu32W );
+ if (!module)
{
- DBGPRINT("DGL_UseFontBitmaps: Get glyph failed\n");
- glDeleteLists((i+listBase), (i-first));
+ WARN("Failed to load glu32\n");
+ return NULL;
}
-
- // Release resources used
- DeleteObject(hFont);
- DeleteDC(hDCMem);
-
- if (bitmapBuffer)
- HeapFree(GetProcessHeap(), 0, bitmapBuffer);
-
- if (invertedBitmapBuffer)
- HeapFree(GetProcessHeap(), 0, invertedBitmapBuffer);
-
- return(bSuccessOrFail);
-}
-
-BOOL APIENTRY IntUseFontBitmapsA(HDC hDC, DWORD first, DWORD count, DWORD listBase)
-{
- /* Just call IntUseFontBitmapsW for now */
- return IntUseFontBitmapsW(hDC, first, count, listBase);
-}
-
-
-
-/*****************************************************************************
-* IntUseFontOutlines
-*
-* Converts a subrange of the glyphs in a TrueType font to OpenGL display
-* lists.
-*****************************************************************************/
-
-BOOL APIENTRY IntUseFontOutlinesW(HDC hDC, DWORD first, DWORD count, DWORD listBase,
FLOAT chordalDeviation,
- FLOAT extrusion, INT format, GLYPHMETRICSFLOAT
*glyphMetricsFloatArray)
-{
- DWORD glyphIndex;
- UCHAR* glyphBuf;
- DWORD glyphBufSize;
-
- /*
- * Flush any previous OpenGL errors. This allows us to check for
- * new errors so they can be reported via the function return value.
- */
- while (glGetError() != GL_NO_ERROR);
-
- /*
- * Make sure that the current font can be sampled accurately.
- */
- hNewFont = CreateHighResolutionFont(hDC);
-
- if (!hNewFont)
- return FALSE;
-
- hOldFont = SelectObject(hDC, hNewFont);
- if (!hOldFont)
- return FALSE;
-
- /*
- * Preallocate a buffer for the outline data, and track its size:
- */
- glyphBuf = (UCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, glyphBufSize =
10240);
-
- if (!glyphBuf)
- return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
-
- /*
- * Process each glyph in the given range:
- */
- for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+#define LOAD_FUNCPTR(f) p##f = (void *)GetProcAddress( module, #f )
+ LOAD_FUNCPTR(gluNewTess);
+ LOAD_FUNCPTR(gluDeleteTess);
+ LOAD_FUNCPTR(gluTessBeginContour);
+ LOAD_FUNCPTR(gluTessNormal);
+ LOAD_FUNCPTR(gluTessBeginPolygon);
+ LOAD_FUNCPTR(gluTessCallback);
+ LOAD_FUNCPTR(gluTessEndContour);
+ LOAD_FUNCPTR(gluTessEndPolygon);
+ LOAD_FUNCPTR(gluTessVertex);
+#undef LOAD_FUNCPTR
+ return module;
+}
+
+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 WINAPI tess_callback_vertex(GLvoid *vertex)
+{
+ GLdouble *dbl = vertex;
+ TRACE("%f, %f, %f\n", dbl[0], dbl[1], dbl[2]);
+ glVertex3dv(vertex);
+}
+
+static void WINAPI tess_callback_begin(GLenum which)
+{
+ TRACE("%d\n", which);
+ glBegin(which);
+}
+
+static void WINAPI tess_callback_end(void)
+{
+ TRACE("\n");
+ glEnd();
+}
+
+typedef struct _bezier_vector {
+ GLdouble x;
+ GLdouble y;
+} bezier_vector;
+
+static double bezier_deviation_squared(const bezier_vector *p)
+{
+ bezier_vector deviation;
+ bezier_vector vertex;
+ bezier_vector base;
+ double base_length;
+ double dot;
+
+ vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4 - p[0].x;
+ vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4 - p[0].y;
+
+ base.x = p[2].x - p[0].x;
+ base.y = p[2].y - p[0].y;
+
+ base_length = sqrt(base.x*base.x + base.y*base.y);
+ base.x /= base_length;
+ base.y /= base_length;
+
+ dot = base.x*vertex.x + base.y*vertex.y;
+ dot = min(max(dot, 0.0), base_length);
+ base.x *= dot;
+ base.y *= dot;
+
+ deviation.x = vertex.x-base.x;
+ deviation.y = vertex.y-base.y;
+
+ return deviation.x*deviation.x + deviation.y*deviation.y;
+}
+
+static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLOAT
deviation)
+{
+ bezier_vector first_curve[3];
+ bezier_vector second_curve[3];
+ bezier_vector vertex;
+ int total_vertices;
+
+ if(bezier_deviation_squared(p) <= deviation*deviation)
{
- GLYPHMETRICS glyphMetrics;
- DWORD glyphSize;
- static MAT2 matrix =
+ if(points)
+ *points = p[2];
+ return 1;
+ }
+
+ vertex.x = (p[0].x + p[1].x*2 + p[2].x)/4;
+ vertex.y = (p[0].y + p[1].y*2 + p[2].y)/4;
+
+ first_curve[0] = p[0];
+ first_curve[1].x = (p[0].x + p[1].x)/2;
+ first_curve[1].y = (p[0].y + p[1].y)/2;
+ first_curve[2] = vertex;
+
+ second_curve[0] = vertex;
+ second_curve[1].x = (p[2].x + p[1].x)/2;
+ second_curve[1].y = (p[2].y + p[1].y)/2;
+ second_curve[2] = p[2];
+
+ total_vertices = bezier_approximate(first_curve, points, deviation);
+ if(points)
+ points += total_vertices;
+ total_vertices += bezier_approximate(second_curve, points, deviation);
+ return total_vertices;
+}
+
+/***********************************************************************
+ * wglUseFontOutlines_common
+ */
+static BOOL 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 = NULL;
+ LOGFONTW lf;
+ HFONT old_font, unscaled_font;
+ UINT em_size = 1024;
+ RECT rc;
+
+ TRACE("(%p, %d, %d, %d, %f, %f, %d, %p, %s)\n", hdc, first, count,
+ listBase, deviation, extrusion, format, lpgmf, unicode ? "W" :
"A");
+
+ if(deviation <= 0.0)
+ deviation = 1.0/em_size;
+
+ if(format == WGL_FONT_POLYGONS)
+ {
+ if (!load_libglu())
{
- {0, 1}, {0, 0},
- {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 == GDI_ERROR)
- return FALSE; /*WGL_STATUS_FAILURE*/
-
- if (glyphSize > glyphBufSize)
+ ERR("glu32 is required for this function but isn't
available\n");
+ return FALSE;
+ }
+
+ tess = pgluNewTess();
+ if(!tess) return FALSE;
+ pgluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tess_callback_vertex);
+ pgluTessCallback(tess, GLU_TESS_BEGIN, (_GLUfuncptr)tess_callback_begin);
+ pgluTessCallback(tess, GLU_TESS_END, tess_callback_end);
+ }
+
+ 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 = NULL;
+ int vertex_total = -1;
+
+ 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);
+
+ 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)
{
- HeapFree(GetProcessHeap(), 0, glyphBuf);
- glyphBuf = (UCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
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) == GDI_ERROR)
+ lpgmf->gmfBlackBoxX = (float)gm.gmBlackBoxX / em_size;
+ lpgmf->gmfBlackBoxY = (float)gm.gmBlackBoxY / em_size;
+ lpgmf->gmfptGlyphOrigin.x = (float)gm.gmptGlyphOrigin.x / em_size;
+ lpgmf->gmfptGlyphOrigin.y = (float)gm.gmptGlyphOrigin.y / em_size;
+ lpgmf->gmfCellIncX = (float)gm.gmCellIncX / em_size;
+ lpgmf->gmfCellIncY = (float)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++;
+ }
+
+ glNewList(listBase++, GL_COMPILE);
+ glFrontFace(GL_CCW);
+ if(format == WGL_FONT_POLYGONS)
{
- HeapFree(GetProcessHeap(), 0, 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))
+ glNormal3d(0.0, 0.0, 1.0);
+ pgluTessNormal(tess, 0, 0, 1);
+ pgluTessBeginPolygon(tess, NULL);
+ }
+
+ while(!vertices)
{
- HeapFree(GetProcessHeap(), 0, glyphBuf);
- return FALSE; /*WGL_STATUS_FAILURE*/
- }
+ if(vertex_total != -1)
+ vertices = HeapAlloc(GetProcessHeap(), 0, vertex_total * 3 *
sizeof(GLdouble));
+ vertex_total = 0;
+
+ pph = (TTPOLYGONHEADER*)buf;
+ while((BYTE*)pph < buf + needed)
+ {
+ GLdouble previous[3];
+ fixed_to_double(pph->pfxStart, em_size, previous);
+
+ if(vertices)
+ TRACE("\tstart %d, %d\n", pph->pfxStart.x.value,
pph->pfxStart.y.value);
+
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessBeginContour(tess);
+ else
+ glBegin(GL_LINE_LOOP);
+
+ if(vertices)
+ {
+ fixed_to_double(pph->pfxStart, em_size, vertices);
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessVertex(tess, vertices, vertices);
+ else
+ glVertex3d(vertices[0], vertices[1], vertices[2]);
+ vertices += 3;
+ }
+ vertex_total++;
+
+ ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph));
+ while((char*)ppc < (char*)pph + pph->cb)
+ {
+ int i, j;
+ int num;
+
+ switch(ppc->wType) {
+ case TT_PRIM_LINE:
+ for(i = 0; i < ppc->cpfx; i++)
+ {
+ if(vertices)
+ {
+ 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);
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessVertex(tess, vertices, vertices);
+ else
+ glVertex3d(vertices[0], vertices[1], vertices[2]);
+ vertices += 3;
+ }
+ fixed_to_double(ppc->apfx[i], em_size, previous);
+ vertex_total++;
+ }
+ break;
+
+ case TT_PRIM_QSPLINE:
+ for(i = 0; i < ppc->cpfx-1; i++)
+ {
+ bezier_vector curve[3];
+ bezier_vector *points;
+ GLdouble curve_vertex[3];
+
+ if(vertices)
+ TRACE("\t\tcurve %d,%d %d,%d\n",
+ ppc->apfx[i].x.value,
ppc->apfx[i].y.value,
+ ppc->apfx[i + 1].x.value, ppc->apfx[i +
1].y.value);
+
+ curve[0].x = previous[0];
+ curve[0].y = previous[1];
+ fixed_to_double(ppc->apfx[i], em_size, curve_vertex);
+ curve[1].x = curve_vertex[0];
+ curve[1].y = curve_vertex[1];
+ fixed_to_double(ppc->apfx[i + 1], em_size, curve_vertex);
+ curve[2].x = curve_vertex[0];
+ curve[2].y = curve_vertex[1];
+ if(i < ppc->cpfx-2)
+ {
+ curve[2].x = (curve[1].x + curve[2].x)/2;
+ curve[2].y = (curve[1].y + curve[2].y)/2;
+ }
+ num = bezier_approximate(curve, NULL, deviation);
+ points = HeapAlloc(GetProcessHeap(), 0,
num*sizeof(bezier_vector));
+ num = bezier_approximate(curve, points, deviation);
+ vertex_total += num;
+ if(vertices)
+ {
+ for(j=0; j<num; j++)
+ {
+ TRACE("\t\t\tvertex at %f,%f\n",
points[j].x, points[j].y);
+ vertices[0] = points[j].x;
+ vertices[1] = points[j].y;
+ vertices[2] = 0.0;
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessVertex(tess, vertices, vertices);
+ else
+ glVertex3d(vertices[0], vertices[1],
vertices[2]);
+ vertices += 3;
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, points);
+ previous[0] = curve[2].x;
+ previous[1] = curve[2].y;
+ }
+ break;
+ default:
+ ERR("\t\tcurve type = %d\n", ppc->wType);
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessEndContour(tess);
+ else
+ glEnd();
+ goto error_in_list;
+ }
+
+ ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) +
+ (ppc->cpfx - 1) * sizeof(POINTFX));
+ }
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessEndContour(tess);
+ else
+ glEnd();
+ pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb);
+ }
+ }
+
+error_in_list:
+ if(format == WGL_FONT_POLYGONS)
+ pgluTessEndPolygon(tess);
+ glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY /
em_size, 0.0);
+ glEndList();
+ HeapFree(GetProcessHeap(), 0, buf);
+ HeapFree(GetProcessHeap(), 0, vertices);
}
- /*
- * Clean up temporary storage and return. If an error occurred,
- * clear all OpenGL error flags and return FAILURE status;
- * otherwise just return SUCCESS.
- */
- HeapFree(GetProcessHeap(), 0, glyphBuf);
-
- DeleteObject(SelectObject(hDC, hOldFont));
-
- if (glGetError() == GL_NO_ERROR)
- {
- return TRUE; /*WGL_STATUS_SUCCESS*/
- }
- else
- {
- while (glGetError() != GL_NO_ERROR);
-
- return FALSE; /*WGL_STATUS_FAILURE*/
- }
-}
-
-BOOL APIENTRY IntUseFontOutlinesA(HDC hDC, DWORD first, DWORD count, DWORD listBase,
FLOAT chordalDeviation,
- FLOAT extrusion, INT format, GLYPHMETRICSFLOAT
*glyphMetricsFloatArray)
-{
- /* Just call IntUseFontOutlinesW for now */
- return IntUseFontOutlinesW(hDC, first, count, listBase, chordalDeviation, extrusion,
format, glyphMetricsFloatArray);
-}
+ error:
+ DeleteObject(SelectObject(hdc, old_font));
+ if(format == WGL_FONT_POLYGONS)
+ pgluDeleteTess(tess);
+ return TRUE;
+
+}
+
+/***********************************************************************
+ * wglUseFontOutlinesA (OPENGL32.@)
+ */
+BOOL WINAPI wglUseFontOutlinesA(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, 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);
+}
Modified: trunk/reactos/dll/opengl/opengl32/opengl32.spec
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/opengl/opengl32/opengl…
==============================================================================
--- trunk/reactos/dll/opengl/opengl32/opengl32.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/opengl/opengl32/opengl32.spec [iso-8859-1] Fri Mar 22 15:10:46 2013
@@ -363,7 +363,7 @@
@ stdcall wglSwapBuffers(long) rosglSwapBuffers
@ stdcall wglSwapLayerBuffers(long long) rosglSwapLayerBuffers
@ stub wglSwapMultipleBuffers
-@ stdcall wglUseFontBitmapsA(long long long long) rosglUseFontBitmapsA
-@ stdcall wglUseFontBitmapsW(long long long long) rosglUseFontBitmapsW
-@ stdcall wglUseFontOutlinesA(long long long long long long long ptr)
rosglUseFontOutlinesA
-@ stdcall wglUseFontOutlinesW(long long long long long long long ptr)
rosglUseFontOutlinesW
+@ stdcall wglUseFontBitmapsA(long long long long)
+@ stdcall wglUseFontBitmapsW(long long long long)
+@ stdcall wglUseFontOutlinesA(long long long long long long long ptr)
+@ stdcall wglUseFontOutlinesW(long long long long long long long ptr)