Sprite Sprite::load(Canvas &canvas, const std::string &id, const XMLResourceDocument &doc) { Sprite sprite(canvas); XMLResourceNode resource = doc.get_resource(id); if (resource.get_type() != "sprite") throw Exception(string_format("Resource '%1' is not of type 'sprite'", id)); // Load base angle float work_angle = StringHelp::text_to_float(resource.get_element().get_attribute("base_angle", "0")); sprite.set_base_angle(Angle(work_angle, angle_degrees)); // Load id sprite.set_id(StringHelp::text_to_int(resource.get_element().get_attribute("id", "0"))); // Load play options DomNode cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); if (tag_name == "image" || tag_name == "image-file") { if (cur_element.has_attribute("fileseq")) { int start_index = 0; if (cur_element.has_attribute("start_index")) start_index = StringHelp::text_to_int(cur_element.get_attribute("start_index")); int skip_index = 1; if (cur_element.has_attribute("skip_index")) skip_index = StringHelp::text_to_int(cur_element.get_attribute("skip_index")); int leading_zeroes = 0; if (cur_element.has_attribute("leading_zeroes")) leading_zeroes = StringHelp::text_to_int(cur_element.get_attribute("leading_zeroes")); std::string prefix = cur_element.get_attribute("fileseq"); std::string suffix = "." + PathHelp::get_extension(prefix); prefix.erase(prefix.length() - suffix.length(), prefix.length()); //remove the extension FileSystem fs = resource.get_file_system(); bool found_initial = false; for (int i = start_index;; i = skip_index) { std::string file_name = prefix; std::string frame_text = StringHelp::int_to_text(i); for (int zeroes_to_add = (leading_zeroes + 1) - frame_text.length(); zeroes_to_add > 0; zeroes_to_add--) file_name = "0"; file_name = frame_text + suffix; try { Texture2D texture = Texture2D(canvas, PathHelp::combine(resource.get_base_path(), file_name), fs); sprite.add_frame(texture); found_initial = true; } catch (const Exception&) { if (!found_initial) { //must have been an error, pass it down throw; } //can't find anymore pics break; } } } else { std::string image_name = cur_element.get_attribute("file"); FileSystem fs = resource.get_file_system(); Texture2D texture = Texture2D(canvas, PathHelp::combine(resource.get_base_path(), image_name), fs); DomNode cur_child(cur_element.get_first_child()); if (cur_child.is_null()) { sprite.add_frame(texture); } else { do { DomElement cur_child_elemnt = cur_child.to_element(); if (cur_child.get_node_name() == "grid") { int xpos = 0; int ypos = 0; int xarray = 1; int yarray = 1; int array_skipframes = 0; int xspacing = 0; int yspacing = 0; int width = 0; int height = 0; std::vector<std::string> image_size = StringHelp::split_text(cur_child_elemnt.get_attribute("size"), ","); if (image_size.size() > 0) width = StringHelp::text_to_int(image_size[0]); if (image_size.size() > 1) height = StringHelp::text_to_int(image_size[1]); if (cur_child_elemnt.has_attribute("pos")) { std::vector<std::string> image_pos = StringHelp::split_text(cur_child_elemnt.get_attribute("pos"), ","); if (image_pos.size() > 0) xpos = StringHelp::text_to_int(image_pos[0]); if (image_pos.size() > 1) ypos = StringHelp::text_to_int(image_pos[1]); } if (cur_child_elemnt.has_attribute("array")) { std::vector<std::string> image_array = StringHelp::split_text(cur_child_elemnt.get_attribute("array"), ","); if (image_array.size() == 2) { xarray = StringHelp::text_to_int(image_array[0]); yarray = StringHelp::text_to_int(image_array[1]); } else { throw Exception("Resource '" + resource.get_name() + "' has incorrect array attribute, must be \"X,Y\"!"); } } if (cur_child_elemnt.has_attribute("array_skipframes")) { array_skipframes = StringHelp::text_to_int(cur_child_elemnt.get_attribute("array_skipframes")); } if (cur_child_elemnt.has_attribute("spacing")) { std::vector<std::string> image_spacing = StringHelp::split_text(cur_child_elemnt.get_attribute("spacing"), ","); xspacing = StringHelp::text_to_int(image_spacing[0]); yspacing = StringHelp::text_to_int(image_spacing[1]); } sprite.add_gridclipped_frames(canvas, texture, xpos, ypos, width, height, xarray, yarray, array_skipframes, xspacing, yspacing); } else if (cur_child.get_node_name() == "palette") { throw Exception("Resource '" + resource.get_name() + "' uses palette cutter - which is not supported anymore"); } else if (cur_child.get_node_name() == "alpha") { int xpos = 0; int ypos = 0; float trans_limit = 0.05f; if (cur_child_elemnt.has_attribute("pos")) { std::vector<std::string> image_pos = StringHelp::split_text(cur_child_elemnt.get_attribute("pos"), ","); xpos = StringHelp::text_to_int(image_pos[0]); ypos = StringHelp::text_to_int(image_pos[1]); } if (cur_child_elemnt.has_attribute("trans_limit")) { trans_limit = StringHelp::text_to_float(cur_child_elemnt.get_attribute("trans_limit")); } if (cur_child_elemnt.has_attribute("free")) { sprite.add_alphaclipped_frames_free(canvas, texture, xpos, ypos, trans_limit); } else { sprite.add_alphaclipped_frames(canvas, texture, xpos, ypos, trans_limit); } } cur_child = cur_child.get_next_sibling(); } while (!cur_child.is_null()); } } } cur_node = cur_node.get_next_sibling(); } cur_node = resource.get_element().get_first_child(); while (!cur_node.is_null()) { if (!cur_node.is_element()) { cur_node = cur_node.get_next_sibling(); continue; } DomElement cur_element = cur_node.to_element(); std::string tag_name = cur_element.get_tag_name(); // <color red="float" green="float" blue="float" alpha="float" /> if (tag_name == "color") { Colorf color; color.r = (float)StringHelp::text_to_float(cur_element.get_attribute("red", "1.0")); color.g = (float)StringHelp::text_to_float(cur_element.get_attribute("green", "1.0")); color.b = (float)StringHelp::text_to_float(cur_element.get_attribute("blue", "1.0")); color.a = (float)StringHelp::text_to_float(cur_element.get_attribute("alpha", "1.0")); sprite.set_color(color); } // <animation speed="integer" loop="[yes,no]" pingpong="[yes,no]" direction="[backward,forward]" on_finish="[blank,last_frame,first_frame]"/> else if (tag_name == "animation") { int delay_ms = StringHelp::text_to_int(cur_element.get_attribute("speed", "60")); int frame_count = sprite.get_frame_count(); for (int i = 0; i < frame_count; ++i) sprite.set_frame_delay(i, delay_ms); sprite.set_play_loop((cur_element.get_attribute("loop", "yes")) == "yes"); sprite.set_play_pingpong((cur_element.get_attribute("pingpong", "no")) == "yes"); sprite.set_play_backward((cur_element.get_attribute("direction", "forward")) == "backward"); std::string on_finish = cur_element.get_attribute("on_finish", "blank"); if (on_finish == "first_frame") sprite.set_show_on_finish(Sprite::show_first_frame); else if (on_finish == "last_frame") sprite.set_show_on_finish(Sprite::show_last_frame); else sprite.set_show_on_finish(Sprite::show_blank); } // <scale x="float" y="float /> else if (tag_name == "scale") { float scale_x = StringHelp::text_to_float(cur_element.get_attribute("x", "1.0")); float scale_y = StringHelp::text_to_float(cur_element.get_attribute("y", "1.0")); sprite.set_scale(scale_x, scale_y); } // <translation origin="string" x="integer" y="integer" /> else if (tag_name == "translation") { std::string hotspot = cur_element.get_attribute("origin", "top_left"); Origin origin; if (hotspot == "center") origin = origin_center; else if (hotspot == "top_center") origin = origin_top_center; else if (hotspot == "top_right") origin = origin_top_right; else if (hotspot == "center_left") origin = origin_center_left; else if (hotspot == "center_right") origin = origin_center_right; else if (hotspot == "bottom_left") origin = origin_bottom_left; else if (hotspot == "bottom_center") origin = origin_bottom_center; else if (hotspot == "bottom_right") origin = origin_bottom_right; else origin = origin_top_left; int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); sprite.set_alignment(origin, xoffset, yoffset); } // <rotation origin="string" x="integer" y="integer" /> else if (tag_name == "rotation") { std::string hotspot = cur_element.get_attribute("origin", "center"); Origin origin; if (hotspot == "top_left") origin = origin_top_left; else if (hotspot == "top_center") origin = origin_top_center; else if (hotspot == "top_right") origin = origin_top_right; else if (hotspot == "center_left") origin = origin_center_left; else if (hotspot == "center_right") origin = origin_center_right; else if (hotspot == "bottom_left") origin = origin_bottom_left; else if (hotspot == "bottom_center") origin = origin_bottom_center; else if (hotspot == "bottom_right") origin = origin_bottom_right; else origin = origin_center; int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); sprite.set_rotation_hotspot(origin, xoffset, yoffset); } // <frame nr="integer" speed="integer" x="integer" y="integer" /> else if (tag_name == "frame") { int nr = StringHelp::text_to_int(cur_element.get_attribute("nr", "0")); int yoffset = StringHelp::text_to_int(cur_element.get_attribute("y", "0")); int xoffset = StringHelp::text_to_int(cur_element.get_attribute("x", "0")); if (nr < 0 || nr >= sprite.get_frame_count()) { throw Exception("Invalid sprite frame index specified"); } if (cur_element.has_attribute("speed")) { sprite.set_frame_delay(nr, StringHelp::text_to_int(cur_element.get_attribute("speed", "60"))); } sprite.set_frame_offset(nr, Point(xoffset, yoffset)); } cur_node = cur_node.get_next_sibling(); } sprite.restart(); return sprite; }
Font Font::load(Canvas &canvas, const std::string &family_name, const FontDescription &reference_desc, FontFamily &font_family, const XMLResourceDocument &doc, std::function<Resource<Sprite>(Canvas &, const std::string &)> cb_get_sprite) { DomElement font_element; XMLResourceNode resource; resource = doc.get_resource(family_name); font_element = resource.get_element(); DomElement sprite_element = font_element.named_item("sprite").to_element(); if (!sprite_element.is_null()) { if (!sprite_element.has_attribute("glyphs")) throw Exception(string_format("Font resource %1 has no 'glyphs' attribute.", resource.get_name())); if (!sprite_element.has_attribute("letters")) throw Exception(string_format("Font resource %1 has no 'letters' attribute.", resource.get_name())); if (!cb_get_sprite) throw Exception(string_format("Font resource %1 requires a sprite loader callback specified.", resource.get_name())); Resource<Sprite> spr_glyphs = cb_get_sprite(canvas, sprite_element.get_attribute("glyphs")); const std::string &letters = sprite_element.get_attribute("letters"); int spacelen = StringHelp::text_to_int(sprite_element.get_attribute("spacelen", "-1")); bool monospace = StringHelp::text_to_bool(sprite_element.get_attribute("monospace", "false")); // Modify the default font metrics, if specified float height = 0.0f; float line_height = 0.0f; float ascent = 0.0f; float descent = 0.0f; float internal_leading = 0.0f; float external_leading = 0.0f; if (sprite_element.has_attribute("height")) height = StringHelp::text_to_float(sprite_element.get_attribute("height", "0")); if (sprite_element.has_attribute("line_height")) line_height = StringHelp::text_to_float(sprite_element.get_attribute("line_height", "0")); if (sprite_element.has_attribute("ascent")) ascent = StringHelp::text_to_float(sprite_element.get_attribute("ascent", "0")); if (sprite_element.has_attribute("descent")) descent = StringHelp::text_to_float(sprite_element.get_attribute("descent", "0")); if (sprite_element.has_attribute("internal_leading")) internal_leading = StringHelp::text_to_float(sprite_element.get_attribute("internal_leading", "0")); if (sprite_element.has_attribute("external_leading")) external_leading = StringHelp::text_to_float(sprite_element.get_attribute("external_leading", "0")); FontMetrics font_metrics(height, ascent, descent, internal_leading, external_leading, line_height, canvas.get_pixel_ratio()); font_family.add(canvas, spr_glyphs.get(), letters, spacelen, monospace, font_metrics); FontDescription desc = reference_desc.clone(); return Font(font_family, desc); } DomElement ttf_element = font_element.named_item("ttf").to_element(); if (ttf_element.is_null()) ttf_element = font_element.named_item("freetype").to_element(); if (!ttf_element.is_null()) { FontDescription desc = reference_desc.clone(); std::string filename; if (ttf_element.has_attribute("file")) { filename = PathHelp::combine(resource.get_base_path(), ttf_element.get_attribute("file")); } if (!ttf_element.has_attribute("typeface")) throw Exception(string_format("Font resource %1 has no 'typeface' attribute.", resource.get_name())); std::string font_typeface_name = ttf_element.get_attribute("typeface"); if (ttf_element.has_attribute("height")) desc.set_height(ttf_element.get_attribute_int("height", 0)); if (ttf_element.has_attribute("average_width")) desc.set_average_width(ttf_element.get_attribute_int("average_width", 0)); if (ttf_element.has_attribute("anti_alias")) desc.set_anti_alias(ttf_element.get_attribute_bool("anti_alias", true)); if (ttf_element.has_attribute("subpixel")) desc.set_subpixel(ttf_element.get_attribute_bool("subpixel", true)); if (filename.empty()) { font_family.add(font_typeface_name, desc); return Font(font_family, desc); } else { font_family.add(desc, filename, resource.get_file_system()); return Font(font_family, desc); } } throw Exception(string_format("Font resource %1 did not have a <sprite> or <ttf> child element", resource.get_name())); }
Font Font_Impl::load(Canvas &canvas, const FontDescription &reference_desc, const std::string &id, const XMLResourceDocument &doc, Callback_2<Resource<Sprite>, Canvas &, const std::string &> cb_get_sprite) { XMLResourceNode resource = doc.get_resource(id); std::string type = resource.get_element().get_tag_name(); if (type != "font") throw Exception(string_format("Resource '%1' is not of type 'font'", id)); DomElement sprite_element = resource.get_element().named_item("sprite").to_element(); FontMetrics font_metrics; if (!sprite_element.is_null()) { if (!sprite_element.has_attribute("glyphs")) throw Exception(string_format("Font resource %1 has no 'glyphs' attribute.", resource.get_name())); if (!sprite_element.has_attribute("letters")) throw Exception(string_format("Font resource %1 has no 'letters' attribute.", resource.get_name())); Resource<Sprite> spr_glyphs = cb_get_sprite.invoke(canvas, sprite_element.get_attribute("glyphs")); const std::string &letters = sprite_element.get_attribute("letters"); int spacelen = StringHelp::text_to_int(sprite_element.get_attribute("spacelen", "-1")); bool monospace = StringHelp::text_to_bool(sprite_element.get_attribute("monospace", "false")); // Modify the default font metrics, if specified if (sprite_element.has_attribute("height")) font_metrics.set_height(StringHelp::text_to_float(sprite_element.get_attribute("height", "0"))); if (sprite_element.has_attribute("ascent")) font_metrics.set_ascent(StringHelp::text_to_float(sprite_element.get_attribute("ascent", "0"))); if (sprite_element.has_attribute("descent")) font_metrics.set_descent(StringHelp::text_to_float(sprite_element.get_attribute("descent", "0"))); if (sprite_element.has_attribute("internal_leading")) font_metrics.set_internal_leading(StringHelp::text_to_float(sprite_element.get_attribute("internal_leading", "0"))); if (sprite_element.has_attribute("external_leading")) font_metrics.set_external_leading(StringHelp::text_to_float(sprite_element.get_attribute("external_leading", "0"))); if (sprite_element.has_attribute("average_character_width")) font_metrics.set_average_character_width(StringHelp::text_to_float(sprite_element.get_attribute("average_character_width", "0"))); if (sprite_element.has_attribute("max_character_width")) font_metrics.set_max_character_width(StringHelp::text_to_float(sprite_element.get_attribute("max_character_width", "0"))); font_metrics.set_weight(400.0f); if (sprite_element.has_attribute("weight")) font_metrics.set_weight(StringHelp::text_to_float(sprite_element.get_attribute("weight", "0"))); if (sprite_element.has_attribute("overhang")) font_metrics.set_overhang(StringHelp::text_to_float(sprite_element.get_attribute("overhang", "0"))); font_metrics.set_digitized_aspect_x(96.0f); if (sprite_element.has_attribute("digitized_aspect_x")) font_metrics.set_digitized_aspect_x(StringHelp::text_to_float(sprite_element.get_attribute("digitized_aspect_x", "0"))); font_metrics.set_digitized_aspect_y(96.0f); if (sprite_element.has_attribute("digitized_aspect_y")) font_metrics.set_digitized_aspect_y(StringHelp::text_to_float(sprite_element.get_attribute("digitized_aspect_y", "0"))); if (sprite_element.has_attribute("italic")) font_metrics.set_italic(StringHelp::text_to_bool(sprite_element.get_attribute("italic", "0"))); if (sprite_element.has_attribute("underlined")) font_metrics.set_underlined(StringHelp::text_to_bool(sprite_element.get_attribute("underlined", "0"))); if (sprite_element.has_attribute("struck_out")) font_metrics.set_struck_out(StringHelp::text_to_bool(sprite_element.get_attribute("struck_out", "0"))); if (sprite_element.has_attribute("fixed_pitch")) font_metrics.set_fixed_pitch(StringHelp::text_to_bool(sprite_element.get_attribute("fixed_pitch", "0"))); return Font(canvas, spr_glyphs.get(), letters, spacelen, monospace, font_metrics); } DomElement ttf_element = resource.get_element().named_item("ttf").to_element(); if (ttf_element.is_null()) ttf_element = resource.get_element().named_item("freetype").to_element(); if (!ttf_element.is_null()) { FontDescription desc = reference_desc.clone(); std::string filename; if (ttf_element.has_attribute("file")) filename = ttf_element.get_attribute("file"); desc.set_typeface_name(ttf_element.get_attribute("file")); if (ttf_element.has_attribute("typeface")) desc.set_typeface_name(ttf_element.get_attribute("typeface")); if (ttf_element.has_attribute("height")) desc.set_height(ttf_element.get_attribute_int("height", 0)); if (ttf_element.has_attribute("average_width")) desc.set_average_width(ttf_element.get_attribute_int("average_width", 0)); if (ttf_element.has_attribute("anti_alias")) desc.set_anti_alias(ttf_element.get_attribute_bool("anti_alias", true)); if (ttf_element.has_attribute("subpixel")) desc.set_subpixel(ttf_element.get_attribute_bool("subpixel", true)); return Font(canvas, desc, filename); } throw Exception(string_format("Font resource %1 did not have a <sprite> or <ttf> child element", resource.get_name())); }