void ftglGetGlyphBBox(FTGLglyph *g, float bounds[6]) { FTBBox ret = _ftglGetGlyphBBox(g); FTPoint lower = ret.Lower(), upper = ret.Upper(); bounds[0] = lower.Xf(); bounds[1] = lower.Yf(); bounds[2] = lower.Zf(); bounds[3] = upper.Xf(); bounds[4] = upper.Yf(); bounds[5] = upper.Zf(); }
void ftgGetlLayoutBBox(FTGLlayout *l, const char * s, float c[6]) { FTBBox ret = _ftgGetlLayoutBBox(l, s); FTPoint lower = ret.Lower(), upper = ret.Upper(); c[0] = lower.Xf(); c[1] = lower.Yf(); c[2] = lower.Zf(); c[3] = upper.Xf(); c[4] = upper.Yf(); c[5] = upper.Zf(); }
void FTPolygonGlyphImpl::DoRender() { GLfloat colors[4]; const FTMesh *mesh = vectoriser->GetMesh(); for(unsigned int t = 0; t < mesh->TesselationCount(); ++t) { const FTTesselation* subMesh = mesh->Tesselation(t); unsigned int polygonType = subMesh->PolygonType(); glGetFloatv(GL_CURRENT_COLOR, colors); glBindTexture(GL_TEXTURE_2D, 0); ftglBegin(polygonType); ftglColor4f(colors[0], colors[1], colors[2], colors[3]); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint point = subMesh->Point(i); ftglTexCoord2f(point.Xf() / hscale, point.Yf() / vscale); ftglVertex3f(point.Xf() / 64.0f, point.Yf() / 64.0f, 0.0f); } ftglEnd(); } }
void FTExtrudeGlyphImpl::RenderFront() { vectoriser->MakeMesh(1.0, 1, frontOutset); glNormal3f(0.0, 0.0, 1.0); GLfloat colors[4]; const FTMesh *mesh = vectoriser->GetMesh(); for(unsigned int j = 0; j < mesh->TesselationCount(); ++j) { const FTTesselation* subMesh = mesh->Tesselation(j); unsigned int polygonType = subMesh->PolygonType(); glGetFloatv(GL_CURRENT_COLOR, colors); glBindTexture(GL_TEXTURE_2D, 0); ftglBegin(polygonType); ftglColor4f(colors[0], colors[1], colors[2], colors[3]); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint pt = subMesh->Point(i); ftglTexCoord2f(pt.Xf() / hscale, pt.Yf() / vscale); ftglVertex3f(pt.Xf() / 64.0f, pt.Yf() / 64.0f, 0.0f); } ftglEnd(); } }
void FTExtrudeGlyphImpl::RenderFront() { vectoriser->MakeMesh(1.0, 1, frontOutset); glNormal3d(0.0, 0.0, 1.0); const FTMesh *mesh = vectoriser->GetMesh(); for(unsigned int j = 0; j < mesh->TesselationCount(); ++j) { const FTTesselation* subMesh = mesh->Tesselation(j); unsigned int polygonType = subMesh->PolygonType(); glBegin(polygonType); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint pt = subMesh->Point(i); glTexCoord2f(pt.Xf() / hscale, pt.Yf() / vscale); glVertex3f(pt.Xf() / 64.0f, pt.Yf() / 64.0f, 0.0f); } glEnd(); } }
void ftglGetFontBBox(FTGLfont *f, const char* s, int len, float c[6]) { FTBBox ret = _ftglGetFontBBox(f, s, len); FTPoint lower = ret.Lower(), upper = ret.Upper(); c[0] = lower.Xf(); c[1] = lower.Yf(); c[2] = lower.Zf(); c[3] = upper.Xf(); c[4] = upper.Yf(); c[5] = upper.Zf(); }
void ftglRenderGlyph(FTGLglyph *g, FTGL_DOUBLE penx, FTGL_DOUBLE peny, int renderMode, FTGL_DOUBLE *advancex, FTGL_DOUBLE *advancey) { FTPoint pen(penx, peny); FTPoint ret = _ftglRenderGlyph(g, pen, renderMode); *advancex = ret.X(); *advancey = ret.Y(); }
Gwen::Point Chowdren::MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString & text ) { FTSimpleLayout layout; layout.SetLineLength(10000); layout.SetFont(get_font(pFont->size)); FTBBox bbox = layout.BBox(text.c_str()); FTPoint size = bbox.Upper() - bbox.Lower(); return Gwen::Point((int)ceil(size.X()), (int)ceil(size.Y())); }
void OgreFTPolygonGlyphImpl::DoRender(const FTPoint& pen) { vectoriser->MakeMesh(1.0, 1, outset); const FTMesh *mesh = vectoriser->GetMesh(); for(unsigned int t = 0; t < mesh->TesselationCount(); ++t) { const FTTesselation* subMesh = mesh->Tesselation(t); unsigned int polygonType = subMesh->PolygonType(); Ogre::RenderOperation renderOperation; switch (polygonType) { case GL_TRIANGLE_STRIP: renderOperation.operationType = Ogre::RenderOperation::OT_TRIANGLE_STRIP; break; case GL_TRIANGLE_FAN: renderOperation.operationType = Ogre::RenderOperation::OT_TRIANGLE_FAN; break; } manualObject->begin("BaseWhite", renderOperation.operationType); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint point = subMesh->Point(i); manualObject->index(i); manualObject->textureCoord(pen.Xf() + (point.Xf() / hscale), pen.Yf() + (point.Yf() / vscale)); manualObject->position(pen.Xf() + (point.Xf() / 64.0f), pen.Yf() + (point.Yf() / 64.0f), 0.0f); } manualObject->end(); } }
FTPolyGlyph::FTPolyGlyph( FT_GlyphSlot glyph, bool useDisplayList) : FTGlyph( glyph), glList(0) { if( ft_glyph_format_outline != glyph->format) { err = 0x14; // Invalid_Outline return; } FTVectoriser vectoriser( glyph); if(( vectoriser.ContourCount() < 1) || ( vectoriser.PointCount() < 3)) { return; } unsigned int horizontalTextureScale = glyph->face->size->metrics.x_ppem * 64; unsigned int verticalTextureScale = glyph->face->size->metrics.y_ppem * 64; vectoriser.MakeMesh( 1.0); if( useDisplayList) { glList = glGenLists( 1); glNewList( glList, GL_COMPILE); } const FTMesh* mesh = vectoriser.GetMesh(); for( unsigned int index = 0; index < mesh->TesselationCount(); ++index) { const FTTesselation* subMesh = mesh->Tesselation( index); unsigned int polyonType = subMesh->PolygonType(); glBegin( polyonType); for( unsigned int pointIndex = 0; pointIndex < subMesh->PointCount(); ++pointIndex) { FTPoint point = subMesh->Point(pointIndex); glTexCoord2f( point.X() / horizontalTextureScale, point.Y() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); } glEnd(); } if(useDisplayList) { glEndList(); } }
void testSetters() { FTPoint point; FTPoint point1(1, 2, 3); point.X(1); point.Y(2); point.Z(3); CPPUNIT_ASSERT(point == point1); }
void cFont::printText(LPCSTR text, FTPoint textPos, colour3f textColour) { glPushMatrix(); glTranslatef(textPos.X(), textPos.Y(), 0); glScalef(1, -1, 1); glColor3f(textColour.r, textColour.g, textColour.b); theFont->Render(text); glPopMatrix(); }
/* ========================================================================== Render the text using the desired font ========================================================================== */ void cFont::printText(LPCSTR text, FTPoint textPos) { glPushMatrix(); glTranslatef(textPos.X(), textPos.Y(), 0 ); // glRotatef(180,1, 0, 0); // Will work too glScalef(1, -1, 1); glColor3f(0.0f, 255.0f, 0.0f); theFont->Render(text); glPopMatrix(); }
/**\brief Internal rendering function.*/ int Font::RenderInternal( int x, int y, const string& text, int h, XPos xpos, YPos ypos) { int xn = 0; int yn = 0; switch( xpos ) { case LEFT: xn = x; break; case CENTER: xn = x - this->TextWidth(text) / 2; break; case RIGHT: xn=x-this->TextWidth(text); break; default: LogMsg(ERR, "Invalid xpos"); assert(0); } // Y coordinates are flipped switch( ypos ) { case TOP: yn = -y - h - TO_INT(floor(this->font->Descender())); break; case MIDDLE: yn = -y - h / 2 - TO_INT(floor(this->font->Descender())); break; case BOTTOM: yn = -y - TO_INT(floor(this->font->Descender())); break; default: LogMsg(ERR, "Invalid ypos"); assert(0); } glColor4f( r, g, b, a ); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPushMatrix(); // to save the current matrix glScalef(1, -1, 1); FTPoint newpoint = this->font->Render( text.c_str(), -1, FTPoint( xn, yn, 1) ); glPopMatrix(); // restore the previous matrix glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); return TO_INT(ceil(newpoint.Xf())) - x; }
FTOutlineGlyph::FTOutlineGlyph( FT_GlyphSlot glyph, bool useDisplayList) : FTGlyph( glyph), glList(0) { if( ft_glyph_format_outline != glyph->format) { err = 0x14; // Invalid_Outline return; } FTVectoriser vectoriser( glyph); size_t numContours = vectoriser.ContourCount(); if ( ( numContours < 1) || ( vectoriser.PointCount() < 3)) { return; } if(useDisplayList) { // Check if we are out of display lists if (glList == 0) { useDisplayList = false; } else glNewList( glList, GL_COMPILE); } for( unsigned int c = 0; c < numContours; ++c) { const FTContour* contour = vectoriser.Contour(c); glBegin( GL_LINE_LOOP); for( unsigned int pointIndex = 0; pointIndex < contour->PointCount(); ++pointIndex) { FTPoint point = contour->Point(pointIndex); glVertex2f( point.X() / 64.0f, point.Y() / 64.0f); } glEnd(); } if(useDisplayList) { glEndList(); } }
void FTOutlineGlyphImpl::DoRender() { for(unsigned int c = 0; c < vectoriser->ContourCount(); ++c) { const FTContour* contour = vectoriser->Contour(c); glBegin(GL_LINE_LOOP); for(unsigned int i = 0; i < contour->PointCount(); ++i) { FTPoint point = FTPoint(contour->Point(i).X() + contour->Outset(i).X() * outset, contour->Point(i).Y() + contour->Outset(i).Y() * outset, 0); glVertex2f(point.Xf() / 64.0f, point.Yf() / 64.0f); } glEnd(); } }
void FTExtrudeGlyphImpl::RenderSide() { int contourFlag = vectoriser->ContourFlag(); for(size_t c = 0; c < vectoriser->ContourCount(); ++c) { const FTContour* contour = vectoriser->Contour(c); size_t n = contour->PointCount(); if(n < 2) { continue; } glBegin(GL_QUAD_STRIP); for(size_t j = 0; j <= n; ++j) { size_t cur = (j == n) ? 0 : j; size_t next = (cur == n - 1) ? 0 : cur + 1; const FTPoint& frontPt = contour->FrontPoint(cur); const FTPoint& nextPt = contour->FrontPoint(next); const FTPoint& backPt = contour->BackPoint(cur); FTPoint normal = FTPoint(0.f, 0.f, 1.f) ^ (frontPt - nextPt); if(normal != FTPoint(0.0f, 0.0f, 0.0f)) { glNormal3dv(static_cast<const FTGL_DOUBLE*>(normal.Normalise())); } glTexCoord2f(frontPt.Xf() / hscale, frontPt.Yf() / vscale); if(contourFlag & ft_outline_reverse_fill) { glVertex3f(backPt.Xf() / 64.0f, backPt.Yf() / 64.0f, 0.0f); glVertex3f(frontPt.Xf() / 64.0f, frontPt.Yf() / 64.0f, -depth); } else { glVertex3f(backPt.Xf() / 64.0f, backPt.Yf() / 64.0f, -depth); glVertex3f(frontPt.Xf() / 64.0f, frontPt.Yf() / 64.0f, 0.0f); } } glEnd(); } }
FTPoint FTExtrdGlyph::GetNormal( const FTPoint &a, const FTPoint &b) { float vectorX = a.X() - b.X(); float vectorY = a.Y() - b.Y(); float length = sqrt( vectorX * vectorX + vectorY * vectorY ); if( length > 0.01f) { length = 1 / length; } else { length = 0.0f; } return FTPoint( -vectorY * length, vectorX * length, 0.0f); }
void FTPolygonGlyphImpl::DoRender() { vectoriser->MakeMesh(1.0, 1, outset); const FTMesh *mesh = vectoriser->GetMesh(); for(unsigned int t = 0; t < mesh->TesselationCount(); ++t) { const FTTesselation* subMesh = mesh->Tesselation(t); unsigned int polygonType = subMesh->PolygonType(); glBegin(polygonType); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint point = subMesh->Point(i); glTexCoord2f(point.Xf() / hscale, point.Yf() / vscale); glVertex3f(point.Xf() / 64.0f, point.Yf() / 64.0f, 0.0f); } glEnd(); } }
void FTOutlineGlyphImpl::RenderContours(const FTPoint& pen) { for(unsigned int c = 0; c < vectoriser->ContourCount(); ++c) { const FTContour* contour = vectoriser->Contour(c); for(unsigned int i = 0; i < contour->PointCount(); ++i) { unsigned ii = (i+1 == contour->PointCount()) ? 0 : i+1; FTPoint point1 = FTPoint(contour->Point(i).X() + contour->Outset(i).X() * outset, contour->Point(i).Y() + contour->Outset(i).Y() * outset, 0); FTPoint point2 = FTPoint(contour->Point(ii).X() + contour->Outset(ii).X() * outset, contour->Point(ii).Y() + contour->Outset(ii).Y() * outset, 0); ftglVertex2f((point1.Xf() / 64.0f) + pen.Xf(), (point1.Yf() / 64.0f) + pen.Yf()); ftglVertex2f((point2.Xf() / 64.0f) + pen.Xf(), (point2.Yf() / 64.0f) + pen.Yf()); } } }
void testKerning() { FTFace test(ARIAL_FONT_FILE); FTPoint kerningVector = test.KernAdvance('A', 'A'); CPPUNIT_ASSERT_EQUAL(kerningVector.X(), 0.); CPPUNIT_ASSERT_EQUAL(kerningVector.Y(), 0.); CPPUNIT_ASSERT_EQUAL(kerningVector.Z(), 0.); kerningVector = test.KernAdvance(0x6FB3, 0x9580); CPPUNIT_ASSERT_EQUAL(kerningVector.X(), 0.); CPPUNIT_ASSERT_EQUAL(kerningVector.Y(), 0.); CPPUNIT_ASSERT_EQUAL(kerningVector.Z(), 0.); }
Bounds Font::getBounds(const vec3& pos, const std::string& text) const { if (!font_) return Bounds(); FTPoint point(static_cast<double>(pos.x), static_cast<double>(pos.y), static_cast<double>(pos.z)); float delta = 0; std::string line; std::stringstream ss(text); std::getline(ss, line); FTBBox box_tmp = font_->BBox(line.c_str(), -1, point); delta -= box_tmp.Upper().Yf() - box_tmp.Lower().Yf(); // height of first line FTBBox box = simpleLayout_->BBox(text.c_str(), -1, point); FTPoint upper = box.Upper(); FTPoint lower = box.Lower(); float height = upper.Yf() - lower.Yf(); switch(vAlign_) { case Font::Top: delta += height; break; case Font::Middle: delta += height * 0.5f; break; case Font::Bottom: break; } vec3 upperTGT = vec3(upper.Xf(), upper.Yf() + delta, upper.Zf()); vec3 lowerTGT = vec3(lower.Xf(), lower.Yf() + delta, lower.Zf()); return Bounds(lowerTGT, upperTGT); }
inline float FTTextureFont::AdvanceI(const T* string, const int len, FTPoint spacing) { float advance = 0.0f; FTUnicodeStringItr<T> ustr(string); for (int i = 0; (len < 0 && *ustr) || (len >= 0 && i < len); i++) { unsigned int thisChar = *ustr++; unsigned int nextChar = *ustr; if (CheckGlyph(thisChar)) { advance += glyphList->Advance(thisChar, nextChar); } if (nextChar) { advance += spacing.Xf(); } } return advance; }
void FTPolygonGlyphImpl::DoRender(const FTPoint& pen) { const FTMesh *mesh = vectoriser->GetMesh(); for (unsigned int t = 0; t < mesh->TesselationCount(); ++t) { const FTTesselation* subMesh = mesh->Tesselation(t); unsigned int polygonType = subMesh->PolygonType(); ftglBindTexture(0); ftglBegin(polygonType); for(unsigned int i = 0; i < subMesh->PointCount(); ++i) { FTPoint point = subMesh->Point(i); ftglColor4f(1.0f, 1.0f, 1.0f, 1.0f); ftglTexCoord2f(point.Xf() / hscale, point.Yf() / vscale); ftglVertex3f(pen.Xf() + point.Xf() / 64.0f, pen.Yf() + point.Yf() / 64.0f, 0.0f); } ftglEnd(); } }
Font::FONT_RECT Font::measureText(const wchar_t* wText) throw(invalid_argument, runtime_error) { ASSERT( (wText != 0), invalid_argument("wText") ); if(font_ == 0) { return Font::FONT_RECT(); } FTBBox bbox = font_->BBox(wText, -1); FTPoint low = bbox.Lower(); FTPoint hi = bbox.Upper(); Font::FONT_RECT rect; rect.width = hi.X() - low.X(); rect.height = hi.Y() - low.Y(); return rect; }
FTContour::FTContour( FT_Vector* contour, char* pointTags, unsigned int numberOfPoints) { for( unsigned int pointIndex = 0; pointIndex < numberOfPoints; ++ pointIndex) { char pointTag = pointTags[pointIndex]; if( pointTag == FT_Curve_Tag_On || numberOfPoints < 2) { AddPoint( contour[pointIndex].x, contour[pointIndex].y); continue; } FTPoint controlPoint( contour[pointIndex]); FTPoint previousPoint = ( 0 == pointIndex) ? FTPoint( contour[numberOfPoints - 1]) : pointList[pointList.size() - 1]; FTPoint nextPoint = ( pointIndex == numberOfPoints - 1) ? pointList[0] : FTPoint( contour[pointIndex + 1]); if( pointTag == FT_Curve_Tag_Conic) { char nextPointTag = ( pointIndex == numberOfPoints - 1) ? pointTags[0] : pointTags[pointIndex + 1]; while( nextPointTag == FT_Curve_Tag_Conic) { nextPoint = ( controlPoint + nextPoint) * 0.5f; controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = nextPoint.X(); controlPoints[2][1] = nextPoint.Y(); evaluateQuadraticCurve(); ++pointIndex; previousPoint = nextPoint; controlPoint = FTPoint( contour[pointIndex]); nextPoint = ( pointIndex == numberOfPoints - 1) ? pointList[0] : FTPoint( contour[pointIndex + 1]); nextPointTag = ( pointIndex == numberOfPoints - 1) ? pointTags[0] : pointTags[pointIndex + 1]; } controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = nextPoint.X(); controlPoints[2][1] = nextPoint.Y(); evaluateQuadraticCurve(); continue; } if( pointTag == FT_Curve_Tag_Cubic) { FTPoint controlPoint2 = nextPoint; FTPoint nextPoint = ( pointIndex == numberOfPoints - 2) ? pointList[0] : FTPoint( contour[pointIndex + 2]); controlPoints[0][0] = previousPoint.X(); controlPoints[0][1] = previousPoint.Y(); controlPoints[1][0] = controlPoint.X(); controlPoints[1][1] = controlPoint.Y(); controlPoints[2][0] = controlPoint2.X(); controlPoints[2][1] = controlPoint2.Y(); controlPoints[3][0] = nextPoint.X(); controlPoints[3][1] = nextPoint.Y(); evaluateCubicCurve(); ++pointIndex; continue; } } }
// This function is a bit tricky. Given a path ABC, it returns the // coordinates of the outset point facing B on the left at a distance // of 64.0. // M // - - - - - - X // ^ / ' // | 64.0 / ' // X---->-----X ==> X--v-------X ' // A B \ A B \ .>' // \ \<' 64.0 // \ \ . // \ \ . // C X C X // FTPoint FTContour::ComputeOutsetPoint(FTPoint A, FTPoint B, FTPoint C) { /* Build the rotation matrix from 'ba' vector */ FTPoint ba = (A - B).Normalise(); FTPoint bc = C - B; /* Rotate bc to the left */ FTPoint tmp(bc.X() * -ba.X() + bc.Y() * -ba.Y(), bc.X() * ba.Y() + bc.Y() * -ba.X()); /* Compute the vector bisecting 'abc' */ FTGL_DOUBLE norm = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y()); FTGL_DOUBLE dist = 64.0 * sqrt((norm - tmp.X()) / (norm + tmp.X())); tmp.X(tmp.Y() < 0.0 ? dist : -dist); tmp.Y(64.0); /* Rotate the new bc to the right */ return FTPoint(tmp.X() * -ba.X() + tmp.Y() * ba.Y(), tmp.X() * -ba.Y() + tmp.Y() * -ba.X()); }
void FTVectoriser::ProcessContours() { short contourLength = 0; short startIndex = 0; short endIndex = 0; contourList = new FTContour*[ftContourCount]; for(int i = 0; i < ftContourCount; ++i) { FT_Vector* pointList = &outline.points[startIndex]; char* tagList = &outline.tags[startIndex]; endIndex = outline.contours[i]; contourLength = (endIndex - startIndex) + 1; FTContour* contour = new FTContour(pointList, tagList, contourLength); contourList[i] = contour; startIndex = endIndex + 1; } // Compute each contour's parity. FIXME: see if FT_Outline_Get_Orientation // can do it for us. for(int i = 0; i < ftContourCount; i++) { FTContour *c1 = contourList[i]; // 1. Find the leftmost point. FTPoint leftmost(65536.0, 0.0); for(size_t n = 0; n < c1->PointCount(); n++) { FTPoint p = c1->Point(n); if(p.X() < leftmost.X()) { leftmost = p; } } // 2. Count how many other contours we cross when going further to // the left. int parity = 0; for(int j = 0; j < ftContourCount; j++) { if(j == i) { continue; } FTContour *c2 = contourList[j]; for(size_t n = 0; n < c2->PointCount(); n++) { FTPoint p1 = c2->Point(n); FTPoint p2 = c2->Point((n + 1) % c2->PointCount()); /* FIXME: combinations of >= > <= and < do not seem stable */ if((p1.Y() < leftmost.Y() && p2.Y() < leftmost.Y()) || (p1.Y() >= leftmost.Y() && p2.Y() >= leftmost.Y()) || (p1.X() > leftmost.X() && p2.X() > leftmost.X())) { continue; } else if(p1.X() < leftmost.X() && p2.X() < leftmost.X()) { parity++; } else { FTPoint a = p1 - leftmost; FTPoint b = p2 - leftmost; if(b.X() * a.Y() > b.Y() * a.X()) { parity++; } } } } // 3. Make sure the glyph has the proper parity. c1->SetParity(parity); } }
void FTExtrudeGlyphImpl::RenderSide() { int contourFlag = vectoriser->ContourFlag(); //LOG_INFO("RenderSide %d", contourFlag); GLfloat colors[4]; for(size_t c = 0; c < vectoriser->ContourCount(); ++c) { const FTContour* contour = vectoriser->Contour(c); size_t n = contour->PointCount(); if(n < 2) { continue; } glGetFloatv(GL_CURRENT_COLOR, colors); ftglBegin(GL_QUADS); ftglColor4f(colors[0]/2, colors[1]/2, colors[2]/2, colors[3]/2); for(size_t j = 0; j < n; j++ ) { size_t cur = j % n; size_t next = (j + 1) % n; FTPoint frontPt = contour->FrontPoint(cur); FTPoint frontPt1 = contour->FrontPoint(next); FTPoint backPt = contour->BackPoint(cur); FTPoint backPt1 = contour->BackPoint(next); FTPoint normal = FTPoint(0.f, 0.f, 1.f) ^ (frontPt - frontPt1); if(normal != FTPoint(0.0f, 0.0f, 0.0f)) { const FTGL_DOUBLE* pD = static_cast<const FTGL_DOUBLE*>(normal.Normalise()); glNormal3f( pD[0], pD[1], pD[2]); } ftglTexCoord2f(frontPt.Xf() / hscale, frontPt.Yf() / vscale); if(contourFlag & ft_outline_reverse_fill) { ftglVertex3f(backPt.Xf() / 64.0f, backPt.Yf() / 64.0f, 0.0f); ftglVertex3f(frontPt.Xf() / 64.0f, frontPt.Yf() / 64.0f, -depth); ftglVertex3f(frontPt1.Xf() / 64.0f, frontPt1.Yf() / 64.0f, -depth); ftglVertex3f(backPt1.Xf() / 64.0f, backPt1.Yf() / 64.0f, 0.0f); } else { ftglVertex3f(backPt.Xf() / 64.0f, backPt.Yf() / 64.0f, -depth); ftglVertex3f(frontPt.Xf() / 64.0f, frontPt.Yf() / 64.0f, 0.0f); ftglVertex3f(frontPt1.Xf() / 64.0f, frontPt1.Yf() / 64.0f, 0.f); ftglVertex3f(backPt1.Xf() / 64.0f, backPt1.Yf() / 64.0f, -depth); } } ftglEnd(); } }
FTExtrdGlyph::FTExtrdGlyph( FT_GlyphSlot glyph, float depth, bool useDisplayList) : FTGlyph( glyph), glList(0) { bBox.SetDepth( -depth); if( ft_glyph_format_outline != glyph->format) { err = 0x14; // Invalid_Outline return; } FTVectoriser vectoriser( glyph); if( ( vectoriser.ContourCount() < 1) || ( vectoriser.PointCount() < 3)) { return; } unsigned int tesselationIndex; if(useDisplayList) { glList = glGenLists(1); glNewList( glList, GL_COMPILE); } vectoriser.MakeMesh( 1.0); glNormal3d(0.0, 0.0, 1.0); unsigned int horizontalTextureScale = glyph->face->size->metrics.x_ppem * 64; unsigned int verticalTextureScale = glyph->face->size->metrics.y_ppem * 64; const FTMesh* mesh = vectoriser.GetMesh(); for( tesselationIndex = 0; tesselationIndex < mesh->TesselationCount(); ++tesselationIndex) { const FTTesselation* subMesh = mesh->Tesselation( tesselationIndex); unsigned int polyonType = subMesh->PolygonType(); glBegin( polyonType); for( unsigned int pointIndex = 0; pointIndex < subMesh->PointCount(); ++pointIndex) { FTPoint point = subMesh->Point(pointIndex); glTexCoord2f( point.X() / horizontalTextureScale, point.Y() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); } glEnd(); } vectoriser.MakeMesh( -1.0); glNormal3d(0.0, 0.0, -1.0); mesh = vectoriser.GetMesh(); for( tesselationIndex = 0; tesselationIndex < mesh->TesselationCount(); ++tesselationIndex) { const FTTesselation* subMesh = mesh->Tesselation( tesselationIndex); unsigned int polyonType = subMesh->PolygonType(); glBegin( polyonType); for( unsigned int pointIndex = 0; pointIndex < subMesh->PointCount(); ++pointIndex) { FTPoint point = subMesh->Point(pointIndex); glTexCoord2f( subMesh->Point(pointIndex).X() / horizontalTextureScale, subMesh->Point(pointIndex).Y() / verticalTextureScale); glVertex3f( subMesh->Point( pointIndex).X() / 64.0f, subMesh->Point( pointIndex).Y() / 64.0f, -depth); } glEnd(); } int contourFlag = vectoriser.ContourFlag(); for( size_t c = 0; c < vectoriser.ContourCount(); ++c) { const FTContour* contour = vectoriser.Contour(c); unsigned int numberOfPoints = contour->PointCount(); glBegin( GL_QUAD_STRIP); for( unsigned int j = 0; j <= numberOfPoints; ++j) { unsigned int pointIndex = ( j == numberOfPoints) ? 0 : j; unsigned int nextPointIndex = ( pointIndex == numberOfPoints - 1) ? 0 : pointIndex + 1; FTPoint point = contour->Point(pointIndex); FTPoint normal = GetNormal( point, contour->Point(nextPointIndex)); if(normal != FTPoint( 0.0f, 0.0f, 0.0f)) { glNormal3dv(static_cast<const FTGL_DOUBLE*>(normal)); } if( contourFlag & ft_outline_reverse_fill) { glTexCoord2f( point.X() / horizontalTextureScale, point.X() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, -depth); } else { glTexCoord2f( point.X() / horizontalTextureScale, point.Y() / verticalTextureScale); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, -depth); glVertex3f( point.X() / 64.0f, point.Y() / 64.0f, 0.0f); } } glEnd(); } if(useDisplayList) { glEndList(); } }