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(); } }
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 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 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::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(); } }
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 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 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; FTPoint frontPt = contour->FrontPoint(cur); FTPoint nextPt = contour->FrontPoint(next); 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(); } }
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 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(); } }
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()); } } }
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); }
/**\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; }
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(); } }
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; }
inline FTPoint FTBufferFontImpl::RenderI(const T* string, const int len, FTPoint position, FTPoint spacing, int renderMode) { const float padding = 3.0f; int width, height, texWidth, texHeight; int cacheIndex = -1; bool inCache = false; // Protect blending functions, GL_BLEND and GL_TEXTURE_2D glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT); // Protect glPixelStorei() calls glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glEnable(GL_TEXTURE_2D); if ((renderMode & FTGL::RENDER_NOBLEND) == 0) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // GL_ONE } // Search whether the string is already in a texture we uploaded for(int n = 0; n < BUFFER_CACHE_SIZE; n++) { int i = (lastString + n + BUFFER_CACHE_SIZE) % BUFFER_CACHE_SIZE; if(stringCache[i] && !StringCompare(stringCache[i], string, len)) { cacheIndex = i; inCache = true; break; } } // If the string was not found, we need to put it in the cache and compute // its new bounding box. if(!inCache) { // FIXME: this cache is not very efficient. We should first expire // strings that are not used very often. cacheIndex = lastString; lastString = (lastString + 1) % BUFFER_CACHE_SIZE; if(stringCache[cacheIndex]) { free(stringCache[cacheIndex]); } // FIXME: only the first N bytes are copied; we want the first N chars. stringCache[cacheIndex] = StringCopy(string, len); bboxCache[cacheIndex] = BBox(string, len, FTPoint(), spacing); } FTBBox bbox = bboxCache[cacheIndex]; width = static_cast<int>(bbox.Upper().X() - bbox.Lower().X() + padding + padding + 0.5); height = static_cast<int>(bbox.Upper().Y() - bbox.Lower().Y() + padding + padding + 0.5); texWidth = NextPowerOf2(width); texHeight = NextPowerOf2(height); glBindTexture(GL_TEXTURE_2D, idCache[cacheIndex]); // If the string was not found, we need to render the text in a new // texture buffer, then upload it to the OpenGL layer. if(!inCache) { buffer->Size(texWidth, texHeight); buffer->Pos(FTPoint(padding, padding) - bbox.Lower()); advanceCache[cacheIndex] = FTFontImpl::Render(string, len, FTPoint(), spacing, renderMode); glBindTexture(GL_TEXTURE_2D, idCache[cacheIndex]); glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* TODO: use glTexSubImage2D later? */ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texWidth, texHeight, 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid *)buffer->Pixels()); buffer->Size(0, 0); } FTPoint low = position + bbox.Lower(); FTPoint up = position + bbox.Upper(); glBegin(GL_QUADS); glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(padding / texWidth, (texHeight - height + padding) / texHeight); glVertex2f(low.Xf(), up.Yf()); glTexCoord2f(padding / texWidth, (texHeight - padding) / texHeight); glVertex2f(low.Xf(), low.Yf()); glTexCoord2f((width - padding) / texWidth, (texHeight - padding) / texHeight); glVertex2f(up.Xf(), low.Yf()); glTexCoord2f((width - padding) / texWidth, (texHeight - height + padding) / texHeight); glVertex2f(up.Xf(), up.Yf()); glEnd(); glPopClientAttrib(); glPopAttrib(); return position + advanceCache[cacheIndex]; }