// Attempts to position unplaced rectangles from the layout into this row. int TextureLayoutRow::Generate(TextureLayout& layout, int max_width, int y) { int placed_rectangles = 0; while(!layout.unplaced_rectangles.empty()) { TextureLayoutRectangle* rectangle = layout.unplaced_rectangles.front(); if (placed_width + rectangle->GetDimensions().x + 1 > max_width) break; // Increment the row height if necessary. height = Math::Max(height, rectangle->GetDimensions().y); // Add this glyph onto our list and mark it as placed. rectangles.push_back(rectangle); if (layout.has_generated) rectangle->Place(layout.GetNumTextures()-1, Vector2i(placed_width, y)); else rectangle->Place(layout.GetNumTextures(), Vector2i(placed_width, y)); ++placed_rectangles; // Increment our width. An extra pixel is added on so the rectangles aren't pushed up // against each other. This will avoid filtering artifacts. if (rectangle->GetDimensions().x > 0) placed_width += rectangle->GetDimensions().x + 1; layout.rectangles.push_back(rectangle); layout.unplaced_rectangles.pop(); } return placed_rectangles; }
// Generates the texture data for a layer (for the texture database). bool FontFaceLayer::GenerateTexture(int texture_id) { if (texture_id < 0 || texture_id > texture_layout.GetNumTextures()) return false; const FontGlyphList& glyphs = handle->GetGlyphs(); // Generate the texture data. TextureLayoutTexture* texture = texture_layout.GetTexture(texture_id); if (texture && !texture->GetTextureData()) texture->AllocateTexture(); int rectangle_count = texture_layout.GetNumRectangles(); for (int i = 0; i < rectangle_count; ++i) { TextureLayoutRectangle* rectangle = texture_layout.GetRectangle(i); if (rectangle->GetTextureIndex() != texture_id) continue; Character* character = characters[(word) rectangle->GetId()]; if (!character) continue; const FontGlyph* glyph = glyphs[rectangle->GetId()]; if (!glyph) continue; if (effect == NULL) { // Copy the glyph's bitmap data into its allocated texture. if (glyph->bitmap_data != NULL) { byte* destination = rectangle->GetTextureData(); byte* source = glyph->bitmap_data; for (int j = 0; j < glyph->bitmap_dimensions.y; ++j) { for (int k = 0; k < glyph->bitmap_dimensions.x; ++k) destination[k * 4 + 3] = source[k]; destination += rectangle->GetTextureStride(); source += glyph->bitmap_dimensions.x; } } } else { effect->GenerateGlyphTexture(rectangle->GetTextureData(), Vector2i(Math::RealToInteger(character->dimensions.x), Math::RealToInteger(character->dimensions.y)), rectangle->GetTextureStride(), *glyph); } } return true; }
TextureLayout& TextureLayout::operator+=(const TextureLayout &layout) { const int texture_size = GetNumTextures(); for (TextureList::const_iterator i = layout.textures.begin(); i != layout.textures.end(); ++i) { TextureLayoutTexture *texture = *i; texture->AddReference(); textures.push_back(texture); } for (RectangleList::const_iterator i = layout.rectangles.begin(); i != layout.rectangles.end(); ++i) { TextureLayoutRectangle *rect = *i; rect->AddReference(); rect->Place(texture_size + rect->GetTextureIndex(), rect->GetPosition()); rectangles.push_back(rect); } return *this; }
// Generate texture layout for all unplaced characters bool FontFaceLayer::GenerateLayout() { int prior_num_rectangles = texture_layout.GetNumRectangles(); int prior_num_textures = texture_layout.GetNumTextures(); // Generate the texture layout; this will position the glyph rectangles efficiently and // allocate the texture data ready for writing. if (!texture_layout.GenerateLayout(512)) return false; // Iterate over each rectangle in the layout, copying the glyph data into the rectangle as // appropriate and generating geometry. int rectangle_count = texture_layout.GetNumRectangles(); for (int i = prior_num_rectangles; i < rectangle_count; ++i) { TextureLayoutRectangle* rectangle = texture_layout.GetRectangle(i); Character* character = characters[(word) rectangle->GetId()]; if (!character) continue; const TextureLayoutTexture* texture = texture_layout.GetTexture(rectangle->GetTextureIndex()); // Set the character's texture index. character->texture_index = rectangle->GetTextureIndex(); // Generate the character's texture coordinates. character->texcoords[0].x = float(rectangle->GetPosition().x) / float(texture->GetDimensions().x); character->texcoords[0].y = float(rectangle->GetPosition().y) / float(texture->GetDimensions().y); character->texcoords[1].x = float(rectangle->GetPosition().x + rectangle->GetDimensions().x) / float(texture->GetDimensions().x); character->texcoords[1].y = float(rectangle->GetPosition().y + rectangle->GetDimensions().y) / float(texture->GetDimensions().y); } if (prior_num_textures > 0 && prior_num_rectangles != rectangle_count) textures[prior_num_textures-1]->Update(); // Generate the textures. int texture_count = texture_layout.GetNumTextures(); for (int i = prior_num_textures; i < texture_count; ++i) { Texture* texture = new Texture(); if (!texture->Load(String(64, "?font::%p/%p/%d/%p", handle, effect, i, texture_layout.GetTexture(i)))) { delete texture; return false; } textures.push_back(texture); } return true; }
bool operator()(const TextureLayoutRectangle& lhs, const TextureLayoutRectangle& rhs) const { return lhs.GetDimensions().y > rhs.GetDimensions().y; }