📄 gameswf_fontlib.cpp
字号:
static void wipe_font_textures(const array<font*>& fonts) { for (int i = 0, n = fonts.size(); i < n; i++) { font* f = fonts[i]; f->wipe_texture_glyphs(); } } // // Public interface // void generate_font_bitmaps(const array<font*>& fonts, movie_definition_sub* owner) // Build cached textures from glyph outlines. { assert(s_render_buffer == NULL); s_render_buffer = new Uint8[s_glyph_render_size * s_glyph_render_size]; // Build the glyph images. array<rendered_glyph_info> glyph_info; for (int i = 0; i < fonts.size(); i++) { generate_font_bitmaps(&glyph_info, fonts[i], owner); } // Pack all the rendered glyphs and push the info into their fonts. pack_and_assign_glyphs(&glyph_info, owner); // Delete glyph images. {for (int i = 0, n = glyph_info.size(); i < n; i++) { delete glyph_info[i].m_image; }} glyph_info.clear(); // Finish off any pending cache texture. finish_current_texture(owner); // Clean up our buffers. if (s_current_cache_image) { delete [] s_current_cache_image; s_current_cache_image = NULL; s_covered_rects.resize(0); s_anchor_points.resize(0); } // Clean up the render buffer that we just used. assert(s_render_buffer); delete [] s_render_buffer; s_render_buffer = NULL; } void output_cached_data( tu_file* out, const array<font*>& fonts, movie_definition_sub* owner, const cache_options& options) // Save cached font data, including glyph textures, to a // stream. This is used by the movie caching code. { assert(out); // skip number of bitmaps. int bitmaps_used_base = owner->get_bitmap_info_count(); int size_pos = out->get_position(); out->write_le16(0); // save bitmaps s_save_dummy_bitmaps = false; if (options.m_include_font_bitmaps == false) { s_save_dummy_bitmaps = true; // HACK!!! } s_file = out; // HACK!!! s_saving = true; // HACK!!! wipe_font_textures(fonts); // HACK -- eliminate the font textures, so generate_font_bitmaps() regen's them. generate_font_bitmaps(fonts, owner); s_saving = false; s_file = NULL; // save number of bitmaps. out->set_position(size_pos); out->write_le16(owner->get_bitmap_info_count() - bitmaps_used_base); out->go_to_end(); // save number of fonts. out->write_le16(fonts.size()); // for each font: for (int f = 0; f < fonts.size(); f++) { font* fnt = fonts[f]; // Write out the nominal glyph size for this font (for calibrating scaling). int nominal_glyph_size = fnt->get_texture_glyph_nominal_size(); out->write_le16(nominal_glyph_size); // skip number of glyphs. int ng = fonts[f]->get_glyph_count(); int ng_position = out->get_position(); out->write_le32(0); int n = 0; // save texture glyphs: for (int g = 0; g < ng; g++) { const texture_glyph& tg = fonts[f]->get_texture_glyph(g); if (tg.is_renderable()) { // save glyph index. out->write_le32(g); // save bitmap index. // @@ blech, linear search int bi; for (bi = bitmaps_used_base; bi < owner->get_bitmap_info_count(); bi++) { if (tg.m_bitmap_info == owner->get_bitmap_info(bi)) { break; } } assert(bi >= bitmaps_used_base && bi < owner->get_bitmap_info_count()); out->write_le16((Uint16) (bi - bitmaps_used_base)); // save rect, position. out->write_float32(tg.m_uv_bounds.m_x_min); out->write_float32(tg.m_uv_bounds.m_y_min); out->write_float32(tg.m_uv_bounds.m_x_max); out->write_float32(tg.m_uv_bounds.m_y_max); out->write_float32(tg.m_uv_origin.m_x); out->write_float32(tg.m_uv_origin.m_y); n++; } } out->set_position(ng_position); out->write_le32(n); out->go_to_end(); // Output cached shape data. fonts[f]->output_cached_data(out, options); } if (out->get_error() != TU_FILE_NO_ERROR) { log_error("gameswf::fontlib::save_cached_font_data(): problem writing to output stream!"); } // @@ NOTE: should drop any bitmap_info's in owner // that have a ref count == 1, since they're orphaned // now... or else use weak_ptr's in owner? } void input_cached_data(tu_file* in, const array<font*>& fonts, movie_definition_sub* owner) // Load a stream containing previously-saved font glyph textures. { // load number of bitmaps. int nb = in->read_le16(); int pw = 0, ph = 0; // load bitmaps. int bitmaps_used_base = owner->get_bitmap_info_count(); for (int b = 0; b < nb; b++) { // load bitmap size int w = in->read_le16(); int h = in->read_le16(); smart_ptr<bitmap_info> bi; if (owner->get_create_bitmaps() == DO_NOT_LOAD_BITMAPS) { // Skip image data bytes. in->set_position(in->get_position() + w * h); // Make a placeholder bitmap. bi = render::create_bitmap_info_empty(); } else { // load bitmap contents if (s_current_cache_image == NULL || w != pw || h != ph) { delete [] s_current_cache_image; s_current_cache_image = new Uint8[w*h]; pw = w; ph = h; } in->read_bytes(s_current_cache_image, w * h); bi = render::create_bitmap_info_alpha( w, h, s_current_cache_image); } owner->add_bitmap_info(bi.get_ptr()); assert(bi->get_ref_count() == 2); // one ref for bi, one for the owner. } delete [] s_current_cache_image; s_current_cache_image = NULL; // load number of fonts. int nf = in->read_le16(); if (nf != fonts.size()) { // Font counts must match! log_error("error: mismatched font count (read %d, expected %d) in cached font data\n", nf, fonts.size()); in->go_to_end(); goto error_exit; } // for each font: {for (int f = 0; f < nf; f++) { font* fnt = fonts[f]; if (in->get_error() != TU_FILE_NO_ERROR) { log_error("error reading cache file (fonts); skipping\n"); return; } if (in->get_eof()) { log_error("unexpected eof reading cache file (fonts); skipping\n"); return; } // Get nominal glyph size for this font (for calibrating scaling). int nominal_glyph_size = in->read_le16(); fnt->set_texture_glyph_nominal_size(nominal_glyph_size); // load number of texture glyphs. int ng = in->read_le32(); // load glyphs: for (int g=0; g<ng; g++) { // load glyph index. int glyph_index = in->read_le32(); texture_glyph tg; // load bitmap index int bi = in->read_le16(); if (bi + bitmaps_used_base >= owner->get_bitmap_info_count()) { // Bad data; give up. log_error("error: invalid bitmap index %d in cached font data\n", bi); in->go_to_end(); goto error_exit; } tg.set_bitmap_info(owner->get_bitmap_info(bi + bitmaps_used_base)); // load glyph bounds and origin. tg.m_uv_bounds.m_x_min = in->read_float32(); tg.m_uv_bounds.m_y_min = in->read_float32(); tg.m_uv_bounds.m_x_max = in->read_float32(); tg.m_uv_bounds.m_y_max = in->read_float32(); tg.m_uv_origin.m_x = in->read_float32(); tg.m_uv_origin.m_y = in->read_float32(); if (glyph_index < 0 || glyph_index >= fnt->get_glyph_count()) { // Cached data doesn't match this font! log_error("error: invalid glyph index %d in cached font data, limit is %d, font is '%s'\n", glyph_index, fnt->get_glyph_count(), fnt->get_name()); } else { fnt->add_texture_glyph(glyph_index, tg); } } // Load cached shape data. fnt->input_cached_data(in); }} error_exit: ; } void clear() // Release all the fonts we know about. { s_fonts.clear(); } int get_font_count() // Return the number of fonts in our library. { return s_fonts.size(); } font* get_font(int index) // Retrieve one of our fonts, by index. { if (index < 0 || index >= s_fonts.size()) { return NULL; } return s_fonts[index].get_ptr(); } font* get_font(const char* name) // Return the named font. { // Dumb linear search. for (int i = 0; i < s_fonts.size(); i++) { font* f = s_fonts[i].get_ptr(); if (f != NULL) { if (strcmp(f->get_name(), name) == 0) { return f; } } } return NULL; } const char* get_font_name(const font* f) // Return the name of the given font. (This basically exists // so that font* can be opaque to the host app). { if (f == NULL) { return "<null>"; } return f->get_name(); } void add_font(font* f) // Add the given font to our library. { assert(f);#ifndef NDEBUG // Make sure font isn't already in the list. for (int i = 0; i < s_fonts.size(); i++) { assert(s_fonts[i] != f); }#endif // not NDEBUG s_fonts.push_back(f); } void draw_glyph(const matrix& mat, const texture_glyph& tg, rgba color, int nominal_glyph_height) // Draw the given texture glyph using the given transform, in // the given color. { assert(tg.is_renderable()); // @@ worth it to precompute these bounds? rect bounds = tg.m_uv_bounds; bounds.m_x_min -= tg.m_uv_origin.m_x; bounds.m_x_max -= tg.m_uv_origin.m_x; bounds.m_y_min -= tg.m_uv_origin.m_y; bounds.m_y_max -= tg.m_uv_origin.m_y; // Scale from uv coords to the 1024x1024 glyph square. // @@ need to factor this out! static float s_scale = GLYPH_CACHE_TEXTURE_SIZE * s_rendering_box / nominal_glyph_height; bounds.m_x_min *= s_scale; bounds.m_x_max *= s_scale; bounds.m_y_min *= s_scale; bounds.m_y_max *= s_scale; render::draw_bitmap(mat, tg.m_bitmap_info.get_ptr(), bounds, tg.m_uv_bounds, color); }#if 0 void draw_string(const font* f, float x, float y, float size, const char* text) // Host-driven text rendering function. This not-tested and unfinished. { // Dummy arrays with a white fill style. For passing to shape_character::display(). static array<fill_style> s_dummy_style; static array<line_style> s_dummy_line_style; static display_info s_dummy_display_info; if (s_dummy_style.size() < 1) { s_dummy_style.resize(1); s_dummy_style.back().set_color(rgba(255, 255, 255, 255)); } // Render each glyph in the string. for (int i = 0; text[i]; i++) { int g = f->get_glyph_index(text[i]); if (g == -1) { continue; // FIXME: advance? } const texture_glyph& tg = f->get_texture_glyph(g); matrix m; m.concatenate_translation(x, y); m.concatenate_scale(size / 1024.0f); if (tg.is_renderable()) { // Draw the glyph using the cached texture-map info. fontlib::draw_glyph(m, tg, rgba()); } else { shape_character_def* glyph = f->get_glyph(g); // Draw the character using the filled outline. if (glyph) { glyph->display(dummy_inst, s_dummy_style, s_dummy_line_style); } } x += f->get_advance(g); } }#endif // 0} // end namespace fontlib} // end namespace gameswf// Local Variables:// mode: C++// c-basic-offset: 8 // tab-width: 8// indent-tabs-mode: t// End:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -