ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

font.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 *   Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
00003 *
00004 *   Permission is hereby granted, free of charge, to any person obtaining a
00005 *   copy of this software and associated documentation files (the "Software"),
00006 *   to deal in the Software without restriction, including without limitation
00007 *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 *   and/or sell copies of the Software, and to permit persons to whom the
00009 *   Software is furnished to do so, subject to the following conditions:
00010 *
00011 *   The above copyright notice and this permission notice shall be included
00012 *   in all copies or substantial portions of the Software.
00013 *
00014 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015 *   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00017 *   SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00018 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00019 *   OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00020 *   SOFTWARE.
00021 ****************************************************************************/
00022 
00023 #include "opengl32.h"
00024 #include <math.h>
00025 
00026 #define LINE_BUF_QUANT 4000
00027 #define VERT_BUF_QUANT 4000
00028 
00029 static HFONT    hNewFont, hOldFont;
00030 static FLOAT    ScaleFactor;
00031 static FLOAT*   LineBuf;
00032 static DWORD    LineBufSize;
00033 static DWORD    LineBufIndex;
00034 static FLOAT*   VertBuf;
00035 static DWORD    VertBufSize;
00036 static DWORD    VertBufIndex;
00037 static GLenum   TessErrorOccurred;
00038 
00039 /*****************************************************************************
00040 * AppendToLineBuf
00041 *
00042 * Appends one floating-point value to the global LineBuf array.  Return value
00043 * is non-zero for success, zero for failure.
00044 *****************************************************************************/
00045 
00046 INT AppendToLineBuf(FLOAT value)
00047 {
00048     if (LineBufIndex >= LineBufSize)
00049     {
00050         FLOAT* f;
00051         LineBufSize += LINE_BUF_QUANT;
00052 
00053         f = (FLOAT*) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,  LineBuf, (LineBufSize) * sizeof(FLOAT));
00054         if (!f)
00055             return 0;
00056         LineBuf = f;
00057     }
00058     LineBuf[LineBufIndex++] = value;
00059     return 1;
00060 }
00061 
00062 /*****************************************************************************
00063 * AppendToVertBuf
00064 *
00065 * Appends one floating-point value to the global VertBuf array.  Return value
00066 * is non-zero for success, zero for failure.
00067 *
00068 * Note that we can't realloc this one, because the tessellator is using
00069 * pointers into it.
00070 *****************************************************************************/
00071 
00072 INT AppendToVertBuf(FLOAT value)
00073 {
00074     if (VertBufIndex >= VertBufSize)
00075         return 0;
00076     VertBuf[VertBufIndex++] = value;
00077     return 1;
00078 }
00079 
00080 /*****************************************************************************
00081 * GetWord
00082 *
00083 * Fetch the next 16-bit word from a little-endian byte stream, and increment
00084 * the stream pointer to the next unscanned byte.
00085 *****************************************************************************/
00086 
00087 LONG GetWord(UCHAR** p)
00088 {
00089     LONG value;
00090 
00091     value = ((*p)[1] << 8) + (*p)[0];
00092     *p += 2;
00093     return value;
00094 }
00095 
00096 /*****************************************************************************
00097 * GetDWord
00098 *
00099 * Fetch the next 32-bit word from a little-endian byte stream, and increment
00100 * the stream pointer to the next unscanned byte.
00101 *****************************************************************************/
00102 
00103 LONG GetDWord(UCHAR** p)
00104 {
00105     LONG value;
00106 
00107     value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
00108     *p += 4;
00109     return value;
00110 }
00111 
00112 /*****************************************************************************
00113 * GetFixed
00114 *
00115 * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
00116 * convert it to floating-point, and increment the stream pointer to the next
00117 * unscanned byte.
00118 *****************************************************************************/
00119 double GetFixed(UCHAR** p)
00120 {
00121     LONG hiBits, loBits;
00122     double value;
00123 
00124     loBits = GetWord(p);
00125     hiBits = GetWord(p);
00126     value = (double) ((hiBits << 16) | loBits) / 65536.0;
00127 
00128     return value * ScaleFactor;
00129 }
00130 
00131 
00132 /*****************************************************************************
00133 **
00134 ** InvertGlyphBitmap.
00135 **
00136 ** Invert the bitmap so that it suits OpenGL's representation.
00137 ** Each row starts on a double word boundary.
00138 **
00139 *****************************************************************************/
00140 
00141 VOID InvertGlyphBitmap(INT w, INT h, DWORD *fptr, DWORD *tptr)
00142 {
00143     INT dWordsInRow = (w+31)/32;
00144     INT i, j;
00145 
00146     if (w <= 0 || h <= 0) {
00147         return;
00148     }
00149 
00150     tptr += ((h-1)*dWordsInRow);
00151     for (i = 0; i < h; i++) {
00152         for (j = 0; j < dWordsInRow; j++) {
00153             *(tptr + j) = *(fptr + j);
00154         }
00155         tptr -= dWordsInRow;
00156         fptr += dWordsInRow;
00157     }
00158 }
00159 
00160 /*****************************************************************************
00161 * CreateHighResolutionFont
00162 *
00163 * Gets metrics for the current font and creates an equivalent font
00164 * scaled to the design units of the font.
00165 * 
00166 *****************************************************************************/
00167 
00168 HFONT CreateHighResolutionFont(HDC hDC)
00169 {
00170     UINT otmSize;
00171     OUTLINETEXTMETRIC *otm;
00172     LONG fontHeight, fontWidth, fontUnits;
00173     LOGFONTW logFont, logFontFaceName;
00174 
00175     otmSize = GetOutlineTextMetricsW(hDC, 0, NULL);
00176     if (!otmSize)
00177         return NULL;
00178 
00179     otm = (OUTLINETEXTMETRIC *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, otmSize);
00180     if (!otm)
00181         return NULL;
00182 
00183     otm->otmSize = otmSize;
00184     if (!GetOutlineTextMetricsW(hDC, otmSize, otm)) 
00185         return NULL;
00186 
00187     GetObjectW(GetCurrentObject(hDC, OBJ_FONT), sizeof(logFontFaceName), &logFontFaceName);
00188 
00189     fontHeight = otm->otmTextMetrics.tmHeight -
00190         otm->otmTextMetrics.tmInternalLeading;
00191     fontWidth = otm->otmTextMetrics.tmAveCharWidth;
00192     fontUnits = (LONG) otm->otmEMSquare;
00193 
00194     ScaleFactor = 1.0F / (FLOAT) fontUnits;
00195 
00196     logFont.lfHeight = - ((LONG) fontUnits);
00197     logFont.lfWidth = (LONG)((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
00198     logFont.lfEscapement = 0;
00199     logFont.lfOrientation = 0;
00200     logFont.lfWeight = otm->otmTextMetrics.tmWeight;
00201     logFont.lfItalic = otm->otmTextMetrics.tmItalic;
00202     logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
00203     logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
00204     logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
00205     logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
00206     logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
00207     logFont.lfQuality = DEFAULT_QUALITY;
00208     logFont.lfPitchAndFamily =
00209         otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
00210     wcscpy(logFont.lfFaceName, logFontFaceName.lfFaceName);
00211 
00212     hNewFont = CreateFontIndirectW(&logFont);
00213 
00214     HeapFree(GetProcessHeap(), 0, otm);
00215 
00216     return hNewFont;
00217 }
00218 
00219 /*****************************************************************************
00220 * MakeLinesFromArc
00221 *
00222 * Subdivides one arc of a quadratic spline until the chordal deviation
00223 * tolerance requirement is met, then places the resulting set of line
00224 * segments in the global LineBuf.
00225 *****************************************************************************/
00226 INT MakeLinesFromArc(FLOAT x0, FLOAT y0, FLOAT x1, FLOAT y1, FLOAT x2, FLOAT y2,
00227                      DWORD vertexCountIndex, FLOAT chordalDeviationSquared)
00228 {
00229     FLOAT x01;
00230     FLOAT y01;
00231     FLOAT x12;
00232     FLOAT y12;
00233     FLOAT midPointX;
00234     FLOAT midPointY;
00235     FLOAT deltaX;
00236     FLOAT deltaY;
00237 
00238     /*
00239     * Calculate midpoint of the curve by de Casteljau:
00240     */
00241     x01 = 0.5F * (x0 + x1);
00242     y01 = 0.5F * (y0 + y1);
00243     x12 = 0.5F * (x1 + x2);
00244     y12 = 0.5F * (y1 + y2);
00245     midPointX = 0.5F * (x01 + x12);
00246     midPointY = 0.5F * (y01 + y12);
00247 
00248 
00249     /*
00250     * Estimate chordal deviation by the distance from the midpoint
00251     * of the curve to its non-pointpolated control point.  If this
00252     * distance is greater than the specified chordal deviation
00253     * constraint, then subdivide.  Otherwise, generate polylines
00254     * from the three control points.
00255     */
00256     deltaX = midPointX - x1;
00257     deltaY = midPointY - y1;
00258 
00259     if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
00260     {
00261         MakeLinesFromArc(   x0, y0,
00262             x01, y01,
00263             midPointX, midPointY,
00264             vertexCountIndex,
00265             chordalDeviationSquared);
00266 
00267         MakeLinesFromArc(   midPointX, midPointY,
00268             x12, y12,
00269             x2, y2,
00270             vertexCountIndex,
00271             chordalDeviationSquared);
00272     }
00273     else
00274     {
00275         /*
00276         * The "pen" is already at (x0, y0), so we don't need to
00277         * add that point to the LineBuf.
00278         */
00279         if (!AppendToLineBuf(x1)
00280             || !AppendToLineBuf(y1)
00281             || !AppendToLineBuf(x2)
00282             || !AppendToLineBuf(y2))
00283             return 0;
00284         LineBuf[vertexCountIndex] += 2.0F;
00285     }
00286 
00287     return 1;
00288 }
00289 
00290 /*****************************************************************************
00291 * MakeLinesFromTTQSpline
00292 *
00293 * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
00294 * structure to polyline points in the global LineBuf.
00295 *****************************************************************************/
00296 
00297 INT MakeLinesFromTTQSpline( UCHAR** pp, DWORD vertexCountIndex, WORD pointCount, FLOAT chordalDeviation)
00298 {
00299     FLOAT x0, y0, x1, y1, x2, y2;
00300     WORD point;
00301 
00302     /*
00303     * Process each of the non-pointpolated points in the outline.
00304     * To do this, we need to generate two pointpolated points (the
00305     * start and end of the arc) for each non-pointpolated point.
00306     * The first pointpolated point is always the one most recently
00307     * stored in LineBuf, so we just extract it from there.  The
00308     * second pointpolated point is either the average of the next
00309     * two points in the QSpline, or the last point in the QSpline
00310     * if only one remains.
00311     */
00312     for (point = 0; point < pointCount - 1; ++point)
00313     {
00314         x0 = LineBuf[LineBufIndex - 2];
00315         y0 = LineBuf[LineBufIndex - 1];
00316 
00317         x1 = (FLOAT) GetFixed(pp);
00318         y1 = (FLOAT) GetFixed(pp);
00319 
00320         if (point == pointCount - 2)
00321         {
00322             /*
00323             * This is the last arc in the QSpline.  The final
00324             * point is the end of the arc.
00325             */
00326             x2 = (FLOAT) GetFixed(pp);
00327             y2 = (FLOAT) GetFixed(pp);
00328         }
00329         else
00330         {
00331             /*
00332             * Peek at the next point in the input to compute
00333             * the end of the arc:
00334             */
00335             x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
00336             y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
00337             /*
00338             * Push the point back onto the input so it will
00339             * be reused as the next off-curve point:
00340             */
00341             *pp -= 8;
00342         }
00343 
00344         if (!MakeLinesFromArc(  x0, y0,
00345             x1, y1,
00346             x2, y2,
00347             vertexCountIndex,
00348             chordalDeviation * chordalDeviation))
00349             return 0;
00350     }
00351 
00352     return 1;
00353 }
00354 
00355 /*****************************************************************************
00356 * MakeLinesFromTTLine
00357 *
00358 * Converts points from the polyline in a TT_PRIM_LINE structure to
00359 * equivalent points in the global LineBuf.
00360 *****************************************************************************/
00361 INT MakeLinesFromTTLine(UCHAR** pp, DWORD vertexCountIndex, WORD pointCount)
00362 {
00363     /*
00364     * Just copy the line segments into the line buffer (converting
00365     * type as we go):
00366     */
00367     LineBuf[vertexCountIndex] += pointCount;
00368     while (pointCount--)
00369     {
00370         if (!AppendToLineBuf((FLOAT) GetFixed(pp))  /* X coord */
00371             || !AppendToLineBuf((FLOAT) GetFixed(pp)))  /* Y coord */
00372             return 0;
00373     }
00374 
00375     return 1;
00376 }
00377 
00378 /*****************************************************************************
00379 * MakeLinesFromTTPolyCurve
00380 *
00381 * Converts the lines and splines in a single TTPOLYCURVE structure to points
00382 * in the global LineBuf.
00383 *****************************************************************************/
00384 
00385 INT MakeLinesFromTTPolycurve(UCHAR** pp, DWORD vertexCountIndex, FLOAT chordalDeviation)
00386 {
00387     WORD type;
00388     WORD pointCount;
00389 
00390     /*
00391     * Pick up the relevant fields of the TTPOLYCURVE structure:
00392     */
00393     type = (WORD) GetWord(pp);
00394     pointCount = (WORD) GetWord(pp);
00395 
00396     /*
00397     * Convert the "curve" to line segments:
00398     */
00399     if (type == TT_PRIM_LINE)
00400         return MakeLinesFromTTLine( pp,
00401         vertexCountIndex,
00402         pointCount);
00403     else if (type == TT_PRIM_QSPLINE)
00404         return MakeLinesFromTTQSpline(  pp,
00405         vertexCountIndex,
00406         pointCount,
00407         chordalDeviation);
00408     else
00409         return 0;
00410 }
00411 
00412 /*****************************************************************************
00413 * MakeLinesFromTTPolygon
00414 *
00415 * Converts a TTPOLYGONHEADER and its associated curve structures into a
00416 * single polyline loop in the global LineBuf.
00417 *****************************************************************************/
00418 
00419 INT MakeLinesFromTTPolygon(UCHAR** pp, FLOAT chordalDeviation)
00420 {
00421     DWORD polySize;
00422     UCHAR* polyStart;
00423     DWORD vertexCountIndex;
00424 
00425     /*
00426     * Record where the polygon data begins, and where the loop's
00427     * vertex count resides:
00428     */
00429     polyStart = *pp;
00430     vertexCountIndex = LineBufIndex;
00431     if (!AppendToLineBuf(0.0F))
00432         return 0;
00433 
00434     /*
00435     * Extract relevant data from the TTPOLYGONHEADER:
00436     */
00437     polySize = GetDWord(pp);
00438     if (GetDWord(pp) != TT_POLYGON_TYPE)    /* polygon type */
00439         return 0;
00440     if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
00441         return 0;
00442     if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
00443         return 0;
00444     LineBuf[vertexCountIndex] += 1.0F;
00445 
00446     /*
00447     * Process each of the TTPOLYCURVE structures in the polygon:
00448     */
00449     while (*pp < polyStart + polySize)
00450         if (!MakeLinesFromTTPolycurve(  pp,
00451             vertexCountIndex,
00452             chordalDeviation))
00453             return 0;
00454 
00455     return 1;
00456 }
00457 
00458 /*****************************************************************************
00459 * TessVertexOut
00460 *
00461 * Used by tessellator to handle output vertexes.
00462 *****************************************************************************/
00463 
00464 VOID CALLBACK TessVertexOutData(FLOAT p[3], GLfloat *pz)
00465 {
00466     GLfloat v[3];
00467     v[0] = (GLfloat) p[0];
00468     v[1] = (GLfloat) p[1];
00469     v[2] = *pz;
00470     glVertex3fv(v);
00471 }
00472 
00473 /*****************************************************************************
00474 * TessCombine
00475 *
00476 * Used by tessellator to handle self-pointsecting contours and degenerate
00477 * geometry.
00478 *****************************************************************************/
00479 VOID CALLBACK TessCombine(double  coords[3], VOID* vertex_data[4], FLOAT weight[4], VOID** outData)
00480 {
00481     if (!AppendToVertBuf((FLOAT) coords[0])
00482         || !AppendToVertBuf((FLOAT) coords[1])
00483         || !AppendToVertBuf((FLOAT) coords[2]))
00484         TessErrorOccurred = GL_OUT_OF_MEMORY;
00485 
00486     *outData = VertBuf + (VertBufIndex - 3);
00487 }
00488 
00489 /*****************************************************************************
00490 * TessError
00491 *
00492 * Saves the last tessellator error code in the global TessErrorOccurred.
00493 *****************************************************************************/
00494 
00495 VOID CALLBACK TessError(GLenum error)
00496 {
00497     TessErrorOccurred = error;
00498 }
00499 
00500 /*****************************************************************************
00501 * MakeLinesFromGlyph
00502 * 
00503 * Converts the outline of a glyph from the TTPOLYGON format to a simple
00504 * array of floating-point values containing one or more loops.
00505 *
00506 * The first element of the output array is a count of the number of loops.
00507 * The loop data follows this count.  Each loop consists of a count of the
00508 * number of vertices it contains, followed by the vertices.  Each vertex
00509 * is an X and Y coordinate.  For example, a single triangle might be
00510 * described by this array:
00511 *
00512 *   1., 3., 0., 0.,     1., 0.,     0., 1.
00513 *       ^    ^   ^    ^      ^    ^      ^    ^
00514 *     #loops    #verts   x1   y1     x2   y2     x3   y3
00515 *
00516 * A two-loop glyph would look like this:
00517 *
00518 *   2., 3.,  0.,0.,  1.,0.,  0.,1., 3.,  .2,.2,  .4,.2,  .2,.4
00519 *
00520 * Line segments from the TTPOLYGON are transferred to the output array in
00521 * the obvious way.  Quadratic splines in the TTPOLYGON are converted to
00522 * collections of line segments
00523 *****************************************************************************/
00524 
00525 INT MakeLinesFromGlyph(UCHAR* glyphBuf, DWORD glyphSize, FLOAT chordalDeviation)
00526 {
00527     UCHAR* p;
00528     INT status = 0;
00529 
00530     /*
00531     * Pick up all the polygons (aka loops) that make up the glyph:
00532     */
00533     if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
00534         goto exit;
00535 
00536     p = glyphBuf;
00537     while (p < glyphBuf + glyphSize)
00538     {
00539         if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
00540             goto exit;
00541         LineBuf[0] += 1.0F; /* increment loop count */
00542     }
00543 
00544     status = 1;
00545 
00546 exit:
00547     return status;
00548 }
00549 
00550 /*****************************************************************************
00551 * DrawGlyph
00552 * 
00553 * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
00554 * as needed, and then draws the glyph.  Tessellation of the quadratic splines
00555 * in the outline is controlled by "chordalDeviation", and the drawing
00556 * primitives (lines or polygons) are selected by "format".
00557 *
00558 * Return value is nonzero for success, zero for failure.
00559 *
00560 * Does not check for OpenGL errors, so if the caller needs to know about them,
00561 * it should call glGetError().
00562 *****************************************************************************/
00563 
00564 INT DrawGlyph(UCHAR* glyphBuf, DWORD glyphSize, FLOAT chordalDeviation, FLOAT extrusion, INT format)
00565 {
00566     INT status = 0;
00567     FLOAT* p;
00568     DWORD loop;
00569     DWORD point;
00570     GLUtesselator* tess = NULL;
00571 
00572     /*
00573     * Initialize the global buffer into which we place the outlines:
00574     */
00575     LineBuf = (FLOAT*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (LINE_BUF_QUANT) * sizeof(FLOAT));
00576 
00577     if(!LineBuf)
00578         goto exit;
00579 
00580     LineBufSize = LINE_BUF_QUANT;
00581     LineBufIndex = 0;
00582 
00583     /*
00584     * Convert the glyph outlines to a set of polyline loops.
00585     * (See MakeLinesFromGlyph() for the format of the loop data
00586     * structure.)
00587     */
00588     if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
00589         goto exit;
00590     p = LineBuf;
00591 
00592 
00593     /*
00594     * Now draw the loops in the appropriate format:
00595     */
00596     if (format == WGL_FONT_LINES)
00597     {
00598         /*
00599         * This is the easy case.  Just draw the outlines.
00600         */
00601         for (loop = (DWORD) *p++; loop; --loop)
00602         {
00603             glBegin(GL_LINE_LOOP);
00604             for (point = (DWORD) *p++; point; --point)
00605             {
00606                 glVertex2fv(p);
00607                 p += 2;
00608             }
00609             glEnd();
00610         }
00611         status = 1;
00612     }
00613 
00614     else if (format == WGL_FONT_POLYGONS)
00615     {
00616         double v[3];
00617         FLOAT *save_p = p;
00618         GLfloat z_value;
00619 
00620         /*
00621         * This is the hard case.  We have to set up a tessellator
00622         * to convert the outlines into a set of polygonal
00623         * primitives, which the tessellator passes to some
00624         * auxiliary routines for drawing.
00625         */
00626 
00627         VertBuf = (FLOAT*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (VERT_BUF_QUANT) * sizeof(FLOAT));
00628 
00629         if (!VertBuf)
00630             goto exit;
00631 
00632         VertBufSize = VERT_BUF_QUANT;
00633         VertBufIndex = 0;
00634 
00635         if (!(tess = gluNewTess()))
00636             goto exit;
00637 
00638         gluTessCallback(tess, GLU_BEGIN,    (VOID(CALLBACK *)()) glBegin);
00639         gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (VOID(CALLBACK *)()) TessVertexOutData);
00640         gluTessCallback(tess, GLU_END,  (VOID(CALLBACK *)()) glEnd);
00641         gluTessCallback(tess, GLU_ERROR,    (VOID(CALLBACK *)()) TessError);
00642         gluTessCallback(tess, GLU_TESS_COMBINE, (VOID(CALLBACK *)()) TessCombine);
00643         gluTessNormal(tess, 0.0F, 0.0F, 1.0F);
00644 
00645         TessErrorOccurred = 0;
00646         glNormal3f(0.0f, 0.0f, 1.0f);
00647         v[2] = 0.0;
00648         z_value = 0.0f;
00649 
00650         gluTessBeginPolygon(tess, &z_value);
00651 
00652         for (loop = (DWORD) *p++; loop; --loop)
00653         {
00654             gluTessBeginContour(tess);
00655 
00656             for (point = (DWORD) *p++; point; --point)
00657             {
00658                 v[0] = p[0];
00659                 v[1] = p[1];
00660                 gluTessVertex(tess, v, p);
00661                 p += 2;
00662             }
00663 
00664             gluTessEndContour(tess);
00665         }
00666         gluTessEndPolygon(tess);
00667 
00668         status = !TessErrorOccurred;
00669 
00670         /* Extrusion code */
00671         if (extrusion) 
00672         {
00673             DWORD loops;
00674             GLfloat thickness = (GLfloat) - extrusion;
00675             FLOAT *vert, *vert2;
00676             DWORD count;
00677 
00678             p = save_p;
00679             loops = (DWORD) *p++;
00680 
00681             for (loop = 0; loop < loops; loop++)
00682             {
00683                 GLfloat dx, dy, len;
00684                 DWORD last;
00685 
00686                 count = (DWORD) *p++;
00687                 glBegin(GL_QUAD_STRIP);
00688 
00689                 /* Check if the first and last vertex are identical
00690                 * so we don't draw the same quad twice.
00691                 */
00692                 vert = p + (count-1)*2;
00693                 last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
00694 
00695                 for (point = 0; point <= last; point++)
00696                 {
00697                     vert  = p + 2 * (point % last);
00698                     vert2 = p + 2 * ((point+1) % last);
00699 
00700                     dx = vert[0] - vert2[0];
00701                     dy = vert[1] - vert2[1];
00702                     len = (GLfloat)sqrt(dx * dx + dy * dy);
00703 
00704                     glNormal3f(dy / len, -dx / len, 0.0f);
00705                     glVertex3f((GLfloat) vert[0],
00706                         (GLfloat) vert[1], thickness);
00707                     glVertex3f((GLfloat) vert[0],
00708                         (GLfloat) vert[1], 0.0f);
00709                 }
00710 
00711                 glEnd();
00712                 p += count*2;
00713             }
00714 
00715             /* Draw the back face */
00716             p = save_p;
00717             v[2] = thickness;
00718             glNormal3f(0.0f, 0.0f, -1.0f);
00719             gluTessNormal(tess, 0.0F, 0.0F, -1.0F);
00720 
00721             gluTessBeginPolygon(tess, &thickness);
00722 
00723             for (loop = (DWORD) *p++; loop; --loop)
00724             {
00725                 count = (DWORD) *p++;
00726 
00727                 gluTessBeginContour(tess);
00728 
00729                 for (point = 0; point < count; point++)
00730                 {
00731                     vert = p + ((count-point-1)<<1);
00732                     v[0] = vert[0];
00733                     v[1] = vert[1];
00734                     gluTessVertex(tess, v, vert);
00735                 }
00736                 p += count*2;
00737 
00738                 gluTessEndContour(tess);
00739             }
00740             gluTessEndPolygon(tess);
00741         }
00742 
00743 #if !defined(NDEBUG)
00744         if (TessErrorOccurred)
00745             DBGPRINT("Tessellation error %s\n", gluErrorString(TessErrorOccurred));
00746 #endif
00747     }
00748 
00749 
00750 exit:
00751 
00752     if(LineBuf)
00753         HeapFree(GetProcessHeap(), 0, LineBuf);
00754 
00755     if(VertBuf)
00756         HeapFree(GetProcessHeap(), 0, VertBuf);
00757 
00758     if (tess)
00759         gluDeleteTess(tess);
00760 
00761     return status;
00762 }
00763 
00764 
00765 /*****************************************************************************
00766 * MakeDisplayListFromGlyph
00767 * 
00768 * Converts the outline of a glyph to an OpenGL display list.
00769 *
00770 * Return value is nonzero for success, zero for failure.
00771 *
00772 * Does not check for OpenGL errors, so if the caller needs to know about them,
00773 * it should call glGetError().
00774 *****************************************************************************/
00775 
00776 INT MakeDisplayListFromGlyph(DWORD listName, UCHAR* glyphBuf, DWORD glyphSize, LPGLYPHMETRICSFLOAT glyphMetricsFloat,
00777                              FLOAT chordalDeviation, FLOAT extrusion, INT format)
00778 {
00779     INT status;
00780 
00781     glNewList(listName, GL_COMPILE);
00782         status = DrawGlyph(glyphBuf, glyphSize, chordalDeviation, extrusion, format);
00783         glTranslatef(glyphMetricsFloat->gmfCellIncX, glyphMetricsFloat->gmfCellIncY, 0.0F);
00784     glEndList();
00785 
00786     return status;
00787 }
00788 
00789 // ***********************************************************************
00790 
00791 /*****************************************************************************
00792 * IntUseFontBitmaps
00793 *
00794 * Converts a subrange of the glyphs in a GDI font to OpenGL display
00795 * lists.
00796 *
00797 * Extended to support any GDI font, not just TrueType fonts. (DaveM)
00798 *
00799 *****************************************************************************/
00800 
00801 BOOL APIENTRY IntUseFontBitmapsW(HDC hDC, DWORD first, DWORD count, DWORD listBase)
00802 {
00803     INT i, ox, oy, ix, iy;
00804     INT w = 0, h = 0;
00805     INT iBufSize, iCurBufSize = 0;
00806     DWORD *bitmapBuffer = NULL;
00807     DWORD *invertedBitmapBuffer = NULL;
00808     BOOL bSuccessOrFail = TRUE;
00809     BOOL bTrueType = FALSE;
00810     TEXTMETRIC tm;
00811     GLYPHMETRICS gm;
00812     RASTERIZER_STATUS rs;
00813     MAT2 mat;
00814     SIZE size;
00815     RECT rect;
00816     HDC hDCMem;
00817     HBITMAP hBitmap;
00818     BITMAPINFO bmi;
00819     HFONT hFont;
00820 
00821     // Set up a unity matrix.
00822     ZeroMemory(&mat, sizeof(mat));
00823     mat.eM11.value = 1;
00824     mat.eM22.value = 1;
00825 
00826     // Test to see if selected font is TrueType or not
00827     ZeroMemory(&tm, sizeof(tm));
00828     if (!GetTextMetrics(hDC, &tm))
00829     {
00830         DBGPRINT("Font metrics error\n");
00831         return FALSE;
00832     }
00833     bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
00834 
00835     // Test to see if TRUE-TYPE capabilities are installed
00836     // (only necessary if TrueType font selected)
00837     ZeroMemory(&rs, sizeof(rs));
00838 
00839     if (bTrueType)
00840     {
00841         if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS)) || !(rs.wFlags & TT_ENABLED))
00842         {
00843             DBGPRINT("No TrueType caps\n");
00844             bTrueType = FALSE;
00845         }
00846     }
00847 
00848     // Trick to get the current font handle
00849     hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
00850     SelectObject(hDC, hFont);
00851 
00852     // Have memory device context available for holding bitmaps of font glyphs
00853     hDCMem = CreateCompatibleDC(hDC);
00854     SelectObject(hDCMem, hFont);
00855     SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
00856     SetBkColor(hDCMem, 0);
00857 
00858     for (i = first; (DWORD) i < (first + count); i++)
00859     {
00860         // Find out how much space is needed for the bitmap so we can
00861         // Set the buffer size correctly.
00862         if (bTrueType)
00863         {
00864             // Use TrueType support to get bitmap size of glyph
00865             iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, 0, NULL, &mat);
00866             if (iBufSize == GDI_ERROR)
00867             {
00868                 bSuccessOrFail = FALSE;
00869                 break;
00870             }
00871         }
00872         else
00873         {
00874             // Use generic GDI support to compute bitmap size of glyph
00875             w = tm.tmMaxCharWidth;
00876             h = tm.tmHeight;
00877             if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size))
00878             {
00879                 w = size.cx;
00880                 h = size.cy;
00881             }
00882             iBufSize = w * h;
00883             // Use DWORD multiple for compatibility
00884             iBufSize += 3;
00885             iBufSize /= 4;
00886             iBufSize *= 4;
00887         }
00888 
00889         // If we need to allocate Larger Buffers, then do so - but allocate
00890         // An extra 50 % so that we don't do too many mallocs !
00891         if (iBufSize > iCurBufSize)
00892         {
00893             if (bitmapBuffer)
00894             {
00895                 HeapFree(GetProcessHeap(), 0, bitmapBuffer);
00896             }
00897             if (invertedBitmapBuffer)
00898             {
00899                 HeapFree(GetProcessHeap(), 0, invertedBitmapBuffer);
00900             }
00901 
00902             iCurBufSize = iBufSize * 2;
00903             bitmapBuffer = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iCurBufSize);
00904             invertedBitmapBuffer = (DWORD *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iCurBufSize);
00905 
00906             if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL)
00907             {
00908                 bSuccessOrFail = FALSE;
00909                 break;
00910             }
00911         }
00912 
00913         // If we fail to get the Glyph data, delete the display lists
00914         // Created so far and return FALSE.
00915         if (bTrueType)
00916         {
00917             // Use TrueType support to get bitmap of glyph
00918             if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm, iBufSize, bitmapBuffer, &mat) == GDI_ERROR)
00919             {
00920                     bSuccessOrFail = FALSE;
00921                     break;
00922             }
00923 
00924             // Setup glBitmap parameters for current font glyph
00925             w  = gm.gmBlackBoxX;
00926             h  = gm.gmBlackBoxY;
00927             ox = gm.gmptGlyphOrigin.x;
00928             oy = gm.gmptGlyphOrigin.y;
00929             ix = gm.gmCellIncX;
00930             iy = gm.gmCellIncY;
00931         }
00932         else
00933         {
00934             // Use generic GDI support to create bitmap of glyph
00935             ZeroMemory(bitmapBuffer, iBufSize);
00936 
00937             if (i >= tm.tmFirstChar && i <= tm.tmLastChar)
00938             {
00939                 // Only create bitmaps for actual font glyphs
00940                 hBitmap = CreateBitmap(w, h, 1, 1, NULL);
00941                 SelectObject(hDCMem, hBitmap);
00942                 // Make bitmap of current font glyph
00943                 SetRect(&rect, 0, 0, w, h);
00944                 DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
00945                     DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
00946                 // Make copy of bitmap in our local buffer
00947                 ZeroMemory(&bmi, sizeof(bmi));
00948                 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00949                 bmi.bmiHeader.biWidth = w;
00950                 bmi.bmiHeader.biHeight = -h;
00951                 bmi.bmiHeader.biPlanes = 1;
00952                 bmi.bmiHeader.biBitCount = 1;
00953                 bmi.bmiHeader.biCompression = BI_RGB;
00954                 GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
00955                 DeleteObject(hBitmap);
00956             }
00957             else 
00958             {
00959                 // Otherwise use empty display list for non-existing glyph
00960                 iBufSize = 0;
00961             }
00962 
00963             // Setup glBitmap parameters for current font glyph
00964             ox = 0;
00965             oy = tm.tmDescent;
00966             ix = w;
00967             iy = 0;
00968         }
00969 
00970         // Create an OpenGL display list.
00971         glNewList((listBase + i), GL_COMPILE);
00972 
00973         // Some fonts have no data for the space character, yet advertise
00974         // a non-zero size.
00975         if (0 == iBufSize)
00976         {
00977             glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
00978         }
00979         else
00980         {
00981             // Invert the Glyph data.
00982             InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
00983 
00984             // Render an OpenGL bitmap and invert the origin.
00985             glBitmap(w, h,
00986                 (GLfloat) ox, (GLfloat) (h-oy),
00987                 (GLfloat) ix, (GLfloat) iy,
00988                 (GLubyte *) invertedBitmapBuffer);
00989         }
00990 
00991         // Close this display list.
00992         glEndList();
00993     }
00994 
00995     if (bSuccessOrFail == FALSE)
00996     {
00997         DBGPRINT("DGL_UseFontBitmaps: Get glyph failed\n");
00998         glDeleteLists((i+listBase), (i-first));
00999     }
01000 
01001     // Release resources used
01002     DeleteObject(hFont);
01003     DeleteDC(hDCMem);
01004 
01005     if (bitmapBuffer)
01006         HeapFree(GetProcessHeap(), 0, bitmapBuffer);
01007 
01008     if (invertedBitmapBuffer)
01009         HeapFree(GetProcessHeap(), 0, invertedBitmapBuffer);
01010 
01011     return(bSuccessOrFail);
01012 }
01013 
01014 BOOL APIENTRY IntUseFontBitmapsA(HDC hDC, DWORD first, DWORD count, DWORD listBase)
01015 {
01016     /* Just call IntUseFontBitmapsW for now */
01017     return IntUseFontBitmapsW(hDC, first, count, listBase);
01018 }
01019 
01020 
01021 
01022 /*****************************************************************************
01023 * IntUseFontOutlines
01024 *
01025 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
01026 * lists.
01027 *****************************************************************************/
01028 
01029 BOOL APIENTRY IntUseFontOutlinesW(HDC hDC, DWORD first, DWORD count, DWORD listBase, FLOAT chordalDeviation,
01030                                  FLOAT extrusion, INT format, GLYPHMETRICSFLOAT *glyphMetricsFloatArray)
01031 {
01032     DWORD  glyphIndex;
01033     UCHAR* glyphBuf;
01034     DWORD  glyphBufSize;
01035 
01036     /*
01037     * Flush any previous OpenGL errors.  This allows us to check for
01038     * new errors so they can be reported via the function return value.
01039     */
01040     while (glGetError() != GL_NO_ERROR);
01041 
01042     /*
01043     * Make sure that the current font can be sampled accurately.
01044     */
01045     hNewFont = CreateHighResolutionFont(hDC);
01046 
01047     if (!hNewFont)
01048         return FALSE;
01049 
01050     hOldFont = SelectObject(hDC, hNewFont);
01051     if (!hOldFont)
01052         return FALSE;
01053 
01054     /*
01055     * Preallocate a buffer for the outline data, and track its size:
01056     */
01057     glyphBuf = (UCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,  glyphBufSize = 10240);
01058 
01059     if (!glyphBuf)
01060         return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
01061 
01062     /*
01063     * Process each glyph in the given range:
01064     */
01065     for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
01066     {
01067         GLYPHMETRICS glyphMetrics;
01068         DWORD glyphSize;
01069         static MAT2 matrix =
01070         {
01071             {0, 1},    {0, 0},
01072             {0, 0},    {0, 1}
01073         };
01074         LPGLYPHMETRICSFLOAT glyphMetricsFloat = &glyphMetricsFloatArray[glyphIndex - first];
01075 
01076         /*
01077         * Determine how much space is needed to store the glyph's
01078         * outlines.  If our glyph buffer isn't large enough,
01079         * resize it.
01080         */
01081 
01082         glyphSize = GetGlyphOutline(hDC, glyphIndex, GGO_NATIVE, &glyphMetrics, 0, NULL, &matrix);
01083 
01084         if (glyphSize == GDI_ERROR)
01085             return FALSE; /*WGL_STATUS_FAILURE*/
01086 
01087         if (glyphSize > glyphBufSize)
01088         {
01089             HeapFree(GetProcessHeap(), 0, glyphBuf);
01090             glyphBuf = (UCHAR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, glyphBufSize = glyphSize);
01091             if (!glyphBuf)
01092                 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
01093         }
01094 
01095 
01096         /*
01097         * Get the glyph's outlines.
01098         */
01099         if (GetGlyphOutline(hDC, glyphIndex, GGO_NATIVE, &glyphMetrics, glyphBufSize, glyphBuf, &matrix) == GDI_ERROR)
01100         {
01101             HeapFree(GetProcessHeap(), 0, glyphBuf);
01102             return FALSE; /*WGL_STATUS_FAILURE*/
01103         }
01104 
01105         glyphMetricsFloat->gmfBlackBoxX =
01106             (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
01107         glyphMetricsFloat->gmfBlackBoxY =
01108             (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
01109         glyphMetricsFloat->gmfptGlyphOrigin.x =
01110             (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
01111         glyphMetricsFloat->gmfptGlyphOrigin.y =
01112             (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
01113         glyphMetricsFloat->gmfCellIncX =
01114             (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
01115         glyphMetricsFloat->gmfCellIncY =
01116             (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
01117 
01118         /*
01119         * Turn the glyph into a display list:
01120         */
01121         if (!MakeDisplayListFromGlyph((glyphIndex - first) + listBase, glyphBuf, glyphSize, glyphMetricsFloat,
01122                                        chordalDeviation + ScaleFactor, extrusion, format))
01123         {
01124             HeapFree(GetProcessHeap(), 0, glyphBuf);
01125             return FALSE; /*WGL_STATUS_FAILURE*/
01126         }
01127     }
01128 
01129     /*
01130     * Clean up temporary storage and return.  If an error occurred,
01131     * clear all OpenGL error flags and return FAILURE status;
01132     * otherwise just return SUCCESS.
01133     */
01134     HeapFree(GetProcessHeap(), 0, glyphBuf);
01135 
01136     DeleteObject(SelectObject(hDC, hOldFont));
01137 
01138     if (glGetError() == GL_NO_ERROR)
01139     {
01140         return TRUE; /*WGL_STATUS_SUCCESS*/
01141     }
01142     else
01143     {
01144         while (glGetError() != GL_NO_ERROR);
01145 
01146         return FALSE; /*WGL_STATUS_FAILURE*/
01147     }
01148 }
01149 
01150 BOOL APIENTRY IntUseFontOutlinesA(HDC hDC, DWORD first, DWORD count, DWORD listBase, FLOAT chordalDeviation,
01151                                  FLOAT extrusion, INT format, GLYPHMETRICSFLOAT *glyphMetricsFloatArray)
01152 {
01153     /* Just call IntUseFontOutlinesW for now */
01154     return IntUseFontOutlinesW(hDC, first, count, listBase, chordalDeviation, extrusion, format, glyphMetricsFloatArray);
01155 }

Generated on Thu May 24 2012 04:21:05 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.