Font::TextSize Font::process(int x, int y, text_iterator start, text_iterator end, Color color) { Vec2f pen(x, y); int startX = 0; int endX = 0; if(DoDraw) { // Subtract one line height (since we flipped the Y origin to be like GDI) pen.y += face->size->metrics.ascender >> 6; } FT_UInt prevGlyphIndex = 0; FT_Pos prevRsbDelta = 0; typedef std::map< unsigned int, std::vector<TexturedVertex> > MapTextureVertices; MapTextureVertices mapTextureVertices; for(text_iterator it = start; it != end; ) { // Get glyph in glyph map glyph_iterator itGlyph = getNextGlyph(it, end); if(itGlyph == glyphs.end()) { continue; } const Glyph & glyph = itGlyph->second; // Kerning if(FT_HAS_KERNING(face)) { if(prevGlyphIndex != 0) { FT_Vector delta; FT_Get_Kerning(face, prevGlyphIndex, glyph.index, FT_KERNING_DEFAULT, &delta); pen.x += delta.x >> 6; } prevGlyphIndex = glyph.index; } // Auto hinting adjustments if(prevRsbDelta - glyph.lsb_delta >= 32) { pen.x--; } else if(prevRsbDelta - glyph.lsb_delta < -32) { pen.x++; } prevRsbDelta = glyph.rsb_delta; // Draw if(DoDraw && glyph.size.x != 0 && glyph.size.y != 0) { addGlyphVertices(mapTextureVertices[glyph.texture], glyph, pen, color); } else { ARX_UNUSED(pen), ARX_UNUSED(color); } // If this is the first drawn char, note the start position if(startX == endX) { startX = glyph.draw_offset.x; } endX = pen.x + glyph.draw_offset.x + glyph.size.x; // Advance pen.x += glyph.advance.x; }
Vec2i Font::process(int x, int y, text_iterator start, text_iterator end, Color color) { if(DoDraw) { GRenderer->SetRenderState(Renderer::Lighting, false); GRenderer->SetRenderState(Renderer::AlphaBlending, true); GRenderer->SetBlendFunc(Renderer::BlendSrcAlpha, Renderer::BlendInvSrcAlpha); GRenderer->SetRenderState(Renderer::DepthTest, false); GRenderer->SetRenderState(Renderer::DepthWrite, false); GRenderer->SetCulling(Renderer::CullNone); // 2D projection setup... Put origin (0,0) in the top left corner like GDI... Rect viewport = GRenderer->GetViewport(); GRenderer->Begin2DProjection(viewport.left, viewport.right, viewport.bottom, viewport.top, -1.f, 1.f); // Fixed pipeline texture stage operation GRenderer->GetTextureStage(0)->SetColorOp(TextureStage::ArgDiffuse); GRenderer->GetTextureStage(0)->SetAlphaOp(TextureStage::ArgTexture); GRenderer->GetTextureStage(0)->SetWrapMode(TextureStage::WrapClamp); GRenderer->GetTextureStage(0)->SetMinFilter(TextureStage::FilterNearest); GRenderer->GetTextureStage(0)->SetMagFilter(TextureStage::FilterNearest); } float penX = x; float penY = y; int startX = 0; int endX = 0; if(DoDraw) { // Subtract one line height (since we flipped the Y origin to be like GDI) penY += face->size->metrics.ascender >> 6; } FT_UInt prevGlyphIndex = 0; FT_Pos prevRsbDelta = 0; for(text_iterator it = start; it != end; ) { // Get glyph in glyph map glyph_iterator itGlyph = getNextGlyph(it, end); if(itGlyph == glyphs.end()) { continue; } const Glyph & glyph = itGlyph->second; // Kerning if(FT_HAS_KERNING(face)) { if(prevGlyphIndex != 0) { FT_Vector delta; FT_Get_Kerning(face, prevGlyphIndex, glyph.index, FT_KERNING_DEFAULT, &delta); penX += delta.x >> 6; } prevGlyphIndex = glyph.index; } // Auto hinting adjustments if(prevRsbDelta - glyph.lsb_delta >= 32) { penX--; } else if( prevRsbDelta - glyph.lsb_delta < -32) { penX++; } prevRsbDelta = glyph.rsb_delta; // Draw if(DoDraw && glyph.size.x != 0 && glyph.size.y != 0) { GRenderer->SetTexture(0, &textures->getTexture(glyph.texture)); GRenderer->DrawTexturedRect( ((int)penX) + glyph.draw_offset.x, ((int)penY) - glyph.draw_offset.y, glyph.size.x, -glyph.size.y, glyph.uv_start.x, glyph.uv_end.y, glyph.uv_end.x, glyph.uv_start.y, color ); } else { ARX_UNUSED(penY), ARX_UNUSED(color); } // If this is the first drawn char, note the start position if(startX == endX) { startX = glyph.draw_offset.x; } endX = penX + glyph.draw_offset.x + glyph.size.x; // Advance penX += glyph.advance.x; }