The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Fix layout containers

These changes was commited to the Birdfont repository Sat, 16 Jan 2016 20:35:38 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Sat, 16 Jan 2016 20:35:38 +0000 (21:35 +0100)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Sat, 16 Jan 2016 20:35:38 +0000 (21:35 +0100)
commit f17b819e135e82e966550170f00a7e4bbedbf9b2
tree 4e767fe4b33b7c923f940bc8bdd6a9a907490eb7
parent 884166a6e938d8017a966cca7a7cf8f152dee009
Fix layout containers

21 files changed:
birdui/AbsoluteLayout.vala [deleted ]
birdui/BoxLayout.vala
birdui/Component.vala
birdui/GtkWidget.vala
birdui/GtkWindow.vala
birdui/SvgComponent.vala
libbirdfont/BirdFontFile.vala
libbirdfont/DrawingTools.vala
libbirdfont/Glyph.vala
libbirdfont/LayerUtils.vala
libbirdfont/SvgParser.vala
libsvgbird/Layer.vala
libsvgbird/Object.vala
libsvgbird/ObjectGroup.vala
libsvgbird/PointValue.vala
libsvgbird/SvgDrawing.vala
libsvgbird/SvgFile.vala
libsvgbird/SvgPath.vala
libsvgbird/SvgTransform.vala
libsvgbird/SvgTransforms.vala
diff --git birdui/AbsoluteLayout.vala(deleted)
--- a/birdui/AbsoluteLayout.vala +++ /dev/null @@ -1,33 +1,1 @@ - /* - Copyright (C) 2016 Johan Mattsson - - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - */ - - using Gee; - using SvgBird; - using B; - - namespace Bird { - - class AbsoluteLayout : Component { - - public AbsoluteLayout (XmlElement layout_tag, Defs defs) { - base (layout_tag, defs); - } - - public override string to_string () { - return "AbsoluteLayout"; - } - } - - }
--- a/birdui/BoxLayout.vala +++ b/birdui/BoxLayout.vala @@ -15,6 +15,7 @@ using Gee; using SvgBird; using B; + using Cairo; namespace Bird { @@ -31,74 +32,178 @@ base (layout_tag, defs); this.orientation = orientation; } - - void set_size_limits (Component component) { - string? min_width = component.style.get_css_property ("min-width"); - if (min_width != null) { - double w = SvgFile.parse_number (min_width); - if (component.width < w) { - component.width = w; - } + + public override void draw (Context cairo) { + cairo.save (); + cairo.translate (padded_x, padded_y); + clip (cairo); + + foreach (Component component in components) { + component.draw (cairo); } - string? min_height = component.style.get_css_property ("min-height"); - if (min_height != null) { - double h = SvgFile.parse_number (min_height); + cairo.restore (); + } - if (component.height < h) { - component.height = h; + bool is_width_remainder (Component component) { + return component.style.property_equals ("width", "remainder"); + } + + bool is_height_remainder (Component component) { + return component.style.property_equals ("height", "remainder"); + } + + /** The smallest size this layout can be. */ + public override void get_min_size (out double min_width, out double min_height) { + min_width = 0; + min_height = 0; + + if (orientation == BoxOrientation.HORIZONTAL) { + foreach (Component component in components) { + double w, h; + + component.get_min_size (out w, out h); + min_width += w; + + if (h > min_height) { + min_height = h; + } + } + } else { + foreach (Component component in components) { + double w, h; + + component.get_min_size (out w, out h); + min_height += h; + + if (w > min_width) { + min_width = w; + } } } - string? max_width = component.style.get_css_property ("max-width"); - if (max_width != null) { - double w = SvgFile.parse_number (max_width); + min_width += get_padding_left (); + min_width += get_padding_right (); + min_height += get_padding_top (); + min_height += get_padding_bottom (); + + limit_size (ref min_width, ref min_height); + } + + public override void layout (double parent_width, double parent_height) { + double w, h; + + get_min_size (out w, out h); + int remainders = count_remainders (); + + if (!is_width_remainder (this)) { + width = w; + } + + if (!is_height_remainder (this)) { + height = h; + } + + if (remainders > 0) { + double remainder_size; - if (component.width > w) { - component.width = w; + if (orientation == BoxOrientation.HORIZONTAL) { + remainder_size = (parent_width - w) / remainders; + layout_variable_size (remainder_size, parent_height); + } else { + remainder_size = (parent_height - h) / remainders; + layout_variable_size (remainder_size, parent_width); } } - - string? max_height = component.style.get_css_property ("max-height"); - if (max_height != null) { - double h = SvgFile.parse_number (max_height); + + if (orientation == BoxOrientation.HORIZONTAL) { + foreach (Component component in components) { + component.layout (parent_width, h); + } + } else { + foreach (Component component in components) { + component.layout (w, parent_height); + } + } + + layout_positions (); + } + + int count_remainders () { + int remainders = 0; + + if (orientation == BoxOrientation.HORIZONTAL) { + foreach (Component component in components) { + if (is_width_remainder (component)) { + remainders++; + } + } + } else { + foreach (Component component in components) { + if (is_height_remainder (component)) { + remainders++; + } + } + } + + return remainders; + } + + void layout_variable_size (double remainder_size, double fixed_size) { + double w, h; + + w = 0; + h = 0; + foreach (Component component in components) { + bool width_remainder = is_width_remainder (component); + bool height_remainder = is_height_remainder (component); - if (component.height > h) { + if (width_remainder && orientation == BoxOrientation.HORIZONTAL) { + w = remainder_size; + w -= component.get_padding_left (); + w -= component.get_padding_right (); + h = fixed_size; + } + + if (height_remainder && orientation == BoxOrientation.VERTICAL) { + w = fixed_size; + h = remainder_size; + h -= component.get_padding_top (); + h -= component.get_padding_bottom (); + } + + if (width_remainder || height_remainder) { + double min_width, min_height; + component.get_min_size (out min_width, out min_height); + + if (w < min_width) { + w = min_width; + } + + if (h < min_height) { + h = min_height; + } + + component.limit_size (ref w, ref h); + component.width = w; component.height = h; } } } - - public override void layout () { + + void layout_positions () { double child_x = 0; double child_y = 0; - + foreach (Component component in components) { - component.x = child_x; - component.y = child_y; - component.layout (); - component.apply_padding (); - set_size_limits (component); + component.x = child_x + component.get_padding_left (); + component.y = child_y + component.get_padding_top (); if (orientation == BoxOrientation.HORIZONTAL) { - child_x += component.padded_width; - - if (component.height > height) { - height = component.height; - } + child_x = component.x + component.padded_width + get_padding_right (); } else { - child_y += component.padded_height; - - if (component.width > width) { - width = component.width; - } + child_y = component.y + component.padded_height + get_padding_bottom (); } - } - - if (orientation == BoxOrientation.HORIZONTAL) { - width = child_x; - } else { - height = child_y; } }
--- a/birdui/Component.vala +++ b/birdui/Component.vala @@ -19,7 +19,7 @@ namespace Bird { - class Component : GLib.Object { + public abstract class Component : GLib.Object { public double width { get; protected set; } public double height { get; protected set; } @@ -32,6 +32,18 @@ public double padded_height { get { return height + get_padding_left () + get_padding_right (); + } + } + + public double padded_x { + get { + return x + get_padding_top (); + } + } + + public double padded_y { + get { + return y + get_padding_left (); } } @@ -55,6 +67,18 @@ Overflow overflow = Overflow.VISIBLE; + public Component.load (string file_name, double width, double height) { + this.width = width; + this.height = height; + load_file (file_name, null); + layout (width, height); + } + + /** Parse component ui file but don't do layout. */ + internal Component.load_component (string file_name, Component parent) { + load_file (file_name, parent); + } + public Component (XmlElement component_tag, Defs defs) { this.defs = defs; this.component_tag = component_tag; @@ -78,17 +102,10 @@ css_class = attribute.get_content (); } } - } - - public Component.load (string file_name) { - load_file (file_name); } private void inherit_styles_sheet (Defs defs) { this.defs = defs; - } - - protected void apply_padding () { } protected void parse_style (XmlElement style_tag) { @@ -111,12 +128,16 @@ protected void add_component (Component component) { components.add (component); - component.inherit_styles_sheet (defs); - component.style = SvgStyle.parse (defs, style, component.component_tag); - component.set_overflow_property_from_css (); - component.set_identification (); + component.set_style_properties (this); } + protected void set_style_properties (Component parent) { + inherit_styles_sheet (parent.defs); + style = SvgStyle.parse (parent.defs, parent.style, component_tag); + set_overflow_property_from_css (); + set_identification (); + } + protected void set_overflow_property_from_css () { string? css_overflow = style.get_css_property ("overflow"); @@ -149,21 +170,26 @@ VBox vbox = new VBox (layout_tag, defs); add_component (vbox); } else { - warning ("Layout of type " + type - + " is supported in this verison."); + warning (type + " layout of type is supported in this verison."); } } - + protected void parse_component (XmlElement component_tag) { foreach (Attribute attribute in component_tag.get_attributes ()) { string attribute_name = attribute.get_name (); if (attribute_name == "file") { - Component component = new Component (component_tag, defs); - add_component (component); - component.load_layout (attribute.get_content ()); - } else { - unused_attribute (attribute_name); + string file_name = attribute.get_content (); + UI ui = new UI.load_component (file_name, this); + + foreach (Component component in ui.components) { + add_component (component); + + SvgStyle copied_style; + copied_style = SvgStyle.parse (defs, style, component_tag); + copied_style.apply (component.style); + component.style = copied_style; + } } } } @@ -196,9 +222,9 @@ warning ("The tag " + tag_name + " is not known in this version."); } - public void load_file (string file_name) { + public void load_file (string file_name, Component? parent) { if (file_name.has_suffix (".ui")) { - load_layout (file_name); + load_layout (file_name, parent); } else if (file_name.has_suffix (".svg")) { SvgComponent svg = new SvgComponent.for_file (file_name); add_component (svg); @@ -207,7 +233,7 @@ } } - public void load_layout (string file_name) { + public void load_layout (string file_name, Component? parent) { string? path = find_file (file_name); if (path == null) { @@ -225,14 +251,19 @@ return; } - XmlTree xml_parser = new XmlTree (xml_data); + XmlTree xml_parser = new XmlTree (xml_data); + XmlElement tag = xml_parser.get_root (); - component_tag = xml_parser.get_root (); - - defs = new Defs (); - parse (component_tag); + if (parent == null) { + component_tag = tag; + defs = new Defs (); + } else { + Component p = (!) parent; + component_tag = p.component_tag; + defs = p.defs; + } - layout (); + parse (tag); } public static string find_file (string file_name) { @@ -245,33 +276,46 @@ return file_name; } - public virtual void layout () { + public virtual void get_min_size (out double min_width, out double min_height) { + min_width = width; + min_height = height; + if (unlikely (components.size > 1)) { warning ("A component has several parts but no layout has been set."); } foreach (Component component in components) { - component.layout (); - component.apply_padding (); - width = component.padded_width; - height = component.padded_height; + component.get_min_size (out min_width, out min_height); } + + min_width += get_padding_left (); + min_width += get_padding_right (); + min_height += get_padding_top (); + min_height += get_padding_bottom (); } - public virtual void draw (Context cairo) { + public virtual void layout (double parent_width, double parent_height) { + warning ("A component without a layout was added to the view."); + + double w, h; + get_min_size (out w, out h); + + width = w; + height = h; + foreach (Component component in components) { - cairo.save (); - cairo.translate (component.x, component.y); - - if (component.overflow == Overflow.HIDDEN) { - cairo.rectangle (0, 0, component.width, component.height); - cairo.clip (); - } - - component.draw (cairo); - cairo.restore (); + component.layout (parent_width, parent_height); } } + + public void clip (Context cairo) { + if (overflow == Overflow.HIDDEN) { + cairo.rectangle (0, 0, width, height); + cairo.clip (); + } + } + + public abstract void draw (Context cairo); public virtual void motion_notify_event (double x, double y) { } @@ -292,30 +336,75 @@ print ("\t"); } - print (@"$(to_string ()), x: $x, y: $y, w: $width, h: $height\n"); + print (@"$(to_string ()) width: $padded_width, height: $padded_height x $x y $y $(style)\n"); foreach (Component component in components) { component.print_tree_level (indent + 1); } } - double get_padding_bottom () { + protected double get_padding_bottom () { return SvgFile.parse_number (style.get_css_property ("padding-bottom")); } - double get_padding_top () { + protected double get_padding_top () { return SvgFile.parse_number (style.get_css_property ("padding-top")); } - double get_padding_left () { + protected double get_padding_left () { return SvgFile.parse_number (style.get_css_property ("padding-left")); } - double get_padding_right () { + protected double get_padding_right () { return SvgFile.parse_number (style.get_css_property ("padding-right")); + } + + protected void limit_size (ref double width, ref double height) { + string? min_width = style.get_css_property ("min-width"); + if (min_width != null) { + double w = SvgFile.parse_number (min_width); + if (width < w) { + width = w; + } + } + + string? min_height = style.get_css_property ("min-height"); + if (min_height != null) { + double h = SvgFile.parse_number (min_height); + + if (height < h) { + height = h; + } + } + + string? max_width = style.get_css_property ("max-width"); + if (max_width != null) { + double w = SvgFile.parse_number (max_width); + + if (width > w) { + width = w; + } + } + + string? max_height = style.get_css_property ("max-height"); + if (max_height != null) { + double h = SvgFile.parse_number (max_height); + + if (height > h) { + height = h; + } + } + + if (width < 0) { + width = 0; + } + + if (height < 0) { + height = 0; + } } } }
--- a/birdui/GtkWidget.vala +++ b/birdui/GtkWidget.vala @@ -19,11 +19,11 @@ namespace Bird { - class Widget : DrawingArea { + public class Widget : DrawingArea { - Component component; + UI component; - public Widget (Component main_component) { + public Widget (UI main_component) { component = main_component; add_events (EventMask.BUTTON_PRESS_MASK @@ -49,9 +49,12 @@ int width = (int) rint (component.padded_width); int height = (int) rint (component.padded_height); set_size_request (width, height); + + size_allocate.connect((allocation) => { + component.resize (allocation.width, allocation.height); + }); } - } }
--- a/birdui/GtkWindow.vala +++ b/birdui/GtkWindow.vala @@ -22,7 +22,9 @@ window.set_title ("UI Bird"); window.destroy.connect (Gtk.main_quit); - Component layout = new Component.load ("test.ui"); + UI layout = new UI ("test.ui", 700, 200); + + layout.print_tree (); Bird.Widget primary_layout = new Bird.Widget (layout);
--- a/birdui/SvgComponent.vala +++ b/birdui/SvgComponent.vala @@ -34,7 +34,18 @@ load_svg (svg_file); } - public override void layout () { + public override void get_min_size (out double min_width, out double min_height) { + min_width = 0; + min_height = 0; + + if (drawing != null) { + SvgDrawing svg = (!) drawing; + min_width = svg.width + get_padding_left () + get_padding_right (); + min_height = svg.height + get_padding_bottom () + get_padding_top (); + } + } + + public override void layout (double parent_width, double parent_height) { if (unlikely (components.size > 0)) { warning ("SVG files can not have subviews."); } @@ -73,10 +84,16 @@ } public override void draw (Context cairo) { + cairo.save (); + cairo.translate (padded_x, padded_y); + clip (cairo); + if (drawing != null) { SvgDrawing svg = (!) drawing; svg.draw (cairo); } + + cairo.restore (); } }
--- a/libbirdfont/BirdFontFile.vala +++ b/libbirdfont/BirdFontFile.vala @@ -434,7 +434,7 @@ public void write_glyph (Glyph g, DataOutputStream os) throws GLib.Error { os.put_string (@"\t<glyph id=\"$(g.version_id)\" left=\"$(double_to_string (g.left_limit))\" right=\"$(double_to_string (g.right_limit))\">\n"); - foreach (Layer layer in g.layers.subgroups) { + foreach (Layer layer in g.layers.get_sublayers ()) { write_layer (layer, os); }
--- a/libbirdfont/DrawingTools.vala +++ b/libbirdfont/DrawingTools.vala @@ -1626,7 +1626,7 @@ int i = 0; layer_tools.tool.clear (); - foreach (Layer layer in g.layers.subgroups) { + foreach (Layer layer in g.layers.get_sublayers ()) { LayerLabel label = new LayerLabel (layer); layer_tools.add_tool (label, 0);
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -158,17 +158,17 @@ } public Layer get_current_layer () { - if (unlikely (!(0 <= current_layer < layers.subgroups.size))) { + if (unlikely (!(0 <= current_layer < layers.objects.size))) { warning ("Layer index out of bounds."); return new Layer (); } - return layers.subgroups.get (current_layer); + return layers.get_sublayers ().get (current_layer); } public void set_current_layer (Layer layer) { int i = 0; - foreach (Layer l in layers.subgroups) { + foreach (Layer l in layers.get_sublayers ()) { if (likely (l == layer)) { current_layer = i; return; @@ -205,12 +205,12 @@ public void add_new_layer () { layers.add_layer (new Layer ()); - current_layer = layers.subgroups.size - 1; + current_layer = layers.objects.size - 1; } public void add_layer (Layer layer) { layers.add_layer (layer); - current_layer = layers.subgroups.size - 1; + current_layer = layers.objects.size - 1; } public int get_layer_index (Layer layer) { @@ -482,7 +482,7 @@ } public virtual void add_path (Path p) { - if (layers.subgroups.size == 0) { + if (layers.objects.size == 0) { layers.add_layer (new Layer ()); } @@ -490,7 +490,7 @@ } public void add_object (SvgBird.Object object) { - if (layers.subgroups.size == 0) { + if (layers.objects.size == 0) { layers.add_layer (new Layer ()); } @@ -530,7 +530,7 @@ if (index != "") { int i = int.parse (index); - if (0 <= i < layers.subgroups.size) { + if (0 <= i < layers.objects.size) { current_layer = i; } } @@ -1578,144 +1578,11 @@ /** Draw filled paths. */ public void draw_paths (Context cr, Color? c = null) { - cr.save (); - cr.new_path (); - - foreach (SvgBird.Object o in get_visible_objects ()) { - if (o is PathObject) { - ((PathObject) o).draw_path (cr, c); - } else { - o.draw (cr); - } - } - - cr.fill (); - cr.restore (); + layers.draw (cr); } public void draw_path (Context cr) { - PathList stroke; - Color color; - - // FIXME: layer transforms - foreach (SvgBird.Object o in get_visible_objects ()) { - if (!(o is PathObject)) { - o.draw (cr); - } - } - - cr.save (); - cr.new_path (); - foreach (Path p in get_visible_paths ()) { - if (p.stroke > 0) { - stroke = p.get_stroke_fast (); - - if (p.is_editable ()) { - color = Theme.get_color ("Filled Stroke"); - color.a = 0.8; - } else { - color = Color.black (); - } - - PathObject.draw_path_list (stroke, cr, color); - } - } - cr.fill (); - cr.restore (); - - if (!(MainWindow.get_toolbox ().get_current_tool () is PenTool) - && !(MainWindow.get_toolbox ().get_current_tool () is PointTool) - && !(MainWindow.get_toolbox ().get_current_tool () is TrackTool) - && !(MainWindow.get_toolbox ().get_current_tool () is BezierTool)) { - cr.save (); - cr.new_path (); - foreach (SvgBird.Object o in active_paths) { - if (o is PathObject) { - Path p = ((PathObject) o).get_path (); - if (p.stroke > 0) { - stroke = p.get_stroke_fast (); - color = Theme.get_color ("Selected SvgBird.Objects"); - PathObject.draw_path_list (stroke, cr, color); - } - } - } - cr.fill (); - cr.restore (); - } - - if (is_open () && Path.fill_open_path) { - cr.save (); - cr.new_path (); - foreach (Path p in get_visible_paths ()) { - if (p.stroke == 0) { - color = p.color == null ? get_path_fill_color () : (!) p.color; - p.draw_path (cr, color); - } - } - cr.fill (); - cr.restore (); - } - - if (is_open ()) { - cr.save (); - cr.new_path (); - foreach (Path p in get_visible_paths ()) { - p.draw_outline (cr); - p.draw_edit_points (cr); - } - cr.restore (); - } - - if (!is_open ()) { - // This was good for testing but it is way too slow: - // Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline); - - cr.save (); - cr.new_path (); - - // FIXME: layer transforms - foreach (SvgBird.Object o in get_visible_objects ()) { - if (o is PathObject) { - Path p = ((PathObject) o).get_path (); - - if (p.stroke == 0) { - color = p.color == null ? Color.black () : (!) p.color; - p.draw_path (cr, color); - } - } - } - - cr.close_path (); - cr.fill (); - cr.restore (); - - foreach (SvgBird.Object o in active_paths) { - if (o is PathObject) { - Path p = ((PathObject) o).get_path (); - cr.save (); - cr.new_path (); - if (p.stroke == 0) { - p.draw_path (cr); - } - cr.close_path (); - cr.fill (); - cr.restore (); - } - } - } - - if (show_orientation_arrow) { - foreach (Path p in get_visible_paths ()) { - if (p.stroke > 0) { - stroke = p.get_stroke_fast (); - foreach (Path ps in stroke.paths) { - ps.draw_orientation_arrow (cr, orientation_arrow_opacity); - } - } else { - p.draw_orientation_arrow (cr, orientation_arrow_opacity); - } - } - } + layers.draw (cr); } private Color get_path_fill_color () { @@ -2348,12 +2215,12 @@ public void move_layer_up () { Layer layer = get_current_layer (); - if (current_layer + 2 <= layers.subgroups.size) { - return_if_fail (0 <= current_layer + 2 <= layers.subgroups.size); - layers.subgroups.insert (current_layer + 2, layer); + if (current_layer + 2 <= layers.objects.size) { + return_if_fail (0 <= current_layer + 2 <= layers.objects.size); + layers.objects.objects.insert (current_layer + 2, layer); - return_if_fail (0 <= current_layer + 1 < layers.subgroups.size); - layers.subgroups.remove_at (current_layer); + return_if_fail (0 <= current_layer + 1 < layers.objects.size); + layers.objects.objects.remove_at (current_layer); set_current_layer (layer); } @@ -2363,11 +2230,11 @@ Layer layer = get_current_layer (); if (current_layer >= 1) { - return_if_fail (0 <= current_layer - 1 < layers.subgroups.size); - layers.subgroups.insert (current_layer - 1, layer); + return_if_fail (0 <= current_layer - 1 < layers.objects.size); + layers.objects.objects.insert (current_layer - 1, layer); - return_if_fail (0 <= current_layer + 1 < layers.subgroups.size); - layers.subgroups.remove_at (current_layer + 1); + return_if_fail (0 <= current_layer + 1 < layers.objects.size); + layers.objects.objects.remove_at (current_layer + 1); set_current_layer (layer); }
--- a/libbirdfont/LayerUtils.vala +++ b/libbirdfont/LayerUtils.vala @@ -77,7 +77,7 @@ layer.objects.remove ((!) p); } - foreach (SvgBird.Layer sublayer in layer.subgroups) { + foreach (SvgBird.Layer sublayer in layer.get_sublayers ()) { remove_path (sublayer, path); } }
--- a/libbirdfont/SvgParser.vala +++ b/libbirdfont/SvgParser.vala @@ -256,7 +256,7 @@ if (t.get_name () == "g") { layer = new Layer (); parse_layer (t, layer); - pl.subgroups.add (layer); + pl.objects.add (layer); } if (t.get_name () == "polygon") { @@ -305,7 +305,7 @@ } private void transform_subgroups (string transform_functions, Layer layer) { - foreach (Layer subgroup in layer.subgroups) { + foreach (Layer subgroup in layer.get_sublayers ()) { transform (transform_functions, subgroup); } }
--- a/libsvgbird/Layer.vala +++ b/libsvgbird/Layer.vala @@ -18,52 +18,67 @@ public class Layer : Object { public ObjectGroup objects; - - public Gee.ArrayList<Layer> subgroups; // FIXME: delete public string name = "Layer"; public Layer () { objects = new ObjectGroup (); - subgroups = new Gee.ArrayList<Layer> (); transforms = new SvgTransforms (); } - public int index_of (Layer sublayer) { - return subgroups.index_of (sublayer); - } - - public ObjectGroup get_all_objects () { - ObjectGroup o = new ObjectGroup (); + public void draw (Context cr) { + cr.save (); + apply_transform (cr); - o.append (objects); - - foreach (Layer sublayer in subgroups) { - o.append (sublayer.get_all_objects ()); + if (clip_path != null) { + ClipPath clipping = (!) clip_path; + clipping.apply (cr); + } + + foreach (Object object in objects) { + cr.save (); + object.apply_transform (cr); + + if (object.clip_path != null) { + ClipPath clipping = (!) object.clip_path; + clipping.apply (cr); + } + + object.draw_outline (cr); + object.paint (cr); + cr.restore (); } - return o; + cr.restore (); } + + public override void draw_outline (Context cr) { + cr.save (); + apply_transform (cr); - public ObjectGroup get_visible_objects () { - ObjectGroup object_group = new ObjectGroup (); - - if (visible) { - foreach (Object o in objects) { - object_group.add (o); - } + foreach (Object object in objects) { + cr.save (); + object.apply_transform (cr); + object.draw_outline (cr); + cr.restore (); } - foreach (Layer sublayer in subgroups) { - if (sublayer.visible) { - object_group.append (sublayer.get_visible_objects ()); - } - } + cr.restore (); + } + + public int index_of (Layer sublayer) { + return objects.index_of (sublayer); + } + + public ObjectGroup get_all_objects () { + return objects; + } - return object_group; + public ObjectGroup get_visible_objects () { + return objects; // FIXME: remove this } public void add_layer (Layer layer) { - subgroups.add (layer); + objects.add (layer); } public void add_object (Object object) { @@ -75,21 +90,19 @@ } public void remove_layer (Layer layer) { - subgroups.remove (layer); + objects.remove (layer); - foreach (Layer sublayer in subgroups) { - sublayer.remove_layer (layer); + foreach (Object object in objects) { + if (object is Layer) { + Layer sublayer = (Layer) object; + sublayer.remove_layer (layer); + } } } public static void copy_layer (Layer from, Layer to) { to.name = from.name; to.objects = from.objects.copy (); - - foreach (Layer l in from.subgroups) { - Layer layer = (Layer) l.copy (); - to.subgroups.add (layer); - } } public override Object copy () { @@ -129,6 +142,21 @@ h = py2 - py; x = px; y = py2; + } + + public Gee.ArrayList<Layer> get_sublayers () { + Gee.ArrayList<Layer> sublayers = new Gee.ArrayList<Layer> (); + + foreach (Object object in objects) { + if (likely (object is Layer)) { + Layer sublayer = (Layer) object; + sublayers.add (sublayer); + } else { + warning ("An object in the group " + name + " is not a layer."); + } + } + + return sublayers; } public void print (int indent = 0) { @@ -137,32 +165,28 @@ if (!visible) { stdout.printf (" hidden"); } + + stdout.printf (@" $(transforms) $(style)"); stdout.printf (@"\n"); - - foreach (Object o in objects) { - for (int i = 0; i < indent; i++) { - stdout.printf ("\t"); - } - stdout.printf (@"Object $(o.to_string ())"); + + foreach (Object object in objects) { + stdout.printf (@"$(object.to_string ()) $(object.transforms) $(object.style)"); - if (o.color != null) { - stdout.printf (" %s", ((!) o.color).to_rgb_hex ()); - } - - if (!o.visible) { + if (!object.visible) { stdout.printf (" hidden"); } stdout.printf ("\n"); - } - - foreach (Layer l in subgroups) { + for (int i = 0; i < indent; i++) { stdout.printf ("\t"); } - stdout.printf ("%s\n", l.name); - l.print (indent + 1); + + if (object is Layer) { + Layer sublayer = (Layer) object; + sublayer.print (indent + 1); + } } } @@ -170,13 +194,7 @@ public override bool is_over (double x, double y) { return false; } - - public override void draw_outline (Context cr) { - foreach (Object object in objects) { - object.draw_outline (cr); - } - } - + public override void move (double dx, double dy) { }
--- a/libsvgbird/Object.vala +++ b/libsvgbird/Object.vala @@ -60,20 +60,6 @@ public abstract void update_region_boundaries (); public abstract bool is_over (double x, double y); public abstract void draw_outline (Context cr); - - public void draw (Context cr) { - cr.save (); - apply_transform (cr); - - if (clip_path != null) { - ClipPath clipping = (!) clip_path; - clipping.apply (cr); - } - - draw_outline (cr); - paint (cr); - cr.restore (); - } public abstract Object copy (); public abstract void move (double dx, double dy);
--- a/libsvgbird/ObjectGroup.vala +++ b/libsvgbird/ObjectGroup.vala @@ -25,6 +25,10 @@ public ObjectGroup () { objects = new Gee.ArrayList<Object> (); + } + + public int index_of (Object o) { + return objects.index_of (o); } public Gee.Iterator<Object> iterator () {
--- a/libsvgbird/PointValue.vala +++ b/libsvgbird/PointValue.vala @@ -20,10 +20,10 @@ double value; } - public static const uchar NONE = 0; - public static const uchar ARC = 1; - public static const uchar CUBIC = 2; - public static const uchar LINE = 3; + public static const uchar POINT_NONE = 0; + public static const uchar POINT_ARC = 1; + public static const uchar POINT_CUBIC = 2; + public static const uchar POINT_LINE = 3; }
--- a/libsvgbird/SvgDrawing.vala +++ b/libsvgbird/SvgDrawing.vala @@ -47,18 +47,13 @@ return (this.x <= x <= this.x + width) && (this.y <= y <= this.y + height); } - + + public void draw (Context cr) { + root_layer.draw (cr); + } + public override void draw_outline (Context cr) { - cr.save (); - cr.translate (x, y); root_layer.draw_outline (cr); - - // FIXME: update layer structure - foreach (Object o in root_layer.get_visible_objects ().objects) { - o.draw (cr); - } - - cr.restore (); } public override Object copy () {
--- a/libsvgbird/SvgFile.vala +++ b/libsvgbird/SvgFile.vala @@ -76,7 +76,7 @@ if (name == "g") { Layer sublayer = new Layer (); parse_layer (layer, parent_style, t); - layer.subgroups.add (sublayer); + layer.objects.add (sublayer); } if (name == "a") { @@ -648,7 +648,7 @@ points.x = bezier_points[i].x0; points.y = bezier_points[i].y0; } else { - points.add_type (LINE); + points.add_type (POINT_LINE); points.add (bezier_points[i].x0); points.add (bezier_points[i].y0); points.add (0); @@ -658,7 +658,7 @@ points.add (0); } } else if (bezier_points[i].type == 'C') { - points.add_type (CUBIC); + points.add_type (POINT_CUBIC); points.add (bezier_points[i].x0); points.add (bezier_points[i].y0); points.add (bezier_points[i].x1); @@ -667,7 +667,7 @@ points.add (bezier_points[i].y2); points.add (0); } else if (bezier_points[i].type == 'L') { - points.add_type (LINE); + points.add_type (POINT_LINE); points.add (bezier_points[i].x0); points.add (bezier_points[i].y0); points.add (0); @@ -688,7 +688,7 @@ out angle_start, out angle_extent, out center_x, out center_y); - points.add_type (ARC); + points.add_type (POINT_ARC); points.add (center_x); points.add (center_y); points.add (b.rx);
--- a/libsvgbird/SvgPath.vala +++ b/libsvgbird/SvgPath.vala @@ -49,18 +49,18 @@ for (int i = 0; i < size; i += 8) { switch (points[i].type) { - case ARC: + case POINT_ARC: draw_arc (cr, points[i + 1].value, points[i + 2].value, points[i + 3].value, points[i + 4].value, points[i + 5].value, points[i + 6].value, points[i + 7].value); break; - case CUBIC: + case POINT_CUBIC: cr.curve_to (points[i + 1].value, points[i + 2].value, points[i + 3].value, points[i + 4].value, points[i + 5].value, points[i + 6].value); break; - case LINE: + case POINT_LINE: cr.line_to (points[i + 1].value, points[i + 2].value); break; }
--- a/libsvgbird/SvgTransform.vala +++ b/libsvgbird/SvgTransform.vala @@ -30,7 +30,20 @@ public SvgTransform () { } - + + public string to_string () { + StringBuilder sb = new StringBuilder (); + + sb.append (@"$type"); + sb.append (" "); + + for (int i = 0; i < arguments.size; i++) { + sb.append (@"$(arguments.get_double (i)) "); + } + + return sb.str; + } + public Matrix get_matrix () { Matrix matrix;
--- a/libsvgbird/SvgTransforms.vala +++ b/libsvgbird/SvgTransforms.vala @@ -41,8 +41,19 @@ } return matrix; + } + + public string to_string () { + StringBuilder sb = new StringBuilder (); + + foreach (SvgTransform t in transforms) { + sb.append (t.to_string ()); + sb.append (" "); + } + + return sb.str; } } }