Merge branch 'expr-v2' of github.com:mapnik/mapnik into expr-v2-group-symbolizer

Conflicts:
	src/text/placement_finder.cpp
	tests/visual_tests/test.py
This commit is contained in:
Jordan Hollinger 2014-02-25 12:19:05 -05:00
commit 533820c63f
85 changed files with 2733 additions and 915 deletions

View file

@ -33,8 +33,8 @@
#include <mapnik/text/formatting/list.hpp> #include <mapnik/text/formatting/list.hpp>
#include <mapnik/text/formatting/format.hpp> #include <mapnik/text/formatting/format.hpp>
#include <mapnik/text/formatting/expression_format.hpp> #include <mapnik/text/formatting/expression_format.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/text/layout.hpp> #include <mapnik/text/layout.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/symbolizer.hpp> #include <mapnik/symbolizer.hpp>
#include "mapnik_enumeration.hpp" #include "mapnik_enumeration.hpp"
@ -224,6 +224,27 @@ struct ExprFormatWrap: formatting::expression_format, wrapper<formatting::expres
} }
}; };
struct LayoutNodeWrap: formatting::layout_node, wrapper<formatting::layout_node>
{
virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&output));
}
else
{
formatting::layout_node::apply(p, feature, output);
}
}
void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const
{
formatting::layout_node::apply(p, feature, output);
}
};
struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node> struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
{ {
//Default constructor //Default constructor

View file

@ -27,7 +27,6 @@
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/box2d.hpp> #include <mapnik/box2d.hpp>
#include <mapnik/font_set.hpp> #include <mapnik/font_set.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
#include <mapnik/value_types.hpp> #include <mapnik/value_types.hpp>
#include <mapnik/pixel_position.hpp> #include <mapnik/pixel_position.hpp>

View file

@ -247,6 +247,47 @@ double path_length(PathType & path)
return length; return length;
} }
template <typename PathType>
bool hit_test_first(PathType & path, double x, double y, double tol)
{
bool inside=false;
double x0 = 0;
double y0 = 0;
double x1 = 0;
double y1 = 0;
path.rewind(0);
unsigned command = path.vertex(&x0, &y0);
if (command == SEG_END)
{
return false;
}
unsigned count = 0;
mapnik::geometry_type::types geom_type = static_cast<mapnik::geometry_type::types>(path.type());
while (SEG_END != (command = path.vertex(&x1, &y1)))
{
if (command == SEG_CLOSE)
{
break;
}
++count;
if (command == SEG_MOVETO)
{
x0 = x1;
y0 = y1;
continue;
}
if ((((y1 <= y) && (y < y0)) ||
((y0 <= y) && (y < y1))) &&
(x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
inside=!inside;
x0 = x1;
y0 = y1;
}
return inside;
}
namespace label { namespace label {
template <typename PathType> template <typename PathType>

View file

@ -0,0 +1,59 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 Artem Pavlenko
*
* 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 2.1 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef FORMATTING_OFFSET_HPP
#define FORMATTING_OFFSET_HPP
#include <mapnik/text/formatting/base.hpp>
#include <mapnik/text/text_properties.hpp>
#include <boost/optional.hpp>
namespace mapnik {
namespace formatting {
class MAPNIK_DECL layout_node: public node {
public:
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const;
virtual void add_expressions(expression_set &output) const;
void set_child(node_ptr child);
node_ptr get_child() const;
boost::optional<double> dx;
boost::optional<double> dy;
boost::optional<horizontal_alignment_e> halign;
boost::optional<vertical_alignment_e> valign;
boost::optional<justify_alignment_e> jalign;
boost::optional<double> text_ratio;
boost::optional<double> wrap_width;
boost::optional<bool> wrap_before;
boost::optional<bool> rotate_displacement;
boost::optional<expression_ptr> orientation;
private:
node_ptr child_;
};
} //ns formatting
} //ns mapnik
#endif // FORMATTING_OFFSET_HPP

View file

@ -30,6 +30,7 @@
#include <mapnik/text/harfbuzz_shaper.hpp> #include <mapnik/text/harfbuzz_shaper.hpp>
#include <mapnik/text/icu_shaper.hpp> #include <mapnik/text/icu_shaper.hpp>
#include <mapnik/text/dummy_shaper.hpp> #include <mapnik/text/dummy_shaper.hpp>
#include <mapnik/text/rotation.hpp>
//stl //stl
#include <vector> #include <vector>
@ -38,13 +39,17 @@
namespace mapnik namespace mapnik
{ {
typedef std::shared_ptr<text_layout> text_layout_ptr;
typedef std::vector<text_layout_ptr> text_layout_vector;
class text_layout class text_layout
{ {
public: public:
typedef std::vector<text_line> line_vector; typedef std::vector<text_line> line_vector;
typedef line_vector::const_iterator const_iterator; typedef line_vector::const_iterator const_iterator;
typedef text_layout_vector::const_iterator child_iterator;
typedef harfbuzz_shaper shaper_type; typedef harfbuzz_shaper shaper_type;
text_layout(face_manager_freetype & font_manager, double scale_factor); text_layout(face_manager_freetype & font_manager, double scale_factor, text_layout_properties_ptr properties);
/** Adds a new text part. Call this function repeatedly to build the complete text. */ /** Adds a new text part. Call this function repeatedly to build the complete text. */
void add_text(mapnik::value_unicode_string const& str, char_properties_ptr format); void add_text(mapnik::value_unicode_string const& str, char_properties_ptr format);
@ -53,7 +58,7 @@ public:
mapnik::value_unicode_string const& text() const; mapnik::value_unicode_string const& text() const;
/** Processes the text into a list of glyphs, performing RTL/LTR handling, shaping and line breaking. */ /** Processes the text into a list of glyphs, performing RTL/LTR handling, shaping and line breaking. */
void layout(double wrap_width, unsigned text_ratio, bool wrap_before); void layout();
/** Clear all data stored in this object. The object's state is the same as directly after construction. */ /** Clear all data stored in this object. The object's state is the same as directly after construction. */
void clear(); void clear();
@ -81,11 +86,29 @@ public:
// Returns the number of glyphs so memory can be preallocated. // Returns the number of glyphs so memory can be preallocated.
inline unsigned glyphs_count() const { return glyphs_count_;} inline unsigned glyphs_count() const { return glyphs_count_;}
void add_child(text_layout_ptr child_layout);
inline const text_layout_vector &get_child_layouts() const { return child_layout_list_; }
inline face_manager<freetype_engine> &get_font_manager() const { return font_manager_; }
inline double get_scale_factor() const { return scale_factor_; }
inline text_layout_properties_ptr get_layout_properties() const { return properties_; }
inline rotation const& orientation() const { return orientation_; }
inline pixel_position const& displacement() const { return displacement_; }
inline box2d<double> const& bounds() const { return bounds_; }
pixel_position alignment_offset() const;
double jalign_offset(double line_width) const;
void init_orientation(feature_impl const& feature);
private: private:
void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before); void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before);
void shape_text(text_line & line); void shape_text(text_line & line);
void add_line(text_line & line); void add_line(text_line & line);
void clear_cluster_widths(unsigned first, unsigned last); void clear_cluster_widths(unsigned first, unsigned last);
void init_alignment();
//input //input
face_manager_freetype &font_manager_; face_manager_freetype &font_manager_;
@ -103,7 +126,60 @@ private:
//output //output
line_vector lines_; line_vector lines_;
//text layout properties
text_layout_properties_ptr properties_;
//alignments
vertical_alignment_e valign_;
horizontal_alignment_e halign_;
justify_alignment_e jalign_;
// Precalculated values for maximum performance
rotation orientation_;
pixel_position displacement_;
box2d<double> bounds_;
//children
text_layout_vector child_layout_list_;
}; };
class layout_container
{
public:
layout_container() : glyphs_count_(0), line_count_(0) {}
void add(text_layout_ptr layout);
void clear();
void layout();
inline size_t size() const { return layouts_.size(); }
inline text_layout_vector::const_iterator begin() const { return layouts_.begin(); }
inline text_layout_vector::const_iterator end() const { return layouts_.end(); }
inline mapnik::value_unicode_string const& text() const { return text_; }
inline unsigned glyphs_count() const { return glyphs_count_; }
inline unsigned line_count() const { return line_count_; }
inline box2d<double> const& bounds() const { return bounds_; }
inline double width() const { return bounds_.width(); }
inline double height() const { return bounds_.height(); }
private:
text_layout_vector layouts_;
mapnik::value_unicode_string text_;
unsigned glyphs_count_;
unsigned line_count_;
box2d<double> bounds_;
};
} }
#endif // TEXT_LAYOUT_HPP #endif // TEXT_LAYOUT_HPP

View file

@ -29,6 +29,7 @@
#include <mapnik/text/placements/base.hpp> #include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements_list.hpp> #include <mapnik/text/placements_list.hpp>
#include <mapnik/text/rotation.hpp> #include <mapnik/text/rotation.hpp>
#include <mapnik/text/vertex_cache.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
namespace mapnik namespace mapnik
@ -62,10 +63,6 @@ public:
void set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, pixel_position const& marker_displacement); void set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, pixel_position const& marker_displacement);
private: private:
void init_alignment();
pixel_position alignment_offset() const;
double jalign_offset(double line_width) const;
bool single_line_placement(vertex_cache &pp, text_upright_e orientation); bool single_line_placement(vertex_cache &pp, text_upright_e orientation);
/** Moves dx pixels but makes sure not to fall of the end. */ /** Moves dx pixels but makes sure not to fall of the end. */
void path_move_dx(vertex_cache &pp); void path_move_dx(vertex_cache &pp);
@ -80,23 +77,16 @@ private:
/** Maps upright==auto, left_only and right_only to left,right to simplify processing. /** Maps upright==auto, left_only and right_only to left,right to simplify processing.
angle = angle of at start of line (to estimate best option for upright==auto) */ angle = angle of at start of line (to estimate best option for upright==auto) */
text_upright_e simplify_upright(text_upright_e upright, double angle) const; text_upright_e simplify_upright(text_upright_e upright, double angle) const;
box2d<double> get_bbox(glyph_info const& glyph, pixel_position const& pos, rotation const& rot); box2d<double> get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot);
feature_impl const& feature_; feature_impl const& feature_;
DetectorType &detector_; DetectorType &detector_;
box2d<double> const& extent_; box2d<double> const& extent_;
// Precalculated values for maximum performance
rotation orientation_;
text_layout layout_;
text_placement_info_ptr info_; text_placement_info_ptr info_;
layout_container layouts_;
bool valid_; bool valid_;
vertical_alignment_e valign_;
/** Horizontal alignment for point placements. */
horizontal_alignment_e halign_point_;
/** Horizontal alignment for line placements. */
horizontal_alignment_e halign_line_;
justify_alignment_e jalign_;
double scale_factor_; double scale_factor_;
face_manager_freetype &font_manager_;
placements_list placements_; placements_list placements_;

View file

@ -15,8 +15,8 @@ struct rotation
void init(double angle) { sin = std::sin(angle); cos = std::cos(angle); } void init(double angle) { sin = std::sin(angle); cos = std::cos(angle); }
double sin; double sin;
double cos; double cos;
rotation operator~() { return rotation(sin, -cos); } rotation operator~() const { return rotation(sin, -cos); }
rotation operator!() { return rotation(-sin, cos); } rotation operator!() const { return rotation(-sin, cos); }
}; };
} }

View file

