void Font_CacheGlyphsFromFile(FontObj* font, const std::string& path) { char* buffer = NULL; int bufferSize = 0; if (File_Load(path, (void*&) buffer, bufferSize)) { Font_CacheGlyphs(font, buffer); free(buffer); } }
void Font_CacheGlyphs(FontObj* font, const std::string& text) { // Convert to UTF32 unsigned int buffer[1024]; unsigned int bufferSize = ARRAYSIZE(buffer); if (!UTF8ToUTF32((const unsigned char*) text.c_str(), text.length(), buffer, bufferSize)) return; // Make sure all glyphs are present Font_CacheGlyphs(font, buffer, bufferSize); }
void Font_Draw(FontObj* font, const Text::DrawParams* params) { // Convert to UTF32 unsigned int buffer[1024]; unsigned int bufferSize = ARRAYSIZE(buffer); if (!UTF8ToUTF32((const unsigned char*) params->text.c_str(), params->text.length(), buffer, bufferSize)) return; // Make sure all glyphs are present Font_CacheGlyphs(font, buffer, bufferSize); // Generate positions and uvs for the text if (!font->texture) return; const float scale = params->scale; std::vector<float> xy; std::vector<float> uv; float x = params->position.x; float y = params->position.y; for (unsigned int i = 0; i < bufferSize; i++) { if (buffer[i] == '\r') continue; if (buffer[i] == '\n') { y += (float) font->size * scale; x = params->position.x; continue; } Glyph* glyph = map_find(font->glyphs, buffer[i]); if (!glyph) continue; uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top); uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top); uv.push_back(glyph->uv.left + glyph->uv.width); uv.push_back(glyph->uv.top + glyph->uv.height); uv.push_back(glyph->uv.left); uv.push_back(glyph->uv.top + glyph->uv.height); uv.push_back(*(uv.end() - 8)); uv.push_back(*(uv.end() - 8)); uv.push_back(*(uv.end() - 6)); uv.push_back(*(uv.end() - 6)); xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + glyph->pos.top * scale); xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + glyph->pos.top * scale); xy.push_back(x + (glyph->pos.left + glyph->pos.width) * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale); xy.push_back(x + glyph->pos.left * scale); xy.push_back(y + (glyph->pos.top + glyph->pos.height) * scale); xy.push_back(*(xy.end() - 8)); xy.push_back(*(xy.end() - 8)); xy.push_back(*(xy.end() - 6)); xy.push_back(*(xy.end() - 6)); x += glyph->advancePos * scale; } // Determine mins and maxes of the text float minX = (float) INT_MAX, maxX = (float) INT_MIN, minY = (float) INT_MAX, maxY = (float) INT_MIN; for (unsigned int i = 0; i < xy.size(); i += 2) { minX = min(minX, xy[i]); maxX = max(maxX, xy[i]); minY = min(minY, xy[i + 1]); maxY = max(maxY, xy[i + 1]); } // Determine the center of the text float centerX = 0.0f, centerY = 0.0f; if (params->width == 0.0f || params->height == 0.0f) { centerX = (minX + maxX) * 0.5f; centerY = (minY + maxY) * 0.5f; } else { centerX = params->position.x + params->width * 0.5f; centerY = params->position.y + params->height * 0.5f; } // Align the text switch (params->horizontalAlignment) { case Text::HorizontalAlignment_Center: { const float offset = params->position.x + params->width * 0.5f - (minX + maxX) * 0.5f; for (unsigned int i = 0; i < xy.size(); i += 2) xy[i] += offset; break; } case Text::HorizontalAlignment_Right: { const float offset = params->position.x + params->width - maxX; for (unsigned int i = 0; i < xy.size(); i += 2) xy[i] += offset; break; } default: //case Text::HorizontalAlignment_Left : break; } switch (params->verticalAlignment) { case Text::VerticalAlignment_Center: { const float offset = params->position.y + params->height * 0.5f - (minY + maxY) * 0.5f; for (unsigned int i = 1; i < xy.size(); i += 2) xy[i] += offset; break; } case Text::VerticalAlignment_Bottom: { const float offset = params->position.y + params->height - maxY; for (unsigned int i = 1; i < xy.size(); i += 2) xy[i] += offset; break; } default: //case Text::VerticalAlignment_Top: break; } // Set up draw params Shape::DrawParams texParams; texParams.SetGeometryType(Shape::Geometry::Type_Triangles); texParams.SetNumVerts(xy.size() / 2); texParams.SetTexCoord(&uv[0]); // Draw shadow if (params->drawShadow) { // Offset verts for the shadow rendering std::vector<float> xyShadow = xy; for (unsigned int i = 0; i < xyShadow.size(); i += 2) { xyShadow[i] += params->shadowOffset.x; xyShadow[i + 1] += params->shadowOffset.y; } // Rotate the shadow text if (params->rotation != 0) { const float rotationSin = sinf(params->rotation); const float rotationCos = cosf(params->rotation); for (unsigned int i = 0; i < xyShadow.size(); i += 2) Vertex_Rotate(xyShadow[i], xyShadow[i + 1], centerX, centerY, rotationSin, rotationCos); } // Draw the shadow texParams.color = params->shadowColor; texParams.SetPosition(&xyShadow[0]); Texture_Draw(font->texture, &texParams); } // Rotate the text if (params->rotation != 0) { const float rotationSin = sinf(params->rotation); const float rotationCos = cosf(params->rotation); for (unsigned int i = 0; i < xy.size(); i += 2) Vertex_Rotate(xy[i], xy[i + 1], centerX, centerY, rotationSin, rotationCos); } // Draw texParams.color = params->color; texParams.SetPosition(&xy[0]); Texture_Draw(font->texture, &texParams); }
void Font::CacheGlyphs(const std::string& text) { if (obj) Font_CacheGlyphs(obj, text); }