diff --git a/dll/opengl/opengl32/wgl_font.c b/dll/opengl/opengl32/wgl_font.c index 9640d41f41..286e956de0 100644 --- a/dll/opengl/opengl32/wgl_font.c +++ b/dll/opengl/opengl32/wgl_font.c @@ -288,6 +288,24 @@ static int bezier_approximate(const bezier_vector *p, bezier_vector *points, FLO return total_vertices; } +void calculate_normal(GLdouble *normal, GLdouble *point1, GLdouble *point2, GLdouble *point3){ + GLdouble vector1[3], vector2[3], norma; + int i; + for (i=0;i<3;i++){ + vector1[i] = point2[i] - point1[i]; + vector2[i] = point3[i] - point1[i]; + } + normal[0] = vector1[1] * vector2[2] - vector1[2] * vector2[1]; + normal[1] = vector1[2] * vector2[0] - vector1[0] * vector2[2]; + normal[2] = vector1[0] * vector2[1] - vector1[1] * vector2[0]; + norma = sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); + if (norma == 0) norma = 0.00001; + normal[0] /= -norma; + normal[1] /= -norma; + normal[2] /= -norma; + +} + /*********************************************************************** * wglUseFontOutlines_common */ @@ -342,6 +360,7 @@ static BOOL wglUseFontOutlines_common(HDC hdc, for (glyph = first; glyph < first + count; glyph++) { + int stage; DWORD needed; GLYPHMETRICS gm; BYTE *buf; @@ -385,144 +404,315 @@ static BOOL wglUseFontOutlines_common(HDC hdc, } funcs->NewList(listBase++, GL_COMPILE); - funcs->FrontFace(GL_CCW); - if(format == WGL_FONT_POLYGONS) - { - funcs->Normal3d(0.0, 0.0, 1.0); - pgluTessNormal(tess, 0, 0, 1); - pgluTessBeginPolygon(tess, NULL); - } + glFrontFace(GL_CCW); + + //0 stage: draw front side + //1rd stage: draw back side + //2nd stage: draw rectangles between front and back + for (stage = 0; stage < ((extrusion > 0.0f) ? 3 : 1); stage++){ + vertices=NULL; + vertices_temp=NULL; + vertex_total=-1; + + if(format == WGL_FONT_POLYGONS && stage < 2) + { + + if (stage) + glNormal3d(0.0, 0.0, 1.0); + else + glNormal3d(0.0, 0.0, -1.0); - while(!vertices) - { - if(vertex_total != -1) - vertices_temp = vertices = HeapAlloc(GetProcessHeap(), 0, vertex_total * 3 * sizeof(GLdouble)); - vertex_total = 0; + pgluTessNormal(tess, 0.0, 0.0, 1); + pgluTessBeginPolygon(tess, NULL); + } - pph = (TTPOLYGONHEADER*)buf; - while((BYTE*)pph < buf + needed) + while(!vertices) { - GLdouble previous[3]; - fixed_to_double(pph->pfxStart, em_size, previous); + if(vertex_total != -1) + vertices_temp = vertices = HeapAlloc(GetProcessHeap(), 0, vertex_total * 3 * sizeof(GLdouble)); + vertex_total = 0; - if(vertices) - TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value); + pph = (TTPOLYGONHEADER*)buf; + while((BYTE*)pph < buf + needed) + { + GLdouble previous[3]; + GLdouble start[3]; //need to link first polygon with the last one + fixed_to_double(pph->pfxStart, em_size, previous); + fixed_to_double(pph->pfxStart, em_size, start); - if(format == WGL_FONT_POLYGONS) - pgluTessBeginContour(tess); - else - funcs->Begin(GL_LINE_LOOP); + if(vertices) + TRACE("\tstart %d, %d\n", pph->pfxStart.x.value, pph->pfxStart.y.value); - if(vertices) - { - fixed_to_double(pph->pfxStart, em_size, vertices); - if(format == WGL_FONT_POLYGONS) - pgluTessVertex(tess, vertices, vertices); - else - funcs->Vertex3d(vertices[0], vertices[1], vertices[2]); - vertices += 3; - } - vertex_total++; + if (stage < 2){ + if(format == WGL_FONT_POLYGONS) + pgluTessBeginContour(tess); + else + glBegin(GL_LINE_LOOP); + } - ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph)); - while((char*)ppc < (char*)pph + pph->cb) - { - int i, j; - int num; + if(vertices && stage < 2) + { + fixed_to_double(pph->pfxStart, em_size, vertices); + if (stage) vertices[2] = extrusion; + if(format == WGL_FONT_POLYGONS) + pgluTessVertex(tess, vertices, vertices); + else + glVertex3d(vertices[0], vertices[1], vertices[2]); + vertices += 3; + } + vertex_total++; - 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 - funcs->Vertex3d(vertices[0], vertices[1], vertices[2]); - vertices += 3; - } - fixed_to_double(ppc->apfx[i], em_size, previous); - vertex_total++; - } - break; + ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph)); + while((char*)ppc < (char*)pph + pph->cb) + { + int i, j; + int num; - 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; jwType) { + case TT_PRIM_LINE: + for(i = 0; i < ppc->cpfx; i++) + + { + if(vertices && stage < 2) + { + 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 (stage) vertices[2]=extrusion; + if(format == WGL_FONT_POLYGONS) + pgluTessVertex(tess, vertices, vertices); + else + glVertex3d(vertices[0], vertices[1], vertices[2]); + vertices += 3; + } + if (vertices && stage == 2){ + //rect + GLdouble extr[12]; //rectangle's coordinates + GLdouble normal[3]; + fixed_to_double(ppc->apfx[i], em_size, extr); + + extr[3]=extr[0]; + extr[4]=extr[1]; + extr[5]=extrusion; + + extr[6]=previous[0]; + extr[7]=previous[1]; + extr[8]=extrusion; + + extr[9]=previous[0]; + extr[10]=previous[1]; + extr[11]=0; + + calculate_normal(normal, extr, extr+3, extr+6); + + if(format == WGL_FONT_POLYGONS) + { + glNormal3dv(normal); + pgluTessNormal(tess, 0, 0, 0); //auto selection + pgluTessBeginPolygon(tess, NULL); + pgluTessBeginContour(tess); + pgluTessVertex(tess, extr, extr); + pgluTessVertex(tess, extr+3, extr+3); + pgluTessVertex(tess, extr+6, extr+6); + pgluTessVertex(tess, extr+9, extr+9); + pgluTessEndContour(tess); + pgluTessEndPolygon(tess); + } else { + glBegin(GL_LINE_LOOP); + glVertex3dv(extr); + glVertex3dv(extr+3); + glVertex3dv(extr+6); + glVertex3dv(extr+9); + glEnd(); + } + //\rect + } + + fixed_to_double(ppc->apfx[i], em_size, previous); + vertex_total++; + + } + break; + + case TT_PRIM_QSPLINE: + for(i = 0; i < ppc->cpfx-1; i++) { - 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 - funcs->Vertex3d(vertices[0], vertices[1], vertices[2]); - vertices += 3; + 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; jwType); + if(format == WGL_FONT_POLYGONS) + pgluTessEndContour(tess); + else + glEnd(); + goto error_in_list; + } - break; - default: - ERR("\t\tcurve type = %d\n", ppc->wType); + + ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) + + (ppc->cpfx - 1) * sizeof(POINTFX)); + } + if (stage < 2){ + if(format == WGL_FONT_POLYGONS) pgluTessEndContour(tess); else - funcs->End(); - goto error_in_list; + glEnd(); } + //linking first polygon with the last one + if (stage == 2){ + //rect + GLdouble extr[12]; //rectangle's coordinates + GLdouble normal[3]; + + + extr[0] = start[0]; + extr[1] = start[1]; + extr[2] = 0.0; + + extr[3] = start[0]; + extr[4] = start[1]; + extr[5] = extrusion; + + extr[6] = previous[0]; + extr[7] = previous[1]; + extr[8] = extrusion; + + extr[9] = previous[0]; + extr[10] = previous[1]; + extr[11] = 0; + + calculate_normal(normal, extr, extr+3, extr+6); + + if(format == WGL_FONT_POLYGONS) + { + glNormal3dv(normal); + pgluTessNormal(tess, 0, 0, 0); //auto selection + pgluTessBeginPolygon(tess, NULL); + pgluTessBeginContour(tess); + pgluTessVertex(tess, extr, extr); + pgluTessVertex(tess, extr+3, extr+3); + pgluTessVertex(tess, extr+6, extr+6); + pgluTessVertex(tess, extr+9, extr+9); + pgluTessEndContour(tess); + pgluTessEndPolygon(tess); + } else { + glBegin(GL_LINE_LOOP); + glVertex3dv(extr); + glVertex3dv(extr+3); + glVertex3dv(extr+6); + glVertex3dv(extr+9); + glEnd(); + } + //\rect + } + pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb); - ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) + - (ppc->cpfx - 1) * sizeof(POINTFX)); } - if(format == WGL_FONT_POLYGONS) - pgluTessEndContour(tess); - else - funcs->End(); - pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb); + } + if(format == WGL_FONT_POLYGONS && stage < 2) + pgluTessEndPolygon(tess); + } error_in_list: - if(format == WGL_FONT_POLYGONS) - pgluTessEndPolygon(tess); - funcs->Translated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0); + glTranslated((GLdouble)gm.gmCellIncX / em_size, (GLdouble)gm.gmCellIncY / em_size, 0.0); funcs->EndList(); HeapFree(GetProcessHeap(), 0, buf);