@ -135,7 +135,7 @@ DEFINE_ENUM(text_upright_e, text_upright);
/** Properties for building the layout of a single text placement */ /** Properties for building the layout of a single text placement */
struct MAPNIK_DECL text_layout_properties struct MAPNIK_DECL text_layout_properties
{ {
text_layout_properties(); text_layout_properties();
/** Load all values from XML ptree. */ /** Load all values from XML ptree. */
void from_xml(xml_node const &sym); void from_xml(xml_node const &sym);

View file

@ -1,151 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* 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 2.1 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_TEXT_SYMBOLIZER_HPP
#define MAPNIK_TEXT_SYMBOLIZER_HPP
// mapnik
/*
#include <mapnik/color.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements/dummy.hpp>
// boost
#include <memory>
// stl
#include <string>
#if (!defined(NO_DEPRECATION_WARNINGS) && __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define func_deprecated __attribute__ ((deprecated))
#else
#define func_deprecated
#endif
namespace mapnik
{
enum halo_rasterizer_enum
{
HALO_RASTERIZER_FULL,
HALO_RASTERIZER_FAST,
halo_rasterizer_enum_MAX
};
DEFINE_ENUM(halo_rasterizer_e, halo_rasterizer_enum);
struct MAPNIK_DECL text_symbolizer : public symbolizer_base
{
// Note - we do not use std::make_shared below as VC2008 and VC2010 are
// not able to compile make_shared used within a constructor
text_symbolizer(text_placements_ptr placements = text_placements_ptr(new text_placements_dummy));
text_symbolizer(expression_ptr name, std::string const& face_name,
double size, color const& fill,
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy)
);
text_symbolizer(expression_ptr name, double size, color const& fill,
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy)
);
text_symbolizer(text_symbolizer const& rhs);
text_symbolizer& operator=(text_symbolizer const& rhs);
expression_ptr get_name() const func_deprecated;
void set_name(expression_ptr expr);
expression_ptr get_orientation() const func_deprecated; // orienation (rotation angle atm)
void set_orientation(expression_ptr expr);
double get_text_ratio() const func_deprecated; // target ratio for text bounding box in pixels
void set_text_ratio(double ratio);
double get_wrap_width() const func_deprecated; // width to wrap text at, or trigger ratio
void set_wrap_width(double width);
unsigned char get_wrap_char() const func_deprecated; // character used to wrap lines
std::string get_wrap_char_string() const func_deprecated; // character used to wrap lines as std::string
void set_wrap_char(unsigned char character);
void set_wrap_char_from_string(std::string const& character);
text_transform_e get_text_transform() const func_deprecated; // text conversion on strings before display
void set_text_transform(text_transform_e convert);
double get_line_spacing() const func_deprecated; // spacing between lines of text
void set_line_spacing(double spacing);
double get_character_spacing() const func_deprecated; // spacing between characters in text
void set_character_spacing(double spacing);
double get_label_spacing() const func_deprecated; // spacing between repeated labels on lines
void set_label_spacing(double spacing);
unsigned get_label_position_tolerance() const func_deprecated; //distance the label can be moved on the line to fit, if 0 the default is used
void set_label_position_tolerance(unsigned tolerance);
bool get_force_odd_labels() const func_deprecated; // try render an odd amount of labels
void set_force_odd_labels(bool force);
double get_max_char_angle_delta() const func_deprecated; // maximum change in angle between adjacent characters
void set_max_char_angle_delta(double angle);
double get_text_size() const func_deprecated;
void set_text_size(double size);
std::string const& get_face_name() const func_deprecated;
void set_face_name(std::string face_name);
boost::optional<font_set> const& get_fontset() const func_deprecated;
void set_fontset(font_set const& fset);
color const& get_fill() const func_deprecated;
void set_fill(color const& fill);
void set_halo_fill(color const& fill);
color const& get_halo_fill() const func_deprecated;
void set_halo_radius(double radius);
double get_halo_radius() const func_deprecated;
void set_halo_rasterizer(halo_rasterizer_e rasterizer_p);
halo_rasterizer_e get_halo_rasterizer() const;
void set_label_placement(label_placement_e label_p);
label_placement_e get_label_placement() const func_deprecated;
void set_vertical_alignment(vertical_alignment_e valign);
vertical_alignment_e get_vertical_alignment() const func_deprecated;
void set_displacement(double x, double y);
void set_displacement(pixel_position const& p);
pixel_position const& get_displacement() const func_deprecated;
void set_avoid_edges(bool avoid);
bool get_avoid_edges() const func_deprecated;
void set_minimum_distance(double distance);
double get_minimum_distance() const func_deprecated;
void set_minimum_padding(double distance);
double get_minimum_padding() const func_deprecated;
void set_minimum_path_length(double size);
double get_minimum_path_length() const;
void set_allow_overlap(bool overlap);
bool get_allow_overlap() const func_deprecated;
void set_text_opacity(double opacity);
double get_text_opacity() const func_deprecated;
void set_wrap_before(bool wrap_before);
bool get_wrap_before() const func_deprecated; // wrap text at wrap_char immediately before current work
void set_horizontal_alignment(horizontal_alignment_e valign);
horizontal_alignment_e get_horizontal_alignment() const func_deprecated;
void set_justify_alignment(justify_alignment_e valign);
justify_alignment_e get_justify_alignment() const func_deprecated;
text_placements_ptr get_placement_options() const;
void set_placement_options(text_placements_ptr placement_options);
void set_largest_bbox_only(bool val);
bool largest_bbox_only() const;
private:
text_placements_ptr placement_options_;
halo_rasterizer_e halo_rasterizer_;
};
}
*/
#endif // MAPNIK_TEXT_SYMBOLIZER_HPP

View file

@ -180,12 +180,14 @@ template <typename T>
struct converter_traits<T,mapnik::clip_poly_tag> struct converter_traits<T,mapnik::clip_poly_tag>
{ {
typedef T geometry_type; typedef T geometry_type;
typedef mapnik::polygon_clipper<geometry_type> conv_type; //typedef mapnik::polygon_clipper<geometry_type> conv_type;
typedef typename agg::conv_clip_polygon<geometry_type> conv_type;
template <typename Args> template <typename Args>
static void setup(geometry_type & geom, Args const& args) static void setup(geometry_type & geom, Args const& args)
{ {
typename boost::mpl::at<Args,boost::mpl::int_<0> >::type box = boost::fusion::at_c<0>(args); typename boost::mpl::at<Args,boost::mpl::int_<0> >::type box = boost::fusion::at_c<0>(args);
geom.set_clip_box(box); geom.clip_box(box.minx(),box.miny(),box.maxx(),box.maxy());
//geom.set_clip_box(box);
} }
}; };

View file

@ -25,12 +25,13 @@
// mapnik // mapnik
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
#include <mapnik/datasource.hpp> #include <mapnik/datasource.hpp>
#include <mapnik/geom_util.hpp>
// boost // boost
using mapnik::datasource_exception; using mapnik::datasource_exception;
using mapnik::geometry_type; using mapnik::geometry_type;
using mapnik::hit_test_first;
const std::string shape_io::SHP = ".shp"; const std::string shape_io::SHP = ".shp";
const std::string shape_io::DBF = ".dbf"; const std::string shape_io::DBF = ".dbf";
const std::string shape_io::INDEX = ".index"; const std::string shape_io::INDEX = ".index";
@ -156,9 +157,9 @@ void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_c
parts[i] = record.read_ndr_integer(); parts[i] = record.read_ndr_integer();
} }
std::unique_ptr<geometry_type> poly(new geometry_type(mapnik::geometry_type::types::Polygon));
for (int k = 0; k < num_parts; ++k) for (int k = 0; k < num_parts; ++k)
{ {
std::unique_ptr<geometry_type> poly(new geometry_type(mapnik::geometry_type::types::Polygon));
int start = parts[k]; int start = parts[k];
int end; int end;
if (k == num_parts - 1) if (k == num_parts - 1)
@ -172,14 +173,19 @@ void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_c
double x = record.read_double(); double x = record.read_double();
double y = record.read_double(); double y = record.read_double();
if (k > 0 && !hit_test_first(*poly, x, y, 0))
{
geom.push_back(poly.release());
poly.reset(new geometry_type(mapnik::geometry_type::types::Polygon));
}
poly->move_to(x, y); poly->move_to(x, y);
for (int j=start+1;j<end;j++) for (int j = start + 1; j < end; ++j)
{ {
x = record.read_double(); x = record.read_double();
y = record.read_double(); y = record.read_double();
poly->line_to(x, y); poly->line_to(x, y);
} }
poly->close_path(); poly->close_path();
geom.push_back(poly.release());
} }
geom.push_back(poly.release());
} }

View file

@ -226,6 +226,7 @@ source = Split(
text/formatting/list.cpp text/formatting/list.cpp
text/formatting/text.cpp text/formatting/text.cpp
text/formatting/format.cpp text/formatting/format.cpp
text/formatting/layout.cpp
text/formatting/registry.cpp text/formatting/registry.cpp
text/placements/registry.cpp text/placements/registry.cpp
text/placements/base.cpp text/placements/base.cpp

View file

@ -0,0 +1,125 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2012 Artem Pavlenko
*
* 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 2.1 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/text/text_properties.hpp>
#include <mapnik/text/layout.hpp>
#include <mapnik/debug.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/ptree_helpers.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/symbolizer.hpp>
// boost
#include <boost/property_tree/ptree.hpp>
namespace mapnik {
namespace formatting {
using boost::property_tree::ptree;
void layout_node::to_xml(ptree &xml) const
{
ptree &new_node = xml.push_back(ptree::value_type("Layout", ptree()))->second;
if (dx) set_attr(new_node, "dx", *dx);
if (dy) set_attr(new_node, "dy", *dy);
if (halign) set_attr(new_node, "horizontal-alignment", *halign);
if (valign) set_attr(new_node, "vertical-alignment", *valign);
if (jalign) set_attr(new_node, "justify-alignment", *jalign);
if (text_ratio) set_attr(new_node, "text-ratio", *text_ratio);
if (wrap_width) set_attr(new_node, "wrap-width", *wrap_width);
if (wrap_before) set_attr(new_node, "wrap-before", *wrap_before);
if (rotate_displacement) set_attr(new_node, "rotate-displacement", *rotate_displacement);
if (orientation) set_attr(new_node, "orientation", to_expression_string(**orientation));
if (child_) child_->to_xml(new_node);
}
node_ptr layout_node::from_xml(xml_node const& xml)
{
std::shared_ptr<layout_node> n = std::make_shared<layout_node>();
node_ptr child = node::from_xml(xml);
n->set_child(child);
n->dx = xml.get_opt_attr<double>("dx");
n->dy = xml.get_opt_attr<double>("dy");
n->halign = xml.get_opt_attr<horizontal_alignment_e>("horizontal-alignment");
n->valign = xml.get_opt_attr<vertical_alignment_e>("vertical-alignment");
n->jalign = xml.get_opt_attr<justify_alignment_e>("justify-alignment");
n->text_ratio = xml.get_opt_attr<double>("text-ratio");
n->wrap_width = xml.get_opt_attr<double>("wrap-width");
n->wrap_before = xml.get_opt_attr<boolean>("wrap-before");
n->rotate_displacement = xml.get_opt_attr<boolean>("rotate-displacement");
n->orientation = xml.get_opt_attr<expression_ptr>("orientation");
return n;
}
void layout_node::apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const
{
text_layout_properties_ptr new_properties = std::make_shared<text_layout_properties>(*output.get_layout_properties());
if (dx) new_properties->displacement.x = *dx;
if (dy) new_properties->displacement.y = *dy;
if (halign) new_properties->halign = *halign;
if (valign) new_properties->valign = *valign;
if (jalign) new_properties->jalign = *jalign;
if (text_ratio) new_properties->text_ratio = *text_ratio;
if (wrap_width) new_properties->wrap_width = *wrap_width;
if (wrap_before) new_properties->wrap_before = *wrap_before;
if (rotate_displacement) new_properties->rotate_displacement = *rotate_displacement;
if (orientation) new_properties->orientation = *orientation;
// starting a new offset child with the new displacement value
text_layout_ptr child_layout = std::make_shared<text_layout>(output.get_font_manager(), output.get_scale_factor(), new_properties);
child_layout->init_orientation(feature);
// process contained format tree into the child node
if (child_) {
child_->apply(p, feature, *child_layout);
} else {
MAPNIK_LOG_WARN(format) << "Useless layout node: Contains no text";
}
output.add_child(child_layout);
}
void layout_node::set_child(node_ptr child)
{
child_ = child;
}
node_ptr layout_node::get_child() const
{
return child_;
}
void layout_node::add_expressions(expression_set &output) const
{
if (child_) child_->add_expressions(output);
}
} //ns formatting
} //ns mapnik

View file

@ -24,6 +24,7 @@
#include <mapnik/text/formatting/text.hpp> #include <mapnik/text/formatting/text.hpp>
#include <mapnik/text/formatting/format.hpp> #include <mapnik/text/formatting/format.hpp>
#include <mapnik/text/formatting/expression_format.hpp> #include <mapnik/text/formatting/expression_format.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/xml_node.hpp> #include <mapnik/xml_node.hpp>
#include <mapnik/config_error.hpp> #include <mapnik/config_error.hpp>
@ -37,6 +38,7 @@ registry::registry()
register_name("<xmltext>", &text_node::from_xml); register_name("<xmltext>", &text_node::from_xml);
register_name("Format", &format_node::from_xml); register_name("Format", &format_node::from_xml);
register_name("ExpressionFormat", &expression_format::from_xml); register_name("ExpressionFormat", &expression_format::from_xml);
register_name("Layout", &layout_node::from_xml);
} }
void registry::register_name(std::string const& name, from_xml_function_ptr ptr, bool overwrite) void registry::register_name(std::string const& name, from_xml_function_ptr ptr, bool overwrite)

View file

@ -22,6 +22,7 @@
#include <mapnik/text/layout.hpp> #include <mapnik/text/layout.hpp>
#include <mapnik/text/text_properties.hpp> #include <mapnik/text/text_properties.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
// ICU // ICU
@ -30,7 +31,29 @@
namespace mapnik namespace mapnik
{ {
text_layout::text_layout(face_manager_freetype & font_manager, double scale_factor) // Output is centered around (0,0)
static void rotated_box2d(box2d<double> & box, rotation const& rot, pixel_position const& center, double width, double height)
{
double half_width, half_height;
if (rot.sin == 0 && rot.cos == 1.)
{
half_width = width / 2.;
half_height = height / 2.;
}
else
{
half_width = (width * rot.cos + height * rot.sin) /2.;
half_height = (width * rot.sin + height * rot.cos) /2.;
}
box.init(center.x - half_width, center.y - half_height, center.x + half_width, center.y + half_height);
}
pixel_position pixel_position::rotate(rotation const& rot) const
{
return pixel_position(x * rot.cos - y * rot.sin, x * rot.sin + y * rot.cos);
}
text_layout::text_layout(face_manager_freetype & font_manager, double scale_factor, text_layout_properties_ptr properties)
: font_manager_(font_manager), : font_manager_(font_manager),
scale_factor_(scale_factor), scale_factor_(scale_factor),
itemizer_(), itemizer_(),
@ -38,7 +61,8 @@ text_layout::text_layout(face_manager_freetype & font_manager, double scale_fact
width_(0.0), width_(0.0),
height_(0.0), height_(0.0),
glyphs_count_(0), glyphs_count_(0),
lines_() lines_(),
properties_(properties)
{ {
} }
@ -47,20 +71,34 @@ void text_layout::add_text(mapnik::value_unicode_string const& str, char_propert
itemizer_.add_text(str, format); itemizer_.add_text(str, format);
} }
void text_layout::add_child(text_layout_ptr child_layout)
{
child_layout_list_.push_back(child_layout);
}
mapnik::value_unicode_string const& text_layout::text() const mapnik::value_unicode_string const& text_layout::text() const
{ {
return itemizer_.text(); return itemizer_.text();
} }
void text_layout::layout(double wrap_width, unsigned text_ratio, bool wrap_before) void text_layout::layout()
{ {
unsigned num_lines = itemizer_.num_lines(); unsigned num_lines = itemizer_.num_lines();
for (unsigned i = 0; i < num_lines; ++i) for (unsigned i = 0; i < num_lines; ++i)
{ {
std::pair<unsigned, unsigned> line_limits = itemizer_.line(i); std::pair<unsigned, unsigned> line_limits = itemizer_.line(i);
text_line line(line_limits.first, line_limits.second); text_line line(line_limits.first, line_limits.second);
break_line(line, wrap_width, text_ratio, wrap_before); //Break line if neccessary //Break line if neccessary
break_line(line, properties_->wrap_width * scale_factor_, properties_->text_ratio, properties_->wrap_before);
} }
init_alignment();
/* Find text origin. */
displacement_ = scale_factor_ * properties_->displacement + alignment_offset();
if (properties_->rotate_displacement) displacement_ = displacement_.rotate(!orientation_);
/* Find layout bounds, expanded for rotation */
rotated_box2d(bounds_, orientation_, displacement_, width_, height_);
} }
/* In the Unicode string characters are always stored in logical order. /* In the Unicode string characters are always stored in logical order.
@ -189,6 +227,7 @@ void text_layout::clear()
width_map_.clear(); width_map_.clear();
width_ = 0.; width_ = 0.;
height_ = 0.; height_ = 0.;
child_layout_list_.clear();
} }
void text_layout::shape_text(text_line & line) void text_layout::shape_text(text_line & line)
@ -196,5 +235,155 @@ void text_layout::shape_text(text_line & line)
shaper_type::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_); shaper_type::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_);
} }
void text_layout::init_orientation(feature_impl const& feature)
{
if (properties_->orientation)
{
// https://github.com/mapnik/mapnik/issues/1352
mapnik::evaluate<feature_impl, value_type> evaluator(feature);
orientation_.init(
boost::apply_visitor(
evaluator,
*(properties_->orientation)).to_double() * M_PI / 180.0);
}
else
{
orientation_.reset();
}
}
void text_layout::init_alignment()
{
text_layout_properties const& p = *(properties_);
valign_ = p.valign;
if (valign_ == V_AUTO)
{
if (p.displacement.y > 0.0)
{
valign_ = V_BOTTOM;
}
else if (p.displacement.y < 0.0)
{
valign_ = V_TOP;
}
else
{
valign_ = V_MIDDLE;
}
}
halign_ = p.halign;
if (halign_ == H_AUTO)
{
if (p.displacement.x > 0.0)
{
halign_ = H_RIGHT;
}
else if (p.displacement.x < 0.0)
{
halign_ = H_LEFT;
}
else
{
halign_ = H_MIDDLE;
}
}
jalign_ = p.jalign;
if (jalign_ == J_AUTO)
{
if (p.displacement.x > 0.0)
{
jalign_ = J_LEFT;
}
else if (p.displacement.x < 0.0)
{
jalign_ = J_RIGHT;
}
else
{
jalign_ = J_MIDDLE;
}
}
}
pixel_position text_layout::alignment_offset() const
{
pixel_position result(0,0);
// if needed, adjust for desired vertical alignment
if (valign_ == V_TOP)
{
result.y = -0.5 * height(); // move center up by 1/2 the total height
}
else if (valign_ == V_BOTTOM)
{
result.y = 0.5 * height(); // move center down by the 1/2 the total height
}
// set horizontal position to middle of text
if (halign_ == H_LEFT)
{
result.x = -0.5 * width(); // move center left by 1/2 the string width
}
else if (halign_ == H_RIGHT)
{
result.x = 0.5 * width(); // move center right by 1/2 the string width
}
return result;
}
double text_layout::jalign_offset(double line_width) const
{
if (jalign_ == J_MIDDLE) return -(line_width / 2.0);
if (jalign_ == J_LEFT) return -(width() / 2.0);
if (jalign_ == J_RIGHT) return (width() / 2.0) - line_width;
return 0;
}
void layout_container::add(text_layout_ptr layout)
{
text_ += layout->text();
layouts_.push_back(layout);
for (text_layout_ptr const& child_layout : layout->get_child_layouts())
{
add(child_layout);
}
}
void layout_container::layout()
{
bounds_.init(0,0,0,0);
glyphs_count_ = 0;
line_count_ = 0;
bool first = true;
for (text_layout_ptr const& layout : layouts_)
{
layout->layout();
glyphs_count_ += layout->glyphs_count();
line_count_ += layout->num_lines();
if (first)
{
bounds_ = layout->bounds();
first = false;
}
else
{
bounds_.expand_to_include(layout->bounds());
}
}
}
void layout_container::clear()
{
layouts_.clear();
text_.remove();
bounds_.init(0,0,0,0);
glyphs_count_ = 0;
line_count_ = 0;
}
} //ns mapnik } //ns mapnik

View file

@ -40,19 +40,6 @@
namespace mapnik namespace mapnik
{ {
// Output is centered around (0,0)
static void rotated_box2d(box2d<double> & box, rotation const& rot, double width, double height)
{
double new_width = width * rot.cos + height * rot.sin;
double new_height = width * rot.sin + height * rot.cos;
box.init(-new_width/2., -new_height/2., new_width/2., new_height/2.);
}
pixel_position pixel_position::rotate(rotation const& rot) const
{
return pixel_position(x * rot.cos - y * rot.sin, x * rot.sin + y * rot.cos);
}
placement_finder::placement_finder(feature_impl const& feature, placement_finder::placement_finder(feature_impl const& feature,
DetectorType &detector, DetectorType &detector,
box2d<double> const& extent, box2d<double> const& extent,
@ -62,10 +49,10 @@ placement_finder::placement_finder(feature_impl const& feature,
: feature_(feature), : feature_(feature),
detector_(detector), detector_(detector),
extent_(extent), extent_(extent),
layout_(font_manager, scale_factor),
info_(placement_info), info_(placement_info),
valid_(true), valid_(true),
scale_factor_(scale_factor), scale_factor_(scale_factor),
font_manager_(font_manager),
placements_(), placements_(),
has_marker_(false), has_marker_(false),
marker_(), marker_(),
@ -86,173 +73,113 @@ bool placement_finder::next_position()
return false; return false;
} }
info_->properties.process(layout_, feature_); text_layout_ptr layout = std::make_shared<text_layout>(font_manager_, scale_factor_, info_->properties.layout_defaults);
layout_.layout(info_->properties.layout_defaults->wrap_width * scale_factor_, info_->properties.layout_defaults->text_ratio, info_->properties.layout_defaults->wrap_before); layout->init_orientation(feature_);
info_->properties.process(*layout, feature_);
layouts_.clear();
layouts_.add(layout);
layouts_.layout();
if (info_->properties.layout_defaults->orientation)
{
// https://github.com/mapnik/mapnik/issues/1352
mapnik::evaluate<feature_impl, value_type> evaluator(feature_);
orientation_.init(
boost::apply_visitor(
evaluator,
*(info_->properties.layout_defaults->orientation)).to_double() * M_PI / 180.0);
}
else
{
orientation_.reset();
}
init_alignment();
return true; return true;
} }
void placement_finder::init_alignment() text_upright_e placement_finder::simplify_upright(text_upright_e upright, double angle) const
{ {
text_layout_properties const& p = *(info_->properties.layout_defaults); if (upright == UPRIGHT_AUTO)
valign_ = p.valign;
if (valign_ == V_AUTO)
{ {
if (p.displacement.y > 0.0) return (std::fabs(normalize_angle(angle)) > 0.5*M_PI) ? UPRIGHT_LEFT : UPRIGHT_RIGHT;
{
valign_ = V_BOTTOM;
}
else if (p.displacement.y < 0.0)
{
valign_ = V_TOP;
}
else
{
valign_ = V_MIDDLE;
}
} }
if (upright == UPRIGHT_LEFT_ONLY)
halign_point_ = p.halign;
halign_line_ = p.halign;
if (halign_point_ == H_AUTO)
{ {
if (p.displacement.x > 0.0) return UPRIGHT_LEFT;
{
halign_point_ = H_RIGHT;
halign_line_ = H_LEFT;
}
else if (p.displacement.x < 0.0)
{
halign_point_ = H_LEFT;
halign_line_= H_RIGHT;
}
else
{
halign_point_ = H_MIDDLE;
halign_line_ = H_MIDDLE;
}
} }
if (upright == UPRIGHT_RIGHT_ONLY)
jalign_ = p.jalign;
if (jalign_ == J_AUTO)
{ {
if (p.displacement.x > 0.0) return UPRIGHT_RIGHT;
{
jalign_ = J_LEFT;
}
else if (p.displacement.x < 0.0)
{
jalign_ = J_RIGHT;
}
else
{
jalign_ = J_MIDDLE;
}
} }
} return upright;
pixel_position placement_finder::alignment_offset() const //TODO
{
pixel_position result(0,0);
// if needed, adjust for desired vertical alignment
if (valign_ == V_TOP)
{
result.y = -0.5 * layout_.height(); // move center up by 1/2 the total height
}
else if (valign_ == V_BOTTOM)
{
result.y = 0.5 * layout_.height(); // move center down by the 1/2 the total height
}
// set horizontal position to middle of text
if (halign_point_ == H_LEFT)
{
result.x = -0.5 * layout_.width(); // move center left by 1/2 the string width
}
else if (halign_point_ == H_RIGHT)
{
result.x = 0.5 * layout_.width(); // move center right by 1/2 the string width
}
return result;
}
double placement_finder::jalign_offset(double line_width) const //TODO
{
if (jalign_ == J_MIDDLE) return -(line_width / 2.0);
if (jalign_ == J_LEFT) return -(layout_.width() / 2.0);
if (jalign_ == J_RIGHT) return (layout_.width() / 2.0) - line_width;
return 0;
} }
bool placement_finder::find_point_placement(pixel_position const& pos) bool placement_finder::find_point_placement(pixel_position const& pos)
{ {
glyph_positions_ptr glyphs = std::make_shared<glyph_positions>(); glyph_positions_ptr glyphs = std::make_shared<glyph_positions>();
std::vector<box2d<double> > bboxes;
/* Find text origin. */ glyphs->reserve(layouts_.glyphs_count());
pixel_position displacement = scale_factor_ * info_->properties.layout_defaults->displacement + alignment_offset(); bboxes.reserve(layouts_.size());
if (info_->properties.layout_defaults->rotate_displacement) displacement = displacement.rotate(!orientation_);
glyphs->set_base_point(pos + displacement);
box2d<double> bbox;
rotated_box2d(bbox, orientation_, layout_.width(), layout_.height());
bbox.re_center(glyphs->get_base_point().x, glyphs->get_base_point().y);
/* For point placements it is faster to just check the bounding box. */ bool base_point_set = false;
if (collision(bbox)) return false; for (auto const& layout_ptr : layouts_)
/* add_marker first checks for collision and then updates the detector.*/
if (has_marker_ && !add_marker(glyphs, pos)) return false;
if (layout_.num_lines()) detector_.insert(bbox, layout_.text());
/* IMPORTANT NOTE:
x and y are relative to the center of the text
coordinate system:
x: grows from left to right
y: grows from bottom to top (opposite of normal computer graphics)
*/
double x, y;
// set for upper left corner of text envelope for the first line, top left of first character
y = layout_.height() / 2.0;
glyphs->reserve(layout_.glyphs_count());
for ( auto const& line : layout_)
{ {
y -= line.height(); //Automatically handles first line differently text_layout const& layout = *layout_ptr;
x = jalign_offset(line.width()); rotation const& orientation = layout.orientation();
for (auto const& glyph : line) /* Find text origin. */
pixel_position layout_center = pos + layout.displacement();
if (!base_point_set)
{ {
// place the character relative to the center of the string envelope glyphs->set_base_point(layout_center);
glyphs->push_back(glyph, pixel_position(x, y).rotate(orientation_), orientation_); base_point_set = true;
if (glyph.width) }
box2d<double> bbox = layout.bounds();
bbox.re_center(layout_center.x, layout_center.y);
/* For point placements it is faster to just check the bounding box. */
if (collision(bbox)) return false;
if (layout.num_lines()) bboxes.push_back(std::move(bbox));
pixel_position layout_offset = layout_center - glyphs->get_base_point();
layout_offset.y = -layout_offset.y;
/* IMPORTANT NOTE:
x and y are relative to the center of the text
coordinate system:
x: grows from left to right
y: grows from bottom to top (opposite of normal computer graphics)
*/
double x, y;
// set for upper left corner of text envelope for the first line, top left of first character
y = layout.height() / 2.0;
for ( auto const& line : layout)
{
y -= line.height(); //Automatically handles first line differently
x = layout.jalign_offset(line.width());
for (auto const& glyph : line)
{ {
//Only advance if glyph is not part of a multiple glyph sequence // place the character relative to the center of the string envelope
x += glyph.width + glyph.format->character_spacing * scale_factor_; glyphs->push_back(glyph, (pixel_position(x, y).rotate(orientation)) + layout_offset, orientation);
if (glyph.width)
{
//Only advance if glyph is not part of a multiple glyph sequence
x += glyph.width + glyph.format->character_spacing * scale_factor_;
}
} }
} }
} }
/* add_marker first checks for collision and then updates the detector.*/
if (has_marker_ && !add_marker(glyphs, pos)) return false;
for (box2d<double> const& bbox : bboxes)
{
detector_.insert(bbox, layouts_.text());
}
placements_.push_back(glyphs); placements_.push_back(glyphs);
return true; return true;
} }
template <typename T> template <typename T>
bool placement_finder::find_line_placements(T & path, bool points) bool placement_finder::find_line_placements(T & path, bool points)
{ {
if (!layout_.num_lines()) return true; //TODO if (!layouts_.line_count()) return true; //TODO
vertex_cache pp(path); vertex_cache pp(path);
bool success = false; bool success = false;
@ -272,13 +199,13 @@ bool placement_finder::find_line_placements(T & path, bool points)
|| ||
(pp.length() <= 0.001) /* Clipping removed whole geometry */ (pp.length() <= 0.001) /* Clipping removed whole geometry */
|| ||
(pp.length() < layout_.width())) (pp.length() < layouts_.width()))
{ {
continue; continue;
} }
} }
double spacing = get_spacing(pp.length(), points ? 0. : layout_.width()); double spacing = get_spacing(pp.length(), points ? 0. : layouts_.width());
horizontal_alignment_e halign = info_->properties.layout_defaults->halign; horizontal_alignment_e halign = info_->properties.layout_defaults->halign;
if (halign == H_LEFT) if (halign == H_LEFT)
@ -314,119 +241,110 @@ bool placement_finder::find_line_placements(T & path, bool points)
return success; return success;
} }
text_upright_e placement_finder::simplify_upright(text_upright_e upright, double angle) const
{
if (upright == UPRIGHT_AUTO)
{
return (std::fabs(normalize_angle(angle)) > 0.5*M_PI) ? UPRIGHT_LEFT : UPRIGHT_RIGHT;
}
if (upright == UPRIGHT_LEFT_ONLY)
{
return UPRIGHT_LEFT;
}
if (upright == UPRIGHT_RIGHT_ONLY)
{
return UPRIGHT_RIGHT;
}
return upright;
}
bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e orientation) bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e orientation)
{ {
/******************************************************************************** /********************************************************************************
* IMPORTANT NOTE: See note about coordinate systems in find_point_placement()! * * IMPORTANT NOTE: See note about coordinate systems in find_point_placement()! *
********************************************************************************/ ********************************************************************************/
vertex_cache::scoped_state s(pp); vertex_cache::scoped_state begin(pp);
text_upright_e real_orientation = simplify_upright(orientation, pp.angle());
glyph_positions_ptr glyphs = std::make_shared<glyph_positions>(); glyph_positions_ptr glyphs = std::make_shared<glyph_positions>();
std::vector<box2d<double> > bboxes; std::vector<box2d<double> > bboxes;
bboxes.reserve(layout_.text().length()); glyphs->reserve(layouts_.glyphs_count());
int upside_down_glyph_count = 0; bboxes.reserve(layouts_.glyphs_count());
text_upright_e real_orientation = simplify_upright(orientation, pp.angle()); unsigned upside_down_glyph_count = 0;
double sign = (real_orientation == UPRIGHT_LEFT) ? -1 : 1; for (auto const& layout_ptr : layouts_)
double offset = alignment_offset().y + info_->properties.layout_defaults->displacement.y * scale_factor_ + sign * layout_.height()/2.;
glyphs->reserve(layout_.glyphs_count());
for (auto const& line : layout_)
{ {
//Only subtract half the line height here and half at the end because text is automatically text_layout const& layout = *layout_ptr;
//centered on the line pixel_position align_offset = layout.alignment_offset();
offset -= sign * line.height()/2; pixel_position const& layout_displacement = layout.get_layout_properties()->displacement;
vertex_cache & off_pp = pp.get_offseted(offset, sign*layout_.width()); double sign = (real_orientation == UPRIGHT_LEFT) ? -1 : 1;
vertex_cache::scoped_state off_state(off_pp); //TODO: Remove this when a clean implementation in vertex_cache::get_offseted was done double offset = align_offset.y + layout_displacement.y * scale_factor_ + sign * layout.height()/2.;
if (!off_pp.move(sign * jalign_offset(line.width()) - alignment_offset().x)) return false; for (auto const& line : layout)
double last_cluster_angle = 999;
int current_cluster = -1;
pixel_position cluster_offset;
double angle;
rotation rot;
double last_glyph_spacing = 0.;
for (auto const& glyph : line)
{ {
if (current_cluster != static_cast<int>(glyph.char_index)) //Only subtract half the line height here and half at the end because text is automatically
//centered on the line
offset -= sign * line.height()/2;
vertex_cache & off_pp = pp.get_offseted(offset, sign*layout.width());
vertex_cache::scoped_state off_state(off_pp); //TODO: Remove this when a clean implementation in vertex_cache::get_offseted was done
if (!off_pp.move(sign * layout.jalign_offset(line.width()) - align_offset.x)) return false;
double last_cluster_angle = 999;
int current_cluster = -1;
pixel_position cluster_offset;
double angle;
rotation rot;
double last_glyph_spacing = 0.;
for (auto const& glyph : line)
{ {
if (!off_pp.move(sign * (layout_.cluster_width(current_cluster) + last_glyph_spacing))) if (current_cluster != static_cast<int>(glyph.char_index))
{ {
return false; if (!off_pp.move(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
{
return false;
}
current_cluster = glyph.char_index;
last_glyph_spacing = glyph.format->character_spacing * scale_factor_;
//Only calculate new angle at the start of each cluster!
angle = normalize_angle(off_pp.angle(sign * layout.cluster_width(current_cluster)));
rot.init(angle);
if ((info_->properties.max_char_angle_delta > 0) && (last_cluster_angle != 999) &&
std::fabs(normalize_angle(angle-last_cluster_angle)) > info_->properties.max_char_angle_delta)
{
return false;
}
cluster_offset.clear();
last_cluster_angle = angle;
} }
current_cluster = glyph.char_index;
last_glyph_spacing = glyph.format->character_spacing * scale_factor_; if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count;
//Only calculate new angle at the start of each cluster!
angle = normalize_angle(off_pp.angle(sign * layout_.cluster_width(current_cluster))); pixel_position pos = off_pp.current_position() + cluster_offset;
rot.init(angle); //Center the text on the line
if ((info_->properties.max_char_angle_delta > 0) && (last_cluster_angle != 999) && double char_height = line.max_char_height();
std::fabs(normalize_angle(angle-last_cluster_angle)) > info_->properties.max_char_angle_delta) pos.y = -pos.y - char_height/2.0*rot.cos;
{ pos.x = pos.x + char_height/2.0*rot.sin;
return false;
} cluster_offset.x += rot.cos * glyph.width;
cluster_offset.clear(); cluster_offset.y -= rot.sin * glyph.width;
last_cluster_angle = angle;
box2d<double> bbox = get_bbox(layout, glyph, pos, rot);
if (collision(bbox)) return false;
bboxes.push_back(std::move(bbox));
glyphs->push_back(glyph, pos, rot);
} }
if (std::abs(angle) > M_PI/2) ++upside_down_glyph_count; //See comment above
offset -= sign * line.height()/2;
pixel_position pos = off_pp.current_position() + cluster_offset;
//Center the text on the line
double char_height = line.max_char_height();
pos.y = -pos.y - char_height/2.0*rot.cos;
pos.x = pos.x + char_height/2.0*rot.sin;
cluster_offset.x += rot.cos * glyph.width;
cluster_offset.y -= rot.sin * glyph.width;
box2d<double> bbox = get_bbox(glyph, pos, rot);
if (collision(bbox)) return false;
bboxes.push_back(bbox);
glyphs->push_back(glyph, pos, rot);
} }
//See comment above
offset -= sign * line.height()/2;
} }
if (upside_down_glyph_count > (layout_.text().length()/2))
if (upside_down_glyph_count > (layouts_.text().length() / 2))
{ {
if (orientation == UPRIGHT_AUTO) if (orientation == UPRIGHT_AUTO)
{ {
//Try again with oposite orientation //Try again with oposite orientation
s.restore(); begin.restore();
return single_line_placement(pp, real_orientation == UPRIGHT_RIGHT ? UPRIGHT_LEFT : UPRIGHT_RIGHT); return single_line_placement(pp, real_orientation == UPRIGHT_RIGHT ? UPRIGHT_LEFT : UPRIGHT_RIGHT);
} }
//upright==left_only or right_only and more than 50% of characters upside down => no placement //upright==left_only or right_only and more than 50% of characters upside down => no placement
if (orientation == UPRIGHT_LEFT_ONLY || orientation == UPRIGHT_RIGHT_ONLY) else if (orientation == UPRIGHT_LEFT_ONLY || orientation == UPRIGHT_RIGHT_ONLY)
{ {
return false; return false;
} }
} }
for (box2d<double> const& bbox : bboxes)
for (box2d<double> const& box : bboxes)
{ {
detector_.insert(bbox, layout_.text()); detector_.insert(box, layouts_.text());
} }
placements_.push_back(glyphs); placements_.push_back(glyphs);
return true; return true;
} }
@ -512,7 +430,7 @@ bool placement_finder::add_marker(glyph_positions_ptr glyphs, pixel_position con
return true; return true;
} }
box2d<double> placement_finder::get_bbox(glyph_info const& glyph, pixel_position const& pos, rotation const& rot) box2d<double> placement_finder::get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot)
{ {
/* /*
@ -525,7 +443,7 @@ box2d<double> placement_finder::get_bbox(glyph_info const& glyph, pixel_position
(0/ymin) (width/ymin) (0/ymin) (width/ymin)
Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)! Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)!
*/ */
double width = layout_.cluster_width(glyph.char_index); double width = layout.cluster_width(glyph.char_index);
if (glyph.width <= 0) width = -width; if (glyph.width <= 0) width = -width;
pixel_position tmp, tmp2; pixel_position tmp, tmp2;
tmp.set(0, glyph.ymax); tmp.set(0, glyph.ymax);

View file

@ -1,494 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* 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 2.1 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//mapnik
#include <mapnik/debug.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/formatting/text.hpp>
namespace mapnik
{
static const char * halo_rasterizer_strings[] = {
"full",
"fast",
""
};
IMPLEMENT_ENUM( halo_rasterizer_e, halo_rasterizer_strings )
static const char * label_placement_strings[] = {
"point",
"line",
"vertex",
"interior",
""
};
IMPLEMENT_ENUM( label_placement_e, label_placement_strings )
static const char * vertical_alignment_strings[] = {
"top",
"middle",
"bottom",
"auto",
""
};
IMPLEMENT_ENUM( vertical_alignment_e, vertical_alignment_strings )
static const char * horizontal_alignment_strings[] = {
"left",
"middle",
"right",
"auto",
""
};
IMPLEMENT_ENUM( horizontal_alignment_e, horizontal_alignment_strings )
static const char * justify_alignment_strings[] = {
"left",
"center", // not 'middle' in order to match CSS
"right",
"auto",
""
};
IMPLEMENT_ENUM( justify_alignment_e, justify_alignment_strings )
static const char * text_transform_strings[] = {
"none",
"uppercase",
"lowercase",
"capitalize",
""
};
IMPLEMENT_ENUM( text_transform_e, text_transform_strings )
#if 0
text_symbolizer::text_symbolizer(text_placements_ptr placements)
: symbolizer_base(),
placement_options_(placements),
halo_rasterizer_(HALO_RASTERIZER_FULL)
{
}
text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name,
float size, color const& fill,
text_placements_ptr placements)
: symbolizer_base(),
placement_options_(placements),
halo_rasterizer_(HALO_RASTERIZER_FULL)
{
set_name(name);
set_face_name(face_name);
set_text_size(size);
set_fill(fill);
}
text_symbolizer::text_symbolizer(expression_ptr name, float size, color const& fill,
text_placements_ptr placements)
: symbolizer_base(),
placement_options_(placements),
halo_rasterizer_(HALO_RASTERIZER_FULL)
{
set_name(name);
set_text_size(size);
set_fill(fill);
}
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
: symbolizer_base(rhs),
placement_options_(rhs.placement_options_),
halo_rasterizer_(rhs.halo_rasterizer_)
/*TODO: Copy options! */
{
}
text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
{
if (this == &other)
return *this;
placement_options_ = other.placement_options_; /*TODO: Copy options? */
halo_rasterizer_ = other.halo_rasterizer_;
return *this;
}
expression_ptr text_symbolizer::get_name() const
{
formatting::text_node *node = dynamic_cast<formatting::text_node *>(placement_options_->defaults.format_tree().get());
if (!node) return expression_ptr();
return node->get_text();
}
void text_symbolizer::set_name(expression_ptr name)
{
placement_options_->defaults.set_old_style_expression(name);
}
expression_ptr text_symbolizer::get_orientation() const
{
return placement_options_->defaults.orientation;
}
void text_symbolizer::set_orientation(expression_ptr orientation)
{
placement_options_->defaults.orientation = orientation;
}
std::string const& text_symbolizer::get_face_name() const
{
return placement_options_->defaults.format.face_name;
}
void text_symbolizer::set_face_name(std::string face_name)
{
placement_options_->defaults.format.face_name = face_name;
}
void text_symbolizer::set_fontset(font_set const& fontset)
{
placement_options_->defaults.format.fontset = fontset;
}
boost::optional<font_set> const& text_symbolizer::get_fontset() const
{
return placement_options_->defaults.format.fontset;
}
double text_symbolizer::get_text_ratio() const
{
return placement_options_->defaults.text_ratio;
}
void text_symbolizer::set_text_ratio(double ratio)
{
placement_options_->defaults.text_ratio = ratio;
}
double text_symbolizer::get_wrap_width() const
{
return placement_options_->defaults.wrap_width;
}
void text_symbolizer::set_wrap_width(double width)
{
placement_options_->defaults.wrap_width = width;
}
bool text_symbolizer::get_wrap_before() const
{
return placement_options_->defaults.format.wrap_before;
}
void text_symbolizer::set_wrap_before(bool wrap_before)
{
placement_options_->defaults.format.wrap_before = wrap_before;
}
unsigned char text_symbolizer::get_wrap_char() const
{
return placement_options_->defaults.format.wrap_char;
}
std::string text_symbolizer::get_wrap_char_string() const
{
return std::string(1, placement_options_->defaults.format.wrap_char);
}
void text_symbolizer::set_wrap_char(unsigned char character)
{
placement_options_->defaults.format.wrap_char = character;
}
void text_symbolizer::set_wrap_char_from_string(std::string const& character)
{
placement_options_->defaults.format.wrap_char = (character)[0];
}
text_transform_e text_symbolizer::get_text_transform() const
{
return placement_options_->defaults.format.text_transform;
}
void text_symbolizer::set_text_transform(text_transform_e convert)
{
placement_options_->defaults.format.text_transform = convert;
}
double text_symbolizer::get_line_spacing() const
{
return placement_options_->defaults.format.line_spacing;
}
void text_symbolizer::set_line_spacing(double spacing)
{
placement_options_->defaults.format.line_spacing = spacing;
}
double text_symbolizer::get_character_spacing() const
{
return placement_options_->defaults.format.character_spacing;
}
void text_symbolizer::set_character_spacing(double spacing)
{
placement_options_->defaults.format.character_spacing = spacing;
}
double text_symbolizer::get_label_spacing() const
{
return placement_options_->defaults.label_spacing;
}
void text_symbolizer::set_label_spacing(double spacing)
{
placement_options_->defaults.label_spacing = spacing;
}
double text_symbolizer::get_label_position_tolerance() const
{
return placement_options_->defaults.label_position_tolerance;
}
void text_symbolizer::set_label_position_tolerance(double tolerance)
{
placement_options_->defaults.label_position_tolerance = tolerance;
}
bool text_symbolizer::get_force_odd_labels() const
{
return placement_options_->defaults.force_odd_labels;
}
void text_symbolizer::set_force_odd_labels(bool force)
{
placement_options_->defaults.force_odd_labels = force;
}
double text_symbolizer::get_max_char_angle_delta() const
{
return placement_options_->defaults.max_char_angle_delta;
}
void text_symbolizer::set_max_char_angle_delta(double angle)
{
placement_options_->defaults.max_char_angle_delta = angle;
}
void text_symbolizer::set_text_size(double size)
{
placement_options_->defaults.format.text_size = size;
}
double text_symbolizer::get_text_size() const
{
return placement_options_->defaults.format.text_size;
}
void text_symbolizer::set_fill(color const& fill)
{
placement_options_->defaults.format.fill = fill;
}
color const& text_symbolizer::get_fill() const
{
return placement_options_->defaults.format.fill;
}
void text_symbolizer::set_halo_fill(color const& fill)
{
placement_options_->defaults.format.halo_fill = fill;
}
color const& text_symbolizer::get_halo_fill() const
{
return placement_options_->defaults.format.halo_fill;
}
void text_symbolizer::set_halo_radius(double radius)
{
placement_options_->defaults.format.halo_radius = radius;
}
double text_symbolizer::get_halo_radius() const
{
return placement_options_->defaults.format.halo_radius;
}
void text_symbolizer::set_halo_rasterizer(halo_rasterizer_e rasterizer_p)
{
halo_rasterizer_ = rasterizer_p;
}
halo_rasterizer_e text_symbolizer::get_halo_rasterizer() const
{
return halo_rasterizer_;
}
void text_symbolizer::set_label_placement(label_placement_e label_p)
{
placement_options_->defaults.label_placement = label_p;
}
label_placement_e text_symbolizer::get_label_placement() const
{
return placement_options_->defaults.label_placement;
}
void text_symbolizer::set_displacement(double x, double y)
{
placement_options_->defaults.displacement = std::make_pair(x,y);
}
void text_symbolizer::set_displacement(position const& p)
{
placement_options_->defaults.displacement = p;
}
position const& text_symbolizer::get_displacement() const
{
return placement_options_->defaults.displacement;
}
bool text_symbolizer::get_avoid_edges() const
{
return placement_options_->defaults.avoid_edges;
}
void text_symbolizer::set_avoid_edges(bool avoid)
{
placement_options_->defaults.avoid_edges = avoid;
}
bool text_symbolizer::largest_bbox_only() const
{
return placement_options_->defaults.largest_bbox_only;
}
void text_symbolizer::set_largest_bbox_only(bool v)
{
placement_options_->defaults.largest_bbox_only = v;
}
double text_symbolizer::get_minimum_distance() const
{
return placement_options_->defaults.minimum_distance;
}
void text_symbolizer::set_minimum_distance(double distance)
{
placement_options_->defaults.minimum_distance = distance;
}
double text_symbolizer::get_minimum_padding() const
{
return placement_options_->defaults.minimum_padding;
}
void text_symbolizer::set_minimum_padding(double distance)
{
placement_options_->defaults.minimum_padding = distance;
}
double text_symbolizer::get_minimum_path_length() const
{
return placement_options_->defaults.minimum_path_length;
}
void text_symbolizer::set_minimum_path_length(double size)
{
placement_options_->defaults.minimum_path_length = size;
}
void text_symbolizer::set_allow_overlap(bool overlap)
{
placement_options_->defaults.allow_overlap = overlap;
}
bool text_symbolizer::get_allow_overlap() const
{
return placement_options_->defaults.allow_overlap;
}
void text_symbolizer::set_text_opacity(double text_opacity)
{
placement_options_->defaults.format.text_opacity = text_opacity;
}
double text_symbolizer::get_text_opacity() const
{
return placement_options_->defaults.format.text_opacity;
}
void text_symbolizer::set_vertical_alignment(vertical_alignment_e valign)
{
placement_options_->defaults.valign = valign;
}
vertical_alignment_e text_symbolizer::get_vertical_alignment() const
{
return placement_options_->defaults.valign;
}
void text_symbolizer::set_horizontal_alignment(horizontal_alignment_e halign)
{
placement_options_->defaults.halign = halign;
}
horizontal_alignment_e text_symbolizer::get_horizontal_alignment() const
{
return placement_options_->defaults.halign;
}
void text_symbolizer::set_justify_alignment(justify_alignment_e jalign)
{
placement_options_->defaults.jalign = jalign;
}
justify_alignment_e text_symbolizer::get_justify_alignment() const
{
return placement_options_->defaults.jalign;
}
text_placements_ptr text_symbolizer::get_placement_options() const
{
return placement_options_;
}
void text_symbolizer::set_placement_options(text_placements_ptr placement_options)
{
placement_options_ = placement_options;
}
#endif
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,224 @@
{
"keys": [
"",
"9",
"8",
"4",
"5",
"7",
"16",
"6",
"10",
"2",
"12",
"13",
"14",
"11",
"3",
"15",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" !! ",
" !!! !!!! !!!!! ",
" !! !! ! !!!! ! ! !!!!! ",
" !!!! !! !!!!!! !! ! !! !!! !!!!! ! ",
" !!!! !! !!!!!!! !!!! !! !!!!!!! !!!!!! ! ",
" !!!!! !! !!!! !!!! !!!! !! !! !!!! !!!! !!!!!!! ! !! ",
" !!!!! !! !!!! ! !!!! !!!!!! !!!!!! !!!!! !!!!!! !! !!! !! ",
" !!!!! !! !! !!! !!!!!! !! ! !! !!!!!!!!! !!!!!!!!!!! !! !!!! ! ",
" !!!!! !!!!!! !!!!!!!!!!! !!!!!! !! !!!!!! !!!! !!!!!!!! ! !! ! !!!! ",
" !!! !! !!!! !!! !!!!!!! !!!!!!! !!! !!! ! !!! ! !!!!!!! !! !!! !!!! !! ",
" !!!!!!!! !! !!!!! ! !!!! !!!!!! !!!!!!!!!!! !! !! !!!! !!!!!! !!!! ! ! ",
" !! !!!!!!!! !! !! !!!!!!!!!!! !!! !!!!!!!! !! !!!!!!! !!!! !!!!!! ",
" !! ! !!! !! !!!!!!!!!!! !!!!!!! !! !! !! !! !!!! !!!! !!!!!! ",
" !! ! !! !! !! !! !!! !!! ! !! ! !!!! !! !!!!!!!!!! !!!!!!!!! !! ",
" !! !!! !! !! !! ! !! !!!! !!!! !! !!!!!!!!!! !!!!!!!!!!! ",
" !!!!!! !!!!! !! !!!!!!! ! !!!! !!!!!! !!!! !! !!!!!!! ",
" !!!!!!!!!!!!! ! !!!!!! !! !!!!!! !!!!! !! !!! ",
" ! !!!!! !! !!!!!! ! !! !!! !!! !! ! !! ",
" !!!! ! !! !! !!!!!! !!!!!! !! ! ",
" !!! !! !! !!!!!!!! !!! ! ",
" !!!!!!! !!!!!!!! ",
" ## !!!!!!!! !!!!!!!!! # $ ",
" ### # # !!!!!!!! # !!!!!! ### $ ",
" ##### ## # ### !!!!!!! ## ### ### !! #### $ ",
" ###### ## ## #### !!! #### ## ## ##### #### # $$ $ ",
" ######### ## ## #### ! #### ## ## ##### ######## #### ## # $$ $ ",
" ######### ## ### ###### ###### # # ## ####### ####### ## ## #### ## $$ $ ",
" ### ## #### ### # ######## ########### ## ### ##### ## ## ##### ### # ## #### ## $$ $$$ ",
" ## ##### #### ######## ###### ###### ####### ### # #### ##### ## #### #### ## ## $$ $$$ $$ ",
" ## ##### #### ## ## #### #### #### # # ######### ## #### ######## ## # $$ $$$ $$ ",
" ## ##### ### # ## #### #### ## # #### ## ##### ## ###### ### $$ $$$ $$ ",
" ## #### ### ## ## #### ####### ## #### # ## ######## ## ## #### $$ $$$$$$ ",
" ## ##### #### ## ## ##### #### ## # ####### ###### ####### ## # ## $$ $$$$ $ ",
" # ### ### ## ## ## #### ### ## ### ## ## #### ##### ##### # ## #### $$ $$$ $ ",
" % # ### # ### ### ## #### ### ## ######## ## # #### #### ## #### $$ $$$ ",
" % ## ## ####### ## ## ## ## ###### ## ####### # #### $$ $ ",
" % ## ##### ## # ## ## ##### ## ## #### $$ $ ",
" %%%% ## ## ## ## ## ## # # ## ## ## ### $$ $ ",
" %%%% ## ##### ## ## ####### #### #### $ ",
" %%%% ####### # ## # ## ### ### # $ ",
" %%%%%%% ## ## ### # ####### # $ ",
" %%%%%%%%% # # ####### # ## #### $ ",
" %%%%%% %% ### # ##### ### ### $ ",
" %%%%%%%%% #### ### ######## $ ",
" %%%%%%%%% ####### &&&&& #### &&&&& $$ $ ",
" %%%%%%% % &&&&& ### &&&&&& &&&&&&& &&& &&&& $$ $ ",
" %%% %%%%% &&&&&& &&&&&&&&& &&&& & &&&&&& &&&&& $$ $$$ ",
" %%%%%%% &&&&&&&& &&&&& &&&& &&&&& &&&&&&& &&&&&&&&& & $$ $$$ ",
" %%%% &&&&&& &&&&&& &&&&& &&& && &&&&& &&& & & &&&&&&&&&&&& && $ $$$ $$ ",
" %%%% &&&&&&&&&&& && &&&& && &&& && &&&&&& &&&&& & && && &&&&& & && $$ $$$ $$ ",
" % % &&& &&&&&&& && &&&&& &&&&&& && && & &&&&&&&& & &&& &&&&&&&& & &&& $$ $$$ $$ ",
" % &&&&&&&&&& && && &&&&&&&& & &&& &&&&&&& && &&&&& && &&&&&&&& &&&& $$ $$$$$$ ",
" % &&&&&&& && & &&& & &&&& &&& &&&& && &&&&&&& &&&& && && &&&&& &&&&& & $$ $$$$$$ ",
" % & &&&&&&&& &&&& & &&&&&&& &&&& & && &&&& & &&&& && && && & &&& &&&& & $$ $$$ ",
" % & &&& &&&&&& && && &&& &&&&&& &&&&& && & &&&&&&&&&&& && &&&&&&&&& && $$ $$$ ",
" % & && & &&&&&&&&& && & &&&&&&&& & & &&& &&&&& &&&&&&& && && $$ $ ",
" % & &&&&&&& && &&&&&&& &&&& &&&&& & &&& &&&&&&& && $$ $ ",
" % &&&& & & && &&&&&& &&& &&&&&&&&&& &&&&& && $ ",
" % %% &&&&&&&&&& &&&& &&&& &&&&& & &&&&&&& $ ",
" % %% &&&&& &&&&&&& &&&&&&& & && &&& $ ",
" %%% %% &&&&&&& &&&&&&& &&& &&& &&&& $ ",
" %%% %% &&& &&& &&&&& & &&&&& &&& $ ",
" %%%%%% %% &&&&& &&& && $ ",
" %%%%%% %% &&& & ''''''''' $$ $ ",
" %% %%% %% '''''''' ''''''' $$ $ ",
" %% %%% %% ''''''''' ' $$ $ ",
" %% %%% % (( ((( ''''' ' $$ $$$ ",
" %%% %% ( ( (( ((((( (((((( ''''' ' $ $$$ $$ ",
" % %% ((( ((((( ((((((( (((((( '''''''''''''''''''''''' $$ $$$ $$ ",
" % %% ((((((( ((((((( ((((( ( (((( ((( $$ $$$ $$ ",
" % %% (((((( ( (((( (( (((((((( ((((((( ''''''''''''' $$ $$$$$$ ",
" % ((((((( (((((((( ( (((( ((((( ((( (((((((( '''''''' '''' $$ $$$$$$ ",
" % ( ((((( ((((( ((( ((((((( ((((( (( (( ( (( '''''''' '''' $$ $$$ ",
" % (( ((( (( ( ((( (( (( (( ((((( (( ( (( (((((( (( ((( $$ $$$ ",
" % (( (((( (( ((( (( ((((((( ( (( (( ((( (((( (( (( (( (((((((( (( ((( ( $$ $ ",
" % (( (((((((( (( ((( (( ((( (((( (( (((( ( (((((( (( (( ((( (( (( (((( ( ((((((( $$ $ ",
" % (( ((((( (( (((( ((( (( ((((( (( ((((((( (( ((((( ( (((((( (( (((( ( ((((((( $ ",
" % ( ((((( (((((( ((((((( ( ((((( ( (((((( (( (((( ( ((((((( (( (((( ( (((((( $ ",
" % %% ( (((( ((( ( ((((((( ( (((( ( ((((( (( ((( (( ((( (( ((( (((((((((( (( $ ",
" % %% ( ((( ((( ((((( (( (( ((( (((( (( (((((((((( ( ((( (( ((( (( $ ",
" %%% %% ( (((((((( (( (( (( (((( ( ((( (( ((( (( ((( (( ( ((( $ ",
" %%% %% ((( ((( (( ((( (( (( (( ((( ((( (( ((((( ((((( $ ",
" %%%%%% %% (((( (( ((( ((( ((((( ((((( (( (((((( $$ $ ",
" %%%%%% %% ( (( ((( ((((( ((((((((( ))) ((( (((( $$ $ ",
" %% %%% %% ((((( ** + (((((((( ((( (((( ))))))))))))) (((((( $$ $ ",
" %% %% %% ((( * ** + ((((((( ((( )))))))) )))) ))))))) $$ $$$ ",
" %% %%% % **** ** + ))))))))) ) ))))))))) $$ $$$ $ ",
" %%% %% **** ** + , ) )))))))))))))))))))) ))) )) $$ $$$ $$ ",
" %%% %% ****** * + , ------ --- )))))))) )))))))) )))) $$ $$$ $$ ",
" % %% **** ****** ** + , -------- ---- )))))))) ))))))))))) $$ $$$$$$ ",
" % %% ****** ****** + , -- ------ ---- )) )))))))))))) $ $$$$ $ ",
" % * ** * **** ++++ , ---------------------------- ))))) )) )))) ) $$ $$$$$ ",
" % ** **** + ++ , ---- - - ))))) ))) )) )) $$ $$$ ",
" % ** **** + ++ , -------- ))))) ) $$ $ ",
" % * ***** +++++++ , -------- ) ) $$ $ ",
" % ** **** ++++++ , . ----- .. . .. ..... )) $$ $ ",
" % ** **** ++++ ++++ , . ..........----- ....... ..... ) $ ",
" % * ** +++++++++ , ,, ........ .... ............. ) $ ",
" % %% ** ++++++ ++ , , ,,, ...... ................................ ) $ ",
" % %% ** ++ +++ ++ ,, , ,, ......... .... . . ) $ ",
" %%%% * * ++ +++++++,, ,,, ,, .. ......... ........ ) )) $ ",
" %% %%% **** ** ++ +++,,,,,,, , . . ....... ........ ) )) $ ",
" % %%%%%% **** ** ///// +++,,,,, ,,,, .. .... ..... )) ) )) $$ $ ",
" %%%%% %%% ******* * ////////// ++++,,,, , ,, . ...... ..... )) ))) )) $$ $ ",
" %%%%% %%%% **** *** ** ** /////////// + ,,,,,,,,,, . ...... ))))))) $$ $$$ ",
" %%%%% %%% ******* ** *** //// ////// / + ,, , ,, . 0 0 0 0 )))) )))) $$ $$$ ",
" %%%%%%%%% * *** * ***** // ////// ////// /// ++ ,, , ,, . 00000000 ))))) ) )) $ $$$ $$ ",
" %% %% %%%% ** **** ///////// ///////// + ,,,, . 00000000 ))))) )))) $$ $$$ $$ ",
" %% %%%% ** *** ////////// ///// + ,,,, . . 00000 ))))) )))) $$ $$$$$$ ",
" %%% * ***** / /////// // /// + ,,,, ... 00000 ))) )))) $$$ $$$$$$ ",
" %%% ** **** // /////// //// // + , ... 00000 ) ))) $$ $$$$$$ ",
" %%% ******* // // /// //// + , ..... . 00000000000000000000000000000 ) )) $$ $$$ ",
" % * *** // /////// / , .. .... 0 0 00 ) )) $$$ $$$ ",
" % ** * // /////// /// , . ... .. 00000000 0000 ) $$ $ ",
" % * // // ////// / // , .. ... .. 00000000 0000 ) $$ $ ",
" % /// ////// //// , .. ... .. )))))))) )) )) $ ",
" % //// // / //// , .. ...... ))))))))) )))))))) ) $ ",
" % /////// / , .. ...... ))))))) )))))))) ) $ ",
" % / /// / .. ... ))))) )))) )) $ ",
" %%%% // /// // // .. ... ))))) )))))) ) $ ",
" %%%% // /// // // .... ))))))))))))) ))))) ) $ ",
" %%%%%% /// ///// / .... ))))))))))))))))))))))))))))) $$$ ",
" %%%%%%% ///////// / . )))))))))) )) $$$ ",
" %%%%%%%% ///////// // . )))))))) )))) )))))))) )))) $$$ ",
" %%%% %%%% /////// / . )))) )))) )))))))) )))) $$$ $$ ",
" %%%% %%% // / / .. .. $$$ $$ $$ ",
" %%%%%%%%% // / / . ... . $$$$$$$$$ ",
" %%%% % % / / . ....... ........ $$$ $$$$$ ",
" %%%%%%% / / . ...... ........ $$$$ $$$$$ ",
" %%% / / .. .. ..... $$$$$$$$$ ",
" %%% / / .. ..... ..... $$$ $$ ",
" %%% / / .. ... ..... $$$ $$ ",
" % // / .. ..................................... $$$$ ",
" % // / ..... . . .. $$$ ",
" % / / ............ ............. $ ",
" % / / ..... .... ............. $ ",
" // // $ ",
" / / $ ",
" / / ",
" / // ",
" // // 1 1 1 ",
" / // 11111111 111111111 ",
" / // 11111111 111111111 ",
" / // 1 11 11111 ",
" /// // 11111 11111 ",
" /////// // 11111 111 1 ",
" /////// // 11111111111111111111111111111111111111111111111 ",
" /// 111 1 1 1111 ",
" 1111111111111 11111111 1111 ",
" 11111111 1111 11111111 1111 ",
" 1 1 ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,209 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ! ",
" ! ",
" ! !!!!! ",
" !!! ! ",
" !!!!!!!! ! ! ! ",
" ! !! ! ! ",
" !! ! !! ! ",
" !! !!! !! ! ",
" ! ! !!! ! ! ",
" ! ! ! ! !! ",
" ! ! ! ! ",
" !! ! ! ! ",
" ! ! ! !! ! !! ",
" ! !!! !! ! ! ! ",
" ! ! !! ! ! !!! ",
" ! !! !!! !! ! ",
" ! !!! ! ! ! ! ",
" ! ! ! !!!! ! ! !! ",
" ! !! ! ! !! ! ",
" ! ! ! ! ! !! ",
" ! !! ! ! !! ",
" !! ! ! ! ! ! !!! ",
" ! !! !!! !! ! !!! ",
" ! ! ! ! ! ! ! !! ",
" !! ! ! !!! ! ! ! ",
" ! !! !! ! !!! ! ",
" !!! ! !!! !! ! ! ! ",
" !! ! ! ! !!! ",
" ! ! ! ! ! ",
" !! ! ! !! ",
" !! ! ! ",
" ! ! ! !! ! ",
" ! ! ! ! ",
" !!! !! !! ! ",
" !!!! ! !! !!! ",
" !! ! ! ! !! ! ",
" ! !!! !!!! !!!! ",
" !! ! ! ! !! ! ",
" !!! ! !!! !! ! ",
" ! ! ! !! ! ",
" !! ! !! ! ",
" ! ! ! ! ",
" ! ! ! ",
" ! !!!!! ! ",
" ! ! ! ! ",
" ! ! !! ! ",
" ! ! !! ! ",
" ! ! ! ",
" ! ! ! ",
" ! !!! ! ! ",
" ! ! ! !!!!! ",
" ! ! !!!!! ! !! ",
" ! ! !! ! ! !!! ",
" ! ! ! ! ! ! !! ",
" ! !!! !!! ! ! !! ",
" ! ! ! ! !! ",
" !!!! ! ! ! ! ",
" ! !!! !! ! !!!! ",
" ! !! !! ! ! ",
" ! ! ! ! ! ",
" ! !! !! ! ! !! ",
" ! ! !!!! ! ! ! ! ",
" ! !! !! !! ! ! ",
" ! !! !!! ! !! ! ",
" ! !!! !!! ! ! ! ",
" ! ! !! ! ! ",
" !!!! ! !!!! ! ",
" !!!! !! ! !! ! ",
" !! ! !! ! ! ",
" ! ! ! !! ! ",
" !! ! ! ! ! ",
" ! ! !! !!!! ",
" !!! ! ! ",
" ! ! !! ! ! ",
" ! ! !! ! ! ! ",
" !! ! ! !!! ! !! ",
" !!! ! ! !!!!! ",
" !!!! !!! ! !! ! ",
" !! ! ! !! !!! ",
" !!! ! ! !! ! ",
" !! ! ! !! ",
" ! ! !! ! ",
" ! ! ! ! ",
" ! !!!! ! ",
" ! ! !! !! ",
" ! ! ! ! ! ",
" ! !! ! ",
" ! ! ! ",
" ! ! ! ",
" ! !! ! ! ",
" ! ! ! ! ! ",
" ! !!! ! ! ! ! ",
" ! ! ! !! ! ! ! ",
" ! !! !!! ! ! ! ",
" !!! !!! ! ! !! ",
" ! !! !! ! ! ! ! ",
" ! !! ! ! ! !!! ",
" ! !!! ! ! ! !!! ",
" ! !!! ! ! ! ! !! ",
" ! ! !! ! ! ",
" ! ! ! ! ! !! ",
" !! !! !!!! ! !! ! ",
" ! ! ! ! !! ",
" ! !! !!! ! ! !! ",
" ! ! ! ! !!! ",
" ! !!! ! ! ! ",
" ! ! ! !!!! ",
" !!!! ! !!!! ! ",
" !! !! ! !! ! ",
" ! ! ! ! ! ",
" !! ! ! !! ! ",
" ! ! ! ! ! ",
" ! ! !!! !!! ",
" !!! ! ! !! ! ",
" ! ! !!! ! ! ",
" !!! ! !! ! ! ",
" !!!! ! ! !!! ",
" !!!! !!!! ! ! ",
" !! ! !!! ! !! ! ",
" !! ! ! ! !! ! ",
" ! ! !! ! ! ",
" ! ! !! !!! ",
" !! ! !! ! ",
" ! ! !! ! ",
" ! ! !!! ! ",
" ! ! ! !! ",
" ! !! ! ",
" ! ! ! ",
" ! !!! ! ! ",
" ! ! !! !! ",
" ! !!! ! ! ",
" ! !!! ! ! ",
" ! ! ! ! ! ! ",
" ! ! !!! ! ! !! ",
" ! !! ! !! ! ",
" ! ! ! ! ! ",
" ! ! ! ! ! ! ! ",
" ! ! ! ! ! ! !!!! ",
" ! !!!! !! ! ! ! ! ",
" ! ! ! !! !! ! ! ",
" ! !! !!!! ! !! ",
" ! ! ! ! ! ! ! ",
" ! ! ! ! ! ! ",
" ! ! ! ! ! !! ",
" ! ! ! ! ! ",
" ! ! ! ! !! ",
" ! ! ! !! ! !! ",
" ! !!! ! !! !! ! ! ",
" ! !! !! ! ! ! ",
" ! ! !! ! !! ! ",
" !!! ! ! !!!!! !!! ",
" !! ! ! !! ! ! ",
" ! !!!!!! !!! ",
" !! ! ! !! ! ! ",
" !! !!! ! ! ",
" !! !! ! ! !! ",
" ! !! ! !!!! ",
" ! ! ! ! ! ! ! ",
" ! ! ! ! ! ",
" ! !! !!!!! !! ! ",
" ! !!! ! !!! ! ! ",
" !!! ! ! ! ! ! ",
" !!!! !! ! ",
" !! ! ! ! ",
" !! ! ! ",
" ! ! !! ",
" ! !! ! ! ",
" ! !!! !! ! ",
" ! !!! !! !! ",
" ! !! ! !! !! ",
" ! !!!! !!!!!! ",
" ! !!! ",
" !!!! !!! ",
" !! ! ",
" !! ! ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,217 @@
{
"keys": [
"",
"8",
"7",
"6",
"5",
"9",
"4",
"2",
"1",
"3"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! ",
" !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! !!!!!!!!! ",
" !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ",
" !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ",
" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
" !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ",
" ",
" !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ",
" !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! ",
" ",
" ",
" ",
" ",
" ",
" ",
" ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ",
" ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ",
" ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ######### ",
" ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ",
" #################################################################################################################################################################################### ",
" ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ",
" ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ##### ",
" #### #### #### #### #### #### #### #### #### #### #### #### ",
" #### #### #### #### #### #### #### #### #### #### #### #### ",
" # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## # ## ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ $$$$$$$$$ ",
" $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ ",
" $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ $$$$$$ $$ ",
" $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ ",
" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ",
" $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ ",
" $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ $$$$$ ",
" $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ ",
" $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ ",
" $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ $$$$ ",
" ",
" ",
" ",
" ",
" ",
" %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% ",
" %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% %%%%%%%% ",
" %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% ",
" %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% ",
" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ",
" %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% %%%%%% ",
" ",
" %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% ",
" %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% %%%% ",
" ",
" ",
" ",
" ",
" ",
" &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ''''''' ' '''''''' (((((((( ",
" '' '''''' '' ''''' (((((((( ( ((((((((( ",
" )))) )))) ''''''' ' '''''''' (((((((( ((( ((( (((((( (( ",
" )))) )))) ) ))))))))) '''''' '''''' ((((((((( (((((((( (( ",
" ))))))))) )))))) ))))))))) '''''''''''''''''''''''''''''''''''''' (((((( ((((((( ",
" )))))))) )))))))))) '''''' '''''' (((((( ((((( ",
" )))))) ))))))) '''''' '''''' (((((( ((((( ",
" ))))) )))))) ''''' ''''' (((( ((((( ",
" ))))) )))))) '''' '' ' (( ( (((( ",
" )))) )))))) '''' '''' ((((( (((( ",
" )))) )))) ( ((((( ",
" )))) )) ) (( ( ",
" ) ) ))) ( ( ",
" ) ) ( ( ",
" )) ) ( ( ",
" ) ) ( (( ",
" ) ) ( ( ",
" ) ) ( ( ",
" ) )) ((((((((( (((( (((( ",
" ) ) ((((((( ( (((( (((( ",
" ))))))))) )))))))) (((((( ((((((((( ",
" ))))))))) )))))))) (((((( ((((( ",
" ))))) )))))))) (((((( ((((( ",
" ))))) )))))) ((((((( ((((( ",
" ))))) )))))) ******** ******** (( (((((((( ",
" )))))) )))))) ******* ******** ((((( (( ((( (((( ",
" ))) )))))))) ****** ****** (((( (( (((( ",
" )))) ))) ))) )))) ****** ****** (((( ",
" )))) )) )) ) ************************************** ",
" )))) ****** ****** ",
" ****** ****** ",
" ***** **** ",
" **** **** ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,73 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,142 @@
{
"keys": [
"",
"2",
"3",
"5",
"6",
"4",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ! # ",
" !! ## ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" $ ",
" $ ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" % ",
" %% ",
" % ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" & ' ",
" && '' ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

View file

@ -0,0 +1,137 @@
{
"keys": [
"",
"1"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ! ",
" !!! ",
" ! !! ",
" ! ! !!! ",
" !! ! ! ",
" !!! !!! ",
" ! ! !!! ",
" ! ! !! ! ",
" ! ! !! !!! ",
" !! !!! !!! ",
" ! ! !!! ! ! ",
" !! ! ! !!!! !! ! ",
" ! ! !! !!! !!! !! ",
" !! !!! ! ! !! ",
" !! !! !! ! ! ",
" !! !!!! !!! !! ",
" !! ! !! !! !!! ! ! ! ",
" !! !!!!!!!!!!! !!!!! !!! ! !!!! ! ! !!! ",
" !! ! !! !!!!!! !!! ! !! !!! !! ! ",
" ! !!! !! !! ! ",
" ! !! ! ! !!! ",
" !! !!! ! !! !!! ! ",
" !! !!!!!!! !!!!! ! !! !!! !!! ",
" !!!!!!!!!! !!! !!!! ! ! ! !! ",
" !!! !!! ! ! ",
" ! !!! !! ",
" ! !!! !!! ",
" ! !!!! ",
" !!! ",
" ! ! ",
" ! ",
" ",
" ",
" ! !! ! !! ! ",
" !!!!!!!!!!!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!! ",
" !!!!!!!!!!!!!!!!!! !!!!!!!! !!!!!!!! !!!!!!!!! ",
" ! !!! ! ! ! !!! ! ! ! ! ! !! ",
" ! ! !!! !! ! !! ! ",
" ! !!!!!!!! !!!!!!!!!!!!!!!!! !!!!!!!!! ",
" !!!!!!!!!! !!!!!!!!!!!!!!!!! !!!!!!!!! ",
" !! ! ! ! ! ! ",
" !!!!!!!!!!!! !!!!!!! ",
" !!!!!!!!!!!! !!!!!!! ",
" ! ! ! ! ! !! ! ",
" ! ! ",
" !!!!!!!!! ",
" !!!!!!!!!! ",
" ! ! ! ",
" !!!!!!! ",
" !!!!!! ",
" !! ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -20,8 +20,10 @@ wkt,name1,ref1,name2,ref2
<GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="50" spacing="100" repeat-key="[name%]+'-'+[ref%]"> <GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="50" spacing="100" repeat-key="[name%]+'-'+[ref%]">
<PairLayout item-margin="1"/> <PairLayout item-margin="1"/>
<GroupRule> <GroupRule>
<ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point" dy="0" fill="#ffffff">[ref%]</ShieldSymbolizer> <ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point">
<TextSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" dy="10">[name%]</TextSymbolizer> <Format fill="#ffffff">[ref%]</Format>
<Layout dy="10">[name%]</Layout>
</ShieldSymbolizer>
</GroupRule> </GroupRule>
</GroupSymbolizer> </GroupSymbolizer>
</Rule> </Rule>
@ -44,8 +46,10 @@ wkt,name1,ref1,name2,ref2
<GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="40" spacing="80" repeat-key="[name%]+'-'+[ref%]"> <GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="40" spacing="80" repeat-key="[name%]+'-'+[ref%]">
<PairLayout item-margin="1"/> <PairLayout item-margin="1"/>
<GroupRule> <GroupRule>
<ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point" dy="0" fill="#ffffff">[ref%]</ShieldSymbolizer> <ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point">
<TextSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" dy="10">[name%]</TextSymbolizer> <Format fill="#ffffff">[ref%]</Format>
<Layout dy="10">[name%]</Layout>
</ShieldSymbolizer>
</GroupRule> </GroupRule>
</GroupSymbolizer> </GroupSymbolizer>
</Rule> </Rule>
@ -68,8 +72,10 @@ wkt,name1,ref1,name2,ref2
<GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="30" spacing="60" repeat-key="[name%]+'-'+[ref%]"> <GroupSymbolizer start-column="1" num-columns="2" placement="line" avoid-edges="false" minimum-distance="30" spacing="60" repeat-key="[name%]+'-'+[ref%]">
<PairLayout item-margin="1"/> <PairLayout item-margin="1"/>
<GroupRule> <GroupRule>
<ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point" dy="0" fill="#ffffff">[ref%]</ShieldSymbolizer> <ShieldSymbolizer file="../../data/svg/rect.svg" face-name="DejaVu Sans Book" size="16" placement="point">
<TextSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" dy="10">[name%]</TextSymbolizer> <Format fill="#ffffff">[ref%]</Format>
<Layout dy="10">[name%]</Layout>
</ShieldSymbolizer>
</GroupRule> </GroupRule>
</GroupSymbolizer> </GroupSymbolizer>
<DebugSymbolizer/> <DebugSymbolizer/>

View file

@ -0,0 +1,91 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'stroke'</Filter>
<LineSymbolizer stroke-width='5' stroke='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'stroke-width'</Filter>
<LineSymbolizer stroke-width='[value]' stroke='#ff0000' />
</Rule>
<Rule>
<Filter>[id] = 'stroke-opacity'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' stroke-opacity="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'offset'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' offset="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'stroke-dasharray'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' stroke-dasharray="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'stroke-linejoin'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' stroke-linejoin="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'stroke-linecap'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' stroke-linecap="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'comp-op'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' comp-op="[value]" />
</Rule>
<Rule>
<TextSymbolizer face-name='DejaVu Sans Book' dy='-5'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
stroke|#ff0000|LineString(-160 -120,160 -120,160 -100)
stroke-width|5|LineString(-160 -90,160 -90,160 -70)
stroke-opacity|0.5|LineString(-160 -60,160 -60,160 -40)
offset|3|LineString(-160 -30,160 -30,160 -10)
stroke-dasharray|3,3|LineString(-160 0,160 0,160 20)
stroke-linejoin|bevel|LineString(-160 30,160 30,160 50)
stroke-linecap|round|LineString(-160 60,160 60,160 80)
comp-op|minus|LineString(-160 90,160 90,160 110)
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,71 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'stroke'</Filter>
<LineSymbolizer stroke-width='5' stroke='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'stroke-width'</Filter>
<LineSymbolizer stroke-width='[value]' stroke='#ff0000' />
</Rule>
<Rule>
<Filter>[id] = 'stroke-opacity'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' stroke-opacity="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'offset'</Filter>
<LineSymbolizer stroke-width='5' stroke='#ff0000' offset="[value]" />
</Rule>
<Rule>
<TextSymbolizer face-name='DejaVu Sans Book' dy='-5'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
stroke|#ff0000|LineString(-160 -120,160 -120,160 -100)
stroke-width|5|LineString(-160 -90,160 -90,160 -70)
stroke-opacity|0.5|LineString(-160 -60,160 -60,160 -40)
offset|3|LineString(-160 -30,160 -30,160 -10)
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<!-- Upright test -->
<Map background-color="white" srs="+proj=latlong +datum=WGS84">
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
<StyleName>lines</StyleName>
<StyleName>text</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="file">../data/lines2.csv</Parameter>
</Datasource>
</Layer>
<Style name="lines">
<Rule>
<LineSymbolizer stroke-width="3" stroke="green"/>
</Rule>
</Style>
<Style name="text">
<Rule>
<TextSymbolizer face-name="DejaVu Sans Book" size="10" placement="line" spacing="25" fill="#00ff00" halo-radius="1" halo-fill="rgba(255,255,255,0.6)" max-char-angle-delta="90">
<Layout dy="-3" vertical-alignment="top" wrap-width="33" wrap-before="true">
<Format fill="#ff0000">"District One"</Format>
</Layout>
<Layout dy="5" vertical-alignment="bottom">
<Format fill="#0000ff">"District Two"</Format>
</Layout>
</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<!-- Upright test -->
<Map background-color="white" srs="+proj=latlong +datum=WGS84">
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
<StyleName>lines</StyleName>
<StyleName>text</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt,nr
"LINESTRING(1.000 1.000, 0.958 0.646, 0.917 0.331, 0.875 0.055, 0.833 -0.185, 0.792 -0.390, 0.750 -0.562, 0.708 -0.703, 0.667 -0.815, 0.625 -0.898, 0.583 -0.956, 0.542 -0.989, 0.500 -1.000, 0.458 -0.990, 0.417 -0.961, 0.375 -0.914, 0.333 -0.852, 0.292 -0.776, 0.250 -0.688, 0.208 -0.589, 0.167 -0.481, 0.125 -0.367, 0.083 -0.248, 0.042 -0.125, 0.000 0.000, -0.042 0.125, -0.083 0.248, -0.125 0.367, -0.167 0.481, -0.208 0.589, -0.250 0.688, -0.292 0.776, -0.333 0.852, -0.375 0.914, -0.417 0.961, -0.458 0.990, -0.500 1.000, -0.542 0.989, -0.583 0.956, -0.625 0.898, -0.667 0.815, -0.708 0.703, -0.750 0.562, -0.792 0.390, -0.833 0.185, -0.875 -0.055, -0.917 -0.331, -0.958 -0.646, -1.000 -1.000)",1
</Parameter>
</Datasource>
</Layer>
<Style name="lines">
<Rule>
<LineSymbolizer stroke-width="3" stroke="green"/>
</Rule>
</Style>
<Style name="text">
<Rule>
<TextSymbolizer face-name="DejaVu Sans Book" size="14" placement="line" spacing="40" upright="left" max-char-angle-delta="45">
<Layout dy="-5" horizontal-alignment="left">"Align Left"</Layout>
<Layout dy="5" horizontal-alignment="right">"Align Right"</Layout>
</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<!-- Upright test -->
<Map background-color="white" srs="+proj=latlong +datum=WGS84">
<Layer name="layer" srs="+proj=latlong +datum=WGS84">
<StyleName>lines</StyleName>
<StyleName>text</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="file">../data/lines.csv</Parameter>
</Datasource>
</Layer>
<Style name="lines">
<Rule>
<LineSymbolizer stroke-width="3" stroke="red"/>
</Rule>
</Style>
<Style name="text">
<Rule>
<ShieldSymbolizer placement="line" spacing="60" minimum-distance="10" label-position-tolerance="0.5" face-name="DejaVu Sans Bold" size="14" fill="#ffffff" file="../../data/svg/rect.svg">
[nr]
<Format size="10" face-name="DejaVu Sans Book" fill="#000000" halo-fill="rgba(255,255,255,0.6)" halo-radius="1.5">
<Layout dy="-10">"SOUTH"</Layout>
<Layout dy="10">"ALT"</Layout>
</Format>
</ShieldSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -0,0 +1,81 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'file'</Filter>
<PointSymbolizer file="[value]" />
</Rule>
<Rule>
<Filter>[id] = 'allow-overlap'</Filter>
<PointSymbolizer allow-overlap="[value]" file="../../data/images/crosshair16x16.png" />
</Rule>
<Rule>
<Filter>[id] = 'opacity'</Filter>
<PointSymbolizer opacity="[value]" file="../../data/images/crosshair16x16.png" />
</Rule>
<Rule>
<Filter>[id] = 'transform'</Filter>
<PointSymbolizer transform="[value]" file="../../data/images/crosshair16x16.png" />
</Rule>
<Rule>
<Filter>[id] = 'ignore-placement'</Filter>
<PointSymbolizer ignore-placement="[value]" file="../../data/images/crosshair16x16.png" />
</Rule>
<Rule>
<Filter>[id] = 'comp-op'</Filter>
<PointSymbolizer comp-op="[value]" file="../../data/images/crosshair16x16.png" />
</Rule>
<Rule>
<TextSymbolizer dy='-16' face-name='DejaVu Sans Book' halo-fill='#ffffff' halo-radius='1'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
file|../../data/images/crosshair16x16.png|Point(-130 -70)
allow-overlap|../../data/images/crosshair16x16.png|Point(0 -70)
opacity|../../data/images/crosshair16x16.png|Point(130 -70)
transform|../../data/images/crosshair16x16.png|Point(-130 30)
ignore-placement|../../data/images/crosshair16x16.png|Point(0 30)
comp-op|../../data/images/crosshair16x16.png|Point(130 30)
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,56 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'file'</Filter>
<PointSymbolizer file="[value]" />
</Rule>
<Rule>
<TextSymbolizer dy='-16' face-name='DejaVu Sans Book' halo-fill='#ffffff' halo-radius='1'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
file|../../data/images/crosshair16x16.png|Point(-130 -70)
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,71 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'fill'</Filter>
<PolygonSymbolizer fill='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'fill-opacity'</Filter>
<PolygonSymbolizer fill='#0000ff' fill-opacity='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'gamma'</Filter>
<PolygonSymbolizer fill='#0000ff' gamma='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'comp-op'</Filter>
<PolygonSymbolizer fill='#0000ff' comp-op='[value]' />
</Rule>
<Rule>
<TextSymbolizer face-name='DejaVu Sans Book' halo-fill='#ffffff' halo-radius='1'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
fill|#0000ff|Polygon((-160 -120,-20 -120,-40 -80,-100 -90,-160 -120))
fill-opacity|0.5|Polygon((-160 -70,-20 -70,-40 -30,-100 -40,-160 -70))
gamma|1.0|Polygon((-160 -20,-20 -20,-40 20,-100 10,-160 -20))
comp-op|minus|Polygon((-160 30,-20 30,-40 70,-100 60,-160 30))
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,66 @@
<Map
background-color="#eee"
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Style name="bug">
<Rule>
<Filter>[id] = 'fill'</Filter>
<PolygonSymbolizer fill='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'fill-opacity'</Filter>
<PolygonSymbolizer fill='#0000ff' fill-opacity='[value]' />
</Rule>
<Rule>
<Filter>[id] = 'gamma'</Filter>
<PolygonSymbolizer fill='#0000ff' gamma='[value]' />
</Rule>
<Rule>
<TextSymbolizer face-name='DejaVu Sans Book' halo-fill='#ffffff' halo-radius='1'>[id]</TextSymbolizer>
</Rule>
</Style>
<Style name="frame">
<Rule>
<PolygonSymbolizer />
</Rule>
</Style>
<!--
frame is a layer with a single polygon that is used to ensure that m.zoom_all() will zoom the
map to a reasonable bounding extent to make the test easy to view with tools like nik2img.py
(which calls m.zoom_all() by default). Another approach in >= Mapnik 2.3.x is to just sent a
manual `extent` for the CSV datasource.
-->
<Layer name="frame" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>frame</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
wkt|name
Polygon((-180.0 -125.0, -180.0 125.0, 180.0 125.0, 180.0 -125.0, -180.0 -125.0))|bounds
</Parameter>
</Datasource>
</Layer>
<!--
"bug" is a layer that should provide sample data that triggers the bug in question. It is
listed after the "frame" layer so that it renders on top and is visible.
-->
<Layer name="bug" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>bug</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
id|value|wkt
fill|#0000ff|Polygon((-160 -120,-20 -120,-40 -80,-100 -90,-160 -120))
fill-opacity|0.5|Polygon((-160 -70,-20 -70,-40 -30,-100 -40,-160 -70))
gamma|1.0|Polygon((-160 -20,-20 -20,-40 20,-100 10,-160 -20))
</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="green" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" minimum-version="2.0.0">
<Layer name="obstacle" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>obstacle</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
lat,long,nr
-0.5,0.5,0
0.5,-0.5,1
0.5,0.5,2
-0.5,-0.5,3
0.08,0,4
-0.08,0,5
</Parameter>
</Datasource>
</Layer>
<Style name="obstacle">
<Rule>
<PointSymbolizer file="../../data/svg/crosshair16x16.svg" transform="scale(0.5)"/>
</Rule>
</Style>
<Layer name="layer1" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>points</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
lat,long,nr,ref
-0.45,-0.45,0,first
0.45,-0.45,1,second
0.45,0.45,2,third
-0.45,0.45,3,fourth
0,0,4,fifth
</Parameter>
</Datasource>
</Layer>
<Style name="points">
<Rule>
<PointSymbolizer allow-overlap="true" ignore-placement="true" file="../../data/raster/white-alpha.png"/>
<TextSymbolizer face-name="DejaVu Sans Book" placement="point" placement-type="list" size="16" dx="-4" dy="-8">
"test "+[nr]
<Layout dx="0" dy="8" horizontal-alignment="right">
<Format fill="red">[ref]</Format>
</Layout>
<Placement size="14" dy="8">
"test "+[nr]
<Format fill="blue">
<Layout dx="0" dy="-8" horizontal-alignment="right">[ref]</Layout>
</Format>
</Placement>
<Placement dx="0" dy="0">
"test "+[nr]
<Format fill="yellow">" ("+[ref]+")"</Format>
</Placement>
</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<Map background-color="green" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" minimum-version="2.0.0">
<Layer name="layer1" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>points</StyleName>
<Datasource>
<Parameter name="type">csv</Parameter>
<Parameter name="inline">
lat,long
0,0
</Parameter>
</Datasource>
</Layer>
<Style name="points">
<Rule>
<PointSymbolizer allow-overlap="true" ignore-placement="true" file="../../data/raster/white-alpha.png"/>
<TextSymbolizer face-name="DejaVu Sans Bold" size="16" wrap-width="60" placement="point" dx="-15" dy="-10">
"Symbolizer Base Text"
<Format face-name="DejaVu Sans Book" size="12">
<Layout orientation="45" dx="25">
"Rotated Layout with "
<Format fill="blue">
"Blue Format Child Node"
<Layout vertical-alignment="top" rotate-displacement="true" dy="-5">
"Rotated child layout with rotate-displacement"
</Layout>
</Format>
</Layout>
<Layout wrap-width="100" wrap-before="true" dy="30">
<Format halo-radius="1.5">
"South Offset Layout"
<Layout dx="30" horizontal-alignment="middle" justify-alignment="center">
<Format halo-fill="turquoise">"South offset child layout, centered"</Format>
</Layout>
<Layout dx="75" wrap-width="20" horizontal-alignment="right" justify-alignment="right">
<Format face-name="DejaVu Sans Oblique">"South offset child layout, right"</Format>
</Layout>
</Format>
</Layout>
</Format>
</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -3,6 +3,7 @@
import mapnik import mapnik
mapnik.logger.set_severity(mapnik.severity_type.None) mapnik.logger.set_severity(mapnik.severity_type.None)
#mapnik.logger.set_severity(mapnik.severity_type.Debug)
import shutil import shutil
import sys import sys
@ -96,6 +97,9 @@ files = {
'lines-5': {'sizes': sizes_few_square,'bbox':default_text_box}, 'lines-5': {'sizes': sizes_few_square,'bbox':default_text_box},
'lines-6': {'sizes': sizes_few_square,'bbox':default_text_box}, 'lines-6': {'sizes': sizes_few_square,'bbox':default_text_box},
'lines-7': {'sizes': sizes_few_square,'bbox':mapnik.Box2d(-1.2, -1.2, 1.2, 1.2)}, 'lines-7': {'sizes': sizes_few_square,'bbox':mapnik.Box2d(-1.2, -1.2, 1.2, 1.2)},
'lines-multi-layout-1': {'sizes': [(800,800)],'bbox':default_text_box},
'lines-multi-layout-2': {'sizes': [(800,800)],'bbox':mapnik.Box2d(-1.2, -1.2, 1.2, 1.2)},
'lines-multi-layout-shield': {'sizes': [(800,800)],'bbox':default_text_box},
'lines-shield': {'sizes': sizes_few_square,'bbox':default_text_box}, 'lines-shield': {'sizes': sizes_few_square,'bbox':default_text_box},
'collision': {'sizes':[(600,400)]}, 'collision': {'sizes':[(600,400)]},
'shield-on-polygon': {'sizes':[(600,400)]}, 'shield-on-polygon': {'sizes':[(600,400)]},
@ -156,6 +160,8 @@ files = {
'text-halign': {'sizes': [(800,800)], 'bbox': default_text_box}, 'text-halign': {'sizes': [(800,800)], 'bbox': default_text_box},
'text-malayalam': {'sizes': [(800, 100)], 'bbox': default_text_box}, 'text-malayalam': {'sizes': [(800, 100)], 'bbox': default_text_box},
'text-bengali': {'sizes': [(800, 100)], 'bbox': default_text_box}, 'text-bengali': {'sizes': [(800, 100)], 'bbox': default_text_box},
'text-multi-layout-1': {'sizes': [(512,512)], 'bbox':mapnik.Box2d(-1, -1, 1, 1)},
'text-multi-layout-2': {'sizes': [(512,512)], 'bbox':mapnik.Box2d(-1, -1, 1, 1)},
'line-pattern-symbolizer': {'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)}, 'line-pattern-symbolizer': {'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)},
'tiff-alpha-gdal': {'sizes':[(600,400)]}, 'tiff-alpha-gdal': {'sizes':[(600,400)]},
'tiff-alpha-broken-assoc-alpha-gdal': {'sizes':[(600,400)]}, 'tiff-alpha-broken-assoc-alpha-gdal': {'sizes':[(600,400)]},
@ -220,6 +226,12 @@ files = {
'tiff-nodata-tolerance':{'sizes':[(512,512)]}, 'tiff-nodata-tolerance':{'sizes':[(512,512)]},
'tiff-nodata-edge-rgba':{'sizes':[(512,512)]}, 'tiff-nodata-edge-rgba':{'sizes':[(512,512)]},
'marker-vs-point':{'sizes':[(512,512)]}, 'marker-vs-point':{'sizes':[(512,512)]},
'line-symbolizer-expressions':{'sizes':[(256,256)]},
'line-symbolizer-expressions-all':{'sizes':[(256,256)]},
'point-symbolizer-expressions':{'sizes':[(256,256)]},
'point-symbolizer-expressions-all':{'sizes':[(256,256)]},
'polygon-symbolizer-expressions':{'sizes':[(256,256)]},
'polygon-symbolizer-expressions-all':{'sizes':[(256,256)]},
'group-symbolizer-1':{'sizes':[(512,512)]}, 'group-symbolizer-1':{'sizes':[(512,512)]},
'group-symbolizer-2':{'sizes':[(512,512)]}, 'group-symbolizer-2':{'sizes':[(512,512)]},
'group-symbolizer-line-1':{'sizes':[(512,512)]}, 'group-symbolizer-line-1':{'sizes':[(512,512)]},