diff --git a/.travis.yml b/.travis.yml index 2d46e6478..e0a579db1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ compiler: env: matrix: - - DEBUG=False ENABLE_LOG=True DEFAULT_LOG_SEVERITY=debug XMLPARSER="libxml2" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="" CUSTOM_LDFLAGS="" + - DEBUG=False PLUGIN_LINKING=static ENABLE_LOG=True DEFAULT_LOG_SEVERITY=debug XMLPARSER="libxml2" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="" CUSTOM_LDFLAGS="" - DEBUG=False ENABLE_LOG=False DEFAULT_LOG_SEVERITY=none XMLPARSER="ptree" DEMO=False BENCHMARK=True CUSTOM_CXXFLAGS="" CUSTOM_LDFLAGS="" # travis + ubuntugis with gdal and postggis leads to many potential dead-end conflicts diff --git a/AUTHORS.md b/AUTHORS.md index 25aa969a4..4c356e70e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -77,3 +77,4 @@ Mapnik is written by Artem Pavlenko with contributions from: * Rich Wareham * Nick Whitelegg * Leslie Wu +* Blake Thompson diff --git a/CHANGELOG.md b/CHANGELOG.md index ff0a81c0b..49849e340 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ For a complete change history, see the git log. ## 3.0.0 +- Added new and experimental `dot` symbolizer for fast rendering of points - Improved support for International Text (now uses harfbuzz library for text shaping) - Uses latest c++11 features for better performance (especially map loading) - Expressions everywhere: all symbolizer properties can now be data driven expressions (with the exception of `face-name` and `fontset-name` on the `TextSymbolizer`). diff --git a/SConstruct b/SConstruct index 80786fe70..03f8ee76a 100644 --- a/SConstruct +++ b/SConstruct @@ -443,6 +443,7 @@ pickle_store = [# Scons internal variables 'PYTHON_SYS_PREFIX', 'COLOR_PRINT', 'HAS_CAIRO', + 'MAPNIK_HAS_DLFCN', 'HAS_PYCAIRO', 'HAS_LIBXML2', 'PYTHON_IS_64BIT', @@ -829,6 +830,24 @@ int main() rm_path(item,'CPPPATH',context.env) return ret +def CheckHasDlfcn(context, silent=False): + if not silent: + context.Message('Checking for dlfcn.h support ... ') + ret = context.TryCompile(""" + +#include + +int main() +{ + return 0; +} + +""", '.cpp') + if silent: + context.did_show_result=1 + context.Result(ret) + return ret + def GetBoostLibVersion(context): ret = context.TryRun(""" @@ -989,6 +1008,7 @@ conf_tests = { 'prioritize_paths' : prioritize_paths, 'FindBoost' : FindBoost, 'CheckBoost' : CheckBoost, 'CheckCairoHasFreetype' : CheckCairoHasFreetype, + 'CheckHasDlfcn' : CheckHasDlfcn, 'GetBoostLibVersion' : GetBoostLibVersion, 'parse_config' : parse_config, 'parse_pg_config' : parse_pg_config, @@ -1199,6 +1219,11 @@ if not preconfigured: ['harfbuzz', 'harfbuzz/hb.h',True,'C++'] ] + if conf.CheckHasDlfcn(): + env.Append(CPPDEFINES = '-DMAPNIK_HAS_DLCFN') + else: + env['SKIPPED_DEPS'].extend(['dlfcn']) + OPTIONAL_LIBSHEADERS = [] if env['JPEG']: @@ -1725,8 +1750,8 @@ if not preconfigured: env.Append(CPPDEFINES = ndebug_defines) # Common flags for g++/clang++ CXX compiler. - # TODO: clean up code more to make -Wextra -Wsign-conversion -Wconversion -Wshadow viable - common_cxx_flags = '-Wall -Wsign-compare %s %s -ftemplate-depth-300 ' % (env['WARNING_CXXFLAGS'], pthread) + # TODO: clean up code more to make -Wextra -Wsign-compare -Wsign-conversion -Wconversion -Wshadow viable + common_cxx_flags = '-Wall %s %s -ftemplate-depth-300 ' % (env['WARNING_CXXFLAGS'], pthread) if 'clang++' in env['CXX']: common_cxx_flags += ' -Wno-unknown-pragmas -Wno-unsequenced ' @@ -1963,6 +1988,7 @@ if not HELP_REQUESTED: # build C++ tests SConscript('tests/cpp_tests/build.py') + SConscript('tests/cxx/build.py') if env['BENCHMARK']: SConscript('benchmark/build.py') diff --git a/benchmark/bench_framework.hpp b/benchmark/bench_framework.hpp index f2afc4857..33c5b0f99 100644 --- a/benchmark/bench_framework.hpp +++ b/benchmark/bench_framework.hpp @@ -37,7 +37,7 @@ public: return iterations_; } virtual bool validate() const = 0; - virtual void operator()() const = 0; + virtual bool operator()() const = 0; virtual ~test_case() {} }; @@ -85,35 +85,40 @@ int run(T const& test_runner, std::string const& name) std::clog << "test did not validate: " << name << "\n"; return -1; } - std::chrono::high_resolution_clock::time_point start; - std::chrono::high_resolution_clock::duration elapsed; - std::stringstream s; - s << name << ":" - << std::setw(45 - (int)s.tellp()) << std::right - << " t:" << test_runner.threads() - << " i:" << test_runner.iterations(); - if (test_runner.threads() > 0) + // run test once before timing + // if it returns false then we'll abort timing + if (test_runner()) { - using thread_group = std::vector >; - using value_type = thread_group::value_type; - thread_group tg; - for (std::size_t i=0;i 0) { - tg.emplace_back(new std::thread(test_runner)); + using thread_group = std::vector >; + using value_type = thread_group::value_type; + thread_group tg; + for (std::size_t i=0;ijoinable()) t->join();}); + elapsed = std::chrono::high_resolution_clock::now() - start; } - start = std::chrono::high_resolution_clock::now(); - std::for_each(tg.begin(), tg.end(), [](value_type & t) {if (t->joinable()) t->join();}); - elapsed = std::chrono::high_resolution_clock::now() - start; + else + { + start = std::chrono::high_resolution_clock::now(); + test_runner(); + elapsed = std::chrono::high_resolution_clock::now() - start; + } + s << std::setw(65 - (int)s.tellp()) << std::right + << std::chrono::duration_cast(elapsed).count() << " milliseconds\n"; + std::clog << s.str(); } - else - { - start = std::chrono::high_resolution_clock::now(); - test_runner(); - elapsed = std::chrono::high_resolution_clock::now() - start; - } - s << std::setw(65 - (int)s.tellp()) << std::right - << std::chrono::duration_cast(elapsed).count() << " milliseconds\n"; - std::clog << s.str(); return 0; } catch (std::exception const& ex) diff --git a/benchmark/compare_images.hpp b/benchmark/compare_images.hpp index 8e4f17740..60f9f0d1c 100644 --- a/benchmark/compare_images.hpp +++ b/benchmark/compare_images.hpp @@ -1,5 +1,5 @@ #ifndef __MAPNIK_COMPARE_IMAGES_HPP__ -#define __MAPNIK_COMPARE_IMAGES_HPP__ +#define __MAPNIK_COMPARE_IMAGES_HPP__ #include #include @@ -28,8 +28,8 @@ namespace benchmark { std::shared_ptr image_ptr2 = std::make_shared(reader2->width(),reader2->height()); reader2->read(0,0,image_ptr2->data()); - image_data_32 const& dest = image_ptr1->data(); - image_data_32 const& src = image_ptr2->data(); + image_data_rgba8 const& dest = image_ptr1->data(); + image_data_rgba8 const& src = image_ptr2->data(); unsigned int width = src.width(); unsigned int height = src.height(); @@ -48,4 +48,4 @@ namespace benchmark { } -#endif // __MAPNIK_COMPARE_IMAGES_HPP__ \ No newline at end of file +#endif // __MAPNIK_COMPARE_IMAGES_HPP__ diff --git a/benchmark/data/gdal-wgs.xml b/benchmark/data/gdal-wgs.xml new file mode 100644 index 000000000..aa5866532 --- /dev/null +++ b/benchmark/data/gdal-wgs.xml @@ -0,0 +1,21 @@ + + + + + + + style + + ./valid.geotiff.tif + gdal + + + + diff --git a/benchmark/data/raster-wgs.xml b/benchmark/data/raster-wgs.xml new file mode 100644 index 000000000..3ee054d2d --- /dev/null +++ b/benchmark/data/raster-wgs.xml @@ -0,0 +1,21 @@ + + + + + + + style + + ./valid.geotiff.tif + raster + + + + diff --git a/benchmark/data/valid.geotiff.tif b/benchmark/data/valid.geotiff.tif new file mode 100644 index 000000000..b2fe90d30 Binary files /dev/null and b/benchmark/data/valid.geotiff.tif differ diff --git a/benchmark/run b/benchmark/run index 901c276b2..13e7e49ed 100755 --- a/benchmark/run +++ b/benchmark/run @@ -29,4 +29,22 @@ run test_font_registration 10 1000 --width 600 \ --height 600 \ --iterations 20 \ - --threads 10 \ No newline at end of file + --threads 10 + +./benchmark/out/test_rendering \ + --name "gdal tiff rendering" \ + --map benchmark/data/gdal-wgs.xml \ + --extent -180.0,-120.0,180.0,120.0 \ + --width 600 \ + --height 600 \ + --iterations 20 \ + --threads 10 + +./benchmark/out/test_rendering \ + --name "raster tiff rendering" \ + --map benchmark/data/raster-wgs.xml \ + --extent -180.0,-120.0,180.0,120.0 \ + --width 600 \ + --height 600 \ + --iterations 20 \ + --threads 10 diff --git a/benchmark/test_array_allocation.cpp b/benchmark/test_array_allocation.cpp index e0e4fade5..05da7ae01 100644 --- a/benchmark/test_array_allocation.cpp +++ b/benchmark/test_array_allocation.cpp @@ -1,6 +1,7 @@ #include "bench_framework.hpp" #include #include +#include #include #include #include @@ -40,7 +41,7 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i(::operator new(sizeof(uint8_t) * size_)); @@ -98,6 +101,7 @@ public: ensure_zero(data,size_); ::operator delete(data); } + return true; } }; @@ -115,7 +119,7 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i(::operator new(sizeof(uint8_t)*size_)); @@ -123,6 +127,7 @@ public: ensure_zero(data,size_); ::operator delete(data),data=0; } + return true; } }; @@ -139,12 +144,13 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i data(size_); ensure_zero(&data[0],data.size()); } + return true; } }; @@ -162,13 +168,14 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i data(0); data.resize(size_,0); ensure_zero(&data[0],data.size()); } + return true; } }; @@ -186,13 +193,68 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i data(0); data.assign(size_,0); ensure_zero(&data[0],data.size()); } + return true; + } +}; + +class test3d : public benchmark::test_case +{ +public: + uint32_t size_; + std::vector array_; + test3d(mapnik::parameters const& params) + : test_case(params), + size_(*params.get("size",256*256)), + array_(size_,0) { } + bool validate() const + { + return true; + } + bool operator()() const + { + for (std::size_t i=0;i data(size_); + for (std::size_t i=0;i array_; + test3d(mapnik::parameters const& params) + : test_case(params), + size_(*params.get("size",256*256)), + array_(size_,0) { } + bool validate() const + { + return true; + } + bool operator()() const + { + for (std::size_t i=0;i data(size_); + for (std::size_t i=0;i data(static_cast(0),static_cast(size_)); ensure_zero(&data[0],size_); } + return true; } }; @@ -307,12 +373,13 @@ public: { return true; } - void operator()() const + bool operator()() const { for (std::size_t i=0;i data(size_,0); ensure_zero(&data[0],size_); } + return true; } }; #endif @@ -353,6 +420,10 @@ int main(int argc, char** argv) test3c test_runner(params); run(test_runner,"vector/assign"); } + { + test3d test_runner(params); + run(test_runner,"deque(N)"); + } { test5 test_runner(params); run(test_runner,"std::string range"); diff --git a/benchmark/test_expression_parse.cpp b/benchmark/test_expression_parse.cpp index 857dde66b..704a69c7c 100644 --- a/benchmark/test_expression_parse.cpp +++ b/benchmark/test_expression_parse.cpp @@ -22,11 +22,12 @@ public: } return ret; } - void operator()() const + bool operator()() const { for (std::size_t i=0;idata(),actual, "png8:m=h:z=1"); return benchmark::compare_images(actual,expected); } - void operator()() const + bool operator()() const { std::string out; for (std::size_t i=0;idata(),"png8:m=h:z=1"); } } + return true; }; BENCHMARK(test,"encoding multicolor png") diff --git a/benchmark/test_polygon_clipping.cpp b/benchmark/test_polygon_clipping.cpp index e72a0aa76..9b6184b0c 100644 --- a/benchmark/test_polygon_clipping.cpp +++ b/benchmark/test_polygon_clipping.cpp @@ -54,7 +54,7 @@ void render(mapnik::geometry_type & geom, ras.add_path(path); agg::scanline_u8 sl; agg::render_scanlines(ras, sl, ren); - mapnik::save_to_file(im,name); + mapnik::save_to_file(im.data(),name); geom.rewind(0); } @@ -108,7 +108,7 @@ public: render(geom2,geom.envelope(),actual); return benchmark::compare_images(actual,expect); } - void operator()() const + bool operator()() const { boost::ptr_vector paths; if (!mapnik::from_wkt(wkt_in_, paths)) @@ -130,6 +130,7 @@ public: while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {} } } + return true; } }; @@ -189,7 +190,7 @@ public: render(geom2,geom.envelope(),actual); return benchmark::compare_images(actual,expect); } - void operator()() const + bool operator()() const { boost::ptr_vector paths; if (!mapnik::from_wkt(wkt_in_, paths)) @@ -217,6 +218,7 @@ public: while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {} } } + return true; } }; @@ -265,7 +267,7 @@ public: render(geom2,geom.envelope(),actual); return benchmark::compare_images(actual,expect); } - void operator()() const + bool operator()() const { boost::ptr_vector paths; if (!mapnik::from_wkt(wkt_in_, paths)) @@ -282,6 +284,7 @@ public: while ((cmd = clipped.vertex(&x, &y)) != mapnik::SEG_END) {} } } + return true; } }; diff --git a/benchmark/test_polygon_clipping_rendering.cpp b/benchmark/test_polygon_clipping_rendering.cpp index 61bfea257..f4ba0f44b 100644 --- a/benchmark/test_polygon_clipping_rendering.cpp +++ b/benchmark/test_polygon_clipping_rendering.cpp @@ -25,10 +25,10 @@ public: mapnik::image_32 im(m.width(),m.height()); mapnik::agg_renderer ren(m,im); ren.apply(); - //mapnik::save_to_file(im,"test.png"); + //mapnik::save_to_file(im.data(),"test.png"); return true; } - void operator()() const + bool operator()() const { mapnik::Map m(256,256); mapnik::load_map(m,xml_); @@ -39,6 +39,7 @@ public: mapnik::agg_renderer ren(m,im); ren.apply(); } + return true; } }; diff --git a/benchmark/test_proj_transform1.cpp b/benchmark/test_proj_transform1.cpp index 180fccab8..38fcf8b14 100644 --- a/benchmark/test_proj_transform1.cpp +++ b/benchmark/test_proj_transform1.cpp @@ -36,7 +36,7 @@ public: (std::fabs(bbox.maxy() - to_.maxy()) < .5) ); } - void operator()() const + bool operator()() const { for (std::size_t i=0;i ren(m,im,scale_factor_); ren.apply(); - if (!preview_.empty()) mapnik::save_to_file(im,preview_); + if (!preview_.empty()) { + std::clog << "preview available at " << preview_ << "\n"; + mapnik::save_to_file(im.data(),preview_); + } return true; } - void operator()() const + bool operator()() const { + if (!preview_.empty()) { + return false; + } mapnik::Map m(width_,height_); mapnik::load_map(m,xml_); if (extent_.valid()) { @@ -76,6 +82,7 @@ public: mapnik::agg_renderer ren(m,im,scale_factor_); ren.apply(); } + return true; } }; diff --git a/benchmark/test_rendering_shared_map.cpp b/benchmark/test_rendering_shared_map.cpp index 3f98f7f3a..c5d5b08f8 100644 --- a/benchmark/test_rendering_shared_map.cpp +++ b/benchmark/test_rendering_shared_map.cpp @@ -26,13 +26,7 @@ template void process_layers(Renderer & ren, if (lyr.visible(scale_denom)) { std::set names; - mapnik::parameters p; - p["type"]="csv"; - p["file"]="benchmark/data/roads.csv"; - mapnik::datasource_ptr ds = mapnik::datasource_cache::instance().create(p); mapnik::layer l(lyr); - l.set_datasource(ds); - l.add_style("labels"); ren.apply_to_layer(l, ren, map_proj, @@ -56,6 +50,7 @@ class test : public benchmark::test_case std::shared_ptr m_; double scale_factor_; std::string preview_; + mutable mapnik::image_32 im_; public: test(mapnik::parameters const& params) : test_case(params), @@ -65,7 +60,8 @@ public: height_(*params.get("height",256)), m_(new mapnik::Map(width_,height_)), scale_factor_(*params.get("scale_factor",2.0)), - preview_(*params.get("preview","")) + preview_(*params.get("preview","")), + im_(m_->width(),m_->height()) { boost::optional map = params.get("map"); if (!map) @@ -75,6 +71,7 @@ public: xml_ = *map; boost::optional ext = params.get("extent"); + mapnik::load_map(*m_,xml_,true); if (ext && !ext->empty()) { if (!extent_.from_string(*ext)) @@ -82,51 +79,67 @@ public: } else { - throw std::runtime_error("please provide a --extent= arg"); + m_->zoom_all(); + extent_ = m_->get_current_extent(); + std::clog << "Defaulting to max extent " << extent_ << "\n"; + std::clog << " (pass --extent= to restrict bounds)\n"; } - mapnik::load_map(*m_,xml_,true); } bool validate() const { mapnik::request m_req(width_,height_,extent_); - mapnik::image_32 im(m_->width(),m_->height()); mapnik::attributes variables; m_req.set_buffer_size(m_->buffer_size()); mapnik::projection map_proj(m_->srs(),true); double scale_denom = mapnik::scale_denominator(m_req.scale(),map_proj.is_geographic()); scale_denom *= scale_factor_; - mapnik::agg_renderer ren(*m_,m_req,variables,im,scale_factor_); + mapnik::agg_renderer ren(*m_,m_req,variables,im_,scale_factor_); ren.start_map_processing(*m_); std::vector const& layers = m_->layers(); process_layers(ren,m_req,map_proj,layers,scale_denom); ren.end_map_processing(*m_); if (!preview_.empty()) { std::clog << "preview available at " << preview_ << "\n"; - mapnik::save_to_file(im,preview_); + mapnik::save_to_file(im_.data(),preview_); } return true; } - void operator()() const + bool operator()() const { - if (preview_.empty()) { - for (unsigned i=0;iwidth(),m_->height()); - mapnik::attributes variables; - m_req.set_buffer_size(m_->buffer_size()); - mapnik::projection map_proj(m_->srs(),true); - double scale_denom = mapnik::scale_denominator(m_req.scale(),map_proj.is_geographic()); - scale_denom *= scale_factor_; - mapnik::agg_renderer ren(*m_,m_req,variables,im,scale_factor_); - ren.start_map_processing(*m_); - std::vector const& layers = m_->layers(); - process_layers(ren,m_req,map_proj,layers,scale_denom); - ren.end_map_processing(*m_); - } + if (!preview_.empty()) { + return false; } + for (unsigned i=0;iwidth(),m_->height()); + mapnik::attributes variables; + m_req.set_buffer_size(m_->buffer_size()); + mapnik::projection map_proj(m_->srs(),true); + double scale_denom = mapnik::scale_denominator(m_req.scale(),map_proj.is_geographic()); + scale_denom *= scale_factor_; + mapnik::agg_renderer ren(*m_,m_req,variables,im,scale_factor_); + ren.start_map_processing(*m_); + std::vector const& layers = m_->layers(); + process_layers(ren,m_req,map_proj,layers,scale_denom); + ren.end_map_processing(*m_); + bool diff = false; + mapnik::image_data_rgba8 const& dest = im.data(); + mapnik::image_data_rgba8 const& src = im_.data(); + for (unsigned int y = 0; y < height_; ++y) + { + const unsigned int* row_from = src.getRow(y); + const unsigned int* row_to = dest.getRow(y); + for (unsigned int x = 0; x < width_; ++x) + { + if (row_from[x] != row_to[x]) diff = true; + } + } + if (diff) throw std::runtime_error("images differ"); + } + return true; } }; diff --git a/benchmark/test_to_bool.cpp b/benchmark/test_to_bool.cpp index 92f073156..83759baaa 100644 --- a/benchmark/test_to_bool.cpp +++ b/benchmark/test_to_bool.cpp @@ -16,13 +16,14 @@ public: mapnik::util::string2bool(value_,result); return (result == true); } - void operator()() const + bool operator()() const { for (std::size_t i=0;i, char32_t> utf32conv; for (std::size_t i=0;i(utf8_); } + return true; } }; @@ -80,13 +82,14 @@ public: utf32[3] != 0x5dd) return false; return true; } - void operator()() const + bool operator()() const { mapnik::transcoder tr_("utf-8"); mapnik::value_unicode_string utf32; for (std::size_t i=0;i +#include #include #include #endif @@ -53,7 +54,6 @@ using mapnik::image_reader; using mapnik::get_image_reader; using mapnik::type_from_filename; using mapnik::save_to_file; -using mapnik::save_to_string; using namespace boost::python; @@ -73,7 +73,7 @@ PyObject* tostring1( image_32 const& im) // encode (png,jpeg) PyObject* tostring2(image_32 const & im, std::string const& format) { - std::string s = save_to_string(im, format); + std::string s = mapnik::save_to_string(im.data(), format); return #if PY_VERSION_HEX >= 0x03000000 ::PyBytes_FromStringAndSize @@ -85,7 +85,7 @@ PyObject* tostring2(image_32 const & im, std::string const& format) PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba_palette const& pal) { - std::string s = save_to_string(im, format, pal); + std::string s = mapnik::save_to_string(im.data(), format, pal); return #if PY_VERSION_HEX >= 0x03000000 ::PyBytes_FromStringAndSize @@ -98,17 +98,17 @@ PyObject* tostring3(image_32 const & im, std::string const& format, mapnik::rgba void save_to_file1(mapnik::image_32 const& im, std::string const& filename) { - save_to_file(im,filename); + save_to_file(im.data(),filename); } void save_to_file2(mapnik::image_32 const& im, std::string const& filename, std::string const& type) { - save_to_file(im,filename,type); + save_to_file(im.data(),filename,type); } void save_to_file3(mapnik::image_32 const& im, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal) { - save_to_file(im,filename,type,pal); + save_to_file(im.data(),filename,type,pal); } bool painted(mapnik::image_32 const& im) @@ -120,12 +120,12 @@ bool is_solid(mapnik::image_32 const& im) { if (im.width() > 0 && im.height() > 0) { - mapnik::image_data_32 const & data = im.data(); - mapnik::image_data_32::pixel_type const* first_row = data.getRow(0); - mapnik::image_data_32::pixel_type const first_pixel = first_row[0]; + mapnik::image_data_rgba8 const & data = im.data(); + mapnik::image_data_rgba8::pixel_type const* first_row = data.getRow(0); + mapnik::image_data_rgba8::pixel_type const first_pixel = first_row[0]; for (unsigned y = 0; y < im.height(); ++y) { - mapnik::image_data_32::pixel_type const * row = data.getRow(y); + mapnik::image_data_rgba8::pixel_type const * row = data.getRow(y); for (unsigned x = 0; x < im.width(); ++x) { if (first_pixel != row[x]) @@ -142,7 +142,7 @@ unsigned get_pixel(mapnik::image_32 const& im, int x, int y) { if (x < static_cast(im.width()) && y < static_cast(im.height())) { - mapnik::image_data_32 const & data = im.data(); + mapnik::image_data_rgba8 const & data = im.data(); return data(x,y); } PyErr_SetString(PyExc_IndexError, "invalid x,y for image dimensions"); @@ -217,7 +217,8 @@ void composite(image_32 & dst, image_32 & src, mapnik::composite_mode_e mode, fl std::shared_ptr from_cairo(PycairoSurface* py_surface) { mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - std::shared_ptr image_ptr = std::make_shared(surface); + std::shared_ptr image_ptr = std::make_shared(cairo_image_surface_get_width(&*surface), cairo_image_surface_get_height(&*surface)); + cairo_image_to_rgba8(image_ptr->data(), surface); return image_ptr; } #endif diff --git a/bindings/python/mapnik_image_view.cpp b/bindings/python/mapnik_image_view.cpp index d68afa2a5..e08129f7f 100644 --- a/bindings/python/mapnik_image_view.cpp +++ b/bindings/python/mapnik_image_view.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,18 +42,18 @@ #include #include -using mapnik::image_data_32; +using mapnik::image_data_rgba8; using mapnik::image_view; using mapnik::save_to_file; // output 'raw' pixels -PyObject* view_tostring1(image_view const& view) +PyObject* view_tostring1(image_view const& view) { std::ostringstream ss(std::ios::out|std::ios::binary); for (unsigned i=0;i(view.getRow(i)), - view.width() * sizeof(image_view::pixel_type)); + view.width() * sizeof(image_view::pixel_type)); } return #if PY_VERSION_HEX >= 0x03000000 @@ -65,7 +65,7 @@ PyObject* view_tostring1(image_view const& view) } // encode (png,jpeg) -PyObject* view_tostring2(image_view const & view, std::string const& format) +PyObject* view_tostring2(image_view const & view, std::string const& format) { std::string s = save_to_string(view, format); return @@ -77,7 +77,7 @@ PyObject* view_tostring2(image_view const & view, std::string con (s.data(),s.size()); } -PyObject* view_tostring3(image_view const & view, std::string const& format, mapnik::rgba_palette const& pal) +PyObject* view_tostring3(image_view const & view, std::string const& format, mapnik::rgba_palette const& pal) { std::string s = save_to_string(view, format, pal); return @@ -89,15 +89,15 @@ PyObject* view_tostring3(image_view const & view, std::string con (s.data(),s.size()); } -bool is_solid(image_view const& view) +bool is_solid(image_view const& view) { if (view.width() > 0 && view.height() > 0) { - mapnik::image_view::pixel_type const* first_row = view.getRow(0); - mapnik::image_view::pixel_type const first_pixel = first_row[0]; + mapnik::image_view::pixel_type const* first_row = view.getRow(0); + mapnik::image_view::pixel_type const first_pixel = first_row[0]; for (unsigned y = 0; y < view.height(); ++y) { - mapnik::image_view::pixel_type const * row = view.getRow(y); + mapnik::image_view::pixel_type const * row = view.getRow(y); for (unsigned x = 0; x < view.width(); ++x) { if (first_pixel != row[x]) @@ -110,20 +110,20 @@ bool is_solid(image_view const& view) return true; } -void save_view1(image_view const& view, +void save_view1(image_view const& view, std::string const& filename) { save_to_file(view,filename); } -void save_view2(image_view const& view, +void save_view2(image_view const& view, std::string const& filename, std::string const& type) { save_to_file(view,filename,type); } -void save_view3(image_view const& view, +void save_view3(image_view const& view, std::string const& filename, std::string const& type, mapnik::rgba_palette const& pal) @@ -135,9 +135,9 @@ void save_view3(image_view const& view, void export_image_view() { using namespace boost::python; - class_ >("ImageView","A view into an image.",no_init) - .def("width",&image_view::width) - .def("height",&image_view::height) + class_ >("ImageView","A view into an image.",no_init) + .def("width",&image_view::width) + .def("height",&image_view::height) .def("is_solid",&is_solid) .def("tostring",&view_tostring1) .def("tostring",&view_tostring2) diff --git a/bindings/python/mapnik_label_collision_detector.cpp b/bindings/python/mapnik_label_collision_detector.cpp index 762f92570..eb16ea87d 100644 --- a/bindings/python/mapnik_label_collision_detector.cpp +++ b/bindings/python/mapnik_label_collision_detector.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp index e463afe75..405755bad 100644 --- a/bindings/python/mapnik_layer.cpp +++ b/bindings/python/mapnik_layer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_logger.cpp b/bindings/python/mapnik_logger.cpp index d26c2ff79..7c9591211 100644 --- a/bindings/python/mapnik_logger.cpp +++ b/bindings/python/mapnik_logger.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_map.cpp b/bindings/python/mapnik_map.cpp index 3363e53be..15ecc67fd 100644 --- a/bindings/python/mapnik_map.cpp +++ b/bindings/python/mapnik_map.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_palette.cpp b/bindings/python/mapnik_palette.cpp index 878ecb6b5..12cf2fdec 100644 --- a/bindings/python/mapnik_palette.cpp +++ b/bindings/python/mapnik_palette.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_parameters.cpp b/bindings/python/mapnik_parameters.cpp index 7074e726e..21504d3ba 100644 --- a/bindings/python/mapnik_parameters.cpp +++ b/bindings/python/mapnik_parameters.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -162,6 +162,11 @@ mapnik::parameter get_params_by_index(mapnik::parameters const& p, int index) throw boost::python::error_already_set(); } +unsigned get_params_size(mapnik::parameters const& p) +{ + return p.size(); +} + void add_parameter(mapnik::parameters & p, mapnik::parameter const& param) { p[param.first] = param.second; @@ -191,6 +196,12 @@ std::shared_ptr create_parameter(mapnik::value_unicode_string return std::make_shared(key_utf8,value); } +bool contains(mapnik::parameters const& p, std::string const& key) +{ + parameters::const_iterator pos = p.find(key); + return pos != p.end(); +} + // needed for Python_Unicode to std::string (utf8) conversion std::shared_ptr create_parameter_from_string(mapnik::value_unicode_string const& key, mapnik::value_unicode_string const& ustr) @@ -227,7 +238,8 @@ void export_parameters() .def("get",get_params_by_key1) .def("__getitem__",get_params_by_key2) .def("__getitem__",get_params_by_index) - .def("__len__",¶meters::size) + .def("__len__",get_params_size) + .def("__contains__",contains) .def("append",add_parameter) .def("iteritems",iterator()) ; diff --git a/bindings/python/mapnik_proj_transform.cpp b/bindings/python/mapnik_proj_transform.cpp index fa6f396ca..393d2b860 100644 --- a/bindings/python/mapnik_proj_transform.cpp +++ b/bindings/python/mapnik_proj_transform.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2009 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_projection.cpp b/bindings/python/mapnik_projection.cpp index 38cd53b3e..235fa9b6c 100644 --- a/bindings/python/mapnik_projection.cpp +++ b/bindings/python/mapnik_projection.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index 69075115a..73fba74f6 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,6 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedef" #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - #include "python_to_value.hpp" #include // for keywords, arg, etc #include @@ -202,13 +201,16 @@ void render(mapnik::Map const& map, void render_with_vars(mapnik::Map const& map, mapnik::image_32& image, - boost::python::dict const& d) + boost::python::dict const& d, + double scale_factor = 1.0, + unsigned offset_x = 0u, + unsigned offset_y = 0u) { mapnik::attributes vars = mapnik::dict2attr(d); mapnik::request req(map.width(),map.height(),map.get_current_extent()); req.set_buffer_size(map.buffer_size()); python_unblock_auto_block b; - mapnik::agg_renderer ren(map,req,vars,image,1,0,0); + mapnik::agg_renderer ren(map,req,vars,image,scale_factor,offset_x,offset_y); ren.apply(); } @@ -385,7 +387,7 @@ void render_to_file1(mapnik::Map const& map, { mapnik::image_32 image(map.width(),map.height()); render(map,image,1.0,0,0); - mapnik::save_to_file(image,filename,format); + mapnik::save_to_file(image.data(),filename,format); } } @@ -404,7 +406,7 @@ void render_to_file2(mapnik::Map const& map,std::string const& filename) { mapnik::image_32 image(map.width(),map.height()); render(map,image,1.0,0,0); - mapnik::save_to_file(image,filename); + mapnik::save_to_file(image.data(),filename); } } @@ -442,7 +444,7 @@ void render_to_file3(mapnik::Map const& map, { mapnik::image_32 image(map.width(),map.height()); render(map,image,scale_factor,0,0); - mapnik::save_to_file(image,filename,format); + mapnik::save_to_file(image.data(),filename,format); } } @@ -580,12 +582,15 @@ bool has_pycairo() } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedef" BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_overloads, load_map, 2, 4) BOOST_PYTHON_FUNCTION_OVERLOADS(load_map_string_overloads, load_map_string, 2, 4) BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_overloads, save_map, 2, 3) BOOST_PYTHON_FUNCTION_OVERLOADS(save_map_to_string_overloads, save_map_to_string, 1, 2) BOOST_PYTHON_FUNCTION_OVERLOADS(render_overloads, render, 2, 5) BOOST_PYTHON_FUNCTION_OVERLOADS(render_with_detector_overloads, render_with_detector, 3, 6) +#pragma GCC diagnostic pop BOOST_PYTHON_MODULE(_mapnik) { @@ -707,7 +712,15 @@ BOOST_PYTHON_MODULE(_mapnik) "\n" ); - def("render_with_vars",&render_with_vars); + def("render_with_vars",&render_with_vars, + (arg("map"), + arg("image"), + arg("vars"), + arg("scale_factor")=1.0, + arg("offset_x")=0, + arg("offset_y")=0 + ) + ); def("render", &render, render_overloads( "\n" diff --git a/bindings/python/mapnik_query.cpp b/bindings/python/mapnik_query.cpp index 893d83631..210182f18 100644 --- a/bindings/python/mapnik_query.cpp +++ b/bindings/python/mapnik_query.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_raster_colorizer.cpp b/bindings/python/mapnik_raster_colorizer.cpp index 725ea166b..413ef84f4 100644 --- a/bindings/python/mapnik_raster_colorizer.cpp +++ b/bindings/python/mapnik_raster_colorizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2010 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp index 53fa4ad21..f4b5cd856 100644 --- a/bindings/python/mapnik_rule.cpp +++ b/bindings/python/mapnik_rule.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_scaling_method.cpp b/bindings/python/mapnik_scaling_method.cpp index 495d38007..1a2c62a4e 100644 --- a/bindings/python/mapnik_scaling_method.cpp +++ b/bindings/python/mapnik_scaling_method.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_style.cpp b/bindings/python/mapnik_style.cpp index 0658f9bf9..6f7762063 100644 --- a/bindings/python/mapnik_style.cpp +++ b/bindings/python/mapnik_style.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_symbolizer.cpp b/bindings/python/mapnik_symbolizer.cpp index 2175b595e..ef23bdb98 100644 --- a/bindings/python/mapnik_symbolizer.cpp +++ b/bindings/python/mapnik_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -105,7 +105,7 @@ std::shared_ptr numeric_wrapper(const objec return result; } -struct extract_python_object : public mapnik::util::static_visitor +struct extract_python_object { using result_type = boost::python::object; @@ -153,7 +153,7 @@ std::size_t hash_impl_2(T const& sym) return mapnik::symbolizer_hash::value(sym); } -struct extract_underlying_type_visitor : mapnik::util::static_visitor +struct extract_underlying_type_visitor { template boost::python::object operator() (T const& sym) const diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index 8ab723e90..955f49b7a 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/mapnik_threads.hpp b/bindings/python/mapnik_threads.hpp index 930ff374c..e48a707e4 100644 --- a/bindings/python/mapnik_threads.hpp +++ b/bindings/python/mapnik_threads.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #include // for thread_specific_ptr #include - + namespace mapnik { class python_thread { diff --git a/bindings/python/mapnik_value_converter.hpp b/bindings/python/mapnik_value_converter.hpp index 42b9ba4bc..4f152a035 100644 --- a/bindings/python/mapnik_value_converter.hpp +++ b/bindings/python/mapnik_value_converter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ namespace boost { namespace python { - struct value_converter : public mapnik::util::static_visitor + struct value_converter { PyObject * operator() (mapnik::value_integer val) const { diff --git a/bindings/python/mapnik_view_transform.cpp b/bindings/python/mapnik_view_transform.cpp index d2194b1f6..b6c9a2058 100644 --- a/bindings/python/mapnik_view_transform.cpp +++ b/bindings/python/mapnik_view_transform.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2009 Artem Pavlenko, Jean-Francois Doyon + * Copyright (C) 2014 Artem Pavlenko, Jean-Francois Doyon * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/python_grid_utils.cpp b/bindings/python/python_grid_utils.cpp index cbb9ad19a..980737c77 100644 --- a/bindings/python/python_grid_utils.cpp +++ b/bindings/python/python_grid_utils.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/python_grid_utils.hpp b/bindings/python/python_grid_utils.hpp index f6089449f..320b342a8 100644 --- a/bindings/python/python_grid_utils.hpp +++ b/bindings/python/python_grid_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/bindings/python/python_optional.hpp b/bindings/python/python_optional.hpp index 3270679f5..91585c2ae 100644 --- a/bindings/python/python_optional.hpp +++ b/bindings/python/python_optional.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2007 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,7 +23,7 @@ #include #include -#include +#include // boost::optional to/from converter from John Wiegley @@ -47,7 +47,7 @@ struct register_python_conversion }; template -struct python_optional : public mapnik::noncopyable +struct python_optional : public mapnik::util::noncopyable { struct optional_to_python { @@ -104,7 +104,7 @@ struct python_optional : public mapnik::noncopyable // to/from boost::optional template <> -struct python_optional : public mapnik::noncopyable +struct python_optional : public mapnik::util::noncopyable { struct optional_to_python { @@ -149,7 +149,7 @@ struct python_optional : public mapnik::noncopyable // to/from boost::optional template <> -struct python_optional : public mapnik::noncopyable +struct python_optional : public mapnik::util::noncopyable { struct optional_to_python { diff --git a/bindings/python/python_to_value.hpp b/bindings/python/python_to_value.hpp index da4830e8a..198305cc1 100644 --- a/bindings/python/python_to_value.hpp +++ b/bindings/python/python_to_value.hpp @@ -35,7 +35,6 @@ #include #include - namespace mapnik { static mapnik::attributes dict2attr(boost::python::dict const& d) @@ -46,7 +45,26 @@ namespace mapnik { boost::python::list keys=d.keys(); for (int i=0; i < len(keys); ++i) { - std::string key = extract(keys[i]); + std::string key; + object obj_key = keys[i]; + if (PyUnicode_Check(obj_key.ptr())) + { + PyObject* temp = PyUnicode_AsUTF8String(obj_key.ptr()); + if (temp) + { + #if PY_VERSION_HEX >= 0x03000000 + char* c_str = PyBytes_AsString(temp); + #else + char* c_str = PyString_AsString(temp); + #endif + key = c_str; + Py_DecRef(temp); + } + } + else + { + key = extract(keys[i]); + } object obj = d[key]; if (PyUnicode_Check(obj.ptr())) { @@ -64,29 +82,37 @@ namespace mapnik { continue; } - extract ex0(obj); - if (ex0.check()) + if (PyBool_Check(obj.ptr())) { - vars[key] = tr_.transcode(ex0().c_str()); - continue; + extract ex(obj); + if (ex.check()) + { + vars[key] = ex(); + } } - extract ex2(obj); - if (ex2.check()) + else if (PyFloat_Check(obj.ptr())) { - vars[key] = ex2(); - continue; + extract ex(obj); + if (ex.check()) + { + vars[key] = ex(); + } } - extract ex3(obj); - if (ex3.check()) + else { - vars[key] = ex3(); - continue; - } - extract ex1(obj); - if (ex1.check()) - { - vars[key] = ex1(); - continue; + extract ex(obj); + if (ex.check()) + { + vars[key] = ex(); + } + else + { + extract ex0(obj); + if (ex0.check()) + { + vars[key] = tr_.transcode(ex0().c_str()); + } + } } } return vars; diff --git a/demo/c++/rundemo.cpp b/demo/c++/rundemo.cpp index 33fca60f2..bb354fdeb 100644 --- a/demo/c++/rundemo.cpp +++ b/demo/c++/rundemo.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,6 +40,7 @@ #if defined(HAVE_CAIRO) #include +#include #endif #include @@ -309,21 +310,21 @@ int main ( int, char** ) ren.apply(); std::string msg("These maps have been rendered using AGG in the current directory:\n"); #ifdef HAVE_JPEG - save_to_file(buf,"demo.jpg","jpeg"); + save_to_file(buf.data(),"demo.jpg","jpeg"); msg += "- demo.jpg\n"; #endif #ifdef HAVE_PNG - save_to_file(buf,"demo.png","png"); - save_to_file(buf,"demo256.png","png8"); + save_to_file(buf.data(),"demo.png","png"); + save_to_file(buf.data(),"demo256.png","png8"); msg += "- demo.png\n"; msg += "- demo256.png\n"; #endif #ifdef HAVE_TIFF - save_to_file(buf,"demo.tif","tiff"); + save_to_file(buf.data(),"demo.tif","tiff"); msg += "- demo.tif\n"; #endif #ifdef HAVE_WEBP - save_to_file(buf,"demo.webp","webp"); + save_to_file(buf.data(),"demo.webp","webp"); msg += "- demo.webp\n"; #endif msg += "Have a look!\n"; @@ -352,8 +353,9 @@ int main ( int, char** ) cairo_surface_write_to_png(&*image_surface, "cairo-demo.png"); // but we can also benefit from quantization by converting // to a mapnik image object and then saving that - image_32 im(image_surface); - save_to_file(im, "cairo-demo256.png","png8"); + mapnik::image_data_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface)); + cairo_image_to_rgba8(im_data, image_surface); + save_to_file(im_data, "cairo-demo256.png","png8"); cairo_surface_finish(&*image_surface); std::cout << "Three maps have been rendered using Cairo in the current directory:\n" diff --git a/demo/python/rundemo.py b/demo/python/rundemo.py index 9bd258d64..65ebe6a77 100755 --- a/demo/python/rundemo.py +++ b/demo/python/rundemo.py @@ -23,13 +23,7 @@ import sys from os import path -try: - import mapnik -except: - print '\n\nThe mapnik library and python bindings must have been compiled and \ -installed successfully before running this script.\n\n' - sys.exit(1) - +import mapnik # Instanciate a map, giving it a width and height. Remember: the word "map" is # reserved in Python! :) diff --git a/demo/viewer/about_dialog.cpp b/demo/viewer/about_dialog.cpp index 270db196f..468a29898 100644 --- a/demo/viewer/about_dialog.cpp +++ b/demo/viewer/about_dialog.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/about_dialog.hpp b/demo/viewer/about_dialog.hpp index 8411a4dc0..b555a6d5f 100644 --- a/demo/viewer/about_dialog.hpp +++ b/demo/viewer/about_dialog.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/info_dialog.cpp b/demo/viewer/info_dialog.cpp index 734293d52..37c243d69 100644 --- a/demo/viewer/info_dialog.cpp +++ b/demo/viewer/info_dialog.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/info_dialog.hpp b/demo/viewer/info_dialog.hpp index 754c1a96f..8ac762022 100644 --- a/demo/viewer/info_dialog.hpp +++ b/demo/viewer/info_dialog.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layer_info_dialog.cpp b/demo/viewer/layer_info_dialog.cpp index c9dfeb876..6d176e8f2 100644 --- a/demo/viewer/layer_info_dialog.cpp +++ b/demo/viewer/layer_info_dialog.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layer_info_dialog.hpp b/demo/viewer/layer_info_dialog.hpp index 9b9d2abc2..9cea6e81f 100644 --- a/demo/viewer/layer_info_dialog.hpp +++ b/demo/viewer/layer_info_dialog.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layerdelegate.cpp b/demo/viewer/layerdelegate.cpp index 73f6f17fa..93b50595c 100644 --- a/demo/viewer/layerdelegate.cpp +++ b/demo/viewer/layerdelegate.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -52,4 +52,3 @@ QSize LayerDelegate::sizeHint(const QStyleOptionViewItem & /* option */, { return QSize(120,24); } - diff --git a/demo/viewer/layerdelegate.hpp b/demo/viewer/layerdelegate.hpp index 616b6f53d..53fd8b381 100644 --- a/demo/viewer/layerdelegate.hpp +++ b/demo/viewer/layerdelegate.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layerlistmodel.cpp b/demo/viewer/layerlistmodel.cpp index 4b1a89a8d..fccfdfdd7 100644 --- a/demo/viewer/layerlistmodel.cpp +++ b/demo/viewer/layerlistmodel.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layerlistmodel.hpp b/demo/viewer/layerlistmodel.hpp index f25a81f59..cc2b73fb7 100644 --- a/demo/viewer/layerlistmodel.hpp +++ b/demo/viewer/layerlistmodel.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layerwidget.cpp b/demo/viewer/layerwidget.cpp index 876d6b13f..93dea25af 100644 --- a/demo/viewer/layerwidget.cpp +++ b/demo/viewer/layerwidget.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/layerwidget.hpp b/demo/viewer/layerwidget.hpp index a3b163c29..d19a16a0e 100644 --- a/demo/viewer/layerwidget.hpp +++ b/demo/viewer/layerwidget.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/main.cpp b/demo/viewer/main.cpp index 3274c5035..da915d374 100644 --- a/demo/viewer/main.cpp +++ b/demo/viewer/main.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/mainwindow.cpp b/demo/viewer/mainwindow.cpp index 6df6fd80e..442b99068 100644 --- a/demo/viewer/mainwindow.cpp +++ b/demo/viewer/mainwindow.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/mainwindow.hpp b/demo/viewer/mainwindow.hpp index b9859ed18..d0943dc91 100644 --- a/demo/viewer/mainwindow.hpp +++ b/demo/viewer/mainwindow.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/mapwidget.cpp b/demo/viewer/mapwidget.cpp index bfcf594c7..59e396893 100644 --- a/demo/viewer/mapwidget.cpp +++ b/demo/viewer/mapwidget.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef HAVE_CAIRO // cairo @@ -539,7 +540,9 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix) mapnik::cairo_renderer renderer(map, cairo, scaling_factor); renderer.apply(); } - image_32 buf(image_surface); + mapnik::image_data_rgba8 data(map.width(), map.height()); + mapnik::cairo_image_to_rgba8(data, image_surface); + image_32 buf(std::move(data)); QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32); pix = QPixmap::fromImage(image.rgbSwapped()); #endif diff --git a/demo/viewer/mapwidget.hpp b/demo/viewer/mapwidget.hpp index e3cff1a98..2373d584c 100644 --- a/demo/viewer/mapwidget.hpp +++ b/demo/viewer/mapwidget.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/demo/viewer/styles_model.cpp b/demo/viewer/styles_model.cpp index 56ef842c8..d8afc2631 100644 --- a/demo/viewer/styles_model.cpp +++ b/demo/viewer/styles_model.cpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -35,7 +35,7 @@ #include #include -class node : private mapnik::noncopyable +class node : private mapnik::util::noncopyable { struct node_base { @@ -122,7 +122,7 @@ private: }; -struct symbolizer_info : public mapnik::util::static_visitor +struct symbolizer_info { QString operator() (mapnik::point_symbolizer const& sym) const { @@ -185,7 +185,7 @@ struct symbolizer_info : public mapnik::util::static_visitor } }; -struct symbolizer_icon : public mapnik::util::static_visitor +struct symbolizer_icon { QIcon operator() (mapnik::polygon_symbolizer const& sym) const { @@ -201,7 +201,7 @@ struct symbolizer_icon : public mapnik::util::static_visitor { // FIXME! /* - std::shared_ptr symbol = sym.get_image(); + std::shared_ptr symbol = sym.get_image(); if (symbol) { QImage image(symbol->getBytes(), diff --git a/demo/viewer/styles_model.hpp b/demo/viewer/styles_model.hpp index 17af661ed..407ec5974 100644 --- a/demo/viewer/styles_model.hpp +++ b/demo/viewer/styles_model.hpp @@ -1,6 +1,6 @@ /* This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * Mapnik is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/deps/agg/include/agg_color_gray.h b/deps/agg/include/agg_color_gray.h index 8e782ef2c..2fc01bd71 100644 --- a/deps/agg/include/agg_color_gray.h +++ b/deps/agg/include/agg_color_gray.h @@ -2,8 +2,8 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // @@ -13,12 +13,12 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Adaptation for high precision colors has been sponsored by +// Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- // // color types gray8, gray16 @@ -34,378 +34,1005 @@ namespace agg { - //===================================================================gray8 - struct gray8 +//===================================================================gray8 +template +struct gray8T +{ + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e { - typedef int8u value_type; - typedef int32u calc_type; - typedef int32 long_type; - enum base_scale_e + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef gray8T self_type; + + value_type v; + value_type a; + + static value_type luminance(const rgba& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); + } + + static value_type luminance(const rgba8& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type((55u * c.r + 184u * c.g + 18u * c.b) >> 8); + } + + static void convert(gray8T& dst, const gray8T& src) + { + dst.v = sRGB_conv::rgb_from_sRGB(src.v); + dst.a = src.a; + } + + static void convert(gray8T& dst, const gray8T& src) + { + dst.v = sRGB_conv::rgb_to_sRGB(src.v); + dst.a = src.a; + } + + static void convert(gray8T& dst, const rgba8& src) + { + dst.v = luminance(src); + dst.a = src.a; + } + + static void convert(gray8T& dst, const srgba8& src) + { + // The RGB weights are only valid for linear values. + convert(dst, rgba8(src)); + } + + static void convert(gray8T& dst, const rgba8& src) + { + dst.v = sRGB_conv::rgb_to_sRGB(luminance(src)); + dst.a = src.a; + } + + static void convert(gray8T& dst, const srgba8& src) + { + // The RGB weights are only valid for linear values. + convert(dst, rgba8(src)); + } + + //-------------------------------------------------------------------- + gray8T() {} + + //-------------------------------------------------------------------- + gray8T(unsigned v_, unsigned a_=base_mask) : + v(int8u(v_)), a(int8u(a_)) {} + + //-------------------------------------------------------------------- + gray8T(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + gray8T(const rgba& c) : + v(luminance(c)), + a(value_type(uround(c.a * base_mask))) {} + + //-------------------------------------------------------------------- + template + gray8T(const gray8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + template + gray8T(const rgba8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + template + T convert_from_sRGB() const + { + typename T::value_type y = sRGB_conv::rgb_from_sRGB(v); + return T(y, y, y, sRGB_conv::alpha_from_sRGB(a)); + } + + template + T convert_to_sRGB() const + { + typename T::value_type y = sRGB_conv::rgb_to_sRGB(v); + return T(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + rgba8 make_rgba8(const linear&) const + { + return rgba8(v, v, v, a); + } + + rgba8 make_rgba8(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba8() const + { + return make_rgba8(Colorspace()); + } + + //-------------------------------------------------------------------- + srgba8 make_srgba8(const linear&) const + { + return convert_to_sRGB(); + } + + srgba8 make_srgba8(const sRGB&) const + { + return srgba8(v, v, v, a); + } + + operator srgba8() const + { + return make_rgba8(Colorspace()); + } + + //-------------------------------------------------------------------- + rgba16 make_rgba16(const linear&) const + { + rgba16::value_type rgb = (v << 8) | v; + return rgba16(rgb, rgb, rgb, (a << 8) | a); + } + + rgba16 make_rgba16(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba16() const + { + return make_rgba16(Colorspace()); + } + + //-------------------------------------------------------------------- + rgba32 make_rgba32(const linear&) const + { + rgba32::value_type v32 = v / 255.0; + return rgba32(v32, v32, v32, a / 255.0); + } + + rgba32 make_rgba32(const sRGB&) const + { + return convert_from_sRGB(); + } + + operator rgba32() const + { + return make_rgba32(Colorspace()); + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return double(a) / base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(uround(a * base_mask)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) { - base_shift = 8, - base_scale = 1 << base_shift, - base_mask = base_scale - 1 - }; - typedef gray8 self_type; - - value_type v; - value_type a; - - //-------------------------------------------------------------------- - gray8() {} - - //-------------------------------------------------------------------- - gray8(unsigned v_, unsigned a_=base_mask) : - v(int8u(v_)), a(int8u(a_)) {} - - //-------------------------------------------------------------------- - gray8(const self_type& c, unsigned a_) : - v(c.v), a(value_type(a_)) {} - - //-------------------------------------------------------------------- - gray8(const rgba& c) : - v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), - a((value_type)uround(c.a * double(base_mask))) {} - - //-------------------------------------------------------------------- - gray8(const rgba& c, double a_) : - v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), - a((value_type)uround(a_ * double(base_mask))) {} - - //-------------------------------------------------------------------- - gray8(const rgba8& c) : - v((c.r*77 + c.g*150 + c.b*29) >> 8), - a(c.a) {} - - //-------------------------------------------------------------------- - gray8(const rgba8& c, unsigned a_) : - v((c.r*77 + c.g*150 + c.b*29) >> 8), - a(a_) {} - - //-------------------------------------------------------------------- - void clear() - { - v = a = 0; + return 0; } - - //-------------------------------------------------------------------- - const self_type& transparent() + else if (a >= b) { - a = 0; - return *this; + return base_mask; } + else return value_type((a * base_mask + (b >> 1)) / b); + } - //-------------------------------------------------------------------- - void opacity(double a_) + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + // Specifically for multiplying a color component by a cover. + static AGG_INLINE value_type mult_cover(value_type a, value_type b) + { + return multiply(a, b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return multiply(b, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return p + q - multiply(p, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& opacity(double a_) + { + if (a_ < 0) a_ = 0; + else if (a_ > 1) a_ = 1; + else a = (value_type)uround(a_ * double(base_mask)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + self_type& premultiply() + { + if (a < base_mask) { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = (value_type)uround(a_ * double(base_mask)); + if (a == 0) v = 0; + else v = multiply(v, a); } + return *this; + } - //-------------------------------------------------------------------- - double opacity() const + //-------------------------------------------------------------------- + self_type& demultiply() + { + if (a < base_mask) { - return double(a) / double(base_mask); - } - - - //-------------------------------------------------------------------- - const self_type& premultiply() - { - if(a == base_mask) return *this; - if(a == 0) + if (a == 0) { v = 0; - return *this; - } - v = value_type((calc_type(v) * a) >> base_shift); - return *this; - } - - //-------------------------------------------------------------------- - const self_type& premultiply(unsigned a_) - { - if(a == base_mask && a_ >= base_mask) return *this; - if(a == 0 || a_ == 0) - { - v = a = 0; - return *this; - } - calc_type v_ = (calc_type(v) * a_) / a; - v = value_type((v_ > a_) ? a_ : v_); - a = value_type(a_); - return *this; - } - - //-------------------------------------------------------------------- - const self_type& demultiply() - { - if(a == base_mask) return *this; - if(a == 0) - { - v = 0; - return *this; - } - calc_type v_ = (calc_type(v) * base_mask) / a; - v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); - return *this; - } - - //-------------------------------------------------------------------- - self_type gradient(self_type c, double k) const - { - self_type ret; - calc_type ik = uround(k * base_scale); - ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); - ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); - return ret; - } - - //-------------------------------------------------------------------- - AGG_INLINE void add(const self_type& c, unsigned cover) - { - calc_type cv, ca; - if(cover == cover_mask) - { - if(c.a == base_mask) - { - *this = c; - } - else - { - cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; - ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; - } } else { - cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); - ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); - v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; - a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? (value_type)base_mask : v_); } } - - //-------------------------------------------------------------------- - static self_type no_color() { return self_type(0,0); } - }; - - - //-------------------------------------------------------------gray8_pre - inline gray8 gray8_pre(unsigned v, unsigned a = gray8::base_mask) - { - return gray8(v,a).premultiply(); - } - inline gray8 gray8_pre(const gray8& c, unsigned a) - { - return gray8(c,a).premultiply(); - } - inline gray8 gray8_pre(const rgba& c) - { - return gray8(c).premultiply(); - } - inline gray8 gray8_pre(const rgba& c, double a) - { - return gray8(c,a).premultiply(); - } - inline gray8 gray8_pre(const rgba8& c) - { - return gray8(c).premultiply(); - } - inline gray8 gray8_pre(const rgba8& c, unsigned a) - { - return gray8(c,a).premultiply(); + return *this; } - - - - //==================================================================gray16 - struct gray16 + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const { - typedef int16u value_type; - typedef int32u calc_type; - typedef int64 long_type; - enum base_scale_e + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = lerp(v, c.v, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if (cover == cover_mask) { - base_shift = 16, - base_scale = 1 << base_shift, - base_mask = base_scale - 1 - }; - typedef gray16 self_type; - - value_type v; - value_type a; - - //-------------------------------------------------------------------- - gray16() {} - - //-------------------------------------------------------------------- - gray16(unsigned v_, unsigned a_=base_mask) : - v(int16u(v_)), a(int16u(a_)) {} - - //-------------------------------------------------------------------- - gray16(const self_type& c, unsigned a_) : - v(c.v), a(value_type(a_)) {} - - //-------------------------------------------------------------------- - gray16(const rgba& c) : - v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), - a((value_type)uround(c.a * double(base_mask))) {} - - //-------------------------------------------------------------------- - gray16(const rgba& c, double a_) : - v((value_type)uround((0.299*c.r + 0.587*c.g + 0.114*c.b) * double(base_mask))), - a((value_type)uround(a_ * double(base_mask))) {} - - //-------------------------------------------------------------------- - gray16(const rgba8& c) : - v(c.r*77 + c.g*150 + c.b*29), - a((value_type(c.a) << 8) | c.a) {} - - //-------------------------------------------------------------------- - gray16(const rgba8& c, unsigned a_) : - v(c.r*77 + c.g*150 + c.b*29), - a((value_type(a_) << 8) | c.a) {} - - //-------------------------------------------------------------------- - void clear() - { - v = a = 0; - } - - //-------------------------------------------------------------------- - const self_type& transparent() - { - a = 0; - return *this; - } - - //-------------------------------------------------------------------- - void opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = (value_type)uround(a_ * double(base_mask)); - } - - //-------------------------------------------------------------------- - double opacity() const - { - return double(a) / double(base_mask); - } - - - //-------------------------------------------------------------------- - const self_type& premultiply() - { - if(a == base_mask) return *this; - if(a == 0) + if (c.a == base_mask) { - v = 0; - return *this; - } - v = value_type((calc_type(v) * a) >> base_shift); - return *this; - } - - //-------------------------------------------------------------------- - const self_type& premultiply(unsigned a_) - { - if(a == base_mask && a_ >= base_mask) return *this; - if(a == 0 || a_ == 0) - { - v = a = 0; - return *this; - } - calc_type v_ = (calc_type(v) * a_) / a; - v = value_type((v_ > a_) ? a_ : v_); - a = value_type(a_); - return *this; - } - - //-------------------------------------------------------------------- - const self_type& demultiply() - { - if(a == base_mask) return *this; - if(a == 0) - { - v = 0; - return *this; - } - calc_type v_ = (calc_type(v) * base_mask) / a; - v = value_type((v_ > base_mask) ? base_mask : v_); - return *this; - } - - //-------------------------------------------------------------------- - self_type gradient(self_type c, double k) const - { - self_type ret; - calc_type ik = uround(k * base_scale); - ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); - ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); - return ret; - } - - //-------------------------------------------------------------------- - AGG_INLINE void add(const self_type& c, unsigned cover) - { - calc_type cv, ca; - if(cover == cover_mask) - { - if(c.a == base_mask) - { - *this = c; - } - else - { - cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; - ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; - } + *this = c; + return; } else { - cv = v + ((c.v * cover + cover_mask/2) >> cover_shift); - ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); - v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; - a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + cv = v + c.v; + ca = a + c.a; } } + else + { + cv = v + mult_cover(c.v, cover); + ca = a + mult_cover(c.a, cover); + } + v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } - //-------------------------------------------------------------------- - static self_type no_color() { return self_type(0,0); } + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } +}; + +typedef gray8T gray8; +typedef gray8T sgray8; + + +//==================================================================gray16 +struct gray16 +{ + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) + }; + typedef gray16 self_type; + + value_type v; + value_type a; + + static value_type luminance(const rgba& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type(uround((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * base_mask)); + } + + static value_type luminance(const rgba16& c) + { + // Calculate grayscale value as per ITU-R BT.709. + return value_type((13933u * c.r + 46872u * c.g + 4732u * c.b) >> 16); + } + + static value_type luminance(const rgba8& c) + { + return luminance(rgba16(c)); + } + + static value_type luminance(const srgba8& c) + { + return luminance(rgba16(c)); + } + + static value_type luminance(const rgba32& c) + { + return luminance(rgba(c)); + } + + //-------------------------------------------------------------------- + gray16() {} + + //-------------------------------------------------------------------- + gray16(unsigned v_, unsigned a_ = base_mask) : + v(int16u(v_)), a(int16u(a_)) {} + + //-------------------------------------------------------------------- + gray16(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + gray16(const rgba& c) : + v(luminance(c)), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + gray16(const rgba8& c) : + v(luminance(c)), + a((value_type(c.a) << 8) | c.a) {} + + //-------------------------------------------------------------------- + gray16(const srgba8& c) : + v(luminance(c)), + a((value_type(c.a) << 8) | c.a) {} + + //-------------------------------------------------------------------- + gray16(const rgba16& c) : + v(luminance(c)), + a(c.a) {} + + //-------------------------------------------------------------------- + gray16(const gray8& c) : + v((value_type(c.v) << 8) | c.v), + a((value_type(c.a) << 8) | c.a) {} + + //-------------------------------------------------------------------- + gray16(const sgray8& c) : + v(sRGB_conv::rgb_from_sRGB(c.v)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + operator rgba8() const + { + return rgba8(v >> 8, v >> 8, v >> 8, a >> 8); + } + + //-------------------------------------------------------------------- + operator srgba8() const + { + value_type y = sRGB_conv::rgb_to_sRGB(v); + return srgba8(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator rgba16() const + { + return rgba16(v, v, v, a); + } + + //-------------------------------------------------------------------- + operator gray8() const + { + return gray8(v >> 8, a >> 8); + } + + //-------------------------------------------------------------------- + operator sgray8() const + { + return sgray8( + sRGB_conv::rgb_to_sRGB(v), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return double(a) / base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(uround(a * base_mask)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int16u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, almost exact over int16u. + // Specifically for multiplying a color component by a cover. + static AGG_INLINE value_type mult_cover(value_type a, cover_type b) + { + return multiply(a, b << 8 | b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return mult_cover(b, a) >> 8; + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return p + q - multiply(p, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& opacity(double a_) + { + if (a_ < 0) a_ = 0; + else if(a_ > 1) a_ = 1; + else a = (value_type)uround(a_ * double(base_mask)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + self_type& premultiply() + { + if (a < base_mask) + { + if(a == 0) v = 0; + else v = multiply(v, a); + } + return *this; + } + + //-------------------------------------------------------------------- + self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + v = 0; + } + else + { + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? base_mask : v_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_scale); + ret.v = lerp(v, c.v, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cv = v + c.v; + ca = a + c.a; + } + } + else + { + cv = v + mult_cover(c.v, cover); + ca = a + mult_cover(c.a, cover); + } + v = (value_type)((cv > calc_type(base_mask)) ? calc_type(base_mask) : cv); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } +}; + + +//===================================================================gray32 +struct gray32 +{ + typedef float value_type; + typedef double calc_type; + typedef double long_type; + typedef gray32 self_type; + + value_type v; + value_type a; + + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, }; + // Calculate grayscale value as per ITU-R BT.709. + static value_type luminance(double r, double g, double b) + { + return value_type(0.2126 * r + 0.7152 * g + 0.0722 * b); + } - //------------------------------------------------------------gray16_pre - inline gray16 gray16_pre(unsigned v, unsigned a = gray16::base_mask) + static value_type luminance(const rgba& c) { - return gray16(v,a).premultiply(); + return luminance(c.r, c.g, c.b); } - inline gray16 gray16_pre(const gray16& c, unsigned a) + + static value_type luminance(const rgba32& c) { - return gray16(c,a).premultiply(); + return luminance(c.r, c.g, c.b); } - inline gray16 gray16_pre(const rgba& c) + + static value_type luminance(const rgba8& c) { - return gray16(c).premultiply(); + return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); } - inline gray16 gray16_pre(const rgba& c, double a) + + static value_type luminance(const rgba16& c) { - return gray16(c,a).premultiply(); + return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); } - inline gray16 gray16_pre(const rgba8& c) + + //-------------------------------------------------------------------- + gray32() {} + + //-------------------------------------------------------------------- + gray32(value_type v_, value_type a_ = 1) : + v(v_), a(a_) {} + + //-------------------------------------------------------------------- + gray32(const self_type& c, value_type a_) : + v(c.v), a(a_) {} + + //-------------------------------------------------------------------- + gray32(const rgba& c) : + v(luminance(c)), + a(value_type(c.a)) {} + + //-------------------------------------------------------------------- + gray32(const rgba8& c) : + v(luminance(c)), + a(value_type(c.a / 255.0)) {} + + //-------------------------------------------------------------------- + gray32(const srgba8& c) : + v(luminance(rgba32(c))), + a(value_type(c.a / 255.0)) {} + + //-------------------------------------------------------------------- + gray32(const rgba16& c) : + v(luminance(c)), + a(value_type(c.a / 65535.0)) {} + + //-------------------------------------------------------------------- + gray32(const rgba32& c) : + v(luminance(c)), + a(value_type(c.a)) {} + + //-------------------------------------------------------------------- + gray32(const gray8& c) : + v(value_type(c.v / 255.0)), + a(value_type(c.a / 255.0)) {} + + //-------------------------------------------------------------------- + gray32(const sgray8& c) : + v(sRGB_conv::rgb_from_sRGB(c.v)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + gray32(const gray16& c) : + v(value_type(c.v / 65535.0)), + a(value_type(c.a / 65535.0)) {} + + //-------------------------------------------------------------------- + operator rgba() const { - return gray16(c).premultiply(); + return rgba(v, v, v, a); } - inline gray16 gray16_pre(const rgba8& c, unsigned a) + + //-------------------------------------------------------------------- + operator gray8() const { - return gray16(c,a).premultiply(); + return gray8(uround(v * 255.0), uround(a * 255.0)); + } + + //-------------------------------------------------------------------- + operator sgray8() const + { + // Return (non-premultiplied) sRGB values. + return sgray8( + sRGB_conv::rgb_to_sRGB(v), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator gray16() const + { + return gray16(uround(v * 65535.0), uround(a * 65535.0)); + } + + //-------------------------------------------------------------------- + operator rgba8() const + { + rgba8::value_type y = uround(v * 255.0); + return rgba8(y, y, y, uround(a * 255.0)); + } + + //-------------------------------------------------------------------- + operator srgba8() const + { + srgba8::value_type y = sRGB_conv::rgb_to_sRGB(v); + return srgba8(y, y, y, sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator rgba16() const + { + rgba16::value_type y = uround(v * 65535.0); + return rgba16(y, y, y, uround(a * 65535.0)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(a); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return 1; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a <= 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a >= 1; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return 1 - x; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + return value_type(a * b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + return (b == 0) ? 0 : value_type(a / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return n > 0 ? a / (1 << n) : a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type mult_cover(value_type a, cover_type b) + { + return value_type(a * b / cover_mask); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return cover_type(uround(a * b)); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return (1 - a) * p + q; // more accurate than "p + q - p * a" + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + // The form "p + a * (q - p)" avoids a multiplication, but may produce an + // inaccurate result. For example, "p + (q - p)" may not be exactly equal + // to q. Therefore, stick to the basic expression, which at least produces + // the correct result at either extreme. + return (1 - a) * p + a * q; + } + + //-------------------------------------------------------------------- + self_type& clear() + { + v = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& opacity(double a_) + { + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; + else a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; } + //-------------------------------------------------------------------- + self_type& premultiply() + { + if (a < 0) v = 0; + else if(a < 1) v *= a; + return *this; + } + + //-------------------------------------------------------------------- + self_type& demultiply() + { + if (a < 0) v = 0; + else if (a < 1) v /= a; + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + return self_type( + value_type(v + (c.v - v) * k), + value_type(a + (c.a - a) * k)); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } +}; } diff --git a/deps/agg/include/agg_color_rgba.h b/deps/agg/include/agg_color_rgba.h index 199537454..2950467e4 100644 --- a/deps/agg/include/agg_color_rgba.h +++ b/deps/agg/include/agg_color_rgba.h @@ -2,19 +2,19 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // //---------------------------------------------------------------------------- // -// Adaptation for high precision colors has been sponsored by +// Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- // Contact: mcseem@antigrain.com // mcseemagg@yahoo.com @@ -26,716 +26,1337 @@ #include #include "agg_basics.h" +#include "agg_gamma_lut.h" namespace agg { - // Supported byte orders for RGB and RGBA pixel formats - //======================================================================= - struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag }; }; //----order_rgb - struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag }; }; //----order_bgr - struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag }; }; //----order_rgba - struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag }; }; //----order_argb - struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag }; }; //----order_abgr - struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag }; }; //----order_bgra +// Supported byte orders for RGB and RGBA pixel formats +//======================================================================= +struct order_rgb { enum rgb_e { R=0, G=1, B=2, rgb_tag, hasAlpha=false }; }; //----order_rgb +struct order_bgr { enum bgr_e { B=0, G=1, R=2, rgb_tag, hasAlpha=false }; }; //----order_bgr +struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_rgba +struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, rgba_tag, hasAlpha=true }; }; //----order_argb +struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, rgba_tag, hasAlpha=true }; }; //----order_abgr +struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, rgba_tag, hasAlpha=true }; }; //----order_bgra - //====================================================================rgba - struct rgba +// Colorspace tag types. +struct linear {}; +struct sRGB {}; + +//====================================================================rgba +struct rgba +{ + typedef double value_type; + + double r; + double g; + double b; + double a; + + //-------------------------------------------------------------------- + rgba() {} + + //-------------------------------------------------------------------- + rgba(double r_, double g_, double b_, double a_=1.0) : + r(r_), g(g_), b(b_), a(a_) {} + + //-------------------------------------------------------------------- + rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} + + //-------------------------------------------------------------------- + rgba& clear() { - typedef double value_type; + r = g = b = a = 0; + return *this; + } - double r; - double g; - double b; - double a; + //-------------------------------------------------------------------- + rgba& transparent() + { + a = 0; + return *this; + } - //-------------------------------------------------------------------- - rgba() {} + //-------------------------------------------------------------------- + rgba& opacity(double a_) + { + if (a_ < 0) a_ = 0; + else if (a_ > 1) a_ = 1; + else a = a_; + return *this; + } - //-------------------------------------------------------------------- - rgba(double r_, double g_, double b_, double a_=1.0) : - r(r_), g(g_), b(b_), a(a_) {} + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } - //-------------------------------------------------------------------- - rgba(const rgba& c, double a_) : r(c.r), g(c.g), b(c.b), a(a_) {} + //-------------------------------------------------------------------- + rgba& premultiply() + { + r *= a; + g *= a; + b *= a; + return *this; + } - //-------------------------------------------------------------------- - void clear() + //-------------------------------------------------------------------- + rgba& premultiply(double a_) + { + if (a <= 0 || a_ <= 0) { r = g = b = a = 0; } - - //-------------------------------------------------------------------- - const rgba& transparent() + else { - a = 0.0; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = a_; - return *this; - } - - //-------------------------------------------------------------------- - double opacity() const - { - return a; - } - - //-------------------------------------------------------------------- - const rgba& premultiply() - { - r *= a; - g *= a; - b *= a; - return *this; - } - - //-------------------------------------------------------------------- - const rgba& premultiply(double a_) - { - if(a <= 0.0 || a_ <= 0.0) - { - r = g = b = a = 0.0; - return *this; - } a_ /= a; r *= a_; g *= a_; b *= a_; a = a_; - return *this; } + return *this; + } - //-------------------------------------------------------------------- - const rgba& demultiply() + //-------------------------------------------------------------------- + rgba& demultiply() + { + if (a == 0) + { + r = g = b = 0; + } + else { - if(a == 0) - { - r = g = b = 0; - return *this; - } double a_ = 1.0 / a; r *= a_; g *= a_; b *= a_; - return *this; } + return *this; + } - //-------------------------------------------------------------------- - rgba gradient(rgba c, double k) const - { - rgba ret; - ret.r = r + (c.r - r) * k; - ret.g = g + (c.g - g) * k; - ret.b = b + (c.b - b) * k; - ret.a = a + (c.a - a) * k; - return ret; - } + //-------------------------------------------------------------------- + rgba gradient(rgba c, double k) const + { + rgba ret; + ret.r = r + (c.r - r) * k; + ret.g = g + (c.g - g) * k; + ret.b = b + (c.b - b) * k; + ret.a = a + (c.a - a) * k; + return ret; + } - //-------------------------------------------------------------------- - static rgba no_color() { return rgba(0,0,0,0); } + rgba& operator+=(const rgba& c) + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } - //-------------------------------------------------------------------- - static rgba from_wavelength(double wl, double gamma = 1.0); + rgba& operator*=(double k) + { + r *= k; + g *= k; + b *= k; + a *= k; + return *this; + } - //-------------------------------------------------------------------- - explicit rgba(double wavelen, double gamma=1.0) - { - *this = from_wavelength(wavelen, gamma); - } + //-------------------------------------------------------------------- + static rgba no_color() { return rgba(0,0,0,0); } + //-------------------------------------------------------------------- + static rgba from_wavelength(double wl, double gamma = 1.0); + + //-------------------------------------------------------------------- + explicit rgba(double wavelen, double gamma=1.0) + { + *this = from_wavelength(wavelen, gamma); + } + +}; + +inline rgba operator+(const rgba& a, const rgba& b) +{ + return rgba(a) += b; +} + +inline rgba operator*(const rgba& a, double b) +{ + return rgba(a) *= b; +} + +//------------------------------------------------------------------------ +inline rgba rgba::from_wavelength(double wl, double gamma) +{ + rgba t(0.0, 0.0, 0.0); + + if (wl >= 380.0 && wl <= 440.0) + { + t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); + t.b = 1.0; + } + else if (wl >= 440.0 && wl <= 490.0) + { + t.g = (wl - 440.0) / (490.0 - 440.0); + t.b = 1.0; + } + else if (wl >= 490.0 && wl <= 510.0) + { + t.g = 1.0; + t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); + } + else if (wl >= 510.0 && wl <= 580.0) + { + t.r = (wl - 510.0) / (580.0 - 510.0); + t.g = 1.0; + } + else if (wl >= 580.0 && wl <= 645.0) + { + t.r = 1.0; + t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); + } + else if (wl >= 645.0 && wl <= 780.0) + { + t.r = 1.0; + } + + double s = 1.0; + if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); + else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); + + t.r = pow(t.r * s, gamma); + t.g = pow(t.g * s, gamma); + t.b = pow(t.b * s, gamma); + return t; +} + +inline rgba rgba_pre(double r, double g, double b, double a) +{ + return rgba(r, g, b, a).premultiply(); +} + + +//===================================================================rgba8 +template +struct rgba8T +{ + typedef int8u value_type; + typedef int32u calc_type; + typedef int32 long_type; + enum base_scale_e + { + base_shift = 8, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) }; + typedef rgba8T self_type; - //----------------------------------------------------------------rgba_pre - inline rgba rgba_pre(double r, double g, double b, double a=1.0) + + value_type r; + value_type g; + value_type b; + value_type a; + + static void convert(rgba8T& dst, const rgba8T& src) { - return rgba(r, g, b, a).premultiply(); - } - inline rgba rgba_pre(const rgba& c) - { - return rgba(c).premultiply(); - } - inline rgba rgba_pre(const rgba& c, double a) - { - return rgba(c, a).premultiply(); + dst.r = sRGB_conv::rgb_from_sRGB(src.r); + dst.g = sRGB_conv::rgb_from_sRGB(src.g); + dst.b = sRGB_conv::rgb_from_sRGB(src.b); + dst.a = src.a; } - //------------------------------------------------------------------------ - inline rgba rgba::from_wavelength(double wl, double gamma) + static void convert(rgba8T& dst, const rgba8T& src) { - rgba t(0.0, 0.0, 0.0); - - if(wl >= 380.0 && wl <= 440.0) - { - t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0); - t.b = 1.0; - } - else - if(wl >= 440.0 && wl <= 490.0) - { - t.g = (wl - 440.0) / (490.0 - 440.0); - t.b = 1.0; - } - else - if(wl >= 490.0 && wl <= 510.0) - { - t.g = 1.0; - t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0); - } - else - if(wl >= 510.0 && wl <= 580.0) - { - t.r = (wl - 510.0) / (580.0 - 510.0); - t.g = 1.0; - } - else - if(wl >= 580.0 && wl <= 645.0) - { - t.r = 1.0; - t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0); - } - else - if(wl >= 645.0 && wl <= 780.0) - { - t.r = 1.0; - } - - double s = 1.0; - if(wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0); - else if(wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0); - - t.r = pow(t.r * s, gamma); - t.g = pow(t.g * s, gamma); - t.b = pow(t.b * s, gamma); - return t; + dst.r = sRGB_conv::rgb_to_sRGB(src.r); + dst.g = sRGB_conv::rgb_to_sRGB(src.g); + dst.b = sRGB_conv::rgb_to_sRGB(src.b); + dst.a = src.a; } - - - - //===================================================================rgba8 - struct rgba8 + static void convert(rgba8T& dst, const rgba& src) { - typedef int8u value_type; - typedef int32u calc_type; - typedef int32 long_type; - enum base_scale_e + dst.r = value_type(uround(src.r * base_mask)); + dst.g = value_type(uround(src.g * base_mask)); + dst.b = value_type(uround(src.b * base_mask)); + dst.a = value_type(uround(src.a * base_mask)); + } + + static void convert(rgba8T& dst, const rgba& src) + { + // Use the "float" table. + dst.r = sRGB_conv::rgb_to_sRGB(float(src.r)); + dst.g = sRGB_conv::rgb_to_sRGB(float(src.g)); + dst.b = sRGB_conv::rgb_to_sRGB(float(src.b)); + dst.a = sRGB_conv::alpha_to_sRGB(float(src.a)); + } + + static void convert(rgba& dst, const rgba8T& src) + { + dst.r = src.r / 255.0; + dst.g = src.g / 255.0; + dst.b = src.b / 255.0; + dst.a = src.a / 255.0; + } + + static void convert(rgba& dst, const rgba8T& src) + { + // Use the "float" table. + dst.r = sRGB_conv::rgb_from_sRGB(src.r); + dst.g = sRGB_conv::rgb_from_sRGB(src.g); + dst.b = sRGB_conv::rgb_from_sRGB(src.b); + dst.a = sRGB_conv::alpha_from_sRGB(src.a); + } + + //-------------------------------------------------------------------- + rgba8T() {} + + //-------------------------------------------------------------------- + rgba8T(unsigned r_, unsigned g_, unsigned b_, unsigned a_ = base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba8T(const rgba& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + rgba8T(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + template + rgba8T(const rgba8T& c) + { + convert(*this, c); + } + + //-------------------------------------------------------------------- + operator rgba() const + { + rgba c; + convert(c, *this); + return c; + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return double(a) / base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(uround(a * base_mask)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return base_mask - x; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) { - base_shift = 8, - base_scale = 1 << base_shift, - base_mask = base_scale - 1 - }; - typedef rgba8 self_type; - - - value_type r; - value_type g; - value_type b; - value_type a; - - //-------------------------------------------------------------------- - rgba8() {} - - //-------------------------------------------------------------------- - rgba8(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : - r(value_type(r_)), - g(value_type(g_)), - b(value_type(b_)), - a(value_type(a_)) {} - - //-------------------------------------------------------------------- - rgba8(const rgba& c, double a_) : - r((value_type)uround(c.r * double(base_mask))), - g((value_type)uround(c.g * double(base_mask))), - b((value_type)uround(c.b * double(base_mask))), - a((value_type)uround(a_ * double(base_mask))) {} - - //-------------------------------------------------------------------- - rgba8(const self_type& c, unsigned a_) : - r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} - - //-------------------------------------------------------------------- - rgba8(const rgba& c) : - r((value_type)uround(c.r * double(base_mask))), - g((value_type)uround(c.g * double(base_mask))), - b((value_type)uround(c.b * double(base_mask))), - a((value_type)uround(c.a * double(base_mask))) {} - - //-------------------------------------------------------------------- - void clear() - { - r = g = b = a = 0; + return 0; } - - //-------------------------------------------------------------------- - const self_type& transparent() + else if (a >= b) { - a = 0; - return *this; + return base_mask; } + else return value_type((a * base_mask + (b >> 1)) / b); + } - //-------------------------------------------------------------------- - const self_type& opacity(double a_) + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int8u. + // Specifically for multiplying a color component by a cover. + static AGG_INLINE value_type mult_cover(value_type a, cover_type b) + { + return multiply(a, b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return multiply(b, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return p + q - multiply(p, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& opacity(double a_) + { + if (a_ < 0) a_ = 0; + else if (a_ > 1) a_ = 1; + else a = (value_type)uround(a_ * double(base_mask)); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a != base_mask) { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = (value_type)uround(a_ * double(base_mask)); - return *this; + r = multiply(r, a); + g = multiply(g, a); + b = multiply(b, a); } + return *this; + } - //-------------------------------------------------------------------- - double opacity() const + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply(unsigned a_) + { + if (a != base_mask || a_ < base_mask) { - return double(a) / double(base_mask); - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& premultiply() - { - if(a == base_mask) return *this; - if(a == 0) - { - r = g = b = 0; - return *this; - } - r = value_type((calc_type(r) * a) >> base_shift); - g = value_type((calc_type(g) * a) >> base_shift); - b = value_type((calc_type(b) * a) >> base_shift); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& premultiply(unsigned a_) - { - if(a == base_mask && a_ >= base_mask) return *this; - if(a == 0 || a_ == 0) + if (a == 0 || a_ == 0) { r = g = b = a = 0; - return *this; - } - calc_type r_ = (calc_type(r) * a_) / a; - calc_type g_ = (calc_type(g) * a_) / a; - calc_type b_ = (calc_type(b) * a_) / a; - r = value_type((r_ > a_) ? a_ : r_); - g = value_type((g_ > a_) ? a_ : g_); - b = value_type((b_ > a_) ? a_ : b_); - a = value_type(a_); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& demultiply() - { - if(a == base_mask) return *this; - if(a == 0) - { - r = g = b = 0; - return *this; - } - calc_type r_ = (calc_type(r) * base_mask) / a; - calc_type g_ = (calc_type(g) * base_mask) / a; - calc_type b_ = (calc_type(b) * base_mask) / a; - r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); - g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); - b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE self_type gradient(const self_type& c, double k) const - { - self_type ret; - calc_type ik = uround(k * base_scale); - ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); - ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); - ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); - ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); - return ret; - } - - //-------------------------------------------------------------------- - AGG_INLINE void add(const self_type& c, unsigned cover) - { - calc_type cr, cg, cb, ca; - if(cover == cover_mask) - { - if(c.a == base_mask) - { - *this = c; - } - else - { - cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; - cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; - cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; - ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; - } } else { - cr = r + ((c.r * cover + cover_mask/2) >> cover_shift); - cg = g + ((c.g * cover + cover_mask/2) >> cover_shift); - cb = b + ((c.b * cover + cover_mask/2) >> cover_shift); - ca = a + ((c.a * cover + cover_mask/2) >> cover_shift); - r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; - g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; - b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; - a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); } } + return *this; + } - //-------------------------------------------------------------------- - template - AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < base_mask) { - r = gamma.dir(r); - g = gamma.dir(g); - b = gamma.dir(b); - } - - //-------------------------------------------------------------------- - template - AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) - { - r = gamma.inv(r); - g = gamma.inv(g); - b = gamma.inv(b); - } - - //-------------------------------------------------------------------- - static self_type no_color() { return self_type(0,0,0,0); } - - //-------------------------------------------------------------------- - static self_type from_wavelength(double wl, double gamma = 1.0) - { - return self_type(rgba::from_wavelength(wl, gamma)); - } - }; - - - //-------------------------------------------------------------rgba8_pre - inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, - unsigned a = rgba8::base_mask) - { - return rgba8(r,g,b,a).premultiply(); - } - inline rgba8 rgba8_pre(const rgba8& c) - { - return rgba8(c).premultiply(); - } - inline rgba8 rgba8_pre(const rgba8& c, unsigned a) - { - return rgba8(c,a).premultiply(); - } - inline rgba8 rgba8_pre(const rgba& c) - { - return rgba8(c).premultiply(); - } - inline rgba8 rgba8_pre(const rgba& c, double a) - { - return rgba8(c,a).premultiply(); - } - - - //-------------------------------------------------------------rgb8_packed - inline rgba8 rgb8_packed(unsigned v) - { - return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); - } - - //-------------------------------------------------------------bgr8_packed - inline rgba8 bgr8_packed(unsigned v) - { - return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); - } - - //------------------------------------------------------------argb8_packed - inline rgba8 argb8_packed(unsigned v) - { - return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); - } - - //---------------------------------------------------------rgba8_gamma_dir - template - rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) - { - return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); - } - - //---------------------------------------------------------rgba8_gamma_inv - template - rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) - { - return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); - } - - - - - - //==================================================================rgba16 - struct rgba16 - { - typedef int16u value_type; - typedef int32u calc_type; - typedef int64 long_type; - enum base_scale_e - { - base_shift = 16, - base_scale = 1 << base_shift, - base_mask = base_scale - 1 - }; - typedef rgba16 self_type; - - value_type r; - value_type g; - value_type b; - value_type a; - - //-------------------------------------------------------------------- - rgba16() {} - - //-------------------------------------------------------------------- - rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : - r(value_type(r_)), - g(value_type(g_)), - b(value_type(b_)), - a(value_type(a_)) {} - - //-------------------------------------------------------------------- - rgba16(const self_type& c, unsigned a_) : - r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} - - //-------------------------------------------------------------------- - rgba16(const rgba& c) : - r((value_type)uround(c.r * double(base_mask))), - g((value_type)uround(c.g * double(base_mask))), - b((value_type)uround(c.b * double(base_mask))), - a((value_type)uround(c.a * double(base_mask))) {} - - //-------------------------------------------------------------------- - rgba16(const rgba& c, double a_) : - r((value_type)uround(c.r * double(base_mask))), - g((value_type)uround(c.g * double(base_mask))), - b((value_type)uround(c.b * double(base_mask))), - a((value_type)uround(a_ * double(base_mask))) {} - - //-------------------------------------------------------------------- - rgba16(const rgba8& c) : - r(value_type((value_type(c.r) << 8) | c.r)), - g(value_type((value_type(c.g) << 8) | c.g)), - b(value_type((value_type(c.b) << 8) | c.b)), - a(value_type((value_type(c.a) << 8) | c.a)) {} - - //-------------------------------------------------------------------- - rgba16(const rgba8& c, unsigned a_) : - r(value_type((value_type(c.r) << 8) | c.r)), - g(value_type((value_type(c.g) << 8) | c.g)), - b(value_type((value_type(c.b) << 8) | c.b)), - a(value_type(( a_ << 8) | c.a)) {} - - //-------------------------------------------------------------------- - void clear() - { - r = g = b = a = 0; - } - - //-------------------------------------------------------------------- - const self_type& transparent() - { - a = 0; - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& opacity(double a_) - { - if(a_ < 0.0) a_ = 0.0; - if(a_ > 1.0) a_ = 1.0; - a = (value_type)uround(a_ * double(base_mask)); - return *this; - } - - //-------------------------------------------------------------------- - double opacity() const - { - return double(a) / double(base_mask); - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& premultiply() - { - if(a == base_mask) return *this; - if(a == 0) + if (a == 0) { r = g = b = 0; - return *this; - } - r = value_type((calc_type(r) * a) >> base_shift); - g = value_type((calc_type(g) * a) >> base_shift); - b = value_type((calc_type(b) * a) >> base_shift); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& premultiply(unsigned a_) - { - if(a == base_mask && a_ >= base_mask) return *this; - if(a == 0 || a_ == 0) - { - r = g = b = a = 0; - return *this; - } - calc_type r_ = (calc_type(r) * a_) / a; - calc_type g_ = (calc_type(g) * a_) / a; - calc_type b_ = (calc_type(b) * a_) / a; - r = value_type((r_ > a_) ? a_ : r_); - g = value_type((g_ > a_) ? a_ : g_); - b = value_type((b_ > a_) ? a_ : b_); - a = value_type(a_); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE const self_type& demultiply() - { - if(a == base_mask) return *this; - if(a == 0) - { - r = g = b = 0; - return *this; - } - calc_type r_ = (calc_type(r) * base_mask) / a; - calc_type g_ = (calc_type(g) * base_mask) / a; - calc_type b_ = (calc_type(b) * base_mask) / a; - r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); - g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); - b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); - return *this; - } - - //-------------------------------------------------------------------- - AGG_INLINE self_type gradient(const self_type& c, double k) const - { - self_type ret; - calc_type ik = uround(k * base_scale); - ret.r = value_type(calc_type(r) + (((calc_type(c.r) - r) * ik) >> base_shift)); - ret.g = value_type(calc_type(g) + (((calc_type(c.g) - g) * ik) >> base_shift)); - ret.b = value_type(calc_type(b) + (((calc_type(c.b) - b) * ik) >> base_shift)); - ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); - return ret; - } - - //-------------------------------------------------------------------- - AGG_INLINE void add(const self_type& c, unsigned cover) - { - calc_type cr, cg, cb, ca; - if(cover == cover_mask) - { - if(c.a == base_mask) - { - *this = c; - } - else - { - cr = r + c.r; r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; - cg = g + c.g; g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; - cb = b + c.b; b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; - ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; - } } else { - cr = r + ((c.r * cover + cover_mask) >> cover_shift); - cg = g + ((c.g * cover + cover_mask) >> cover_shift); - cb = b + ((c.b * cover + cover_mask) >> cover_shift); - ca = a + ((c.a * cover + cover_mask) >> cover_shift); - r = (cr > calc_type(base_mask)) ? calc_type(base_mask) : cr; - g = (cg > calc_type(base_mask)) ? calc_type(base_mask) : cg; - b = (cb > calc_type(base_mask)) ? calc_type(base_mask) : cb; - a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); } } + return *this; + } - //-------------------------------------------------------------------- - template - AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_mask); + ret.r = lerp(r, c.r, ik); + ret.g = lerp(g, c.g, ik); + ret.b = lerp(b, c.b, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if (cover == cover_mask) { - r = gamma.dir(r); - g = gamma.dir(g); - b = gamma.dir(b); + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cr = r + c.r; + cg = g + c.g; + cb = b + c.b; + ca = a + c.a; + } } - - //-------------------------------------------------------------------- - template - AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + else { - r = gamma.inv(r); - g = gamma.inv(g); - b = gamma.inv(b); + cr = r + mult_cover(c.r, cover); + cg = g + mult_cover(c.g, cover); + cb = b + mult_cover(c.b, cover); + ca = a + mult_cover(c.a, cover); } + r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr); + g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg); + b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } - //-------------------------------------------------------------------- - static self_type no_color() { return self_type(0,0,0,0); } + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } - //-------------------------------------------------------------------- - static self_type from_wavelength(double wl, double gamma = 1.0) - { - return self_type(rgba::from_wavelength(wl, gamma)); - } + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } +}; + +typedef rgba8T rgba8; +typedef rgba8T srgba8; + +//-------------------------------------------------------------rgba8_pre +inline rgba8 rgba8_pre(unsigned r, unsigned g, unsigned b, + unsigned a = rgba8::base_mask) +{ + return rgba8(r,g,b,a).premultiply(); +} +inline rgba8 rgba8_pre(const rgba8& c) +{ + return rgba8(c).premultiply(); +} +inline rgba8 rgba8_pre(const rgba8& c, unsigned a) +{ + return rgba8(c,a).premultiply(); +} +inline rgba8 rgba8_pre(const rgba& c) +{ + return rgba8(c).premultiply(); +} +inline rgba8 rgba8_pre(const rgba& c, double a) +{ + return rgba8(c,a).premultiply(); +} + + + + +//-------------------------------------------------------------rgb8_packed +inline rgba8 rgb8_packed(unsigned v) +{ + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); +} + +//-------------------------------------------------------------bgr8_packed +inline rgba8 bgr8_packed(unsigned v) +{ + return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF); +} + +//------------------------------------------------------------argb8_packed +inline rgba8 argb8_packed(unsigned v) +{ + return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24); +} + +//---------------------------------------------------------rgba8_gamma_dir +template +rgba8 rgba8_gamma_dir(rgba8 c, const GammaLUT& gamma) +{ + return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); +} + +//---------------------------------------------------------rgba8_gamma_inv +template +rgba8 rgba8_gamma_inv(rgba8 c, const GammaLUT& gamma) +{ + return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); +} + + + +//==================================================================rgba16 +struct rgba16 +{ + typedef int16u value_type; + typedef int32u calc_type; + typedef int64 long_type; + enum base_scale_e + { + base_shift = 16, + base_scale = 1 << base_shift, + base_mask = base_scale - 1, + base_MSB = 1 << (base_shift - 1) }; + typedef rgba16 self_type; + value_type r; + value_type g; + value_type b; + value_type a; + //-------------------------------------------------------------------- + rgba16() {} - //--------------------------------------------------------------rgba16_pre - inline rgba16 rgba16_pre(unsigned r, unsigned g, unsigned b, - unsigned a = rgba16::base_mask) + //-------------------------------------------------------------------- + rgba16(unsigned r_, unsigned g_, unsigned b_, unsigned a_=base_mask) : + r(value_type(r_)), + g(value_type(g_)), + b(value_type(b_)), + a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const self_type& c, unsigned a_) : + r(c.r), g(c.g), b(c.b), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + rgba16(const rgba& c) : + r((value_type)uround(c.r * double(base_mask))), + g((value_type)uround(c.g * double(base_mask))), + b((value_type)uround(c.b * double(base_mask))), + a((value_type)uround(c.a * double(base_mask))) {} + + //-------------------------------------------------------------------- + rgba16(const rgba8& c) : + r(value_type((value_type(c.r) << 8) | c.r)), + g(value_type((value_type(c.g) << 8) | c.g)), + b(value_type((value_type(c.b) << 8) | c.b)), + a(value_type((value_type(c.a) << 8) | c.a)) {} + + //-------------------------------------------------------------------- + rgba16(const srgba8& c) : + r(sRGB_conv::rgb_from_sRGB(c.r)), + g(sRGB_conv::rgb_from_sRGB(c.g)), + b(sRGB_conv::rgb_from_sRGB(c.b)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + operator rgba() const { - return rgba16(r,g,b,a).premultiply(); - } - inline rgba16 rgba16_pre(const rgba16& c, unsigned a) - { - return rgba16(c,a).premultiply(); - } - inline rgba16 rgba16_pre(const rgba& c) - { - return rgba16(c).premultiply(); - } - inline rgba16 rgba16_pre(const rgba& c, double a) - { - return rgba16(c,a).premultiply(); - } - inline rgba16 rgba16_pre(const rgba8& c) - { - return rgba16(c).premultiply(); - } - inline rgba16 rgba16_pre(const rgba8& c, unsigned a) - { - return rgba16(c,a).premultiply(); + return rgba( + r / 65535.0, + g / 65535.0, + b / 65535.0, + a / 65535.0); } + //-------------------------------------------------------------------- + operator rgba8() const + { + return rgba8(r >> 8, g >> 8, b >> 8, a >> 8); + } - //------------------------------------------------------rgba16_gamma_dir + //-------------------------------------------------------------------- + operator srgba8() const + { + // Return (non-premultiplied) sRGB values. + return srgba8( + sRGB_conv::rgb_to_sRGB(r), + sRGB_conv::rgb_to_sRGB(g), + sRGB_conv::rgb_to_sRGB(b), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return double(a) / base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(uround(a * base_mask)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return base_mask; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a == 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a == base_mask; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return base_mask - x; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, exact over int16u. + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + calc_type t = a * b + base_MSB; + return value_type(((t >> base_shift) + t) >> base_shift); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + if (a * b == 0) + { + return 0; + } + else if (a >= b) + { + return base_mask; + } + else return value_type((a * base_mask + (b >> 1)) / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a >> base_shift; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return a >> n; + } + + //-------------------------------------------------------------------- + // Fixed-point multiply, almost exact over int16u. + // Specifically for multiplying a color component by a cover. + static AGG_INLINE value_type mult_cover(value_type a, cover_type b) + { + return multiply(a, (b << 8) | b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return multiply((a << 8) | a, b) >> 8; + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return p + q - multiply(p, a); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + int t = (q - p) * a + base_MSB - (p > q); + return value_type(p + (((t >> base_shift) + t) >> base_shift)); + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& opacity(double a_) + { + if (a_ < 0) a_ = 0; + if (a_ > 1) a_ = 1; + a = value_type(uround(a_ * double(base_mask))); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a != base_mask) + { + r = multiply(r, a); + g = multiply(g, a); + b = multiply(b, a); + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply(unsigned a_) + { + if (a < base_mask || a_ < base_mask) + { + if (a == 0 || a_ == 0) + { + r = g = b = a = 0; + } + else + { + calc_type r_ = (calc_type(r) * a_) / a; + calc_type g_ = (calc_type(g) * a_) / a; + calc_type b_ = (calc_type(b) * a_) / a; + r = value_type((r_ > a_) ? a_ : r_); + g = value_type((g_ > a_) ? a_ : g_); + b = value_type((b_ > a_) ? a_ : b_); + a = value_type(a_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < base_mask) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + calc_type r_ = (calc_type(r) * base_mask) / a; + calc_type g_ = (calc_type(g) * base_mask) / a; + calc_type b_ = (calc_type(b) * base_mask) / a; + r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_); + g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_); + b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_); + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + calc_type ik = uround(k * base_mask); + ret.r = lerp(r, c.r, ik); + ret.g = lerp(g, c.g, ik); + ret.b = lerp(b, c.b, ik); + ret.a = lerp(a, c.a, ik); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cr, cg, cb, ca; + if (cover == cover_mask) + { + if (c.a == base_mask) + { + *this = c; + return; + } + else + { + cr = r + c.r; + cg = g + c.g; + cb = b + c.b; + ca = a + c.a; + } + } + else + { + cr = r + mult_cover(c.r, cover); + cg = g + mult_cover(c.g, cover); + cb = b + mult_cover(c.b, cover); + ca = a + mult_cover(c.a, cover); + } + r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr); + g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg); + b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb); + a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca); + } + + //-------------------------------------------------------------------- template - rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) { - return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); } - //------------------------------------------------------rgba16_gamma_inv + //-------------------------------------------------------------------- template - rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) { - return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); } + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } +}; + + +//------------------------------------------------------rgba16_gamma_dir +template +rgba16 rgba16_gamma_dir(rgba16 c, const GammaLUT& gamma) +{ + return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a); +} + +//------------------------------------------------------rgba16_gamma_inv +template +rgba16 rgba16_gamma_inv(rgba16 c, const GammaLUT& gamma) +{ + return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a); +} + +//====================================================================rgba32 +struct rgba32 +{ + typedef float value_type; + typedef double calc_type; + typedef double long_type; + typedef rgba32 self_type; + + value_type r; + value_type g; + value_type b; + value_type a; + + //-------------------------------------------------------------------- + rgba32() {} + + //-------------------------------------------------------------------- + rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) : + r(r_), g(g_), b(b_), a(a_) {} + + //-------------------------------------------------------------------- + rgba32(const self_type& c, float a_) : + r(c.r), g(c.g), b(c.b), a(a_) {} + + //-------------------------------------------------------------------- + rgba32(const rgba& c) : + r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {} + + //-------------------------------------------------------------------- + rgba32(const rgba8& c) : + r(value_type(c.r / 255.0)), + g(value_type(c.g / 255.0)), + b(value_type(c.b / 255.0)), + a(value_type(c.a / 255.0)) {} + + //-------------------------------------------------------------------- + rgba32(const srgba8& c) : + r(sRGB_conv::rgb_from_sRGB(c.r)), + g(sRGB_conv::rgb_from_sRGB(c.g)), + b(sRGB_conv::rgb_from_sRGB(c.b)), + a(sRGB_conv::alpha_from_sRGB(c.a)) {} + + //-------------------------------------------------------------------- + rgba32(const rgba16& c) : + r(value_type(c.r / 65535.0)), + g(value_type(c.g / 65535.0)), + b(value_type(c.b / 65535.0)), + a(value_type(c.a / 65535.0)) {} + + //-------------------------------------------------------------------- + operator rgba() const + { + return rgba(r, g, b, a); + } + + //-------------------------------------------------------------------- + operator rgba8() const + { + return rgba8( + uround(r * 255.0), + uround(g * 255.0), + uround(b * 255.0), + uround(a * 255.0)); + } + + //-------------------------------------------------------------------- + operator srgba8() const + { + return srgba8( + sRGB_conv::rgb_to_sRGB(r), + sRGB_conv::rgb_to_sRGB(g), + sRGB_conv::rgb_to_sRGB(b), + sRGB_conv::alpha_to_sRGB(a)); + } + + //-------------------------------------------------------------------- + operator rgba16() const + { + return rgba8( + uround(r * 65535.0), + uround(g * 65535.0), + uround(b * 65535.0), + uround(a * 65535.0)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE double to_double(value_type a) + { + return a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type from_double(double a) + { + return value_type(a); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type empty_value() + { + return 0; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type full_value() + { + return 1; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_transparent() const + { + return a <= 0; + } + + //-------------------------------------------------------------------- + AGG_INLINE bool is_opaque() const + { + return a >= 1; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type invert(value_type x) + { + return 1 - x; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type multiply(value_type a, value_type b) + { + return value_type(a * b); + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type demultiply(value_type a, value_type b) + { + return (b == 0) ? 0 : value_type(a / b); + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downscale(T a) + { + return a; + } + + //-------------------------------------------------------------------- + template + static AGG_INLINE T downshift(T a, unsigned n) + { + return n > 0 ? a / (1 << n) : a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE value_type mult_cover(value_type a, cover_type b) + { + return value_type(a * b / cover_mask); + } + + //-------------------------------------------------------------------- + static AGG_INLINE cover_type scale_cover(cover_type a, value_type b) + { + return cover_type(uround(a * b)); + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a, assuming q is premultiplied by a. + static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a) + { + return (1 - a) * p + q; // more accurate than "p + q - p * a" + } + + //-------------------------------------------------------------------- + // Interpolate p to q by a. + static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a) + { + // The form "p + a * (q - p)" avoids a multiplication, but may produce an + // inaccurate result. For example, "p + (q - p)" may not be exactly equal + // to q. Therefore, stick to the basic expression, which at least produces + // the correct result at either extreme. + return (1 - a) * p + a * q; + } + + //-------------------------------------------------------------------- + self_type& clear() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& opacity(double a_) + { + if (a_ < 0) a_ = 0; + else if (a_ > 1) a_ = 1; + else a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& premultiply() + { + if (a < 1) + { + if (a <= 0) + { + r = g = b = 0; + } + else + { + r *= a; + g *= a; + b *= a; + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type& demultiply() + { + if (a < 1) + { + if (a <= 0) + { + r = g = b = 0; + } + else + { + r /= a; + g /= a; + b /= a; + } + } + return *this; + } + + //-------------------------------------------------------------------- + AGG_INLINE self_type gradient(const self_type& c, double k) const + { + self_type ret; + ret.r = value_type(r + (c.r - r) * k); + ret.g = value_type(g + (c.g - g) * k); + ret.b = value_type(b + (c.b - b) * k); + ret.a = value_type(a + (c.a - a) * k); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + if (cover == cover_mask) + { + if (c.is_opaque()) + { + *this = c; + return; + } + else + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + } + } + else + { + r += mult_cover(c.r, cover); + g += mult_cover(c.g, cover); + b += mult_cover(c.b, cover); + a += mult_cover(c.a, cover); + } + if (a > 1) a = 1; + if (r > a) r = a; + if (g > a) g = a; + if (b > a) b = a; + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_dir(const GammaLUT& gamma) + { + r = gamma.dir(r); + g = gamma.dir(g); + b = gamma.dir(b); + } + + //-------------------------------------------------------------------- + template + AGG_INLINE void apply_gamma_inv(const GammaLUT& gamma) + { + r = gamma.inv(r); + g = gamma.inv(g); + b = gamma.inv(b); + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0,0,0); } + + //-------------------------------------------------------------------- + static self_type from_wavelength(double wl, double gamma = 1) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } +}; } diff --git a/deps/agg/include/agg_ellipse.h b/deps/agg/include/agg_ellipse.h index b046b1cd0..671fd571c 100644 --- a/deps/agg/include/agg_ellipse.h +++ b/deps/agg/include/agg_ellipse.h @@ -48,6 +48,7 @@ namespace agg void approximation_scale(double scale); void rewind(unsigned path_id); unsigned vertex(double* x, double* y); + unsigned num_steps() { return m_num; } private: void calc_num_steps(); diff --git a/deps/agg/include/agg_gamma_functions.h b/deps/agg/include/agg_gamma_functions.h index 619ef95b4..0ad1115b5 100644 --- a/deps/agg/include/agg_gamma_functions.h +++ b/deps/agg/include/agg_gamma_functions.h @@ -120,6 +120,15 @@ namespace agg double m_mul; }; + inline double sRGB_to_linear(double x) + { + return (x <= 0.04045) ? (x / 12.92) : pow((x + 0.055) / (1.055), 2.4); + } + + inline double linear_to_sRGB(double x) + { + return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 1 / 2.4) - 0.055); + } } #endif diff --git a/deps/agg/include/agg_gamma_lut.h b/deps/agg/include/agg_gamma_lut.h index b366ae30d..6f3ccb9b4 100644 --- a/deps/agg/include/agg_gamma_lut.h +++ b/deps/agg/include/agg_gamma_lut.h @@ -2,8 +2,8 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // @@ -18,12 +18,13 @@ #include #include "agg_basics.h" +#include "agg_gamma_functions.h" namespace agg { - template class gamma_lut { public: @@ -49,8 +50,8 @@ namespace agg pod_allocator::deallocate(m_dir_gamma, gamma_size); } - gamma_lut() : - m_gamma(1.0), + gamma_lut() : + m_gamma(1.0), m_dir_gamma(pod_allocator::allocate(gamma_size)), m_inv_gamma(pod_allocator::allocate(hi_res_size)) { @@ -67,14 +68,14 @@ namespace agg } gamma_lut(double g) : - m_gamma(1.0), + m_gamma(1.0), m_dir_gamma(pod_allocator::allocate(gamma_size)), m_inv_gamma(pod_allocator::allocate(hi_res_size)) { gamma(g); } - void gamma(double g) + void gamma(double g) { m_gamma = g; @@ -98,13 +99,13 @@ namespace agg return m_gamma; } - HiResT dir(LoResT v) const - { - return m_dir_gamma[unsigned(v)]; + HiResT dir(LoResT v) const + { + return m_dir_gamma[unsigned(v)]; } - LoResT inv(HiResT v) const - { + LoResT inv(HiResT v) const + { return m_inv_gamma[unsigned(v)]; } @@ -116,6 +117,189 @@ namespace agg HiResT* m_dir_gamma; LoResT* m_inv_gamma; }; + + // + // sRGB support classes + // + + // Optimized sRGB lookup table. The direct conversion (sRGB to linear) + // is a straightforward lookup. The inverse conversion (linear to sRGB) + // is implemented using binary search. + template + class sRGB_lut_base + { + public: + LinearType dir(int8u v) const + { + return m_dir_table[v]; + } + + int8u inv(LinearType v) const + { + // Unrolled binary search. + int8u x = 0; + if (v > m_inv_table[128]) x = 128; + if (v > m_inv_table[x + 64]) x += 64; + if (v > m_inv_table[x + 32]) x += 32; + if (v > m_inv_table[x + 16]) x += 16; + if (v > m_inv_table[x + 8]) x += 8; + if (v > m_inv_table[x + 4]) x += 4; + if (v > m_inv_table[x + 2]) x += 2; + if (v > m_inv_table[x + 1]) x += 1; + return x; + } + + protected: + LinearType m_dir_table[256]; + LinearType m_inv_table[256]; + + // Only derived classes may instantiate. + sRGB_lut_base() + { + } + }; + + // sRGB_lut - implements sRGB conversion for the various types. + // Base template is undefined, specializations are provided below. + template + class sRGB_lut; + + template<> + class sRGB_lut : public sRGB_lut_base + { + public: + sRGB_lut() + { + // Generate lookup tables. + m_dir_table[0] = 0; + m_inv_table[0] = 0; + for (unsigned i = 1; i <= 255; ++i) + { + // Floating-point RGB is in range [0,1]. + m_dir_table[i] = float(sRGB_to_linear(i / 255.0)); + m_inv_table[i] = float(sRGB_to_linear((i - 0.5) / 255.0)); + } + } + }; + + template<> + class sRGB_lut : public sRGB_lut_base + { + public: + sRGB_lut() + { + // Generate lookup tables. + m_dir_table[0] = 0; + m_inv_table[0] = 0; + for (unsigned i = 1; i <= 255; ++i) + { + // 16-bit RGB is in range [0,65535]. + m_dir_table[i] = uround(65535.0 * sRGB_to_linear(i / 255.0)); + m_inv_table[i] = uround(65535.0 * sRGB_to_linear((i - 0.5) / 255.0)); + } + } + }; + + template<> + class sRGB_lut : public sRGB_lut_base + { + public: + sRGB_lut() + { + // Generate lookup tables. + m_dir_table[0] = 0; + m_inv_table[0] = 0; + for (unsigned i = 1; i <= 255; ++i) + { + // 8-bit RGB is handled with simple bidirectional lookup tables. + m_dir_table[i] = uround(255.0 * sRGB_to_linear(i / 255.0)); + m_inv_table[i] = uround(255.0 * linear_to_sRGB(i / 255.0)); + } + } + + int8u inv(int8u v) const + { + // In this case, the inverse transform is a simple lookup. + return m_inv_table[v]; + } + }; + + // Common base class for sRGB_conv objects. Defines an internal + // sRGB_lut object so that users don't have to. + template + class sRGB_conv_base + { + public: + static T rgb_from_sRGB(int8u x) + { + return lut.dir(x); + } + + static int8u rgb_to_sRGB(T x) + { + return lut.inv(x); + } + + private: + static sRGB_lut lut; + }; + + // Definition of sRGB_conv_base::lut. Due to the fact that this a template, + // we don't need to place the definition in a cpp file. Hurrah. + template + sRGB_lut sRGB_conv_base::lut; + + // Wrapper for sRGB-linear conversion. + // Base template is undefined, specializations are provided below. + template + class sRGB_conv; + + template<> + class sRGB_conv : public sRGB_conv_base + { + public: + static float alpha_from_sRGB(int8u x) + { + return float(x / 255.0); + } + + static int8u alpha_to_sRGB(float x) + { + if (x <= 0) return 0; + else if (x >= 1) return 255; + else return int8u(0.5 + x * 255); + } + }; + + template<> + class sRGB_conv : public sRGB_conv_base + { + public: + static int16u alpha_from_sRGB(int8u x) + { + return (x << 8) | x; + } + + static int8u alpha_to_sRGB(int16u x) + { + return x >> 8; + } + }; + + template<> + class sRGB_conv : public sRGB_conv_base + { + public: + static int8u alpha_from_sRGB(int8u x) + { + return x; + } + + static int8u alpha_to_sRGB(int8u x) + { + return x; + } + }; } #endif diff --git a/deps/agg/include/agg_pixfmt_base.h b/deps/agg/include/agg_pixfmt_base.h new file mode 100644 index 000000000..57ae19cfe --- /dev/null +++ b/deps/agg/include/agg_pixfmt_base.h @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_PIXFMT_BASE_INCLUDED +#define AGG_PIXFMT_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_color_rgba.h" + +namespace agg +{ + struct pixfmt_gray_tag + { + }; + + struct pixfmt_rgb_tag + { + }; + + struct pixfmt_rgba_tag + { + }; + + //--------------------------------------------------------------blender_base + template + struct blender_base + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static rgba get(value_type r, value_type g, value_type b, value_type a, cover_type cover = cover_full) + { + if (cover > cover_none) + { + rgba c( + color_type::to_double(r), + color_type::to_double(g), + color_type::to_double(b), + color_type::to_double(a)); + + if (cover < cover_full) + { + double x = double(cover) / cover_full; + c.r *= x; + c.g *= x; + c.b *= x; + c.a *= x; + } + + return c; + } + else return rgba::no_color(); + } + + static rgba get(const value_type* p, cover_type cover = cover_full) + { + return get( + p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A], + cover); + } + + static void set(value_type* p, value_type r, value_type g, value_type b, value_type a) + { + p[order_type::R] = r; + p[order_type::G] = g; + p[order_type::B] = b; + p[order_type::A] = a; + } + + static void set(value_type* p, const rgba& c) + { + p[order_type::R] = color_type::from_double(c.r); + p[order_type::G] = color_type::from_double(c.g); + p[order_type::B] = color_type::from_double(c.b); + p[order_type::A] = color_type::from_double(c.a); + } + }; +} + +#endif diff --git a/deps/agg/include/agg_pixfmt_gray.h b/deps/agg/include/agg_pixfmt_gray.h index 3632e2826..a303bd3a7 100644 --- a/deps/agg/include/agg_pixfmt_gray.h +++ b/deps/agg/include/agg_pixfmt_gray.h @@ -2,8 +2,8 @@ // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) // -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all copies. +// Permission to copy, use, modify, sell and distribute this software +// is granted provided this copyright notice appears in all copies. // This software is provided "as is" without express or implied // warranty, and with no claim as to its suitability for any purpose. // @@ -13,37 +13,46 @@ // http://www.antigrain.com //---------------------------------------------------------------------------- // -// Adaptation for high precision colors has been sponsored by +// Adaptation for high precision colors has been sponsored by // Liberty Technology Systems, Inc., visit http://lib-sys.com // // Liberty Technology Systems, Inc. is the provider of // PostScript and PDF technology for software developers. -// +// //---------------------------------------------------------------------------- #ifndef AGG_PIXFMT_GRAY_INCLUDED #define AGG_PIXFMT_GRAY_INCLUDED #include -#include "agg_basics.h" -#include "agg_color_gray.h" +#include "agg_pixfmt_base.h" #include "agg_rendering_buffer.h" namespace agg { - + //============================================================blender_gray template struct blender_gray { typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum base_scale_e { base_shift = color_type::base_shift }; + typedef typename color_type::long_type long_type; - static AGG_INLINE void blend_pix(value_type* p, unsigned cv, - unsigned alpha, unsigned cover=0) + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. Since the render buffer is opaque we skip the + // initial premultiply and final demultiply. + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha, cover_type cover) { - *p = (value_type)((((cv - calc_type(*p)) * alpha) + (calc_type(*p) << base_shift)) >> base_shift); + blend_pix(p, cv, color_type::mult_cover(alpha, cover)); + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha) + { + *p = color_type::lerp(*p, cv, alpha); } }; @@ -54,23 +63,24 @@ namespace agg typedef ColorT color_type; typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum base_scale_e { base_shift = color_type::base_shift }; + typedef typename color_type::long_type long_type; - static AGG_INLINE void blend_pix(value_type* p, unsigned cv, - unsigned alpha, unsigned cover) + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha, cover_type cover) { - alpha = color_type::base_mask - alpha; - cover = (cover + 1) << (base_shift - 8); - *p = (value_type)((*p * alpha + cv * cover) >> base_shift); + blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover)); } - static AGG_INLINE void blend_pix(value_type* p, unsigned cv, - unsigned alpha) + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha) { - *p = (value_type)(((*p * (color_type::base_mask - alpha)) >> base_shift) + cv); + *p = color_type::prelerp(*p, cv, alpha); } }; - + //=====================================================apply_gamma_dir_gray @@ -112,10 +122,11 @@ namespace agg //=================================================pixfmt_alpha_blend_gray - template + template class pixfmt_alpha_blend_gray { public: + typedef pixfmt_gray_tag pixfmt_category; typedef RenBuf rbuf_type; typedef typename rbuf_type::row_data row_data; typedef Blender blender_type; @@ -123,54 +134,117 @@ namespace agg typedef int order_type; // A fake one typedef typename color_type::value_type value_type; typedef typename color_type::calc_type calc_type; - enum base_scale_e + enum { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(value_type), - pix_step = Step, - pix_offset = Offset + num_components = 1, + pix_width = sizeof(value_type) * Step, + pix_step = Step, + pix_offset = Offset, + }; + struct pixel_type + { + value_type c[num_components]; + + void set(value_type v) + { + c[0] = v; + } + + void set(const color_type& color) + { + set(color.v); + } + + void get(value_type& v) const + { + v = c[0]; + } + + color_type get() const + { + return color_type(c[0]); + } + + pixel_type* next() + { + return (pixel_type*)(c + pix_step); + } + + const pixel_type* next() const + { + return (const pixel_type*)(c + pix_step); + } + + pixel_type* advance(int n) + { + return (pixel_type*)(c + n * pix_step); + } + + const pixel_type* advance(int n) const + { + return (const pixel_type*)(c + n * pix_step); + } }; private: //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - const color_type& c, - unsigned cover) + AGG_INLINE void blend_pix(pixel_type* p, + value_type v, value_type a, + unsigned cover) { - if (c.a) + blender_type::blend_pix(p->c, v, a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, value_type v, value_type a) + { + blender_type::blend_pix(p->c, v, a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + blender_type::blend_pix(p->c, c.v, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + blender_type::blend_pix(p->c, c.v, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) { - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) + if (c.is_opaque() && cover == cover_mask) { - *p = c.v; + p->set(c); } else { - Blender::blend_pix(p, c.v, alpha, cover); + blend_pix(p, c, cover); } } } - - static AGG_INLINE void copy_or_blend_pix(value_type* p, - const color_type& c) + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) { - if (c.a) + if (!c.is_transparent()) { - if(c.a == base_mask) + if (c.is_opaque()) { - *p = c.v; + p->set(c); } else { - Blender::blend_pix(p, c.v, c.a); + blend_pix(p, c); } } } - public: //-------------------------------------------------------------------- explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : @@ -183,10 +257,10 @@ namespace agg bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + if (r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) { int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), (r.x2 - r.x1) + 1, (r.y2 - r.y1) + 1, stride); @@ -201,61 +275,98 @@ namespace agg AGG_INLINE int stride() const { return m_rbuf->stride(); } //-------------------------------------------------------------------- - int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } row_data row(int y) const { return m_rbuf->row(y); } - const int8u* pix_ptr(int x, int y) const + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) { - return m_rbuf->row_ptr(y) + x * Step + Offset; + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); } - int8u* pix_ptr(int x, int y) + AGG_INLINE const int8u* pix_ptr(int x, int y) const { - return m_rbuf->row_ptr(y) + x * Step + Offset; + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + // Return pointer to pixel value, forcing row to be allocated. + AGG_INLINE pixel_type* pix_value_ptr(int x, int y, unsigned len) + { + return (pixel_type*)(m_rbuf->row_ptr(x, y, len) + sizeof(value_type) * (x * pix_step + pix_offset)); + } + + // Return pointer to pixel value, or null if row not allocated. + AGG_INLINE const pixel_type* pix_value_ptr(int x, int y) const + { + int8u* p = m_rbuf->row_ptr(y); + return p ? (pixel_type*)(p + sizeof(value_type) * (x * pix_step + pix_offset)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)((value_type*)p + pix_offset); + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)((const value_type*)p + pix_offset); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void write_plain_color(void* p, color_type c) + { + // Grayscale formats are implicitly premultiplied. + c.premultiply(); + pix_value_ptr(p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static color_type read_plain_color(const void* p) + { + return pix_value_ptr(p)->get(); } //-------------------------------------------------------------------- AGG_INLINE static void make_pix(int8u* p, const color_type& c) { - *(value_type*)p = c.v; + ((pixel_type*)p)->set(c); } //-------------------------------------------------------------------- AGG_INLINE color_type pixel(int x, int y) const { - value_type* p = (value_type*)m_rbuf->row_ptr(y) + x * Step + Offset; - return color_type(*p); + if (const pixel_type* p = pix_value_ptr(x, y)) + { + return p->get(); + } + return color_type::no_color(); } //-------------------------------------------------------------------- AGG_INLINE void copy_pixel(int x, int y, const color_type& c) { - *((value_type*)m_rbuf->row_ptr(x, y, 1) + x * Step + Offset) = c.v; + pix_value_ptr(x, y, 1)->set(c); } //-------------------------------------------------------------------- AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) { - copy_or_blend_pix((value_type*) - m_rbuf->row_ptr(x, y, 1) + x * Step + Offset, - c, - cover); + copy_or_blend_pix(pix_value_ptr(x, y, 1), c, cover); } - //-------------------------------------------------------------------- - AGG_INLINE void copy_hline(int x, int y, - unsigned len, + AGG_INLINE void copy_hline(int x, int y, + unsigned len, const color_type& c) { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y, len) + x * Step + Offset; - + pixel_type* p = pix_value_ptr(x, y, len); do { - *p = c.v; - p += Step; + p->set(c); + p = p->next(); } while(--len); } @@ -263,49 +374,44 @@ namespace agg //-------------------------------------------------------------------- AGG_INLINE void copy_vline(int x, int y, - unsigned len, + unsigned len, const color_type& c) { do { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - *p = c.v; + pix_value_ptr(x, y++, 1)->set(c); } - while(--len); + while (--len); } //-------------------------------------------------------------------- void blend_hline(int x, int y, - unsigned len, + unsigned len, const color_type& c, int8u cover) { - if (c.a) + if (!c.is_transparent()) { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + pixel_type* p = pix_value_ptr(x, y, len); - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) + if (c.is_opaque() && cover == cover_mask) { do { - *p = c.v; - p += Step; + p->set(c); + p = p->next(); } - while(--len); + while (--len); } else { do { - Blender::blend_pix(p, c.v, alpha, cover); - p += Step; + blend_pix(p, c, cover); + p = p->next(); } - while(--len); + while (--len); } } } @@ -313,35 +419,27 @@ namespace agg //-------------------------------------------------------------------- void blend_vline(int x, int y, - unsigned len, + unsigned len, const color_type& c, int8u cover) { - if (c.a) + if (!c.is_transparent()) { - value_type* p; - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) + if (c.is_opaque() && cover == cover_mask) { do { - p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - *p = c.v; + pix_value_ptr(x, y++, 1)->set(c); } - while(--len); + while (--len); } else { do { - p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - Blender::blend_pix(p, c.v, alpha, cover); + blend_pix(pix_value_ptr(x, y++, 1), c, cover); } - while(--len); + while (--len); } } } @@ -349,200 +447,162 @@ namespace agg //-------------------------------------------------------------------- void blend_solid_hspan(int x, int y, - unsigned len, + unsigned len, const color_type& c, const int8u* covers) { - if (c.a) + if (!c.is_transparent()) { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + pixel_type* p = pix_value_ptr(x, y, len); - do + do { - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) + if (c.is_opaque() && *covers == cover_mask) { - *p = c.v; + p->set(c); } else { - Blender::blend_pix(p, c.v, alpha, *covers); + blend_pix(p, c, *covers); } - p += Step; + p = p->next(); ++covers; } - while(--len); + while (--len); } } //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, - unsigned len, + unsigned len, const color_type& c, const int8u* covers) { - if (c.a) + if (!c.is_transparent()) { - do + do { - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + pixel_type* p = pix_value_ptr(x, y++, 1); - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - if(alpha == base_mask) + if (c.is_opaque() && *covers == cover_mask) { - *p = c.v; + p->set(c); } else { - Blender::blend_pix(p, c.v, alpha, *covers); + blend_pix(p, c, *covers); } ++covers; } - while(--len); + while (--len); } } //-------------------------------------------------------------------- void copy_color_hspan(int x, int y, - unsigned len, + unsigned len, const color_type* colors) { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + pixel_type* p = pix_value_ptr(x, y, len); - do + do { - *p = colors->v; - p += Step; - ++colors; + p->set(*colors++); + p = p->next(); } - while(--len); + while (--len); } //-------------------------------------------------------------------- void copy_color_vspan(int x, int y, - unsigned len, + unsigned len, const color_type* colors) { - do + do { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - *p = colors->v; - ++colors; + pix_value_ptr(x, y++, 1)->set(*colors++); } - while(--len); + while (--len); } //-------------------------------------------------------------------- void blend_color_hspan(int x, int y, - unsigned len, + unsigned len, const color_type* colors, const int8u* covers, int8u cover) { - value_type* p = (value_type*) - m_rbuf->row_ptr(x, y, len) + x * Step + Offset; + pixel_type* p = pix_value_ptr(x, y, len); - if(covers) + if (covers) { - do + do { copy_or_blend_pix(p, *colors++, *covers++); - p += Step; + p = p->next(); } - while(--len); + while (--len); } else { - if(cover == 255) + if (cover == cover_mask) { - do + do { - if(colors->a == base_mask) - { - *p = colors->v; - } - else - { - copy_or_blend_pix(p, *colors); - } - p += Step; - ++colors; + copy_or_blend_pix(p, *colors++); + p = p->next(); } - while(--len); + while (--len); } else { - do + do { copy_or_blend_pix(p, *colors++, cover); - p += Step; + p = p->next(); } - while(--len); + while (--len); } } } - //-------------------------------------------------------------------- void blend_color_vspan(int x, int y, - unsigned len, + unsigned len, const color_type* colors, const int8u* covers, int8u cover) { - value_type* p; - if(covers) + if (covers) { - do + do { - p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - copy_or_blend_pix(p, *colors++, *covers++); + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); } - while(--len); + while (--len); } else { - if(cover == 255) + if (cover == cover_mask) { - do + do { - p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - if(colors->a == base_mask) - { - *p = colors->v; - } - else - { - copy_or_blend_pix(p, *colors); - } - ++colors; + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); } - while(--len); + while (--len); } else { - do + do { - p = (value_type*) - m_rbuf->row_ptr(x, y++, 1) + x * Step + Offset; - - copy_or_blend_pix(p, *colors++, cover); + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); } - while(--len); + while (--len); } } } @@ -551,22 +611,19 @@ namespace agg template void for_each_pixel(Function f) { unsigned y; - for(y = 0; y < height(); ++y) + for (y = 0; y < height(); ++y) { row_data r = m_rbuf->row(y); - if(r.ptr) + if (r.ptr) { unsigned len = r.x2 - r.x1 + 1; - - value_type* p = (value_type*) - m_rbuf->row_ptr(r.x1, y, len) + r.x1 * Step + Offset; - + pixel_type* p = pix_value_ptr(r.x1, y, len); do { - f(p); - p += Step; + f(p->c); + p = p->next(); } - while(--len); + while (--len); } } } @@ -585,69 +642,70 @@ namespace agg //-------------------------------------------------------------------- template - void copy_from(const RenBuf2& from, + void copy_from(const RenBuf2& from, int xdst, int ydst, int xsrc, int ysrc, unsigned len) { - const int8u* p = from.row_ptr(ysrc); - if(p) + if (const int8u* p = from.row_ptr(ysrc)) { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, len * pix_width); } } //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. template - void blend_from_color(const SrcPixelFormatRenderer& from, + void blend_from_color(const SrcPixelFormatRenderer& from, const color_type& color, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; - do + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do { - copy_or_blend_pix(pdst, - color, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - ++pdst; + copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); } - while(--len); + while (--len); } } //-------------------------------------------------------------------- + // Blend from color table, using grayscale surface as indexes into table. + // Obviously, this only works for integer value types. template - void blend_from_lut(const SrcPixelFormatRenderer& from, + void blend_from_lut(const SrcPixelFormatRenderer& from, const color_type* color_lut, int xdst, int ydst, int xsrc, int ysrc, unsigned len, int8u cover) { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; - do + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do { - copy_or_blend_pix(pdst, color_lut[*psrc], cover); - ++psrc; - ++pdst; + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); } - while(--len); + while (--len); } } @@ -655,16 +713,25 @@ namespace agg rbuf_type* m_rbuf; }; - typedef blender_gray blender_gray8; - typedef blender_gray_pre blender_gray8_pre; - typedef blender_gray blender_gray16; - typedef blender_gray_pre blender_gray16_pre; + typedef blender_gray blender_gray8; + typedef blender_gray blender_sgray8; + typedef blender_gray blender_gray16; + typedef blender_gray blender_gray32; - typedef pixfmt_alpha_blend_gray pixfmt_gray8; //----pixfmt_gray8 - typedef pixfmt_alpha_blend_gray pixfmt_gray8_pre; //----pixfmt_gray8_pre - typedef pixfmt_alpha_blend_gray pixfmt_gray16; //----pixfmt_gray16 - typedef pixfmt_alpha_blend_gray pixfmt_gray16_pre; //----pixfmt_gray16_pre + typedef blender_gray_pre blender_gray8_pre; + typedef blender_gray_pre blender_sgray8_pre; + typedef blender_gray_pre blender_gray16_pre; + typedef blender_gray_pre blender_gray32_pre; + + typedef pixfmt_alpha_blend_gray pixfmt_gray8; + typedef pixfmt_alpha_blend_gray pixfmt_sgray8; + typedef pixfmt_alpha_blend_gray pixfmt_gray16; + typedef pixfmt_alpha_blend_gray pixfmt_gray32; + + typedef pixfmt_alpha_blend_gray pixfmt_gray8_pre; + typedef pixfmt_alpha_blend_gray pixfmt_sgray8_pre; + typedef pixfmt_alpha_blend_gray pixfmt_gray16_pre; + typedef pixfmt_alpha_blend_gray pixfmt_gray32_pre; } #endif - diff --git a/deps/mapnik/sparsehash/internal/densehashtable.h b/deps/mapnik/sparsehash/internal/densehashtable.h index d4495ed42..c0a2fedca 100644 --- a/deps/mapnik/sparsehash/internal/densehashtable.h +++ b/deps/mapnik/sparsehash/internal/densehashtable.h @@ -1175,7 +1175,7 @@ class dense_hashtable { pointer realloc_or_die(pointer /*ptr*/, size_type /*n*/) { fprintf(stderr, "realloc_or_die is only supported for " "libc_allocator_with_realloc\n"); - exit(1); + //exit(1); return NULL; } }; @@ -1197,7 +1197,7 @@ class dense_hashtable { if (retval == NULL) { fprintf(stderr, "sparsehash: FATAL ERROR: failed to reallocate " "%lu elements for ptr %p", static_cast(n), ptr); - exit(1); + //exit(1); } return retval; } diff --git a/docs/contributing.markdown b/docs/contributing.markdown index 7130880f3..74c6c2ebf 100644 --- a/docs/contributing.markdown +++ b/docs/contributing.markdown @@ -85,6 +85,21 @@ Mapnik is written in C++, and we try to follow general coding guidelines. If you see bits of code around that do not follow these please don't hesitate to flag the issue or correct it yourself. +#### Prefix cmath functions with std:: + +The avoids ambiguity and potential bugs of using old C library math directly. + +So always do `std::abs()` instead of `abs()`. Here is a script to fix your code in one fell swoop: + + +```sh +DIR=./bindings +for i in {abs,fabs,tan,sin,cos,floor,ceil,atan2,acos,asin}; do + find $DIR -type f -name '*.cpp' -or -name '*.h' -or -name '*.hpp' | xargs perl -i -p -e "s/ $i\(/ std::$i\(/g;" + find $DIR -type f -name '*.cpp' -or -name '*.h' -or -name '*.hpp' | xargs perl -i -p -e "s/\($i\(/\(std::$i\(/g;" +done +``` + #### Avoid boost::lexical_cast It's slow both to compile and at runtime. @@ -118,6 +133,9 @@ which triggers locks void my_function(std::string const& val); // if std::string or user type, pass by const& +#### Use unique_ptr instead of new/delete + +#### Use std::copy instead of memcpy #### When to use shared_ptr and unique_ptr diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp index c3bc759d2..8e2b1b2d7 100644 --- a/include/mapnik/agg_helpers.hpp +++ b/include/mapnik/agg_helpers.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/agg_pattern_source.hpp b/include/mapnik/agg_pattern_source.hpp index 14a1c33b2..324dee630 100644 --- a/include/mapnik/agg_pattern_source.hpp +++ b/include/mapnik/agg_pattern_source.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include // agg #include "agg_color_rgba.h" @@ -33,10 +33,10 @@ namespace mapnik { -class pattern_source : private mapnik::noncopyable +class pattern_source : private util::noncopyable { public: - pattern_source(image_data_32 const& pattern, double opacity = 1.0) + pattern_source(image_data_rgba8 const& pattern, double opacity = 1.0) : pattern_(pattern), opacity_(opacity) {} @@ -57,7 +57,7 @@ public: static_cast(((c >> 24) & 0xff) * opacity_)); } private: - image_data_32 const& pattern_; + image_data_rgba8 const& pattern_; double opacity_; }; } diff --git a/include/mapnik/agg_rasterizer.hpp b/include/mapnik/agg_rasterizer.hpp index 5e82f03f1..0232f8858 100644 --- a/include/mapnik/agg_rasterizer.hpp +++ b/include/mapnik/agg_rasterizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,14 +24,14 @@ #define MAPNIK_AGG_RASTERIZER_HPP // mapnik -#include +#include // agg #include "agg_rasterizer_scanline_aa.h" namespace mapnik { -struct rasterizer : agg::rasterizer_scanline_aa, mapnik::noncopyable {}; +struct rasterizer : agg::rasterizer_scanline_aa, util::noncopyable {}; } diff --git a/include/mapnik/agg_render_marker.hpp b/include/mapnik/agg_render_marker.hpp index 95e657fd5..dcd7dac9c 100644 --- a/include/mapnik/agg_render_marker.hpp +++ b/include/mapnik/agg_render_marker.hpp @@ -66,7 +66,7 @@ void render_vector_marker(SvgRenderer & svg_renderer, RasterizerType & ras, Rend } template -void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_32 const& src, +void render_raster_marker(RendererType renb, RasterizerType & ras, image_data_rgba8 const& src, agg::trans_affine const& tr, double opacity, float scale_factor, bool snap_to_pixels) { diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 627ee61f9..7e50aea86 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include // for MAPNIK_DECL #include -#include // for noncopyable +#include // for noncopyable #include // for rule, symbolizers #include // for box2d #include // for color @@ -60,7 +60,7 @@ namespace mapnik { template class MAPNIK_DECL agg_renderer : public feature_style_processor >, - private mapnik::noncopyable + private util::noncopyable { public: @@ -122,6 +122,9 @@ public: void process(debug_symbolizer const& sym, feature_impl & feature, proj_transform const& prj_trans); + void process(dot_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans); inline bool process(rule::symbolizers const&, mapnik::feature_impl&, diff --git a/include/mapnik/attribute.hpp b/include/mapnik/attribute.hpp index 9716b388d..0e581e24d 100644 --- a/include/mapnik/attribute.hpp +++ b/include/mapnik/attribute.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index 7ed802449..9f2e81573 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include #include #include #include // for expression_ptr, etc @@ -52,7 +52,7 @@ namespace mapnik { template -struct expression_attributes : util::static_visitor +struct expression_attributes { explicit expression_attributes(Container& names) : names_(names) {} @@ -92,7 +92,7 @@ private: Container& names_; }; -class group_attribute_collector : public mapnik::noncopyable +class group_attribute_collector : public util::noncopyable { private: std::set& names_; @@ -107,7 +107,7 @@ public: }; template -struct extract_attribute_names : util::static_visitor +struct extract_attribute_names { explicit extract_attribute_names(Container& names) : names_(names), @@ -159,7 +159,7 @@ private: expression_attributes > f_attr_; }; -struct symbolizer_attributes : public util::static_visitor<> +struct symbolizer_attributes { symbolizer_attributes(std::set& names, double & filter_factor) @@ -209,7 +209,7 @@ private: }; -class attribute_collector : public mapnik::noncopyable +class attribute_collector : public util::noncopyable { private: std::set & names_; diff --git a/include/mapnik/attribute_descriptor.hpp b/include/mapnik/attribute_descriptor.hpp index 70368ea23..3a17392da 100644 --- a/include/mapnik/attribute_descriptor.hpp +++ b/include/mapnik/attribute_descriptor.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/boolean.hpp b/include/mapnik/boolean.hpp index bbee2b513..122604fc0 100644 --- a/include/mapnik/boolean.hpp +++ b/include/mapnik/boolean.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/box2d.hpp b/include/mapnik/box2d.hpp index b3bb22f10..e6fc2a976 100644 --- a/include/mapnik/box2d.hpp +++ b/include/mapnik/box2d.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index 93b812834..022d04092 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -75,7 +75,7 @@ void check_object_status_and_throw_exception(T const& object) check_status_and_throw_exception(object.get_status()); } -class cairo_face : private mapnik::noncopyable +class cairo_face : private util::noncopyable { public: cairo_face(std::shared_ptr const& library, face_ptr const& face); @@ -106,7 +106,7 @@ private: using cairo_face_ptr = std::shared_ptr; -class cairo_face_manager : private mapnik::noncopyable +class cairo_face_manager : private util::noncopyable { public: cairo_face_manager(std::shared_ptr library); @@ -118,10 +118,10 @@ private: cairo_face_cache cache_; }; -class cairo_pattern : private mapnik::noncopyable +class cairo_pattern : private util::noncopyable { public: - explicit cairo_pattern(image_data_32 const& data, double opacity = 1.0) + explicit cairo_pattern(image_data_rgba8 const& data, double opacity = 1.0) { int pixels = data.width() * data.height(); const unsigned int *in_ptr = data.getData(); @@ -192,7 +192,7 @@ private: }; -class cairo_gradient : private mapnik::noncopyable +class cairo_gradient : private util::noncopyable { public: cairo_gradient(mapnik::gradient const& grad, double opacity=1.0) @@ -276,7 +276,7 @@ inline cairo_ptr create_context(cairo_surface_ptr const& surface) return cairo_ptr(cairo_create(&*surface),cairo_closer()); } -class cairo_context : private mapnik::noncopyable +class cairo_context : private util::noncopyable { public: @@ -308,8 +308,8 @@ public: void paint(); void set_pattern(cairo_pattern const& pattern); void set_gradient(cairo_gradient const& pattern, box2d const& bbox); - void add_image(double x, double y, image_data_32 & data, double opacity = 1.0); - void add_image(agg::trans_affine const& tr, image_data_32 & data, double opacity = 1.0); + void add_image(double x, double y, image_data_rgba8 & data, double opacity = 1.0); + void add_image(agg::trans_affine const& tr, image_data_rgba8 & data, double opacity = 1.0); void set_font_face(cairo_face_manager & manager, face_ptr face); void set_font_matrix(cairo_matrix_t const& matrix); void set_matrix(cairo_matrix_t const& matrix); @@ -321,7 +321,6 @@ public: void glyph_path(unsigned long index, pixel_position const& pos); void add_text(glyph_positions const& pos, cairo_face_manager & manager, - face_manager_freetype & font_manager, composite_mode_e comp_op = src_over, composite_mode_e halo_comp_op = src_over, double scale_factor = 1.0); diff --git a/include/mapnik/cairo/cairo_image_util.hpp b/include/mapnik/cairo/cairo_image_util.hpp new file mode 100644 index 000000000..5fe764bcf --- /dev/null +++ b/include/mapnik/cairo/cairo_image_util.hpp @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2015 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_CAIRO_IMAGE_UTIL_HPP +#define MAPNIK_CAIRO_IMAGE_UTIL_HPP + +// mapnik +#include +#include // for cairo_surface_ptr + +// stl +#include + +namespace mapnik { + +static inline void cairo_image_to_rgba8(mapnik::image_data_rgba8 & data, + cairo_surface_ptr const& surface) +{ + if (cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32) + { + throw std::runtime_error("Unable to convert this Cairo format to rgba8 image"); + } + + if (cairo_image_surface_get_width(&*surface) != data.width() || + cairo_image_surface_get_height(&*surface) != data.height()) + { + throw std::runtime_error("Mismatch in dimensions: size of image must match side of cairo surface"); + } + + int stride = cairo_image_surface_get_stride(&*surface) / 4; + + const std::unique_ptr out_row(new unsigned int[data.width()]); + const unsigned int *in_row = (const unsigned int *)cairo_image_surface_get_data(&*surface); + + for (unsigned int row = 0; row < data.height(); row++, in_row += stride) + { + for (unsigned int column = 0; column < data.width(); column++) + { + unsigned int in = in_row[column]; + unsigned int a = (in >> 24) & 0xff; + unsigned int r = (in >> 16) & 0xff; + unsigned int g = (in >> 8) & 0xff; + unsigned int b = (in >> 0) & 0xff; + +#define DE_ALPHA(x) do { \ + if (a == 0) x = 0; \ + else x = x * 255 / a; \ + if (x > 255) x = 255; \ + } while(0) + + DE_ALPHA(r); + DE_ALPHA(g); + DE_ALPHA(b); + + out_row[column] = color(r, g, b, a).rgba(); + } + data.setRow(row, out_row.get(), data.width()); + } +} + +} + + +#endif // MAPNIK_CAIRO_IMAGE_UTIL_HPP diff --git a/include/mapnik/cairo/cairo_render_vector.hpp b/include/mapnik/cairo/cairo_render_vector.hpp index 6141be191..b529a508f 100644 --- a/include/mapnik/cairo/cairo_render_vector.hpp +++ b/include/mapnik/cairo/cairo_render_vector.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/cairo/cairo_renderer.hpp b/include/mapnik/cairo/cairo_renderer.hpp index fe9f81914..5aedba82f 100644 --- a/include/mapnik/cairo/cairo_renderer.hpp +++ b/include/mapnik/cairo/cairo_renderer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ // mapnik #include #include -#include +#include #include // for all symbolizers #include #include @@ -67,7 +67,7 @@ struct cairo_save_restore template class MAPNIK_DECL cairo_renderer : public feature_style_processor >, - private mapnik::noncopyable + private util::noncopyable { public: using processor_impl_type = cairo_renderer; diff --git a/include/mapnik/color.hpp b/include/mapnik/color.hpp index 458add451..f220ddd07 100644 --- a/include/mapnik/color.hpp +++ b/include/mapnik/color.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/color_factory.hpp b/include/mapnik/color_factory.hpp index 033363472..6bc360b95 100644 --- a/include/mapnik/color_factory.hpp +++ b/include/mapnik/color_factory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/config.hpp b/include/mapnik/config.hpp index 0e9d902f2..c96948b47 100644 --- a/include/mapnik/config.hpp +++ b/include/mapnik/config.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/config_error.hpp b/include/mapnik/config_error.hpp index 6f590b806..2f6b3f6f4 100644 --- a/include/mapnik/config_error.hpp +++ b/include/mapnik/config_error.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/coord.hpp b/include/mapnik/coord.hpp index 79f2318e1..040c76b88 100644 --- a/include/mapnik/coord.hpp +++ b/include/mapnik/coord.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/coord_array.hpp b/include/mapnik/coord_array.hpp index dc3c2edd6..04b920645 100644 --- a/include/mapnik/coord_array.hpp +++ b/include/mapnik/coord_array.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/css_color_grammar.hpp b/include/mapnik/css_color_grammar.hpp index 8a68de16c..7c7942d98 100644 --- a/include/mapnik/css_color_grammar.hpp +++ b/include/mapnik/css_color_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/css_color_grammar_impl.hpp b/include/mapnik/css_color_grammar_impl.hpp index a1cad2a6f..4fe462711 100644 --- a/include/mapnik/css_color_grammar_impl.hpp +++ b/include/mapnik/css_color_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/datasource.hpp b/include/mapnik/datasource.hpp index 1c13c7fef..ae2524c06 100644 --- a/include/mapnik/datasource.hpp +++ b/include/mapnik/datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include // boost @@ -63,15 +63,15 @@ private: std::string message_; }; -class MAPNIK_DECL datasource : private mapnik::noncopyable +class MAPNIK_DECL datasource : private util::noncopyable { public: - enum datasource_t { + enum datasource_t : std::uint8_t { Vector, Raster }; - enum geometry_t { + enum geometry_t : std::uint8_t { Point = 1, LineString = 2, Polygon = 3, diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index 2a8b75205..a4ff89c7d 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // stl #include @@ -42,7 +42,7 @@ class PluginInfo; class MAPNIK_DECL datasource_cache : public singleton, - private mapnik::noncopyable + private util::noncopyable { friend class CreateStatic; public: diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp index 3aa851053..4e9609d90 100644 --- a/include/mapnik/debug.hpp +++ b/include/mapnik/debug.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include // std #include @@ -48,7 +48,7 @@ namespace mapnik { */ class MAPNIK_DECL logger : public singleton, - private mapnik::noncopyable + private util::noncopyable { public: enum severity_type @@ -184,7 +184,7 @@ namespace mapnik { class Ch = char, class Tr = std::char_traits, class A = std::allocator > - class base_log : public mapnik::noncopyable + class base_log : public util::noncopyable { public: using output_policy = OutputPolicy; @@ -254,7 +254,7 @@ namespace mapnik { class Ch = char, class Tr = std::char_traits, class A = std::allocator > - class base_log_always : public mapnik::noncopyable + class base_log_always : public util::noncopyable { public: using output_policy = OutputPolicy; diff --git a/include/mapnik/ellipsoid.hpp b/include/mapnik/ellipsoid.hpp index 018a0170f..e1be68ca3 100644 --- a/include/mapnik/ellipsoid.hpp +++ b/include/mapnik/ellipsoid.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index c0ca1c79e..935d2f8e2 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/evaluate_global_attributes.hpp b/include/mapnik/evaluate_global_attributes.hpp index 309c5c831..63f0348a4 100644 --- a/include/mapnik/evaluate_global_attributes.hpp +++ b/include/mapnik/evaluate_global_attributes.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -39,7 +39,7 @@ namespace mapnik { namespace { template -struct evaluate_expression : util::static_visitor +struct evaluate_expression { using value_type = T; @@ -133,7 +133,7 @@ struct evaluate_expression : util::static_visitor }; template -struct evaluate_expression : util::static_visitor +struct evaluate_expression { using value_type = T; @@ -271,10 +271,10 @@ std::tuple pre_evaluate_expression (expression_ptr const& expr) } } -struct evaluate_global_attributes : mapnik::noncopyable +struct evaluate_global_attributes : util::noncopyable { template - struct evaluator : util::static_visitor<> + struct evaluator { evaluator(symbolizer_base::cont_type::value_type & prop, Attributes const& attributes) : prop_(prop), @@ -296,7 +296,7 @@ struct evaluate_global_attributes : mapnik::noncopyable }; template - struct extract_symbolizer : util::static_visitor<> + struct extract_symbolizer { extract_symbolizer(Attributes const& attributes) : attributes_(attributes) {} diff --git a/include/mapnik/expression.hpp b/include/mapnik/expression.hpp index 3ec453107..88945074a 100644 --- a/include/mapnik/expression.hpp +++ b/include/mapnik/expression.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/expression_evaluator.hpp b/include/mapnik/expression_evaluator.hpp index e766a4ecd..1d37bdecc 100644 --- a/include/mapnik/expression_evaluator.hpp +++ b/include/mapnik/expression_evaluator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,12 +35,12 @@ namespace mapnik { template -struct evaluate : util::static_visitor +struct evaluate { using feature_type = T0; using value_type = T1; using variable_type = T2; - + using result_type = T1; // we need this because automatic result_type deduction fails explicit evaluate(feature_type const& f, variable_type const& v) : feature_(f), vars_(v) {} diff --git a/include/mapnik/expression_grammar.hpp b/include/mapnik/expression_grammar.hpp index 11a75bb62..f82387ea1 100644 --- a/include/mapnik/expression_grammar.hpp +++ b/include/mapnik/expression_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/expression_grammar_impl.hpp b/include/mapnik/expression_grammar_impl.hpp index 18347cdb5..a4d8353b0 100644 --- a/include/mapnik/expression_grammar_impl.hpp +++ b/include/mapnik/expression_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/expression_node.hpp b/include/mapnik/expression_node.hpp index c46e852f0..e9f00dcaa 100644 --- a/include/mapnik/expression_node.hpp +++ b/include/mapnik/expression_node.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/expression_node_types.hpp b/include/mapnik/expression_node_types.hpp index 665b8080d..aff37adf7 100644 --- a/include/mapnik/expression_node_types.hpp +++ b/include/mapnik/expression_node_types.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/expression_string.hpp b/include/mapnik/expression_string.hpp index 42c61a7c6..afb6331ca 100644 --- a/include/mapnik/expression_string.hpp +++ b/include/mapnik/expression_string.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/factory.hpp b/include/mapnik/factory.hpp index cc5487e06..87b437157 100644 --- a/include/mapnik/factory.hpp +++ b/include/mapnik/factory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 9a600b0f4..1baa2f594 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ #include #include #include -#include +#include // stl #include @@ -49,7 +49,7 @@ class feature_impl; using raster_ptr = std::shared_ptr; template -class context : private mapnik::noncopyable +class context : private util::noncopyable { friend class feature_impl; @@ -90,7 +90,7 @@ using context_ptr = std::shared_ptr; static const value default_feature_value; -class MAPNIK_DECL feature_impl : private mapnik::noncopyable +class MAPNIK_DECL feature_impl : private util::noncopyable { friend class feature_kv_iterator; public: diff --git a/include/mapnik/feature_factory.hpp b/include/mapnik/feature_factory.hpp index c2bf8d352..57ed6dc6d 100644 --- a/include/mapnik/feature_factory.hpp +++ b/include/mapnik/feature_factory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_kv_iterator.hpp b/include/mapnik/feature_kv_iterator.hpp index 060b6fc78..5d9b93a9b 100644 --- a/include/mapnik/feature_kv_iterator.hpp +++ b/include/mapnik/feature_kv_iterator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_layer_desc.hpp b/include/mapnik/feature_layer_desc.hpp index c9d613c2e..e42396b89 100644 --- a/include/mapnik/feature_layer_desc.hpp +++ b/include/mapnik/feature_layer_desc.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_style_processor.hpp b/include/mapnik/feature_style_processor.hpp index 29b4bed28..cc36c01e6 100644 --- a/include/mapnik/feature_style_processor.hpp +++ b/include/mapnik/feature_style_processor.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_style_processor_context.hpp b/include/mapnik/feature_style_processor_context.hpp index ff2970b25..585c746ef 100644 --- a/include/mapnik/feature_style_processor_context.hpp +++ b/include/mapnik/feature_style_processor_context.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index ee37572db..6e0094ba1 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index 783595401..0f0d839fb 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/featureset.hpp b/include/mapnik/featureset.hpp index 869798452..e23532a4f 100644 --- a/include/mapnik/featureset.hpp +++ b/include/mapnik/featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include // boost #include @@ -35,7 +35,7 @@ namespace mapnik { class feature_impl; using feature_ptr = std::shared_ptr; -struct MAPNIK_DECL Featureset : private mapnik::noncopyable +struct MAPNIK_DECL Featureset : private util::noncopyable { virtual feature_ptr next() = 0; virtual ~Featureset() {} diff --git a/include/mapnik/filter_featureset.hpp b/include/mapnik/filter_featureset.hpp index 77ce4fe91..b70462556 100644 --- a/include/mapnik/filter_featureset.hpp +++ b/include/mapnik/filter_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp index e141131d8..78dc055d5 100644 --- a/include/mapnik/font_engine_freetype.hpp +++ b/include/mapnik/font_engine_freetype.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include // stl #include @@ -100,7 +100,7 @@ private: static font_memory_cache_type global_memory_fonts_; }; -class MAPNIK_DECL face_manager : private mapnik::noncopyable +class MAPNIK_DECL face_manager : private util::noncopyable { using face_ptr_cache_type = std::map; diff --git a/include/mapnik/font_set.hpp b/include/mapnik/font_set.hpp index ff0ea8438..8803c99eb 100644 --- a/include/mapnik/font_set.hpp +++ b/include/mapnik/font_set.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/geom_util.hpp b/include/mapnik/geom_util.hpp index 104bef22e..6e8827974 100644 --- a/include/mapnik/geom_util.hpp +++ b/include/mapnik/geom_util.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 471e043e8..29ff13b12 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,12 +26,12 @@ // mapnik #include #include -#include +#include namespace mapnik { template class Container=vertex_vector> -class geometry : private mapnik::noncopyable +class geometry : private util::noncopyable { public: diff --git a/include/mapnik/geometry_container.hpp b/include/mapnik/geometry_container.hpp index ae654d24b..2c5507db2 100644 --- a/include/mapnik/geometry_container.hpp +++ b/include/mapnik/geometry_container.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/global.hpp b/include/mapnik/global.hpp index d1dcf0774..f9b3d3a5a 100644 --- a/include/mapnik/global.hpp +++ b/include/mapnik/global.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/gradient.hpp b/include/mapnik/gradient.hpp index 41493ca0c..a7e628a56 100644 --- a/include/mapnik/gradient.hpp +++ b/include/mapnik/gradient.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -61,8 +61,8 @@ DEFINE_ENUM( gradient_unit_e, gradient_unit_enum ); class MAPNIK_DECL gradient { - gradient_e gradient_type_; - stop_array stops_; + // transform + agg::trans_affine transform_; // control points for the gradient, x1/y1 is the start point, x2/y2 the stop point. double x1_; double y1_; @@ -71,11 +71,11 @@ class MAPNIK_DECL gradient // for radial gradients r specifies the radius of the stop circle centered on x2/y2 double r_; + stop_array stops_; // units for the coordinates gradient_unit_e units_; + gradient_e gradient_type_; - // transform - agg::trans_affine transform_; public: gradient(); gradient(gradient const& other); diff --git a/include/mapnik/graphics.hpp b/include/mapnik/graphics.hpp index b15d9f46b..98e800107 100644 --- a/include/mapnik/graphics.hpp +++ b/include/mapnik/graphics.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,29 +39,20 @@ // boost #include -struct _cairo_surface; -typedef struct _cairo_surface cairo_surface_t; - namespace mapnik { -using cairo_surface_ptr = std::shared_ptr; - class MAPNIK_DECL image_32 { private: - unsigned width_; - unsigned height_; + image_data_rgba8 data_; boost::optional background_; - image_data_32 data_; bool painted_; bool premultiplied_; public: image_32(int width,int height); image_32(image_32 const& rhs); -#ifdef HAVE_CAIRO - explicit image_32(cairo_surface_ptr const& surface); -#endif + image_32(image_data_rgba8 && data); ~image_32(); void painted(bool painted) @@ -98,12 +89,12 @@ public: void set_alpha(float opacity); - inline const image_data_32& data() const + inline const image_data_rgba8& data() const { return data_; } - inline image_data_32& data() + inline image_data_rgba8& data() { return data_; } @@ -118,16 +109,16 @@ public: return data_.getBytes(); } - inline image_view get_view(unsigned x,unsigned y, unsigned w,unsigned h) + inline image_view get_view(unsigned x,unsigned y, unsigned w,unsigned h) { - return image_view(x,y,w,h,data_); + return image_view(x,y,w,h,data_); } private: inline bool checkBounds(int x, int y) const { - return (x >= 0 && x < static_cast(width_) && y >= 0 && y < static_cast(height_)); + return (x >= 0 && x < static_cast(data_.width()) && y >= 0 && y < static_cast(data_.height())); } public: @@ -143,17 +134,17 @@ public: inline unsigned width() const { - return width_; + return data_.width(); } inline unsigned height() const { - return height_; + return data_.height(); } - inline void set_rectangle(int x0,int y0,image_data_32 const& data) + inline void set_rectangle(int x0,int y0,image_data_rgba8 const& data) { - box2d ext0(0,0,width_,height_); + box2d ext0(0,0,data_.width(),data_.height()); box2d ext1(x0,y0,x0+data.width(),y0+data.height()); if (ext0.intersects(ext1)) @@ -175,9 +166,9 @@ public: } } - inline void set_rectangle_alpha(int x0,int y0,const image_data_32& data) + inline void set_rectangle_alpha(int x0,int y0,const image_data_rgba8& data) { - box2d ext0(0,0,width_,height_); + box2d ext0(0,0,data_.width(),data_.height()); box2d ext1(x0,y0,x0 + data.width(),y0 + data.height()); if (ext0.intersects(ext1)) @@ -219,9 +210,9 @@ public: } } - inline void set_rectangle_alpha2(image_data_32 const& data, unsigned x0, unsigned y0, float opacity) + inline void set_rectangle_alpha2(image_data_rgba8 const& data, unsigned x0, unsigned y0, float opacity) { - box2d ext0(0,0,width_,height_); + box2d ext0(0,0,data_.width(),data_.height()); box2d ext1(x0,y0,x0 + data.width(),y0 + data.height()); if (ext0.intersects(ext1)) @@ -267,9 +258,9 @@ public: } template - inline void merge_rectangle(image_data_32 const& data, unsigned x0, unsigned y0, float opacity) + inline void merge_rectangle(image_data_rgba8 const& data, unsigned x0, unsigned y0, float opacity) { - box2d ext0(0,0,width_,height_); + box2d ext0(0,0,data_.width(),data_.height()); box2d ext1(x0,y0,x0 + data.width(),y0 + data.height()); if (ext0.intersects(ext1)) diff --git a/include/mapnik/grid/grid.hpp b/include/mapnik/grid/grid.hpp index 9267303d4..bd4cd1e5d 100644 --- a/include/mapnik/grid/grid.hpp +++ b/include/mapnik/grid/grid.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -195,7 +195,7 @@ public: return height_; } - inline void set_rectangle(value_type id,image_data_32 const& data,int x0,int y0) + inline void set_rectangle(value_type id,image_data_rgba8 const& data,int x0,int y0) { box2d ext0(0,0,width_,height_); box2d ext1(x0,y0,x0+data.width(),y0+data.height()); diff --git a/include/mapnik/grid/grid_marker_helpers.hpp b/include/mapnik/grid/grid_marker_helpers.hpp new file mode 100644 index 000000000..4a27f841a --- /dev/null +++ b/include/mapnik/grid/grid_marker_helpers.hpp @@ -0,0 +1,236 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_GRID_MARKER_HELPERS_HPP +#define MAPNIK_GRID_MARKER_HELPERS_HPP + +// mapnik +#include +#include +#include +#include + +// agg +#include "agg_renderer_scanline.h" +#include "agg_scanline_bin.h" +#include "agg_image_filters.h" +#include "agg_trans_bilinear.h" +#include "agg_span_allocator.h" +#include "agg_image_accessors.h" +#include "agg_span_image_filter_gray.h" + + +namespace mapnik { + +template +struct raster_markers_rasterizer_dispatch_grid : util::noncopyable +{ + using pixfmt_type = typename RendererBase::pixfmt_type; + using color_type = typename RendererBase::pixfmt_type::color_type; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + using PixMapType = typename std::tuple_element<2,RendererContext>::type; + + raster_markers_rasterizer_dispatch_grid(image_data_rgba8 const& src, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + mapnik::feature_impl const& feature, + attributes const& vars, + RendererContext const& renderer_context) + : buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + ras_(std::get<1>(renderer_context)), + src_(src), + marker_trans_(marker_trans), + sym_(sym), + detector_(detector), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + pixmap_(std::get<2>(renderer_context)), + placed_(false) {} + + template + void add_path(T & path) + { + agg::scanline_bin sl_; + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); + box2d bbox(0,0, src_.width(), src_.height()); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + markers_placement_finder placement_finder( + placement_method, path, detector_, params); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = marker_trans_; + matrix.rotate(angle); + matrix.translate(x, y); + render_raster_marker(matrix); + if (!placed_) + { + pixmap_.add_feature(feature_); + placed_ = true; + } + } + } + + void render_raster_marker(agg::trans_affine const& marker_tr) + { + agg::scanline_bin sl_; + double width = src_.width(); + double height = src_.height(); + double p[8]; + p[0] = 0; p[1] = 0; + p[2] = width; p[3] = 0; + p[4] = width; p[5] = height; + p[6] = 0; p[7] = height; + marker_tr.transform(&p[0], &p[1]); + marker_tr.transform(&p[2], &p[3]); + marker_tr.transform(&p[4], &p[5]); + marker_tr.transform(&p[6], &p[7]); + ras_.move_to_d(p[0],p[1]); + ras_.line_to_d(p[2],p[3]); + ras_.line_to_d(p[4],p[5]); + ras_.line_to_d(p[6],p[7]); + RendererType ren(renb_); + ren.color(color_type(feature_.id())); + agg::render_scanlines(ras_, sl_, ren); + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + RendererBase renb_; + RasterizerType & ras_; + image_data_rgba8 const& src_; + agg::trans_affine const& marker_trans_; + markers_symbolizer const& sym_; + Detector & detector_; + double scale_factor_; + mapnik::feature_impl const& feature_; + attributes const& vars_; + PixMapType & pixmap_; + bool placed_; +}; + + +template +struct vector_markers_rasterizer_dispatch_grid : util::noncopyable +{ + using renderer_base = typename SvgRenderer::renderer_base ; + using vertex_source_type = typename SvgRenderer::vertex_source_type ; + using attribute_source_type = typename SvgRenderer::attribute_source_type; + using pixfmt_type = typename renderer_base::pixfmt_type ; + + using BufferType = typename std::tuple_element<0,RendererContext>::type; + using RasterizerType = typename std::tuple_element<1,RendererContext>::type; + using PixMapType = typename std::tuple_element<2,RendererContext>::type; + + vector_markers_rasterizer_dispatch_grid(vertex_source_type & path, + attribute_source_type const& attrs, + box2d const& bbox, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + mapnik::feature_impl const& feature, + attributes const& vars, + bool /*snap_to_pixels*/, + RendererContext const& renderer_context) + : buf_(std::get<0>(renderer_context)), + pixf_(buf_), + renb_(pixf_), + svg_renderer_(path, attrs), + ras_(std::get<1>(renderer_context)), + bbox_(bbox), + marker_trans_(marker_trans), + sym_(sym), + detector_(detector), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + pixmap_(std::get<2>(renderer_context)), + placed_(false) + { + } + + template + void add_path(T & path) + { + agg::scanline_bin sl_; + marker_placement_enum placement_method = + get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + double opacity = get(sym_,keys::opacity, feature_, vars_, 1.0); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool avoid_edges = get(sym_, keys::avoid_edges, feature_, vars_, false); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + coord2d center = bbox_.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine tr = recenter * marker_trans_; + markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap, avoid_edges }; + markers_placement_finder placement_finder( + placement_method, path, detector_, params); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = tr; + matrix.rotate(angle); + matrix.translate(x, y); + svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, opacity, bbox_); + if (!placed_) + { + pixmap_.add_feature(feature_); + placed_ = true; + } + } + } + +private: + BufferType & buf_; + pixfmt_type pixf_; + renderer_base renb_; + SvgRenderer svg_renderer_; + RasterizerType & ras_; + box2d const& bbox_; + agg::trans_affine const& marker_trans_; + markers_symbolizer const& sym_; + Detector & detector_; + double scale_factor_; + mapnik::feature_impl const& feature_; + attributes const& vars_; + PixMapType & pixmap_; + bool placed_; +}; + +} +#endif diff --git a/include/mapnik/grid/grid_pixel.hpp b/include/mapnik/grid/grid_pixel.hpp index 88bf28bcb..5ef1c78bd 100644 --- a/include/mapnik/grid/grid_pixel.hpp +++ b/include/mapnik/grid/grid_pixel.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/grid/grid_pixfmt.hpp b/include/mapnik/grid/grid_pixfmt.hpp index e3cfb3b7a..6f61b9933 100644 --- a/include/mapnik/grid/grid_pixfmt.hpp +++ b/include/mapnik/grid/grid_pixfmt.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/grid/grid_rasterizer.hpp b/include/mapnik/grid/grid_rasterizer.hpp index 9cdbf2724..cd7381384 100644 --- a/include/mapnik/grid/grid_rasterizer.hpp +++ b/include/mapnik/grid/grid_rasterizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,12 +23,12 @@ #ifndef MAPNIK_GRID_RASTERIZER_HPP #define MAPNIK_GRID_RASTERIZER_HPP -#include +#include #include "agg_rasterizer_scanline_aa.h" namespace mapnik { -struct grid_rasterizer : agg::rasterizer_scanline_aa<>, mapnik::noncopyable {}; +struct grid_rasterizer : agg::rasterizer_scanline_aa<>, util::noncopyable {}; } diff --git a/include/mapnik/grid/grid_render_marker.hpp b/include/mapnik/grid/grid_render_marker.hpp index bbf0b90f8..454ae038f 100644 --- a/include/mapnik/grid/grid_render_marker.hpp +++ b/include/mapnik/grid/grid_render_marker.hpp @@ -41,7 +41,7 @@ namespace mapnik { template void render_raster_marker(RendererType ren, RasterizerType & ras, - image_data_32 & src, + image_data_rgba8 & src, mapnik::feature_impl const& feature, agg::trans_affine const& marker_tr, double opacity) diff --git a/include/mapnik/grid/grid_renderer.hpp b/include/mapnik/grid/grid_renderer.hpp index a07ff76c4..500c95059 100644 --- a/include/mapnik/grid/grid_renderer.hpp +++ b/include/mapnik/grid/grid_renderer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include // for rule, symbolizers #include // for box2d #include // for color @@ -59,7 +59,7 @@ namespace mapnik { template class MAPNIK_DECL grid_renderer : public feature_style_processor >, - private mapnik::noncopyable + private util::noncopyable { public: diff --git a/include/mapnik/grid/grid_renderer_base.hpp b/include/mapnik/grid/grid_renderer_base.hpp index a165f58f8..9524b1661 100644 --- a/include/mapnik/grid/grid_renderer_base.hpp +++ b/include/mapnik/grid/grid_renderer_base.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/grid/grid_rendering_buffer.hpp b/include/mapnik/grid/grid_rendering_buffer.hpp index e418d4c57..d5031c826 100644 --- a/include/mapnik/grid/grid_rendering_buffer.hpp +++ b/include/mapnik/grid/grid_rendering_buffer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/grid/grid_util.hpp b/include/mapnik/grid/grid_util.hpp index f681debb7..e740d5794 100644 --- a/include/mapnik/grid/grid_util.hpp +++ b/include/mapnik/grid/grid_util.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/grid/grid_view.hpp b/include/mapnik/grid/grid_view.hpp index dff5e1ec3..e43633e97 100644 --- a/include/mapnik/grid/grid_view.hpp +++ b/include/mapnik/grid/grid_view.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/group/group_layout.hpp b/include/mapnik/group/group_layout.hpp index 81ff4abcd..2087b0b6c 100644 --- a/include/mapnik/group/group_layout.hpp +++ b/include/mapnik/group/group_layout.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/group/group_layout_manager.hpp b/include/mapnik/group/group_layout_manager.hpp index b44921b93..89acf5338 100644 --- a/include/mapnik/group/group_layout_manager.hpp +++ b/include/mapnik/group/group_layout_manager.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/group/group_rule.hpp b/include/mapnik/group/group_rule.hpp index 71dd7df79..a0442ce10 100644 --- a/include/mapnik/group/group_rule.hpp +++ b/include/mapnik/group/group_rule.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/group/group_symbolizer_helper.hpp b/include/mapnik/group/group_symbolizer_helper.hpp index 20b97c778..ec9d21e17 100644 --- a/include/mapnik/group/group_symbolizer_helper.hpp +++ b/include/mapnik/group/group_symbolizer_helper.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/group/group_symbolizer_properties.hpp b/include/mapnik/group/group_symbolizer_properties.hpp index bd6ef2f91..fce169431 100644 --- a/include/mapnik/group/group_symbolizer_properties.hpp +++ b/include/mapnik/group/group_symbolizer_properties.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 166398a75..d9d3fe71b 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // stl #include @@ -52,7 +52,7 @@ struct RGBAPolicy }; template -class hextree : private mapnik::noncopyable +class hextree : private util::noncopyable { struct node { diff --git a/include/mapnik/hit_test_filter.hpp b/include/mapnik/hit_test_filter.hpp index cb9c6f1ec..86a712f2a 100644 --- a/include/mapnik/hit_test_filter.hpp +++ b/include/mapnik/hit_test_filter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index 892dbade5..c72f62daa 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -82,21 +82,13 @@ enum composite_mode_e MAPNIK_DECL boost::optional comp_op_from_string(std::string const& name); MAPNIK_DECL boost::optional comp_op_to_string(composite_mode_e comp_op); -template -MAPNIK_DECL void composite(T1 & dst, T2 & src, +template +MAPNIK_DECL void composite(T & dst, T const& src, composite_mode_e mode, float opacity=1, int dx=0, int dy=0, bool premultiply_src=false); -extern template MAPNIK_DECL void composite(mapnik::image_data_32 & dst, - mapnik::image_data_32 & src, - composite_mode_e mode, - float opacity, - int dx, - int dy, - bool premultiply_src); - } #endif // MAPNIK_IMAGE_COMPOSITING_HPP diff --git a/include/mapnik/image_data.hpp b/include/mapnik/image_data.hpp index ee194c9f4..833a0f16e 100644 --- a/include/mapnik/image_data.hpp +++ b/include/mapnik/image_data.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,167 +25,232 @@ // mapnik #include - // stl #include #include #include -namespace mapnik +namespace mapnik { + +namespace detail { + +struct buffer { -template -class image_data -{ -public: - using pixel_type = T; + explicit buffer(std::size_t size) + : size_(size), + data_(static_cast(size_ != 0 ? ::operator new(size_) : nullptr)) + {} - image_data(int width, int height) - : width_(static_cast(width)), - height_(static_cast(height)), - owns_data_(true) + buffer(buffer && rhs) noexcept + : size_(std::move(rhs.size_)), + data_(std::move(rhs.data_)) { - if (width < 0) - { - throw std::runtime_error("negative width not allowed for image_data"); - } - if (height < 0) - { - throw std::runtime_error("negative height not allowed for image_data"); - } - pData_ = (width!=0 && height!=0) ? static_cast(::operator new(sizeof(T) * width * height)):0; - if (pData_) std::fill(pData_, pData_ + width_ * height_, 0); + rhs.size_ = 0; + rhs.data_ = nullptr; } - image_data(int width, int height, T * data) - : width_(static_cast(width)), - height_(static_cast(height)), - owns_data_(false), - pData_(data) + buffer(buffer const& rhs) + : size_(rhs.size_), + data_(static_cast(size_ != 0 ? ::operator new(size_) : nullptr)) { - if (width < 0) - { - throw std::runtime_error("negative width not allowed for image_data"); - } - if (height < 0) - { - throw std::runtime_error("negative height not allowed for image_data"); - } + if (data_) std::copy(rhs.data_, rhs.data_ + rhs.size_, data_); } - image_data(image_data const& rhs) - :width_(rhs.width_), - height_(rhs.height_), - owns_data_(true), - pData_((rhs.width_!=0 && rhs.height_!=0)? - static_cast(::operator new(sizeof(T) * rhs.width_ * rhs.height_)) : 0) - { - if (pData_) std::copy(rhs.pData_, rhs.pData_ + rhs.width_* rhs.height_, pData_); - } - - image_data(image_data && rhs) noexcept - : width_(rhs.width_), - height_(rhs.height_), - pData_(rhs.pData_) - { - rhs.width_ = 0; - rhs.height_ = 0; - rhs.pData_ = nullptr; - } - - image_data& operator=(image_data rhs) + buffer& operator=(buffer rhs) { swap(rhs); return *this; } - void swap(image_data & rhs) + void swap(buffer & rhs) + { + std::swap(size_, rhs.size_); + std::swap(data_, rhs.data_); + } + + inline bool operator!() const { return (data_ == nullptr)? false : true; } + ~buffer() + { + ::operator delete(data_); + } + + inline unsigned char* data() { return data_; } + inline unsigned char const* data() const { return data_; } + inline std::size_t size() const { return size_; } + std::size_t size_; + unsigned char* data_; + +}; + +template +struct image_dimensions +{ + image_dimensions(int width, int height) + : width_(width), + height_(height) + { + if (width < 0 || static_cast(width) > max_size) throw std::runtime_error("Invalid width for image dimensions requested"); + if (height < 0 || static_cast(height) > max_size) throw std::runtime_error("Invalid height for image dimensions requested"); + } + + image_dimensions(image_dimensions const& other) = default; + image_dimensions(image_dimensions && other) = default; + image_dimensions& operator= (image_dimensions rhs) { std::swap(width_, rhs.width_); std::swap(height_, rhs.height_); - std::swap(pData_, rhs.pData_); + return *this; } - - inline T& operator() (unsigned i,unsigned j) - { - assert(i +class image_data +{ +public: + using pixel_type = T; + static constexpr std::size_t pixel_size = sizeof(pixel_type); + + image_data(int width, int height, bool initialize = true) + : dimensions_(width, height), + buffer_(dimensions_.width() * dimensions_.height() * pixel_size), + pData_(reinterpret_cast(buffer_.data())) { - std::fill(pData_, pData_ + width_ * height_, t); + if (pData_ && initialize) std::fill(pData_, pData_ + dimensions_.width() * dimensions_.height(), 0); } - inline const T* getData() const + image_data(image_data const& rhs) + : dimensions_(rhs.dimensions_), + buffer_(rhs.buffer_), + pData_(reinterpret_cast(buffer_.data())) + {} + + image_data(image_data && rhs) noexcept + : dimensions_(std::move(rhs.dimensions_)), + buffer_(std::move(rhs.buffer_)), + pData_(reinterpret_cast(buffer_.data())) + { + rhs.dimensions_ = { 0, 0 }; + rhs.pData_ = nullptr; + } + + image_data& operator=(image_data rhs) + { + swap(rhs); + return *this; + } + + void swap(image_data & rhs) + { + std::swap(dimensions_, rhs.dimensions_); + std::swap(buffer_, rhs.buffer_); + } + + inline pixel_type& operator() (std::size_t i, std::size_t j) + { + assert(i < dimensions_.width() && j < dimensions_.height()); + return pData_[j * dimensions_.width() + i]; + } + inline const pixel_type& operator() (std::size_t i, std::size_t j) const + { + assert(i < dimensions_.width() && j < dimensions_.height()); + return pData_[j * dimensions_.width() + i]; + } + inline std::size_t width() const + { + return dimensions_.width(); + } + inline std::size_t height() const + { + return dimensions_.height(); + } + inline unsigned getSize() const + { + return dimensions_.height() * dimensions_.width() * pixel_size; + } + inline unsigned getRowSize() const + { + return dimensions_.width() * pixel_size; + } + inline void set(pixel_type const& t) + { + std::fill(pData_, pData_ + dimensions_.width() * dimensions_.height(), t); + } + + inline const pixel_type* getData() const { return pData_; } - inline T* getData() + inline pixel_type* getData() { return pData_; } inline const unsigned char* getBytes() const { - return reinterpret_cast(pData_); + return buffer_.data(); } inline unsigned char* getBytes() { - return reinterpret_cast(pData_); + return buffer_.data(); } - inline const T* getRow(unsigned row) const + inline const pixel_type* getRow(std::size_t row) const { - return pData_+row*width_; + return pData_ + row * dimensions_.width(); } - inline T* getRow(unsigned row) + inline const pixel_type* getRow(std::size_t row, std::size_t x0) const { - return pData_+row*width_; + return pData_ + row * dimensions_.width() + x0; } - inline void setRow(unsigned row, T const* buf, unsigned size) + inline pixel_type* getRow(std::size_t row) { - assert(row dimensions_; + detail::buffer buffer_; + pixel_type *pData_; }; -using image_data_32 = image_data; -using image_data_8 = image_data ; +using image_data_rgba8 = image_data; +using image_data_gray8 = image_data ; +using image_data_gray16 = image_data; +using image_data_gray32f = image_data; } #endif // MAPNIK_IMAGE_DATA_HPP diff --git a/include/mapnik/image_data_any.hpp b/include/mapnik/image_data_any.hpp new file mode 100644 index 000000000..c09bfdf7d --- /dev/null +++ b/include/mapnik/image_data_any.hpp @@ -0,0 +1,112 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_IMAGE_DATA_ANY_HPP +#define MAPNIK_IMAGE_DATA_ANY_HPP + +#include +#include + +namespace mapnik { + +struct image_data_null +{ + unsigned char const* getBytes() const { return nullptr; } + unsigned char* getBytes() { return nullptr;} + std::size_t width() const { return 0; } + std::size_t height() const { return 0; } +}; + +using image_data_base = util::variant; + +namespace detail { + +struct get_bytes_visitor +{ + template + unsigned char* operator()(T & data) + { + return data.getBytes(); + } +}; + +struct get_bytes_visitor_const +{ + template + unsigned char const* operator()(T const& data) const + { + return data.getBytes(); + } +}; + +struct get_width_visitor +{ + template + std::size_t operator()(T const& data) const + { + return data.width(); + } +}; + +struct get_height_visitor +{ + template + std::size_t operator()(T const& data) const + { + return data.height(); + } +}; + +} // namespace detail + +struct image_data_any : image_data_base +{ + image_data_any() = default; + + template + image_data_any(T && data) noexcept + : image_data_base(std::move(data)) {} + + unsigned char const* getBytes() const + { + return util::apply_visitor(detail::get_bytes_visitor_const(),*this); + } + + unsigned char* getBytes() + { + return util::apply_visitor(detail::get_bytes_visitor(),*this); + } + + std::size_t width() const + { + return util::apply_visitor(detail::get_width_visitor(),*this); + } + + std::size_t height() const + { + return util::apply_visitor(detail::get_height_visitor(),*this); + } +}; + +} + +#endif // MAPNIK_IMAGE_DATA_ANY_HPP diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index b4fe9ae93..064e94a43 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -761,7 +761,7 @@ void apply_filter(Src & src, invert const& /*op*/) } template -struct filter_visitor : util::static_visitor +struct filter_visitor { filter_visitor(Src & src) : src_(src) {} @@ -775,7 +775,7 @@ struct filter_visitor : util::static_visitor Src & src_; }; -struct filter_radius_visitor : util::static_visitor +struct filter_radius_visitor { int & radius_; filter_radius_visitor(int & radius) diff --git a/include/mapnik/image_filter_grammar.hpp b/include/mapnik/image_filter_grammar.hpp index 9f94a3b1e..a7c0bd90c 100644 --- a/include/mapnik/image_filter_grammar.hpp +++ b/include/mapnik/image_filter_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/image_filter_grammar_impl.hpp b/include/mapnik/image_filter_grammar_impl.hpp index 38fbcc1f4..c88089f90 100644 --- a/include/mapnik/image_filter_grammar_impl.hpp +++ b/include/mapnik/image_filter_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/image_filter_types.hpp b/include/mapnik/image_filter_types.hpp index 0a8abb13f..e4c9df03b 100644 --- a/include/mapnik/image_filter_types.hpp +++ b/include/mapnik/image_filter_types.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,6 @@ // mapnik #include #include -#include #include // stl @@ -34,6 +33,7 @@ #include #include // for std::back_insert_iterator #include // std::ref +#include namespace mapnik { namespace filter { @@ -101,7 +101,7 @@ struct scale_hsla : image_filter_base a0 < 0 || a0 > 1 || a1 < 0 || a1 > 1) { - throw config_error("scale-hsla values must be between 0 and 1"); + throw std::runtime_error("scale-hsla values must be between 0 and 1"); } } inline bool is_identity() const { @@ -267,7 +267,7 @@ inline std::ostream& operator<< (std::ostream& os, colorize_alpha const& filter) template -struct to_string_visitor : util::static_visitor +struct to_string_visitor { to_string_visitor(Out & out) : out_(out) {} diff --git a/include/mapnik/image_reader.hpp b/include/mapnik/image_reader.hpp index e571ba0b1..31a12f4f0 100644 --- a/include/mapnik/image_reader.hpp +++ b/include/mapnik/image_reader.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,10 +24,11 @@ #define MAPNIK_IMAGE_READER_HPP // mapnik -#include +#include #include -#include +#include #include +#include // boost #include // stl @@ -53,13 +54,15 @@ public: } }; -struct MAPNIK_DECL image_reader : private mapnik::noncopyable +struct MAPNIK_DECL image_reader : private util::noncopyable { - virtual unsigned width() const=0; - virtual unsigned height() const=0; - virtual bool has_alpha() const=0; - virtual bool premultiplied_alpha() const=0; - virtual void read(unsigned x,unsigned y,image_data_32& image)=0; + virtual unsigned width() const = 0; + virtual unsigned height() const = 0; + virtual bool has_alpha() const = 0; + virtual bool premultiplied_alpha() const = 0; + virtual boost::optional > bounding_box() const = 0; + virtual void read(unsigned x,unsigned y,image_data_rgba8& image) = 0; + virtual image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) = 0; virtual ~image_reader() {} }; @@ -69,7 +72,7 @@ bool register_image_reader(std::string const& type, image_reader* (* fun)(Args.. return factory::instance().register_product(type, fun); } -MAPNIK_DECL image_reader* get_image_reader(std::string const& file,std::string const& type); +MAPNIK_DECL image_reader* get_image_reader(std::string const& file, std::string const& type); MAPNIK_DECL image_reader* get_image_reader(std::string const& file); MAPNIK_DECL image_reader* get_image_reader(char const* data, size_t size); diff --git a/include/mapnik/image_scaling.hpp b/include/mapnik/image_scaling.hpp index a7d843480..c8c916fa6 100644 --- a/include/mapnik/image_scaling.hpp +++ b/include/mapnik/image_scaling.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -60,25 +60,14 @@ enum scaling_method_e MAPNIK_DECL boost::optional scaling_method_from_string(std::string const& name); MAPNIK_DECL boost::optional scaling_method_to_string(scaling_method_e scaling_method); -template -MAPNIK_DECL void scale_image_agg(Image & target, - Image const& source, - scaling_method_e scaling_method, - double image_ratio_x, - double image_ratio_y, - double x_off_f, - double y_off_f, - double filter_factor); - -extern template MAPNIK_DECL void scale_image_agg( - mapnik::image_data_32 & target, - mapnik::image_data_32 const& source, - scaling_method_e scaling_method, - double image_ratio_x, - double image_ratio_y, - double x_off_f, - double y_off_f, - double filter_radius); - +template +MAPNIK_DECL void scale_image_agg(T & target, T const& source, + scaling_method_e scaling_method, + double image_ratio_x, + double image_ratio_y, + double x_off_f, + double y_off_f, + double filter_factor); } + #endif // MAPNIK_IMAGE_SCALING_HPP diff --git a/include/mapnik/image_scaling_traits.hpp b/include/mapnik/image_scaling_traits.hpp new file mode 100644 index 000000000..fe2ce61ed --- /dev/null +++ b/include/mapnik/image_scaling_traits.hpp @@ -0,0 +1,132 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_IMAGE_SCALING_TRAITS_HPP +#define MAPNIK_IMAGE_SCALING_TRAITS_HPP + +// agg +#include "agg_image_accessors.h" +#include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" +#include "agg_span_allocator.h" +#include "agg_span_image_filter_gray.h" +#include "agg_span_image_filter_rgba.h" +#include "agg_span_interpolator_linear.h" + +namespace mapnik { namespace detail { + +template +struct agg_scaling_traits {}; + +template <> +struct agg_scaling_traits +{ + using pixfmt_pre = agg::pixfmt_rgba32_pre; + using color_type = agg::rgba8; + using interpolator_type = agg::span_interpolator_linear<>; + using img_src_type = agg::image_accessor_clone; + using span_image_filter = agg::span_image_filter_rgba_nn; + using span_image_resample_affine = agg::span_image_resample_rgba_affine; + +}; + +template <> +struct agg_scaling_traits +{ + using pixfmt_pre = agg::pixfmt_gray8_pre; + using color_type = agg::gray8; + using interpolator_type = agg::span_interpolator_linear<>; + using img_src_type = agg::image_accessor_clone; + using span_image_filter = agg::span_image_filter_gray_nn; + using span_image_resample_affine = agg::span_image_resample_gray_affine; +}; + +template <> +struct agg_scaling_traits +{ + using pixfmt_pre = agg::pixfmt_gray16_pre; + using color_type = agg::gray16; + using interpolator_type = agg::span_interpolator_linear<>; + using img_src_type = agg::image_accessor_clone; + using span_image_filter = agg::span_image_filter_gray_nn; + using span_image_resample_affine = agg::span_image_resample_gray_affine; +}; + +template <> +struct agg_scaling_traits +{ + using pixfmt_pre = agg::pixfmt_gray32_pre; + using color_type = agg::gray32; + using interpolator_type = agg::span_interpolator_linear<>; + using img_src_type = agg::image_accessor_clone; + using span_image_filter = agg::span_image_filter_gray_nn; + using span_image_resample_affine = agg::span_image_resample_gray_affine; +}; + +template +void set_scaling_method(Filter & filter, scaling_method_e scaling_method, double filter_factor) +{ + switch(scaling_method) + { + case SCALING_BILINEAR: + filter.calculate(agg::image_filter_bilinear(), true); break; + case SCALING_BICUBIC: + filter.calculate(agg::image_filter_bicubic(), true); break; + case SCALING_SPLINE16: + filter.calculate(agg::image_filter_spline16(), true); break; + case SCALING_SPLINE36: + filter.calculate(agg::image_filter_spline36(), true); break; + case SCALING_HANNING: + filter.calculate(agg::image_filter_hanning(), true); break; + case SCALING_HAMMING: + filter.calculate(agg::image_filter_hamming(), true); break; + case SCALING_HERMITE: + filter.calculate(agg::image_filter_hermite(), true); break; + case SCALING_KAISER: + filter.calculate(agg::image_filter_kaiser(), true); break; + case SCALING_QUADRIC: + filter.calculate(agg::image_filter_quadric(), true); break; + case SCALING_CATROM: + filter.calculate(agg::image_filter_catrom(), true); break; + case SCALING_GAUSSIAN: + filter.calculate(agg::image_filter_gaussian(), true); break; + case SCALING_BESSEL: + filter.calculate(agg::image_filter_bessel(), true); break; + case SCALING_MITCHELL: + filter.calculate(agg::image_filter_mitchell(), true); break; + case SCALING_SINC: + filter.calculate(agg::image_filter_sinc(filter_factor), true); break; + case SCALING_LANCZOS: + filter.calculate(agg::image_filter_lanczos(filter_factor), true); break; + case SCALING_BLACKMAN: + filter.calculate(agg::image_filter_blackman(filter_factor), true); break; + default: + break; + } +} + +} + +} // + + +#endif // MAPNIK_IMAGE_SCALING_TRAITS_HPP diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index ec946b30c..95bc64c0d 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,7 +45,6 @@ namespace mapnik { // fwd declares class Map; class rgba_palette; -class image_32; class ImageWriterException : public std::exception { @@ -211,114 +210,76 @@ void add_border(T & image) } - -/////////// save_to_file ////////////////////////////////////////////////// - -MAPNIK_DECL void save_to_file(image_32 const& image, - std::string const& file); - -MAPNIK_DECL void save_to_file (image_32 const& image, - std::string const& file, - std::string const& type); - -MAPNIK_DECL void save_to_file (image_32 const& image, - std::string const& file, - std::string const& type, - rgba_palette const& palette); - -/////////////////////////////////////////////////////////////////////////// - - -MAPNIK_DECL std::string save_to_string(image_32 const& image, - std::string const& type); - -MAPNIK_DECL std::string save_to_string(image_32 const& image, - std::string const& type, - rgba_palette const& palette); - -/////////////////////////////////////////////////////////////////////////// - -MAPNIK_DECL void save_to_stream(image_32 const& image, - std::ostream & stream, - std::string const& type, - rgba_palette const& palette); - -MAPNIK_DECL void save_to_stream(image_32 const& image, - std::ostream & stream, - std::string const& type); - -/////////////////////////////////////////////////////////////////////////// - -extern template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&, rgba_palette const&); -extern template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&); -extern template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&, rgba_palette const&); -extern template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_rgba8 const&, std::string const&); -extern template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&, rgba_palette const&); -extern template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&); -extern template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, rgba_palette const&); -extern template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&); -extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_rgba8 const&, std::string const&); -extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_rgba8 const&, std::string const&, rgba_palette const&); -extern template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&); -extern template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&, rgba_palette const&); #ifdef _MSC_VER -template MAPNIK_DECL void save_to_stream( - image_data_32 const& image, +template MAPNIK_DECL void save_to_stream( + image_data_rgba8 const& image, std::ostream & stream, std::string const& type, rgba_palette const& palette ); -template MAPNIK_DECL void save_to_stream( - image_data_32 const& image, +template MAPNIK_DECL void save_to_stream( + image_data_rgba8 const& image, std::ostream & stream, std::string const& type ); -template MAPNIK_DECL void save_to_stream > ( - image_view const& image, +template MAPNIK_DECL void save_to_stream > ( + image_view const& image, std::ostream & stream, std::string const& type, rgba_palette const& palette ); -template MAPNIK_DECL void save_to_stream > ( - image_view const& image, +template MAPNIK_DECL void save_to_stream > ( + image_view const& image, std::ostream & stream, std::string const& type ); diff --git a/include/mapnik/image_view.hpp b/include/mapnik/image_view.hpp index 71921f0d8..3daed9e31 100644 --- a/include/mapnik/image_view.hpp +++ b/include/mapnik/image_view.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,8 @@ class image_view { public: using pixel_type = typename T::pixel_type; - + static constexpr std::size_t pixel_size = sizeof(pixel_type); + image_view(unsigned x, unsigned y, unsigned width, unsigned height, T const& data) : x_(x), y_(y), @@ -84,19 +85,26 @@ public: return height_; } + inline unsigned getSize() const + { + return height_ * width_ * pixel_size; + } + + inline unsigned getRowSize() const + { + return width_ * pixel_size; + } + inline const pixel_type* getRow(unsigned row) const { return data_.getRow(row + y_) + x_; } + + inline const pixel_type* getRow(unsigned row, std::size_t x0) const + { + return data_.getRow(row + y_, x0) + x_; + } - inline const unsigned char* getBytes() const - { - return data_.getBytes(); - } - inline T& data() - { - return data_; - } inline T const& data() const { return data_; diff --git a/include/mapnik/jpeg_io.hpp b/include/mapnik/jpeg_io.hpp index 3e6181123..683764e4d 100644 --- a/include/mapnik/jpeg_io.hpp +++ b/include/mapnik/jpeg_io.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/feature_collection_grammar.hpp b/include/mapnik/json/feature_collection_grammar.hpp index 9f5e24bff..6ffcd2bde 100644 --- a/include/mapnik/json/feature_collection_grammar.hpp +++ b/include/mapnik/json/feature_collection_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,35 +40,20 @@ namespace phoenix = boost::phoenix; namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; -struct generate_id -{ - using result_type = int; - - generate_id(int start) - : id_(start) {} - - int operator() () const - { - return id_++; - } - mutable int id_; -}; - template struct feature_collection_grammar : - qi::grammar(context_ptr const&), space_type> + qi::grammar(context_ptr const&, std::size_t& ), space_type> { feature_collection_grammar(mapnik::transcoder const& tr); feature_grammar feature_g; geometry_grammar geometry_g; phoenix::function extract_geometry_; - qi::rule(context_ptr const&), space_type> start; // START - qi::rule(context_ptr const&), space_type> feature_collection; + qi::rule(context_ptr const&, std::size_t&), space_type> start; // START + qi::rule(context_ptr const&, std::size_t&), space_type> feature_collection; qi::rule type; - qi::rule(context_ptr const&), space_type> features; - qi::rule, void(context_ptr const& ctx, std::vector&), space_type> feature; - qi::rule, void(context_ptr const& ctx, std::vector&), space_type> feature_from_geometry; - boost::phoenix::function generate_id_; + qi::rule(context_ptr const&, std::size_t&), space_type> features; + qi::rule, void(context_ptr const& ctx, std::size_t, std::vector&), space_type> feature; + qi::rule, void(context_ptr const& ctx, std::size_t, std::vector&), space_type> feature_from_geometry; }; }} diff --git a/include/mapnik/json/feature_collection_grammar_impl.hpp b/include/mapnik/json/feature_collection_grammar_impl.hpp index 93c49b7b9..7d1c77819 100644 --- a/include/mapnik/json/feature_collection_grammar_impl.hpp +++ b/include/mapnik/json/feature_collection_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,8 +34,7 @@ namespace mapnik { namespace json { template feature_collection_grammar::feature_collection_grammar(mapnik::transcoder const& tr) : feature_collection_grammar::base_type(start,"start"), - feature_g(tr), - generate_id_(1) + feature_g(tr) { qi::lit_type lit; qi::eps_type eps; @@ -46,15 +45,16 @@ feature_collection_grammar::feature_collection_grammar(map qi::_val_type _val; qi::_r1_type _r1; qi::_r2_type _r2; + qi::_r3_type _r3; using phoenix::push_back; using phoenix::construct; using phoenix::new_; using phoenix::val; - start = feature_collection(_r1) | feature_from_geometry(_r1, _val) | feature(_r1, _val) + start = feature_collection(_r1, _r2) | feature_from_geometry(_r1, _r2, _val) | feature(_r1, _r2, _val) ; - feature_collection = lit('{') >> (type | features(_r1) | feature_g.json_.key_value) % lit(',') >> lit('}') + feature_collection = lit('{') >> (type | features(_r1, _r2) | feature_g.json_.key_value) % lit(',') >> lit('}') ; type = lit("\"type\"") >> lit(':') >> lit("\"FeatureCollection\"") @@ -63,17 +63,17 @@ feature_collection_grammar::feature_collection_grammar(map features = lit("\"features\"") >> lit(':') >> lit('[') - >> -(feature(_r1, _val) % lit(',')) + >> -(feature(_r1, _r2, _val) [_r2 +=1] % lit(',')) >> lit(']') ; - feature = eps[_a = phoenix::construct(new_(_r1, generate_id_()))] - >> feature_g(*_a)[push_back(_r2,_a)] + feature = eps[_a = phoenix::construct(new_(_r1, _r2))] + >> feature_g(*_a)[push_back(_r3,_a)] ; feature_from_geometry = - eps[_a = phoenix::construct(new_(_r1, generate_id_()))] - >> geometry_g(extract_geometry_(*_a)) [push_back(_r2, _a)] + eps[_a = phoenix::construct(new_(_r1, _r2))] + >> geometry_g(extract_geometry_(*_a)) [push_back(_r3, _a)] ; start.name("start"); diff --git a/include/mapnik/json/feature_generator.hpp b/include/mapnik/json/feature_generator.hpp index bf5a2e5ac..0d3fcb847 100644 --- a/include/mapnik/json/feature_generator.hpp +++ b/include/mapnik/json/feature_generator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,7 @@ namespace mapnik { namespace json { inline bool to_geojson(std::string & json, mapnik::feature_impl const& feature) { using sink_type = std::back_insert_iterator; - static const mapnik::json::feature_generator_grammar grammar; + static const mapnik::json::feature_generator_grammar grammar; sink_type sink(json); return boost::spirit::karma::generate(sink, grammar, feature); } diff --git a/include/mapnik/json/feature_generator_grammar.hpp b/include/mapnik/json/feature_generator_grammar.hpp index a0239757d..84a30022e 100644 --- a/include/mapnik/json/feature_generator_grammar.hpp +++ b/include/mapnik/json/feature_generator_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,23 +24,13 @@ #define MAPNIK_JSON_FEATURE_GENERATOR_GRAMMAR_HPP // mapnik -#include -#include #include #include #include -#include +#include // boost #include -#include -#include -#include -#include -#include -#include -#include -#include namespace boost { namespace spirit { namespace traits { @@ -90,84 +80,27 @@ namespace mapnik { namespace json { namespace karma = boost::spirit::karma; +template struct get_id { - template - struct result { using type = int; }; - - int operator() (mapnik::feature_impl const& f) const + using feature_type = T; + using result_type = int; + int operator() (feature_type const& f) const { return f.id(); } }; -struct make_properties_range + +template +struct feature_generator_grammar : + karma::grammar { - using properties_range_type = boost::iterator_range; - - template - struct result { using type = properties_range_type; }; - - properties_range_type operator() (mapnik::feature_impl const& f) const - { - return boost::make_iterator_range(f.begin(),f.end()); - } -}; - -struct utf8 -{ - template - struct result { using type = std::string; }; - - std::string operator() (mapnik::value_unicode_string const& ustr) const - { - std::string result; - to_utf8(ustr,result); - return result; - } -}; - -template -struct escaped_string - : karma::grammar -{ - escaped_string(); - karma::rule esc_str; - karma::symbols esc_char; -}; - -struct extract_string -{ - using result_type = std::tuple; - - result_type operator() (mapnik::value const& val) const - { - bool need_quotes = val.is(); - return std::make_tuple(val.to_string(), need_quotes); - } -}; - -template -struct feature_generator_grammar: - karma::grammar -{ - using pair_type = std::tuple; - using range_type = make_properties_range::properties_range_type; - feature_generator_grammar(); - karma::rule feature; + karma::rule feature; multi_geometry_generator_grammar geometry; - escaped_string escaped_string_; - karma::rule properties; - karma::rule pair; - karma::rule()> value; - karma::rule value_null_; - karma::rule ustring; - typename karma::int_generator int__; - boost::phoenix::function id_; - boost::phoenix::function extract_string_; - boost::phoenix::function utf8_; - std::string quote_; + properties_generator_grammar properties; + boost::phoenix::function > id_; }; }} diff --git a/include/mapnik/json/feature_generator_grammar_impl.hpp b/include/mapnik/json/feature_generator_grammar_impl.hpp index 1d1d3c907..7147bd892 100644 --- a/include/mapnik/json/feature_generator_grammar_impl.hpp +++ b/include/mapnik/json/feature_generator_grammar_impl.hpp @@ -29,50 +29,14 @@ namespace mapnik { namespace json { -namespace karma = boost::spirit::karma; - -template -escaped_string::escaped_string() - : escaped_string::base_type(esc_str) -{ - karma::lit_type lit; - karma::_r1_type _r1; - karma::hex_type hex; - karma::right_align_type right_align; - karma::print_type kprint; - esc_char.add - ('"', "\\\"") - ('\\', "\\\\") - ('\b', "\\b") - ('\f', "\\f") - ('\n', "\\n") - ('\r', "\\r") - ('\t', "\\t") - ; - - esc_str = lit(_r1) - << *(esc_char - | kprint - | "\\u" << right_align(4,lit('0'))[hex]) - << lit(_r1) - ; -} - -template -feature_generator_grammar::feature_generator_grammar() - : feature_generator_grammar::base_type(feature), - quote_("\"") +template +feature_generator_grammar::feature_generator_grammar() + : feature_generator_grammar::base_type(feature) { boost::spirit::karma::lit_type lit; boost::spirit::karma::uint_type uint_; - boost::spirit::karma::bool_type bool_; - boost::spirit::karma::double_type double_; boost::spirit::karma::_val_type _val; boost::spirit::karma::_1_type _1; - boost::spirit::karma::string_type kstring; - boost::spirit::karma::eps_type eps; - - using boost::phoenix::at_c; feature = lit("{\"type\":\"Feature\",\"id\":") << uint_[_1 = id_(_val)] @@ -80,30 +44,6 @@ feature_generator_grammar::feature_generator_grammar() << lit(",\"properties\":") << properties << lit('}') ; - - properties = lit('{') - << -(pair % lit(',')) - << lit('}') - ; - - pair = lit('"') - << kstring[_1 = boost::phoenix::at_c<0>(_val)] << lit('"') - << lit(':') - << value[_1 = extract_string_(at_c<1>(_val))] - ; - - value = eps(at_c<1>(_val)) << escaped_string_(quote_.c_str())[_1 = at_c<0>(_val)] - | - kstring[_1 = at_c<0>(_val)] - ; - - // FIXME http://boost-spirit.com/home/articles/karma-examples/creating-your-own-generator-component-for-spirit-karma/ - //value = (value_null_| bool_ | int__ | double_ | ustring)//[_1 = value_base_(_r1)] - // ; - //value_null_ = kstring[_1 = "null"] - // ; - //ustring = escaped_string_(quote_.c_str())[_1 = utf8_(_val)] - // ; } }} diff --git a/include/mapnik/json/feature_grammar.hpp b/include/mapnik/json/feature_grammar.hpp index 90f65b004..a75a84f3a 100644 --- a/include/mapnik/json/feature_grammar.hpp +++ b/include/mapnik/json/feature_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -46,7 +46,7 @@ namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; class attribute_value_visitor - : public mapnik::util::static_visitor + { public: attribute_value_visitor(mapnik::transcoder const& tr) diff --git a/include/mapnik/json/feature_grammar_impl.hpp b/include/mapnik/json/feature_grammar_impl.hpp index e8928165f..51239a9a7 100644 --- a/include/mapnik/json/feature_grammar_impl.hpp +++ b/include/mapnik/json/feature_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/feature_parser.hpp b/include/mapnik/json/feature_parser.hpp index 9154aca6b..c7ef79aee 100644 --- a/include/mapnik/json/feature_parser.hpp +++ b/include/mapnik/json/feature_parser.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/generic_json.hpp b/include/mapnik/json/generic_json.hpp index e8baaf1eb..fda147792 100644 --- a/include/mapnik/json/generic_json.hpp +++ b/include/mapnik/json/generic_json.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/geometry_generator_grammar.hpp b/include/mapnik/json/geometry_generator_grammar.hpp index befb80391..77b522e8f 100644 --- a/include/mapnik/json/geometry_generator_grammar.hpp +++ b/include/mapnik/json/geometry_generator_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/geometry_parser.hpp b/include/mapnik/json/geometry_parser.hpp index 57f5ac6c0..9d6fabe6b 100644 --- a/include/mapnik/json/geometry_parser.hpp +++ b/include/mapnik/json/geometry_parser.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/geometry_util.hpp b/include/mapnik/json/geometry_util.hpp index dd0c56694..be42d7ede 100644 --- a/include/mapnik/json/geometry_util.hpp +++ b/include/mapnik/json/geometry_util.hpp @@ -31,7 +31,7 @@ namespace mapnik { namespace json { // geometries template -struct create_point : util::static_visitor<> +struct create_point { explicit create_point(Path & path) : path_(path) {} @@ -49,7 +49,7 @@ struct create_point : util::static_visitor<> }; template -struct create_linestring : util::static_visitor<> +struct create_linestring { explicit create_linestring(Path & path) : path_(path) {} @@ -77,7 +77,7 @@ struct create_linestring : util::static_visitor<> }; template -struct create_polygon : util::static_visitor<> +struct create_polygon { explicit create_polygon(Path & path) : path_(path) {} @@ -111,7 +111,7 @@ struct create_polygon : util::static_visitor<> // multi-geometries template -struct create_multipoint : util::static_visitor<> +struct create_multipoint { explicit create_multipoint(Path & path) : path_(path) {} @@ -133,7 +133,7 @@ struct create_multipoint : util::static_visitor<> }; template -struct create_multilinestring : util::static_visitor<> +struct create_multilinestring { explicit create_multilinestring(Path & path) : path_(path) {} @@ -163,7 +163,7 @@ struct create_multilinestring : util::static_visitor<> }; template -struct create_multipolygon : util::static_visitor<> +struct create_multipolygon { explicit create_multipolygon(Path & path) : path_(path) {} diff --git a/include/mapnik/json/properties_generator_grammar.hpp b/include/mapnik/json/properties_generator_grammar.hpp new file mode 100644 index 000000000..e52b55ed4 --- /dev/null +++ b/include/mapnik/json/properties_generator_grammar.hpp @@ -0,0 +1,83 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_JSON_PROPERTIES_GENERATOR_GRAMMAR_HPP +#define MAPNIK_JSON_PROPERTIES_GENERATOR_GRAMMAR_HPP + +#include +#include +#include + +// boost +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik { namespace json { + +template +struct escaped_string + : karma::grammar +{ + escaped_string(); + karma::rule esc_str; + karma::symbols esc_char; +}; + +struct extract_string +{ + using result_type = std::tuple; + + result_type operator() (mapnik::value const& val) const + { + bool need_quotes = val.is(); + return std::make_tuple(val.to_string(), need_quotes); + } +}; + +template +struct properties_generator_grammar : karma::grammar + +{ + using pair_type = std::tuple; + properties_generator_grammar(); + // rules + karma::rule properties; + karma::rule pair; + karma::rule()> value; + karma::rule value_null_; + karma::rule ustring; + escaped_string escaped_string_; + typename karma::int_generator int__; + boost::phoenix::function extract_string_; + std::string quote_; +}; + +}} + +#endif //MAPNIK_JSON_PROPERTIES_GENERATOR_GRAMMAR_HPP diff --git a/include/mapnik/json/properties_generator_grammar_impl.hpp b/include/mapnik/json/properties_generator_grammar_impl.hpp new file mode 100644 index 000000000..197f00026 --- /dev/null +++ b/include/mapnik/json/properties_generator_grammar_impl.hpp @@ -0,0 +1,92 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + + +#include + +namespace mapnik { namespace json { + +namespace karma = boost::spirit::karma; + +template +escaped_string::escaped_string() + : escaped_string::base_type(esc_str) +{ + karma::lit_type lit; + karma::_r1_type _r1; + karma::char_type char_; + esc_char.add + ('\a', "\\u0007") + ('\b', "\\b") + ('\f', "\\f") + ('\n', "\\n") + ('\r', "\\r") + ('\t', "\\t") + ('\v', "\\u000b") + ('"', "\\\"") + ('\\', "\\\\") + ; + esc_str = lit(_r1) + << *(esc_char | char_) + << lit(_r1) + ; +} + +template +properties_generator_grammar::properties_generator_grammar() + : properties_generator_grammar::base_type(properties), + quote_("\"") +{ + + boost::spirit::karma::lit_type lit; + boost::spirit::karma::_val_type _val; + boost::spirit::karma::_1_type _1; + boost::spirit::karma::string_type kstring; + boost::spirit::karma::eps_type eps; + using boost::phoenix::at_c; + + properties = lit('{') + << -(pair % lit(',')) + << lit('}') + ; + + pair = lit('"') + << kstring[_1 = boost::phoenix::at_c<0>(_val)] << lit('"') + << lit(':') + << value[_1 = extract_string_(at_c<1>(_val))] + ; + + value = eps(at_c<1>(_val)) << escaped_string_(quote_.c_str())[_1 = at_c<0>(_val)] + | + kstring[_1 = at_c<0>(_val)] + ; + + // FIXME http://boost-spirit.com/home/articles/karma-examples/creating-your-own-generator-component-for-spirit-karma/ + //value = (value_null_| bool_ | int__ | double_ | ustring)//[_1 = value_base_(_r1)] + // ; + //value_null_ = kstring[_1 = "null"] + // ; + //ustring = escaped_string_(quote_.c_str())[_1 = utf8_(_val)] + // ; +} + +}} diff --git a/include/mapnik/json/symbolizer_grammar.hpp b/include/mapnik/json/symbolizer_grammar.hpp index 5f1a7c32e..bd34af0bd 100644 --- a/include/mapnik/json/symbolizer_grammar.hpp +++ b/include/mapnik/json/symbolizer_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,7 +45,7 @@ namespace standard_wide = boost::spirit::standard_wide; using standard_wide::space_type; template -struct json_value_visitor : mapnik::util::static_visitor<> +struct json_value_visitor { json_value_visitor(Symbolizer & sym, mapnik::keys key) : sym_(sym), key_(key) {} @@ -82,7 +82,7 @@ struct json_value_visitor : mapnik::util::static_visitor<> }; template -struct put_property_visitor : mapnik::util::static_visitor<> +struct put_property_visitor { using value_type = T; diff --git a/include/mapnik/json/topojson_grammar.hpp b/include/mapnik/json/topojson_grammar.hpp index b36f8abc4..944814f5e 100644 --- a/include/mapnik/json/topojson_grammar.hpp +++ b/include/mapnik/json/topojson_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/topojson_grammar_impl.hpp b/include/mapnik/json/topojson_grammar_impl.hpp index 3231c9f67..bb54680af 100644 --- a/include/mapnik/json/topojson_grammar_impl.hpp +++ b/include/mapnik/json/topojson_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/json/topojson_utils.hpp b/include/mapnik/json/topojson_utils.hpp index e3d4a0812..5f7e739d5 100644 --- a/include/mapnik/json/topojson_utils.hpp +++ b/include/mapnik/json/topojson_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ namespace mapnik { namespace topojson { -struct bounding_box_visitor : public mapnik::util::static_visitor > +struct bounding_box_visitor { bounding_box_visitor(topology const& topo) : topo_(topo) {} diff --git a/include/mapnik/json/topology.hpp b/include/mapnik/json/topology.hpp index ad316978f..7b93fcb58 100644 --- a/include/mapnik/json/topology.hpp +++ b/include/mapnik/json/topology.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/label_collision_detector.hpp b/include/mapnik/label_collision_detector.hpp index 585be4f64..a33747b90 100644 --- a/include/mapnik/label_collision_detector.hpp +++ b/include/mapnik/label_collision_detector.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include #include // icu @@ -63,7 +63,7 @@ private: }; // quad_tree based label collision detector -class label_collision_detector2 : mapnik::noncopyable +class label_collision_detector2 : util::noncopyable { using tree_t = quad_tree >; tree_t tree_; @@ -92,7 +92,7 @@ public: }; // quad_tree based label collision detector with seperate check/insert -class label_collision_detector3 : mapnik::noncopyable +class label_collision_detector3 : util::noncopyable { using tree_t = quad_tree< box2d >; tree_t tree_; @@ -126,7 +126,7 @@ public: //quad tree based label collision detector so labels dont appear within a given distance -class label_collision_detector4 : mapnik::noncopyable +class label_collision_detector4 : util::noncopyable { public: struct label diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index 9ce8ff7f9..7d0e3bf31 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/load_map.hpp b/include/mapnik/load_map.hpp index 1ef69fb0e..5696a9e8f 100644 --- a/include/mapnik/load_map.hpp +++ b/include/mapnik/load_map.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 815d6a8ee..ee1c7a3b7 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -231,7 +231,7 @@ public: /*! \brief register fonts. */ - bool register_fonts(std::string const& dir, bool recurse); + bool register_fonts(std::string const& dir, bool recurse = false); /*! \brief cache registered fonts. */ diff --git a/include/mapnik/mapped_memory_cache.hpp b/include/mapnik/mapped_memory_cache.hpp index c1f9c5030..3673c15e0 100644 --- a/include/mapnik/mapped_memory_cache.hpp +++ b/include/mapnik/mapped_memory_cache.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // boost #include @@ -42,7 +42,7 @@ using mapped_region_ptr = std::shared_ptr; class MAPNIK_DECL mapped_memory_cache : public singleton, - private mapnik::noncopyable + private util::noncopyable { friend class CreateStatic; std::unordered_map cache_; diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index 9f008ff0c..63fe16c18 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include #include #include -#include +#include // agg #include "agg_array.h" @@ -45,18 +45,18 @@ namespace mapnik using attr_storage = agg::pod_bvector; using svg_storage_type = mapnik::svg::svg_storage; using svg_path_ptr = std::shared_ptr; -using image_ptr = std::shared_ptr; +using image_ptr = std::shared_ptr; /** * A class to hold either vector or bitmap marker data. This allows these to be treated equally * in the image caches and most of the render paths. */ -class marker: private mapnik::noncopyable +class marker: private util::noncopyable { public: marker() { // create default OGC 4x4 black pixel - bitmap_data_ = boost::optional(std::make_shared(4,4)); + bitmap_data_ = boost::optional(std::make_shared(4,4)); (*bitmap_data_)->set(0xff000000); } diff --git a/include/mapnik/marker_cache.hpp b/include/mapnik/marker_cache.hpp index 6210deb5f..34907cc80 100644 --- a/include/mapnik/marker_cache.hpp +++ b/include/mapnik/marker_cache.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // boost #include @@ -43,7 +43,7 @@ using marker_ptr = std::shared_ptr; class MAPNIK_DECL marker_cache : public singleton , - private mapnik::noncopyable + private util::noncopyable { friend class CreateUsingNew; private: diff --git a/include/mapnik/marker_helpers.hpp b/include/mapnik/marker_helpers.hpp index 2a0ae16c2..c7fd8becf 100644 --- a/include/mapnik/marker_helpers.hpp +++ b/include/mapnik/marker_helpers.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -57,7 +57,7 @@ struct clip_poly_tag; using svg_attribute_type = agg::pod_bvector; template -struct vector_markers_dispatch : mapnik::noncopyable +struct vector_markers_dispatch : util::noncopyable { vector_markers_dispatch(svg_path_ptr const& src, agg::trans_affine const& marker_trans, @@ -116,9 +116,9 @@ protected: }; template -struct raster_markers_dispatch : mapnik::noncopyable +struct raster_markers_dispatch : util::noncopyable { - raster_markers_dispatch(image_data_32 & src, + raster_markers_dispatch(image_data_rgba8 & src, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, @@ -163,7 +163,7 @@ struct raster_markers_dispatch : mapnik::noncopyable virtual void render_marker(agg::trans_affine const& marker_tr, double opacity) = 0; protected: - image_data_32 & src_; + image_data_rgba8 & src_; agg::trans_affine const& marker_trans_; symbolizer_base const& sym_; Detector & detector_; diff --git a/include/mapnik/markers_placement.hpp b/include/mapnik/markers_placement.hpp index 88e20b55e..1472e6ea1 100644 --- a/include/mapnik/markers_placement.hpp +++ b/include/mapnik/markers_placement.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,7 @@ namespace mapnik { template -class markers_placement_finder : mapnik::noncopyable +class markers_placement_finder : util::noncopyable { public: using markers_placement = util::variant, @@ -44,7 +44,7 @@ public: markers_vertex_first_placement, markers_vertex_last_placement>; - class get_point_visitor : public util::static_visitor + class get_point_visitor { public: get_point_visitor(double &x, double &y, double &angle, bool ignore_placement) diff --git a/include/mapnik/markers_placements/interior.hpp b/include/mapnik/markers_placements/interior.hpp index 6d36c44ae..395ee07a1 100644 --- a/include/mapnik/markers_placements/interior.hpp +++ b/include/mapnik/markers_placements/interior.hpp @@ -37,6 +37,10 @@ public: { } + markers_interior_placement(markers_interior_placement && rhs) + : markers_point_placement(std::move(rhs)) + {} + bool get_point(double &x, double &y, double &angle, bool ignore_placement) { if (this->done_) diff --git a/include/mapnik/markers_placements/line.hpp b/include/mapnik/markers_placements/line.hpp index 3c829e787..24bb229ec 100644 --- a/include/mapnik/markers_placements/line.hpp +++ b/include/mapnik/markers_placements/line.hpp @@ -25,10 +25,8 @@ #include #include -#include -#include //round - -#include +#include +#include namespace mapnik { @@ -38,29 +36,28 @@ class markers_line_placement : public markers_point_placement public: markers_line_placement(Locator &locator, Detector &detector, markers_placement_params const& params) : markers_point_placement(locator, detector, params), - last_x(0.0), - last_y(0.0), - next_x(0.0), - next_y(0.0), + first_point_(true), spacing_(0.0), marker_width_((params.size * params.tr).width()), - error_(0.0), - spacing_left_(0.0), - marker_nr_(0) + path_(locator) { spacing_ = params.spacing < 1 ? 100 : params.spacing; rewind(); } + markers_line_placement(markers_line_placement && rhs) + : markers_point_placement(std::move(rhs)), + first_point_(std::move(rhs.first_point_)), + spacing_(std::move(rhs.spacing_)), + marker_width_(std::move(rhs.marker_width_)), + path_(std::move(rhs.path_)) + {} + void rewind() { this->locator_.rewind(0); - //Get first point - this->done_ = agg::is_stop(this->locator_.vertex(&next_x, &next_y)); - last_x = next_x; - last_y = next_y; // Force request of new segment - error_ = 0.0; - marker_nr_ = 0; + this->done_ = false; + first_point_ = true; } bool get_point(double &x, double &y, double &angle, bool ignore_placement) @@ -75,159 +72,56 @@ public: return markers_point_placement::get_point(x, y, angle, ignore_placement); } - unsigned cmd; - /* This functions starts at the position of the previous marker, - walks along the path, counting how far it has to go in spacing_left. - If one marker can't be placed at the position it should go to it is - moved a bit. The error is compensated for in the next call to this - function. + double move = spacing_; - error > 0: Marker too near to the end of the path. - error = 0: Perfect position. - error < 0: Marker too near to the beginning of the path. - */ - if (marker_nr_ == 0) + if (first_point_) { - //First marker - marker_nr_++; - spacing_left_ = spacing_ / 2; + if (!path_.next_subpath()) + { + this->done_ = true; + return false; + } + first_point_ = false; + move = spacing_ / 2.0; } - else + + while (path_.forward(move)) { - spacing_left_ = spacing_; - } - spacing_left_ -= error_; - error_ = 0.0; - double max_err_allowed = this->params_.max_error * spacing_; - //Loop exits when a position is found or when no more segments are available - while (true) - { - //Do not place markers too close to the beginning of a segment - if (spacing_left_ < this->marker_width_ / 2) - { - set_spacing_left(this->marker_width_ / 2); //Only moves forward - } - //Error for this marker is too large. Skip to the next position. - if (std::fabs(error_) > max_err_allowed) - { - while (this->error_ > spacing_) - { - error_ -= spacing_; //Avoid moving backwards - } - spacing_left_ += spacing_ - this->error_; - error_ = 0.0; - } - double dx = next_x - last_x; - double dy = next_y - last_y; - double segment_length = std::sqrt(dx * dx + dy * dy); - if (segment_length <= spacing_left_) - { - //Segment is too short to place marker. Find next segment - spacing_left_ -= segment_length; - last_x = next_x; - last_y = next_y; - while (agg::is_move_to(cmd = this->locator_.vertex(&next_x, &next_y))) - { - //Skip over "move" commands - last_x = next_x; - last_y = next_y; - } - if (agg::is_stop(cmd) || cmd == SEG_CLOSE) - { - this->done_ = true; - return false; - } - continue; //Try again - } - /* At this point we know the following things: - - segment_length > spacing_left - - error is small enough - - at least half a marker fits into this segment - */ - //Check if marker really fits in this segment - if (segment_length < this->marker_width_) - { - //Segment to short => Skip this segment - set_spacing_left(segment_length + this->marker_width_/2); //Only moves forward - continue; - } - else if (segment_length - spacing_left_ < this->marker_width_/2) - { - //Segment is long enough, but we are to close to the end - //Note: This function moves backwards. This could lead to an infinite - // loop when another function adds a positive offset. Therefore we - // only move backwards when there is no offset - if (error_ == 0) - { - set_spacing_left(segment_length - this->marker_width_/2, true); - } - else - { - //Skip this segment - set_spacing_left(segment_length + this->marker_width_/2); //Only moves forward - } - continue; //Force checking of max_error constraint - } - angle = std::atan2(dy, dx); - x = last_x + dx * (spacing_left_ / segment_length); - y = last_y + dy * (spacing_left_ / segment_length); - box2d box = this->perform_transform(angle, x, y); - if (this->params_.avoid_edges && !this->detector_.extent().contains(box)) - { - set_spacing_left(spacing_left_ + spacing_ * this->params_.max_error / 10.0); - continue; - } - if (!this->params_.allow_overlap && !this->detector_.has_placement(box)) - { - //10.0 is the approxmiate number of positions tried and choosen arbitrarily - set_spacing_left(spacing_left_ + spacing_ * this->params_.max_error / 10.0); //Only moves forward - continue; - } - if (!ignore_placement) - { - this->detector_.insert(box); - } - last_x = x; - last_y = y; - return true; + tolerance_iterator tolerance_offset(spacing_ * this->params_.max_error, 0.0); + while (tolerance_offset.next()) + { + vertex_cache::scoped_state state(path_); + if (path_.move(tolerance_offset.get()) && (path_.linear_position() + marker_width_ / 2.0) < path_.length()) + { + pixel_position pos = path_.current_position(); + x = pos.x; + y = pos.y; + angle = path_.current_segment_angle(); + box2d box = this->perform_transform(angle, x, y); + if ((this->params_.avoid_edges && !this->detector_.extent().contains(box)) + || (!this->params_.allow_overlap && !this->detector_.has_placement(box))) + { + continue; + } + if (!ignore_placement) + { + this->detector_.insert(box); + } + return true; + } + } } + + this->done_ = true; + + return false; } private: - double last_x; - double last_y; - double next_x; - double next_y; + bool first_point_; double spacing_; double marker_width_; - // If a marker could not be placed at the exact point where it should - // go the next marker's distance will be a bit lower. - double error_; - double spacing_left_; - unsigned marker_nr_; - - // Set spacing_left_, adjusts error_ and performs sanity checks. - void set_spacing_left(double sl, bool allow_negative=false) - { - double delta_error = sl - spacing_left_; - if (!allow_negative && delta_error < 0) - { - MAPNIK_LOG_WARN(markers_line_placement) - << "Unexpected negative error in markers_line_placement. " - "Please file a bug report."; - return; - } -#ifdef MAPNIK_DEBUG - if (delta_error == 0.0) - { - MAPNIK_LOG_WARN(markers_line_placement) - << "Not moving at all in set_spacing_left()! " - "Please file a bug report."; - } -#endif - error_ += delta_error; - spacing_left_ = sl; - } + vertex_cache path_; }; } diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index e9af96f8e..3ca1ce5c8 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -41,7 +41,7 @@ struct markers_placement_params }; template -class markers_point_placement +class markers_point_placement : util::noncopyable { public: markers_point_placement(Locator &locator, Detector &detector, markers_placement_params const& params) @@ -53,6 +53,14 @@ public: rewind(); } + markers_point_placement(markers_point_placement && rhs) + : locator_(rhs.locator_), + detector_(rhs.detector_), + params_(rhs.params_), + done_(rhs.done_) + {} + + // Start again at first marker. Returns the same list of markers only works when they were NOT added to the detector. void rewind() { diff --git a/include/mapnik/markers_placements/vertext_first.hpp b/include/mapnik/markers_placements/vertext_first.hpp index 8ac11e2b4..9f142e160 100644 --- a/include/mapnik/markers_placements/vertext_first.hpp +++ b/include/mapnik/markers_placements/vertext_first.hpp @@ -36,6 +36,10 @@ public: { } + markers_vertex_first_placement(markers_vertex_first_placement && rhs) + : markers_point_placement(std::move(rhs)) + {} + bool get_point(double &x, double &y, double &angle, bool ignore_placement) { if (this->done_) diff --git a/include/mapnik/markers_placements/vertext_last.hpp b/include/mapnik/markers_placements/vertext_last.hpp index 3268c7c64..456687003 100644 --- a/include/mapnik/markers_placements/vertext_last.hpp +++ b/include/mapnik/markers_placements/vertext_last.hpp @@ -32,7 +32,12 @@ class markers_vertex_last_placement : public markers_point_placement(locator, detector, params) {} + : markers_point_placement(locator, detector, params) + {} + + markers_vertex_last_placement(markers_vertex_last_placement && rhs) + : markers_point_placement(std::move(rhs)) + {} bool get_point(double &x, double &y, double &angle, bool ignore_placement) { diff --git a/include/mapnik/memory.hpp b/include/mapnik/memory.hpp index 98a225a5f..c4bff29f2 100644 --- a/include/mapnik/memory.hpp +++ b/include/mapnik/memory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/memory_datasource.hpp b/include/mapnik/memory_datasource.hpp index a442d6179..93d970008 100644 --- a/include/mapnik/memory_datasource.hpp +++ b/include/mapnik/memory_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/memory_featureset.hpp b/include/mapnik/memory_featureset.hpp index 9deb6fe5b..5466354bc 100644 --- a/include/mapnik/memory_featureset.hpp +++ b/include/mapnik/memory_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/miniz_png.hpp b/include/mapnik/miniz_png.hpp index cc59931c8..bc9221f36 100644 --- a/include/mapnik/miniz_png.hpp +++ b/include/mapnik/miniz_png.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -83,12 +83,12 @@ private: static const unsigned char IEND_tpl[]; }; -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_data_8 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT >(image_view const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_data_32 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDAT >(image_view const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha(image_data_32 const& image); -extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha >(image_view const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_data_gray8 const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDAT >(image_view const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDAT(image_data_rgba8 const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDAT >(image_view const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha(image_data_rgba8 const& image); +extern template MAPNIK_DECL void PNGWriter::writeIDATStripAlpha >(image_view const& image); }} diff --git a/include/mapnik/octree.hpp b/include/mapnik/octree.hpp index f98eb53f8..6119bd6cb 100644 --- a/include/mapnik/octree.hpp +++ b/include/mapnik/octree.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // stl #include @@ -49,7 +49,7 @@ struct RGBPolicy }; template -class octree : private mapnik::noncopyable +class octree : private util::noncopyable { struct node { diff --git a/include/mapnik/offset_converter.hpp b/include/mapnik/offset_converter.hpp index e01c1d7e6..aed014fa4 100644 --- a/include/mapnik/offset_converter.hpp +++ b/include/mapnik/offset_converter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/palette.hpp b/include/mapnik/palette.hpp index 0d1d9e6f9..5dc3a4cdf 100644 --- a/include/mapnik/palette.hpp +++ b/include/mapnik/palette.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include #define USE_DENSE_HASH_MAP @@ -103,7 +103,7 @@ struct MAPNIK_DECL rgba }; -class MAPNIK_DECL rgba_palette : private mapnik::noncopyable { +class MAPNIK_DECL rgba_palette : private util::noncopyable { public: enum palette_type { PALETTE_RGBA = 0, PALETTE_RGB = 1, PALETTE_ACT = 2 }; diff --git a/include/mapnik/params.hpp b/include/mapnik/params.hpp index 6699e631e..83e2934e2 100644 --- a/include/mapnik/params.hpp +++ b/include/mapnik/params.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/params_impl.hpp b/include/mapnik/params_impl.hpp index 1362f228d..58ae52b00 100644 --- a/include/mapnik/params_impl.hpp +++ b/include/mapnik/params_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -121,7 +121,7 @@ boost::optional param_cast(std::string const& source) } // end namespace detail template -struct value_extractor_visitor : public util::static_visitor<> +struct value_extractor_visitor { value_extractor_visitor(boost::optional & var) diff --git a/include/mapnik/parse_path.hpp b/include/mapnik/parse_path.hpp index 3d61bb5f0..0667e901a 100644 --- a/include/mapnik/parse_path.hpp +++ b/include/mapnik/parse_path.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/parse_transform.hpp b/include/mapnik/parse_transform.hpp index b19c448bc..7baef79d2 100644 --- a/include/mapnik/parse_transform.hpp +++ b/include/mapnik/parse_transform.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/path_expression.hpp b/include/mapnik/path_expression.hpp index ab568dd5a..296348bed 100644 --- a/include/mapnik/path_expression.hpp +++ b/include/mapnik/path_expression.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/path_expression_grammar.hpp b/include/mapnik/path_expression_grammar.hpp index 1a0a3acb7..f39947ef6 100644 --- a/include/mapnik/path_expression_grammar.hpp +++ b/include/mapnik/path_expression_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/path_expression_grammar_impl.hpp b/include/mapnik/path_expression_grammar_impl.hpp index 6b764ed92..4801d2014 100644 --- a/include/mapnik/path_expression_grammar_impl.hpp +++ b/include/mapnik/path_expression_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -43,7 +43,7 @@ path_expression_grammar::path_expression_grammar() qi::lexeme_type lexeme; using phoenix::push_back; using boost::phoenix::construct; - + expr = * ( str [ push_back(_val, _1)] @@ -51,7 +51,7 @@ path_expression_grammar::path_expression_grammar() ( '[' >> attr [ push_back(_val, construct( _1 )) ] >> ']') ) ; - + attr %= +(char_ - ']'); str %= lexeme[+(char_ -'[')]; } diff --git a/include/mapnik/pixel_position.hpp b/include/mapnik/pixel_position.hpp index 11501bca7..40d00ace8 100644 --- a/include/mapnik/pixel_position.hpp +++ b/include/mapnik/pixel_position.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/plugin.hpp b/include/mapnik/plugin.hpp index bc25ff185..4be5f4ff3 100644 --- a/include/mapnik/plugin.hpp +++ b/include/mapnik/plugin.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #define MAPNIK_PLUGIN_HPP // mapnik -#include +#include // stl #include @@ -35,7 +35,7 @@ namespace mapnik // Opaque structure for handle using mapnik_lib_t = struct _mapnik_lib_t; -class PluginInfo : mapnik::noncopyable +class PluginInfo : util::noncopyable { public: using name_func = const char* (*) (); diff --git a/include/mapnik/png_io.hpp b/include/mapnik/png_io.hpp index 3df3197a4..7034ca293 100644 --- a/include/mapnik/png_io.hpp +++ b/include/mapnik/png_io.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -149,7 +149,7 @@ void save_as_png(T1 & file, template void reduce_8(T const& in, - image_data_8 & out, + image_data_gray8 & out, octree trees[], unsigned limits[], unsigned levels, @@ -166,8 +166,8 @@ void reduce_8(T const& in, } for (unsigned y = 0; y < height; ++y) { - mapnik::image_data_32::pixel_type const * row = in.getRow(y); - mapnik::image_data_8::pixel_type * row_out = out.getRow(y); + mapnik::image_data_rgba8::pixel_type const * row = in.getRow(y); + mapnik::image_data_gray8::pixel_type * row_out = out.getRow(y); for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; @@ -200,7 +200,7 @@ void reduce_8(T const& in, template void reduce_4(T const& in, - image_data_8 & out, + image_data_gray8 & out, octree trees[], unsigned limits[], unsigned levels, @@ -217,8 +217,8 @@ void reduce_4(T const& in, } for (unsigned y = 0; y < height; ++y) { - mapnik::image_data_32::pixel_type const * row = in.getRow(y); - mapnik::image_data_8::pixel_type * row_out = out.getRow(y); + mapnik::image_data_rgba8::pixel_type const * row = in.getRow(y); + mapnik::image_data_gray8::pixel_type * row_out = out.getRow(y); for (unsigned x = 0; x < width; ++x) { unsigned val = row[x]; @@ -256,7 +256,7 @@ void reduce_4(T const& in, // 1-bit but only one color. template void reduce_1(T const&, - image_data_8 & out, + image_data_gray8 & out, octree /*trees*/[], unsigned /*limits*/[], std::vector & /*alpha*/) @@ -266,7 +266,7 @@ void reduce_1(T const&, template void save_as_png(T & file, std::vector const& palette, - mapnik::image_data_8 const& image, + mapnik::image_data_gray8 const& image, unsigned width, unsigned height, unsigned color_depth, @@ -556,7 +556,7 @@ void save_as_png8_oct(T1 & file, if (palette.size() > 16 ) { // >16 && <=256 colors -> write 8-bit color depth - image_data_8 reduced_image(width,height); + image_data_gray8 reduced_image(width,height); reduce_8(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable); save_as_png(file,palette,reduced_image,width,height,8,alphaTable,opts); } @@ -565,7 +565,7 @@ void save_as_png8_oct(T1 & file, // 1 color image -> write 1-bit color depth PNG unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary unsigned image_height = height; - image_data_8 reduced_image(image_width,image_height); + image_data_gray8 reduced_image(image_width,image_height); reduce_1(image,reduced_image,trees, limits, alphaTable); if (meanAlpha<255 && cols[0]==0) { @@ -579,7 +579,7 @@ void save_as_png8_oct(T1 & file, // <=16 colors -> write 4-bit color depth PNG unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary unsigned image_height = height; - image_data_8 reduced_image(image_width,image_height); + image_data_gray8 reduced_image(image_width,image_height); reduce_4(image, reduced_image, trees, limits, TRANSPARENCY_LEVELS, alphaTable); save_as_png(file,palette,reduced_image,width,height,4,alphaTable,opts); } @@ -600,11 +600,11 @@ void save_as_png8(T1 & file, if (palette.size() > 16 ) { // >16 && <=256 colors -> write 8-bit color depth - image_data_8 reduced_image(width, height); + image_data_gray8 reduced_image(width, height); for (unsigned y = 0; y < height; ++y) { - mapnik::image_data_32::pixel_type const * row = image.getRow(y); - mapnik::image_data_8::pixel_type * row_out = reduced_image.getRow(y); + mapnik::image_data_rgba8::pixel_type const * row = image.getRow(y); + mapnik::image_data_gray8::pixel_type * row_out = reduced_image.getRow(y); for (unsigned x = 0; x < width; ++x) { row_out[x] = tree.quantize(row[x]); @@ -617,7 +617,7 @@ void save_as_png8(T1 & file, // 1 color image -> write 1-bit color depth PNG unsigned image_width = ((width + 15) >> 3) & ~1U; // 1-bit image, round up to 16-bit boundary unsigned image_height = height; - image_data_8 reduced_image(image_width, image_height); + image_data_gray8 reduced_image(image_width, image_height); reduced_image.set(0); save_as_png(file, palette, reduced_image, width, height, 1, alphaTable, opts); } @@ -626,11 +626,11 @@ void save_as_png8(T1 & file, // <=16 colors -> write 4-bit color depth PNG unsigned image_width = ((width + 7) >> 1) & ~3U; // 4-bit image, round up to 32-bit boundary unsigned image_height = height; - image_data_8 reduced_image(image_width, image_height); + image_data_gray8 reduced_image(image_width, image_height); for (unsigned y = 0; y < height; ++y) { - mapnik::image_data_32::pixel_type const * row = image.getRow(y); - mapnik::image_data_8::pixel_type * row_out = reduced_image.getRow(y); + mapnik::image_data_rgba8::pixel_type const * row = image.getRow(y); + mapnik::image_data_gray8::pixel_type * row_out = reduced_image.getRow(y); byte index = 0; for (unsigned x = 0; x < width; ++x) { diff --git a/include/mapnik/polygon_clipper.hpp b/include/mapnik/polygon_clipper.hpp index a9384fc0a..546a32d88 100644 --- a/include/mapnik/polygon_clipper.hpp +++ b/include/mapnik/polygon_clipper.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/pool.hpp b/include/mapnik/pool.hpp index 52147a56d..87580b262 100644 --- a/include/mapnik/pool.hpp +++ b/include/mapnik/pool.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // boost #include @@ -41,7 +41,7 @@ namespace mapnik { template class Creator> -class Pool : private mapnik::noncopyable +class Pool : private util::noncopyable { using HolderType = std::shared_ptr; using ContType = std::deque; diff --git a/include/mapnik/proj_transform.hpp b/include/mapnik/proj_transform.hpp index b15eaa0c2..aa32a1aa0 100644 --- a/include/mapnik/proj_transform.hpp +++ b/include/mapnik/proj_transform.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,14 +25,14 @@ // mapnik #include -#include +#include namespace mapnik { class projection; template class box2d; -class MAPNIK_DECL proj_transform : private mapnik::noncopyable +class MAPNIK_DECL proj_transform : private util::noncopyable { public: proj_transform(projection const& source, diff --git a/include/mapnik/projection.hpp b/include/mapnik/projection.hpp index 238280a7b..5267dd702 100644 --- a/include/mapnik/projection.hpp +++ b/include/mapnik/projection.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/ptree_helpers.hpp b/include/mapnik/ptree_helpers.hpp index dece1308c..fe1a1de50 100644 --- a/include/mapnik/ptree_helpers.hpp +++ b/include/mapnik/ptree_helpers.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/quad_tree.hpp b/include/mapnik/quad_tree.hpp index 5af4c6149..d8d405434 100644 --- a/include/mapnik/quad_tree.hpp +++ b/include/mapnik/quad_tree.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include // boost #pragma GCC diagnostic push @@ -41,7 +41,7 @@ namespace mapnik { template -class quad_tree : mapnik::noncopyable +class quad_tree : util::noncopyable { struct node { diff --git a/include/mapnik/query.hpp b/include/mapnik/query.hpp index d74608969..4c9455e16 100644 --- a/include/mapnik/query.hpp +++ b/include/mapnik/query.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/raster.hpp b/include/mapnik/raster.hpp index 5cde2f6b5..8fafd27b2 100644 --- a/include/mapnik/raster.hpp +++ b/include/mapnik/raster.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,28 +25,30 @@ // mapnik #include -#include -#include - +#include +#include +#include // boost #include namespace mapnik { -class raster : private mapnik::noncopyable + +class raster : private util::noncopyable { public: box2d ext_; - image_data_32 data_; + image_data_any data_; double filter_factor_; bool premultiplied_alpha_; boost::optional nodata_; + + template raster(box2d const& ext, - unsigned width, - unsigned height, + ImageData && data, double filter_factor, bool premultiplied_alpha = false) : ext_(ext), - data_(width,height), + data_(std::move(data)), filter_factor_(filter_factor), premultiplied_alpha_(premultiplied_alpha) {} diff --git a/include/mapnik/raster_colorizer.hpp b/include/mapnik/raster_colorizer.hpp index 63397b15d..fe66769b8 100644 --- a/include/mapnik/raster_colorizer.hpp +++ b/include/mapnik/raster_colorizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,7 +40,9 @@ #include #include #include - +#include + // boost +#include // boost #include @@ -55,7 +57,7 @@ class raster; //! \brief Enumerates the modes of interpolation -enum colorizer_mode_enum +enum colorizer_mode_enum : std::uint8_t { COLORIZER_INHERIT = 0, //!< The stop inherits the mode from the colorizer COLORIZER_LINEAR = 1, //!< Linear interpolation between colors @@ -195,12 +197,8 @@ public: //! \return The list of stops colorizer_stops const& get_stops() const { return stops_; } - - //! \brief Colorize a raster - //! - //! \param[in, out] raster A raster stored in float32 single channel format, which gets colorized in place. - void colorize(std::shared_ptr const& raster, feature_impl const& f) const; - + template + void colorize(image_data_rgba8 & out, T const& in, boost::optionalconst& nodata, feature_impl const& f) const; //! \brief Perform the translation of input to output //! diff --git a/include/mapnik/renderer_common.hpp b/include/mapnik/renderer_common.hpp index 45b70f8a7..ab74956b2 100644 --- a/include/mapnik/renderer_common.hpp +++ b/include/mapnik/renderer_common.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include // for box2d #include // for view_transform #include -#include +#include // fwd declarations to speed up compile namespace mapnik { @@ -40,7 +40,7 @@ namespace mapnik { namespace mapnik { -struct renderer_common : private mapnik::noncopyable +struct renderer_common : private util::noncopyable { renderer_common(Map const &m, attributes const& vars, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height, double scale_factor); diff --git a/include/mapnik/renderer_common/process_building_symbolizer.hpp b/include/mapnik/renderer_common/process_building_symbolizer.hpp index e4e8ab78e..25d8e0857 100644 --- a/include/mapnik/renderer_common/process_building_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_building_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index a5d72eaaf..348302ef8 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -56,7 +56,7 @@ class text_symbolizer_helper; using svg::svg_path_adapter; using svg_attribute_type = agg::pod_bvector; -struct virtual_renderer_common : private mapnik::noncopyable +struct virtual_renderer_common : private util::noncopyable { virtual_renderer_common(renderer_common & common) : width_(common.width_), @@ -103,7 +103,7 @@ struct virtual_renderer_common : private mapnik::noncopyable // stores all the arguments necessary to re-render this point // symbolizer at a later time. -struct vector_marker_render_thunk +struct vector_marker_render_thunk : util::noncopyable { svg_path_ptr src_; svg_attribute_type attrs_; @@ -128,15 +128,15 @@ struct vector_marker_render_thunk snap_to_pixels_(std::move(rhs.snap_to_pixels_)) {} }; -struct raster_marker_render_thunk +struct raster_marker_render_thunk : util::noncopyable { - image_data_32 & src_; + image_data_rgba8 & src_; agg::trans_affine tr_; double opacity_; composite_mode_e comp_op_; bool snap_to_pixels_; - raster_marker_render_thunk(image_data_32 & src, + raster_marker_render_thunk(image_data_rgba8 & src, agg::trans_affine const& marker_trans, double opacity, composite_mode_e comp_op, @@ -152,7 +152,7 @@ struct raster_marker_render_thunk using helper_ptr = std::unique_ptr; -struct text_render_thunk : noncopyable +struct text_render_thunk : util::noncopyable { // helper is stored here in order // to keep in scope the text rendering structures @@ -190,7 +190,7 @@ using render_thunk_list = std::list; // The bounding boxes can be used for layout, and the thunks are // used to re-render at locations according to the group layout. -struct render_thunk_extractor : public util::static_visitor<> +struct render_thunk_extractor { render_thunk_extractor(box2d & box, render_thunk_list & thunks, diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index 1d6feda7b..f62687ab9 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp index 262b31360..bc047411a 100644 --- a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index 2fdeca64f..7229c60f2 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,24 +34,159 @@ // agg #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" +#include "agg_rasterizer_scanline_aa.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" namespace mapnik { +namespace detail { + template -void render_raster_symbolizer(raster_symbolizer const &sym, - mapnik::feature_impl &feature, - proj_transform const &prj_trans, - renderer_common &common, +struct image_data_dispatcher +{ + using composite_function = F; + image_data_dispatcher(int start_x, int start_y, + int width, int height, + double scale_x, double scale_y, + scaling_method_e method, double filter_factor, + double opacity, composite_mode_e comp_op, + raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional const& nodata) + : start_x_(start_x), + start_y_(start_y), + width_(width), + height_(height), + scale_x_(scale_x), + scale_y_(scale_y), + method_(method), + filter_factor_(filter_factor), + opacity_(opacity), + comp_op_(comp_op), + sym_(sym), + feature_(feature), + composite_(composite), + nodata_(nodata) {} + + void operator() (image_data_null const& data_in) const {} //no-op + void operator() (image_data_rgba8 const& data_in) const + { + image_data_rgba8 data_out(width_, height_); + scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_); + composite_(data_out, comp_op_, opacity_, start_x_, start_y_); + } + + template + void operator() (T const& data_in) const + { + using image_data_type = T; + image_data_type data_out(width_, height_); + scale_image_agg(data_out, data_in, method_, scale_x_, scale_y_, 0.0, 0.0, filter_factor_); + image_data_rgba8 dst(width_, height_); + raster_colorizer_ptr colorizer = get(sym_, keys::colorizer); + if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_); + composite_(dst, comp_op_, opacity_, start_x_, start_y_); + } +private: + int start_x_; + int start_y_; + int width_; + int height_; + double scale_x_; + double scale_y_; + scaling_method_e method_; + double filter_factor_; + double opacity_; + composite_mode_e comp_op_; + raster_symbolizer const& sym_; + feature_impl const& feature_; + composite_function & composite_; + boost::optional const& nodata_; +}; + +template +struct image_data_warp_dispatcher +{ + using composite_function = F; + image_data_warp_dispatcher(proj_transform const& prj_trans, + int start_x, int start_y, int width, int height, + box2d const& target_ext, box2d const& source_ext, + double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, + double filter_factor, double opacity, composite_mode_e comp_op, + raster_symbolizer const& sym, feature_impl const& feature, F & composite, boost::optional const& nodata) + : prj_trans_(prj_trans), + start_x_(start_x), + start_y_(start_y), + width_(width), + height_(height), + target_ext_(target_ext), + source_ext_(source_ext), + offset_x_(offset_x), + offset_y_(offset_y), + mesh_size_(mesh_size), + scaling_method_(scaling_method), + filter_factor_(filter_factor), + opacity_(opacity), + comp_op_(comp_op), + sym_(sym), + feature_(feature), + composite_(composite), + nodata_(nodata) {} + + void operator() (image_data_null const& data_in) const {} //no-op + + void operator() (image_data_rgba8 const& data_in) const + { + image_data_rgba8 data_out(width_, height_); + warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_); + composite_(data_out, comp_op_, opacity_, start_x_, start_y_); + } + + template + void operator() (T const& data_in) const + { + using image_data_type = T; + image_data_type data_out(width_, height_); + if (nodata_) data_out.set(*nodata_); + warp_image(data_out, data_in, prj_trans_, target_ext_, source_ext_, offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_); + image_data_rgba8 dst(width_, height_); + raster_colorizer_ptr colorizer = get(sym_, keys::colorizer); + if (colorizer) colorizer->colorize(dst, data_out, nodata_, feature_); + composite_(dst, comp_op_, opacity_, start_x_, start_y_); + } +private: + proj_transform const& prj_trans_; + int start_x_; + int start_y_; + int width_; + int height_; + box2d const& target_ext_; + box2d const& source_ext_; + double offset_x_; + double offset_y_; + unsigned mesh_size_; + scaling_method_e scaling_method_; + double filter_factor_; + double opacity_; + composite_mode_e comp_op_; + raster_symbolizer const& sym_; + feature_impl const& feature_; + composite_function & composite_; + boost::optional const& nodata_; +}; + +} + +template +void render_raster_symbolizer(raster_symbolizer const& sym, + mapnik::feature_impl& feature, + proj_transform const& prj_trans, + renderer_common& common, F composite) { raster_ptr const& source = feature.get_raster(); if (source) { - // If there's a colorizer defined, use it to color the raster in-place - raster_colorizer_ptr colorizer = get(sym, keys::colorizer); - if (colorizer) - colorizer->colorize(source,feature); - box2d target_ext = box2d(source->ext_); prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS); box2d ext = common.t_.forward(target_ext); @@ -66,36 +201,37 @@ void render_raster_symbolizer(raster_symbolizer const &sym, scaling_method_e scaling_method = get(sym, keys::scaling, feature, common.vars_, SCALING_NEAR); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common.vars_, src_over); double opacity = get(sym,keys::opacity,feature, common.vars_, 1.0); - bool premultiply_source = !source->premultiplied_alpha_; - auto is_premultiplied = get_optional(sym, keys::premultiplied, feature, common.vars_); - if (is_premultiplied) + // only premultiply rgba8 images + if (source->data_.is()) { - if (*is_premultiplied) premultiply_source = false; - else premultiply_source = true; - } - if (premultiply_source) - { - agg::rendering_buffer buffer(source->data_.getBytes(), - source->data_.width(), - source->data_.height(), - source->data_.width() * 4); - agg::pixfmt_rgba32 pixf(buffer); - pixf.premultiply(); + bool premultiply_source = !source->premultiplied_alpha_; + auto is_premultiplied = get_optional(sym, keys::premultiplied, feature, common.vars_); + if (is_premultiplied) + { + if (*is_premultiplied) premultiply_source = false; + else premultiply_source = true; + } + if (premultiply_source) + { + agg::rendering_buffer buffer(source->data_.getBytes(), + source->data_.width(), + source->data_.height(), + source->data_.width() * 4); + agg::pixfmt_rgba32 pixf(buffer); + pixf.premultiply(); + } } + if (!prj_trans.equal()) { double offset_x = ext.minx() - start_x; double offset_y = ext.miny() - start_y; - raster target(target_ext, raster_width, raster_height, source->get_filter_factor()); unsigned mesh_size = static_cast(get(sym,keys::mesh_size,feature, common.vars_, 16)); - reproject_and_scale_raster(target, - *source, - prj_trans, - offset_x, - offset_y, - mesh_size, - scaling_method); - composite(target.data_, comp_op, opacity, start_x, start_y); + detail::image_data_warp_dispatcher dispatcher(prj_trans, start_x, start_y, raster_width, raster_height, + target_ext, source->ext_, offset_x, offset_y, mesh_size, + scaling_method, source->get_filter_factor(), + opacity, comp_op, sym, feature, composite, source->nodata()); + util::apply_visitor(dispatcher, source->data_); } else { @@ -107,20 +243,18 @@ void render_raster_symbolizer(raster_symbolizer const &sym, (std::abs(start_x) <= eps) && (std::abs(start_y) <= eps) ) { - composite(source->data_, comp_op, opacity, start_x, start_y); + if (source->data_.is()) + { + composite(util::get(source->data_), comp_op, opacity, start_x, start_y); + } } else { - raster target(target_ext, raster_width, raster_height, source->get_filter_factor()); - scale_image_agg(target.data_, - source->data_, - scaling_method, - image_ratio_x, - image_ratio_y, - 0.0, - 0.0, - source->get_filter_factor()); - composite(target.data_, comp_op, opacity, start_x, start_y); + detail::image_data_dispatcher dispatcher(start_x, start_y, raster_width, raster_height, + image_ratio_x, image_ratio_y, + scaling_method, source->get_filter_factor(), + opacity, comp_op, sym, feature, composite, source->nodata()); + util::apply_visitor(dispatcher, source->data_); } } } diff --git a/include/mapnik/renderer_common/render_pattern.hpp b/include/mapnik/renderer_common/render_pattern.hpp index 885d89c07..e694b5454 100644 --- a/include/mapnik/renderer_common/render_pattern.hpp +++ b/include/mapnik/renderer_common/render_pattern.hpp @@ -37,7 +37,7 @@ namespace mapnik { struct rasterizer; class marker; -std::shared_ptr render_pattern(rasterizer & ras, +std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr, double opacity); diff --git a/include/mapnik/request.hpp b/include/mapnik/request.hpp index 8f5272b31..e351f57f1 100644 --- a/include/mapnik/request.hpp +++ b/include/mapnik/request.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/rule.hpp b/include/mapnik/rule.hpp index bc3168598..e32210e99 100644 --- a/include/mapnik/rule.hpp +++ b/include/mapnik/rule.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/rule_cache.hpp b/include/mapnik/rule_cache.hpp index 244b89d6a..44a340659 100644 --- a/include/mapnik/rule_cache.hpp +++ b/include/mapnik/rule_cache.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include // stl #include @@ -34,7 +34,7 @@ namespace mapnik { -class rule_cache : private noncopyable +class rule_cache : private util::noncopyable { public: using rule_ptrs = std::vector; diff --git a/include/mapnik/save_map.hpp b/include/mapnik/save_map.hpp index ed950efc5..894532062 100644 --- a/include/mapnik/save_map.hpp +++ b/include/mapnik/save_map.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/scale_denominator.hpp b/include/mapnik/scale_denominator.hpp index 37d841326..e4aaee967 100644 --- a/include/mapnik/scale_denominator.hpp +++ b/include/mapnik/scale_denominator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/segment.hpp b/include/mapnik/segment.hpp index ef0582118..2cf10398a 100644 --- a/include/mapnik/segment.hpp +++ b/include/mapnik/segment.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/simplify_converter.hpp b/include/mapnik/simplify_converter.hpp index 6e4ddda3e..cbc1fa7e3 100644 --- a/include/mapnik/simplify_converter.hpp +++ b/include/mapnik/simplify_converter.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include // stl #include @@ -19,7 +19,7 @@ namespace mapnik { -struct weighted_vertex : private mapnik::noncopyable +struct weighted_vertex : private util::noncopyable { vertex2d coord; double weight; @@ -45,7 +45,7 @@ struct weighted_vertex : private mapnik::noncopyable struct ascending_sort { - bool operator() (const weighted_vertex *a, const weighted_vertex *b) + bool operator() (const weighted_vertex *a, const weighted_vertex *b) const { return b->weight > a->weight; } @@ -100,7 +100,7 @@ public: pos_(0) {} - enum status + enum status : std::uint8_t { initial, process, @@ -204,7 +204,7 @@ private: return SEG_CLOSE; } - vertex2d last(vertex2d::no_init); + vertex2d last; vertex2d vtx(vertex2d::no_init); while ((vtx.cmd = geom_.vertex(&vtx.x, &vtx.y)) != SEG_END) { @@ -217,7 +217,7 @@ private: // continue } } else if (vtx.cmd == SEG_CLOSE) { - if (last.cmd == vertex2d::no_init) { + if (last.cmd == SEG_END) { // The previous vertex was already output in the previous call. // We can now safely output SEG_CLOSE. status_ = end; diff --git a/include/mapnik/span_image_filter.hpp b/include/mapnik/span_image_filter.hpp index 8d5008ee9..c84ee0435 100644 --- a/include/mapnik/span_image_filter.hpp +++ b/include/mapnik/span_image_filter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/sql_utils.hpp b/include/mapnik/sql_utils.hpp index f8ade315a..ddadd21cb 100644 --- a/include/mapnik/sql_utils.hpp +++ b/include/mapnik/sql_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/geometry_svg_generator.hpp b/include/mapnik/svg/geometry_svg_generator.hpp index e3061d29e..281a6e82d 100644 --- a/include/mapnik/svg/geometry_svg_generator.hpp +++ b/include/mapnik/svg/geometry_svg_generator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/geometry_svg_generator_impl.hpp b/include/mapnik/svg/geometry_svg_generator_impl.hpp index 3f284ae1e..b5fc0eeeb 100644 --- a/include/mapnik/svg/geometry_svg_generator_impl.hpp +++ b/include/mapnik/svg/geometry_svg_generator_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/output/svg_generator.hpp b/include/mapnik/svg/output/svg_generator.hpp index e9ff4bd24..8bf5d54d3 100644 --- a/include/mapnik/svg/output/svg_generator.hpp +++ b/include/mapnik/svg/output/svg_generator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include @@ -42,7 +42,7 @@ namespace mapnik { namespace svg { * structure. */ template - class svg_generator : private mapnik::noncopyable + class svg_generator : private util::noncopyable { public: explicit svg_generator(OutputIterator& output_iterator); diff --git a/include/mapnik/svg/output/svg_output_attributes.hpp b/include/mapnik/svg/output/svg_output_attributes.hpp index 8bdf6a358..1de976969 100644 --- a/include/mapnik/svg/output/svg_output_attributes.hpp +++ b/include/mapnik/svg/output/svg_output_attributes.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/output/svg_output_grammars.hpp b/include/mapnik/svg/output/svg_output_grammars.hpp index 428a9f780..f3ef886e7 100644 --- a/include/mapnik/svg/output/svg_output_grammars.hpp +++ b/include/mapnik/svg/output/svg_output_grammars.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/output/svg_path_iterator.hpp b/include/mapnik/svg/output/svg_path_iterator.hpp index 73886aca3..693b8612d 100644 --- a/include/mapnik/svg/output/svg_path_iterator.hpp +++ b/include/mapnik/svg/output/svg_path_iterator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/output/svg_renderer.hpp b/include/mapnik/svg/output/svg_renderer.hpp index 1784d4214..43b3a77c2 100644 --- a/include/mapnik/svg/output/svg_renderer.hpp +++ b/include/mapnik/svg/output/svg_renderer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include // for rule, symbolizers #include // for box2d #include // for color @@ -64,7 +64,7 @@ namespace mapnik // can target many other output destinations besides streams. template class MAPNIK_DECL svg_renderer : public feature_style_processor >, - private mapnik::noncopyable + private util::noncopyable { public: using processor_impl_type = svg_renderer; diff --git a/include/mapnik/svg/svg_converter.hpp b/include/mapnik/svg/svg_converter.hpp index 6c4fe711d..ddde41d82 100644 --- a/include/mapnik/svg/svg_converter.hpp +++ b/include/mapnik/svg/svg_converter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // agg #include "agg_path_storage.h" @@ -44,7 +44,7 @@ namespace mapnik { namespace svg { template -class svg_converter : mapnik::noncopyable +class svg_converter : util::noncopyable { public: @@ -255,11 +255,13 @@ public: } void fill_none() { + cur_attr().fill_none = true; cur_attr().fill_flag = false; } void stroke_none() { + cur_attr().stroke_none = true; cur_attr().stroke_flag = false; } diff --git a/include/mapnik/svg/svg_parser.hpp b/include/mapnik/svg/svg_parser.hpp index 0806aa233..5198bfd53 100644 --- a/include/mapnik/svg/svg_parser.hpp +++ b/include/mapnik/svg/svg_parser.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,14 +28,14 @@ #include #include #include -#include +#include // stl #include namespace mapnik { namespace svg { - class svg_parser : private mapnik::noncopyable + class svg_parser : private util::noncopyable { public: explicit svg_parser(svg_converter_type & path); diff --git a/include/mapnik/svg/svg_path_adapter.hpp b/include/mapnik/svg/svg_path_adapter.hpp index 417fe86f3..72fa29a65 100644 --- a/include/mapnik/svg/svg_path_adapter.hpp +++ b/include/mapnik/svg/svg_path_adapter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ #define MAPNIK_SVG_PATH_ADAPTER_HPP // mapnik -#include +#include #include // agg #include "agg_math.h" @@ -40,7 +40,7 @@ namespace svg { using namespace agg; -template class path_adapter : mapnik::noncopyable +template class path_adapter : util::noncopyable { public: using container_type = VertexContainer ; @@ -838,7 +838,7 @@ void path_adapter::translate_all_paths(double dx, double dy) } -template class vertex_stl_adapter : mapnik::noncopyable +template class vertex_stl_adapter : util::noncopyable { public: diff --git a/include/mapnik/svg/svg_path_attributes.hpp b/include/mapnik/svg/svg_path_attributes.hpp index 831fd1f5a..29194ba70 100644 --- a/include/mapnik/svg/svg_path_attributes.hpp +++ b/include/mapnik/svg/svg_path_attributes.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -36,90 +36,97 @@ namespace svg { struct path_attributes { - unsigned index; + mapnik::gradient fill_gradient; + mapnik::gradient stroke_gradient; + agg::trans_affine transform; double opacity; - agg::rgba8 fill_color; double fill_opacity; - agg::rgba8 stroke_color; double stroke_opacity; + double miter_limit; + double stroke_width; + unsigned index; + agg::rgba8 fill_color; + agg::rgba8 stroke_color; + agg::line_join_e line_join; + agg::line_cap_e line_cap; bool fill_flag; + bool fill_none; bool stroke_flag; + bool stroke_none; bool even_odd_flag; bool visibility_flag; bool display_flag; - agg::line_join_e line_join; - agg::line_cap_e line_cap; - double miter_limit; - double stroke_width; - agg::trans_affine transform; - mapnik::gradient fill_gradient; - mapnik::gradient stroke_gradient; // Empty constructor path_attributes() : - index(0), + fill_gradient(), + stroke_gradient(), + transform(), opacity(1.0), - fill_color(agg::rgba(0,0,0)), fill_opacity(1.0), - stroke_color(agg::rgba(0,0,0)), stroke_opacity(1.0), - fill_flag(true), - stroke_flag(false), - even_odd_flag(false), - visibility_flag(true), - display_flag(true), - line_join(agg::miter_join), - line_cap(agg::butt_cap), miter_limit(4.0), stroke_width(1.0), - transform(), - fill_gradient(), - stroke_gradient() + index(0), + fill_color(agg::rgba(0,0,0)), + stroke_color(agg::rgba(0,0,0)), + line_join(agg::miter_join), + line_cap(agg::butt_cap), + fill_flag(true), + fill_none(false), + stroke_flag(false), + stroke_none(false), + even_odd_flag(false), + visibility_flag(true), + display_flag(true) { } // Copy constructor - path_attributes(const path_attributes& attr) - : index(attr.index), + path_attributes(path_attributes const& attr) + : fill_gradient(attr.fill_gradient), + stroke_gradient(attr.stroke_gradient), + transform(attr.transform), opacity(attr.opacity), - fill_color(attr.fill_color), fill_opacity(attr.fill_opacity), - stroke_color(attr.stroke_color), stroke_opacity(attr.stroke_opacity), - fill_flag(attr.fill_flag), - stroke_flag(attr.stroke_flag), - even_odd_flag(attr.even_odd_flag), - visibility_flag(attr.visibility_flag), - display_flag(attr.display_flag), - line_join(attr.line_join), - line_cap(attr.line_cap), miter_limit(attr.miter_limit), stroke_width(attr.stroke_width), - transform(attr.transform), - fill_gradient(attr.fill_gradient), - stroke_gradient(attr.stroke_gradient) + index(attr.index), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + line_join(attr.line_join), + line_cap(attr.line_cap), + fill_flag(attr.fill_flag), + fill_none(attr.fill_none), + stroke_flag(attr.stroke_flag), + stroke_none(attr.stroke_none), + even_odd_flag(attr.even_odd_flag), + visibility_flag(attr.visibility_flag), + display_flag(attr.display_flag) {} - // Copy constructor with new index value path_attributes(path_attributes const& attr, unsigned idx) - : index(idx), + : fill_gradient(attr.fill_gradient), + stroke_gradient(attr.stroke_gradient), + transform(attr.transform), opacity(attr.opacity), - fill_color(attr.fill_color), fill_opacity(attr.fill_opacity), - stroke_color(attr.stroke_color), stroke_opacity(attr.stroke_opacity), - fill_flag(attr.fill_flag), - stroke_flag(attr.stroke_flag), - even_odd_flag(attr.even_odd_flag), - visibility_flag(attr.visibility_flag), - display_flag(attr.display_flag), - line_join(attr.line_join), - line_cap(attr.line_cap), miter_limit(attr.miter_limit), stroke_width(attr.stroke_width), - transform(attr.transform), - fill_gradient(attr.fill_gradient), - stroke_gradient(attr.stroke_gradient) + index(idx), + fill_color(attr.fill_color), + stroke_color(attr.stroke_color), + line_join(attr.line_join), + line_cap(attr.line_cap), + fill_flag(attr.fill_flag), + fill_none(attr.fill_none), + stroke_flag(attr.stroke_flag), + stroke_none(attr.stroke_none), + even_odd_flag(attr.even_odd_flag), + visibility_flag(attr.visibility_flag), + display_flag(attr.display_flag) {} }; diff --git a/include/mapnik/svg/svg_path_commands.hpp b/include/mapnik/svg/svg_path_commands.hpp index 23df6ee9c..905f262a2 100644 --- a/include/mapnik/svg/svg_path_commands.hpp +++ b/include/mapnik/svg/svg_path_commands.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/svg_path_grammar.hpp b/include/mapnik/svg/svg_path_grammar.hpp index 74c935828..1710b61dc 100644 --- a/include/mapnik/svg/svg_path_grammar.hpp +++ b/include/mapnik/svg/svg_path_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/svg_path_parser.hpp b/include/mapnik/svg/svg_path_parser.hpp index 46539ee64..e72ad1ab4 100644 --- a/include/mapnik/svg/svg_path_parser.hpp +++ b/include/mapnik/svg/svg_path_parser.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/svg_points_grammar.hpp b/include/mapnik/svg/svg_points_grammar.hpp index ffc41292e..e993d35ed 100644 --- a/include/mapnik/svg/svg_points_grammar.hpp +++ b/include/mapnik/svg/svg_points_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/svg/svg_renderer_agg.hpp b/include/mapnik/svg/svg_renderer_agg.hpp index 90ff20af7..569f3fa35 100644 --- a/include/mapnik/svg/svg_renderer_agg.hpp +++ b/include/mapnik/svg/svg_renderer_agg.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include #if defined(GRID_RENDERER) #include @@ -98,7 +98,7 @@ private: }; template -class svg_renderer_agg : mapnik::noncopyable +class svg_renderer_agg : util::noncopyable { public: using curved_type = agg::conv_curve ; diff --git a/include/mapnik/svg/svg_storage.hpp b/include/mapnik/svg/svg_storage.hpp index 89e6ebca4..c3618b625 100644 --- a/include/mapnik/svg/svg_storage.hpp +++ b/include/mapnik/svg/svg_storage.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,13 +25,13 @@ // mapnik #include -#include +#include namespace mapnik { namespace svg { template -class svg_storage : mapnik::noncopyable +class svg_storage : util::noncopyable { public: svg_storage() : diff --git a/include/mapnik/svg/svg_transform_grammar.hpp b/include/mapnik/svg/svg_transform_grammar.hpp index 5b0f4955d..ce5563df1 100644 --- a/include/mapnik/svg/svg_transform_grammar.hpp +++ b/include/mapnik/svg/svg_transform_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index a0b4d9577..d15c1e10e 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -289,7 +289,7 @@ struct evaluate_expression_wrapper mapnik::color operator() (T1 const& expr, T2 const& feature, T3 const& vars) const { mapnik::value_type val = util::apply_visitor(mapnik::evaluate(feature,vars), expr); - if (val.is_null()) return mapnik::color(255,192,203); // pink + if (val.is_null()) return mapnik::color(0,0,0,0); // transparent return mapnik::color(val.to_string()); } }; @@ -339,7 +339,7 @@ struct evaluate_expression_wrapper }; template -struct extract_value : public util::static_visitor +struct extract_value { using result_type = T; @@ -379,7 +379,7 @@ struct extract_value : public util::static_visitor }; template -struct extract_raw_value : public util::static_visitor +struct extract_raw_value { using result_type = T1; @@ -400,14 +400,10 @@ struct extract_raw_value : public util::static_visitor } }; - -// - using property_meta_type = std::tuple, property_types>; MAPNIK_DECL property_meta_type const& get_meta(mapnik::keys key); MAPNIK_DECL mapnik::keys get_key(std::string const& name); -// template void put(symbolizer_base & sym, keys key, T const& val) { diff --git a/include/mapnik/symbolizer_base.hpp b/include/mapnik/symbolizer_base.hpp index 55472fa97..39a78a2b2 100644 --- a/include/mapnik/symbolizer_base.hpp +++ b/include/mapnik/symbolizer_base.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -149,6 +149,7 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base {}; struct MAPNIK_DECL building_symbolizer : public symbolizer_base {}; struct MAPNIK_DECL group_symbolizer : public symbolizer_base {}; struct MAPNIK_DECL debug_symbolizer : public symbolizer_base {}; +struct MAPNIK_DECL dot_symbolizer : public symbolizer_base {}; // symbolizer using symbolizer = util::variant; + debug_symbolizer, + dot_symbolizer>; } diff --git a/include/mapnik/symbolizer_dispatch.hpp b/include/mapnik/symbolizer_dispatch.hpp index a0320cc77..213a38835 100644 --- a/include/mapnik/symbolizer_dispatch.hpp +++ b/include/mapnik/symbolizer_dispatch.hpp @@ -67,7 +67,7 @@ struct process_impl * \param sym Symbolizer object */ template -struct symbolizer_dispatch : public util::static_visitor<> +struct symbolizer_dispatch { symbolizer_dispatch(Processor & output, mapnik::feature_impl & f, diff --git a/include/mapnik/symbolizer_enumerations.hpp b/include/mapnik/symbolizer_enumerations.hpp index fef3638eb..4b2770ffa 100644 --- a/include/mapnik/symbolizer_enumerations.hpp +++ b/include/mapnik/symbolizer_enumerations.hpp @@ -27,7 +27,7 @@ namespace mapnik { -enum line_cap_enum +enum line_cap_enum : std::uint8_t { BUTT_CAP, SQUARE_CAP, @@ -37,7 +37,7 @@ enum line_cap_enum DEFINE_ENUM( line_cap_e, line_cap_enum ); -enum line_join_enum +enum line_join_enum : std::uint8_t { MITER_JOIN, MITER_REVERT_JOIN, @@ -48,7 +48,7 @@ enum line_join_enum DEFINE_ENUM( line_join_e, line_join_enum ); -enum line_rasterizer_enum +enum line_rasterizer_enum : std::uint8_t { RASTERIZER_FULL, // agg::renderer_scanline_aa_solid RASTERIZER_FAST, // agg::rasterizer_outline_aa, twice as fast but only good for thin lines @@ -58,7 +58,7 @@ enum line_rasterizer_enum DEFINE_ENUM( line_rasterizer_e, line_rasterizer_enum ); -enum halo_rasterizer_enum +enum halo_rasterizer_enum : std::uint8_t { HALO_RASTERIZER_FULL, HALO_RASTERIZER_FAST, @@ -67,7 +67,7 @@ enum halo_rasterizer_enum DEFINE_ENUM(halo_rasterizer_e, halo_rasterizer_enum); -enum point_placement_enum +enum point_placement_enum : std::uint8_t { CENTROID_POINT_PLACEMENT, INTERIOR_POINT_PLACEMENT, @@ -76,7 +76,7 @@ enum point_placement_enum DEFINE_ENUM( point_placement_e, point_placement_enum ); -enum pattern_alignment_enum +enum pattern_alignment_enum : std::uint8_t { LOCAL_ALIGNMENT, GLOBAL_ALIGNMENT, @@ -85,7 +85,7 @@ enum pattern_alignment_enum DEFINE_ENUM( pattern_alignment_e, pattern_alignment_enum ); -enum debug_symbolizer_mode_enum +enum debug_symbolizer_mode_enum : std::uint8_t { DEBUG_SYM_MODE_COLLISION, DEBUG_SYM_MODE_VERTEX, @@ -97,7 +97,7 @@ DEFINE_ENUM( debug_symbolizer_mode_e, debug_symbolizer_mode_enum ); // markers // TODO - consider merging with text_symbolizer label_placement_e -enum marker_placement_enum +enum marker_placement_enum : std::uint8_t { MARKER_POINT_PLACEMENT, MARKER_INTERIOR_PLACEMENT, @@ -109,7 +109,7 @@ enum marker_placement_enum DEFINE_ENUM( marker_placement_e, marker_placement_enum ); -enum marker_multi_policy_enum +enum marker_multi_policy_enum : std::uint8_t { MARKER_EACH_MULTI, // each component in a multi gets its marker MARKER_WHOLE_MULTI, // consider all components of a multi as a whole @@ -119,18 +119,19 @@ enum marker_multi_policy_enum DEFINE_ENUM( marker_multi_policy_e, marker_multi_policy_enum ); -enum text_transform_enum +enum text_transform_enum : std::uint8_t { NONE = 0, UPPERCASE, LOWERCASE, CAPITALIZE, + REVERSE, text_transform_enum_MAX }; DEFINE_ENUM(text_transform_e, text_transform_enum); -enum label_placement_enum +enum label_placement_enum : std::uint8_t { POINT_PLACEMENT, LINE_PLACEMENT, @@ -141,7 +142,7 @@ enum label_placement_enum DEFINE_ENUM(label_placement_e, label_placement_enum); -enum vertical_alignment_enum +enum vertical_alignment_enum : std::uint8_t { V_TOP = 0, V_MIDDLE, @@ -152,7 +153,7 @@ enum vertical_alignment_enum DEFINE_ENUM(vertical_alignment_e, vertical_alignment_enum); -enum horizontal_alignment_enum +enum horizontal_alignment_enum : std::uint8_t { H_LEFT = 0, H_MIDDLE, @@ -164,7 +165,7 @@ enum horizontal_alignment_enum DEFINE_ENUM(horizontal_alignment_e, horizontal_alignment_enum); -enum justify_alignment_enum +enum justify_alignment_enum : std::uint8_t { J_LEFT = 0, J_MIDDLE, @@ -175,7 +176,7 @@ enum justify_alignment_enum DEFINE_ENUM(justify_alignment_e, justify_alignment_enum); -enum text_upright_enum +enum text_upright_enum : std::uint8_t { UPRIGHT_AUTO, UPRIGHT_LEFT, @@ -187,7 +188,8 @@ enum text_upright_enum DEFINE_ENUM(text_upright_e, text_upright_enum); -enum gamma_method_enum { +enum gamma_method_enum : std::uint8_t +{ GAMMA_POWER, //agg::gamma_power GAMMA_LINEAR, //agg::gamma_linear GAMMA_NONE, //agg::gamma_none diff --git a/include/mapnik/symbolizer_hash.hpp b/include/mapnik/symbolizer_hash.hpp index 18f0a68d3..feadf02d3 100644 --- a/include/mapnik/symbolizer_hash.hpp +++ b/include/mapnik/symbolizer_hash.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ namespace mapnik { -struct property_value_hash_visitor : util::static_visitor +struct property_value_hash_visitor { std::size_t operator() (color const& val) const { @@ -82,7 +82,7 @@ struct symbolizer_hash } }; -struct symbolizer_hash_visitor : util::static_visitor +struct symbolizer_hash_visitor { template std::size_t operator() (Symbolizer const& sym) const diff --git a/include/mapnik/symbolizer_keys.hpp b/include/mapnik/symbolizer_keys.hpp index 817ce2fdc..4867d3764 100644 --- a/include/mapnik/symbolizer_keys.hpp +++ b/include/mapnik/symbolizer_keys.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index 17fb3a320..00a4f0208 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -120,10 +120,16 @@ struct symbolizer_traits static char const* name() { return "DebugSymbolizer";} }; +template<> +struct symbolizer_traits +{ + static char const* name() { return "DotSymbolizer";} +}; + // symbolizer name impl namespace detail { -struct symbolizer_name_impl : public util::static_visitor +struct symbolizer_name_impl { public: template @@ -144,7 +150,7 @@ inline std::string symbolizer_name(symbolizer const& sym) /* template -class symbolizer_property_value_string : public util::static_visitor +class symbolizer_property_value_string { public: symbolizer_property_value_string (Meta const& meta) @@ -231,7 +237,7 @@ private: Meta const& meta_; }; -struct symbolizer_to_json : public util::static_visitor +struct symbolizer_to_json { using result_type = std::string; diff --git a/include/mapnik/text/evaluated_format_properties_ptr.hpp b/include/mapnik/text/evaluated_format_properties_ptr.hpp index be6d6d2af..8ead5f690 100644 --- a/include/mapnik/text/evaluated_format_properties_ptr.hpp +++ b/include/mapnik/text/evaluated_format_properties_ptr.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/face.hpp b/include/mapnik/text/face.hpp index 43363bc67..31dd45aa2 100644 --- a/include/mapnik/text/face.hpp +++ b/include/mapnik/text/face.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ //mapnik #include #include -#include +#include // freetype2 extern "C" @@ -44,7 +44,7 @@ extern "C" namespace mapnik { -class font_face : mapnik::noncopyable +class font_face : util::noncopyable { public: font_face(FT_Face face); @@ -77,7 +77,7 @@ private: using face_ptr = std::shared_ptr; -class MAPNIK_DECL font_face_set : private mapnik::noncopyable +class MAPNIK_DECL font_face_set : private util::noncopyable { public: using iterator = std::vector::iterator; @@ -97,7 +97,7 @@ using face_set_ptr = std::unique_ptr; // FT_Stroker wrapper -class stroker : mapnik::noncopyable +class stroker : util::noncopyable { public: explicit stroker(FT_Stroker s) diff --git a/include/mapnik/text/font_library.hpp b/include/mapnik/text/font_library.hpp index b31efe68c..fc5959a54 100644 --- a/include/mapnik/text/font_library.hpp +++ b/include/mapnik/text/font_library.hpp @@ -25,7 +25,7 @@ // mapnik #include -#include +#include // stl #include @@ -35,7 +35,7 @@ struct FT_MemoryRec_; namespace mapnik { -class MAPNIK_DECL font_library : public noncopyable +class MAPNIK_DECL font_library : public util::noncopyable { public: explicit font_library(); diff --git a/include/mapnik/text/formatting/base.hpp b/include/mapnik/text/formatting/base.hpp index 7859e6b88..efda3d63e 100644 --- a/include/mapnik/text/formatting/base.hpp +++ b/include/mapnik/text/formatting/base.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/formatting/format.hpp b/include/mapnik/text/formatting/format.hpp index 7f53768df..372598610 100644 --- a/include/mapnik/text/formatting/format.hpp +++ b/include/mapnik/text/formatting/format.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/formatting/layout.hpp b/include/mapnik/text/formatting/layout.hpp index 14cadca39..1ea1810c7 100644 --- a/include/mapnik/text/formatting/layout.hpp +++ b/include/mapnik/text/formatting/layout.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/formatting/list.hpp b/include/mapnik/text/formatting/list.hpp index c23a7170e..79314cfbe 100644 --- a/include/mapnik/text/formatting/list.hpp +++ b/include/mapnik/text/formatting/list.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/formatting/registry.hpp b/include/mapnik/text/formatting/registry.hpp index c6a71c766..5ad22dd5a 100644 --- a/include/mapnik/text/formatting/registry.hpp +++ b/include/mapnik/text/formatting/registry.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ #include #include #include -#include +#include // stl #include @@ -40,7 +40,7 @@ namespace formatting using from_xml_function_ptr = node_ptr (*) (xml_node const&, fontset_map const&) ; class registry : public singleton, - private mapnik::noncopyable + private util::noncopyable { public: registry(); diff --git a/include/mapnik/text/formatting/text.hpp b/include/mapnik/text/formatting/text.hpp index a7c6b1c76..214b3cf65 100644 --- a/include/mapnik/text/formatting/text.hpp +++ b/include/mapnik/text/formatting/text.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/glyph_info.hpp b/include/mapnik/text/glyph_info.hpp index 0daf7bb4e..4b82ffb72 100644 --- a/include/mapnik/text/glyph_info.hpp +++ b/include/mapnik/text/glyph_info.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ //mapnik #include #include -#include +#include #include #include @@ -36,7 +36,7 @@ namespace mapnik class font_face; using face_ptr = std::shared_ptr; -struct glyph_info : noncopyable +struct glyph_info : util::noncopyable { glyph_info(unsigned g_index, unsigned c_index, diff --git a/include/mapnik/text/glyph_positions.hpp b/include/mapnik/text/glyph_positions.hpp index 2db077b18..86c0302ef 100644 --- a/include/mapnik/text/glyph_positions.hpp +++ b/include/mapnik/text/glyph_positions.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 443f59b75..8bb37b180 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -43,7 +43,7 @@ namespace mapnik static inline hb_script_t _icu_script_to_script(UScriptCode script) { if (script == USCRIPT_INVALID_CODE) return HB_SCRIPT_INVALID; - return hb_script_from_string(uscript_getShortName(script), -1); + return hb_script_from_string(uscript_getShortName(script), -1); } static inline const uint16_t * uchar_to_utf16(const UChar* src) @@ -70,7 +70,6 @@ static void shape_text(text_line & line, if (!length) return; std::list const& list = itemizer.itemize(start, end); - if (list.empty()) return; line.reserve(length); @@ -79,8 +78,6 @@ static void shape_text(text_line & line, hb_buffer_pre_allocate(buffer.get(), length); mapnik::value_unicode_string const& text = itemizer.text(); - font_feature_settings const& ff_settings = list.front().format_->ff_settings; - for (auto const& text_item : list) { face_set_ptr face_set = font_manager.get_face_set(text_item.format_->face_name, text_item.format_->fontset); @@ -88,6 +85,7 @@ static void shape_text(text_line & line, face_set->set_unscaled_character_sizes(); std::size_t num_faces = face_set->size(); std::size_t pos = 0; + font_feature_settings const& ff_settings = text_item.format_->ff_settings; for (auto const& face : *face_set) { ++pos; diff --git a/include/mapnik/text/itemizer.hpp b/include/mapnik/text/itemizer.hpp index e73ef9274..0b28bc34d 100644 --- a/include/mapnik/text/itemizer.hpp +++ b/include/mapnik/text/itemizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ //mapnik #include #include -#include +#include // stl #include @@ -41,7 +41,7 @@ namespace mapnik { -struct text_item : noncopyable +struct text_item : util::noncopyable { text_item(unsigned s, unsigned e, @@ -84,7 +84,7 @@ public: std::pair line(unsigned i) const; unsigned num_lines() const; private: - template struct run : noncopyable + template struct run : util::noncopyable { run(T const& data, unsigned start, unsigned end) : start(start), end(end), data(data) {} diff --git a/include/mapnik/text/placement_finder.hpp b/include/mapnik/text/placement_finder.hpp index f5c863572..5069dc33f 100644 --- a/include/mapnik/text/placement_finder.hpp +++ b/include/mapnik/text/placement_finder.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace mapnik { @@ -42,7 +42,7 @@ class vertex_cache; class text_placement_info; struct glyph_info; -class placement_finder : mapnik::noncopyable +class placement_finder : util::noncopyable { public: placement_finder(feature_impl const& feature, diff --git a/include/mapnik/text/placement_finder_impl.hpp b/include/mapnik/text/placement_finder_impl.hpp index 866a09553..9bf7256cf 100644 --- a/include/mapnik/text/placement_finder_impl.hpp +++ b/include/mapnik/text/placement_finder_impl.hpp @@ -28,8 +28,8 @@ #include #include #include -#include -#include +#include +#include // agg #include "agg_conv_clip_polyline.h" diff --git a/include/mapnik/text/placements/base.hpp b/include/mapnik/text/placements/base.hpp index e46907e8b..06c6cce20 100644 --- a/include/mapnik/text/placements/base.hpp +++ b/include/mapnik/text/placements/base.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,11 +33,14 @@ namespace mapnik using dimension_type = std::pair; class MAPNIK_DECL text_placements; +class feature_impl; +struct attribute; + // Generate a possible placement. // This placement has first to be tested by placement_finder to verify it // can actually be used. -class MAPNIK_DECL text_placement_info : mapnik::noncopyable +class MAPNIK_DECL text_placement_info : util::noncopyable { public: // Constructor. Takes the parent text_placements object as a parameter @@ -84,7 +87,7 @@ public: // return text_placement_info_ptr(new text_placement_info_XXX(this)); // } - virtual text_placement_info_ptr get_placement_info(double scale_factor) const = 0; + virtual text_placement_info_ptr get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const = 0; // Get a list of all expressions used in any placement. // This function is used to collect attributes. diff --git a/include/mapnik/text/placements/dummy.hpp b/include/mapnik/text/placements/dummy.hpp index b56634bae..18d81fea6 100644 --- a/include/mapnik/text/placements/dummy.hpp +++ b/include/mapnik/text/placements/dummy.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,12 +30,14 @@ namespace mapnik { class text_placement_info_dummy; +class feature_impl; +struct attribute; // Dummy placement algorithm. Always takes the default value. class MAPNIK_DECL text_placements_dummy: public text_placements { public: - text_placement_info_ptr get_placement_info(double scale_factor) const; + text_placement_info_ptr get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const; friend class text_placement_info_dummy; }; diff --git a/include/mapnik/text/placements/list.hpp b/include/mapnik/text/placements/list.hpp index 2ef2ede07..1fa4c8712 100644 --- a/include/mapnik/text/placements/list.hpp +++ b/include/mapnik/text/placements/list.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,14 +26,15 @@ namespace mapnik { class text_placement_info_list; - +class feature_impl; +struct attribute; // Tries a list of placements. class text_placements_list: public text_placements { public: text_placements_list(); - text_placement_info_ptr get_placement_info(double scale_factor) const; + text_placement_info_ptr get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const; virtual void add_expressions(expression_set & output) const; text_symbolizer_properties & add(); text_symbolizer_properties & get(unsigned i); diff --git a/include/mapnik/text/placements/registry.hpp b/include/mapnik/text/placements/registry.hpp index eb0c257b8..eadfdb361 100644 --- a/include/mapnik/text/placements/registry.hpp +++ b/include/mapnik/text/placements/registry.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include #include -#include +#include // stl #include @@ -39,7 +39,7 @@ namespace placements using from_xml_function_ptr = text_placements_ptr (*) (xml_node const&, fontset_map const&, bool) ; class registry : public singleton, - private mapnik::noncopyable + private util::noncopyable { public: registry(); diff --git a/include/mapnik/text/placements/simple.hpp b/include/mapnik/text/placements/simple.hpp index ff3cdf6bc..2a9b983d7 100644 --- a/include/mapnik/text/placements/simple.hpp +++ b/include/mapnik/text/placements/simple.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,21 +29,25 @@ namespace mapnik { class text_placement_info_simple; +class feature_impl; +struct attribute; // Automatically generates placement options from a user selected list of directions and text sizes. class text_placements_simple: public text_placements { public: - text_placements_simple(); - text_placements_simple(std::string const& positions); - text_placement_info_ptr get_placement_info(double scale_factor) const; - void set_positions(std::string const& positions); - std::string get_positions(); - static text_placements_ptr from_xml(xml_node const &xml, fontset_map const & fontsets, bool is_shield); -private: - std::string positions_; + text_placements_simple(symbolizer_base::value_type const& positions); + text_placements_simple(symbolizer_base::value_type const& positions, + std::vector && direction, + std::vector && text_sizes); + text_placement_info_ptr get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const; + std::string get_positions() const; + static text_placements_ptr from_xml(xml_node const& xml, fontset_map const& fontsets, bool is_shield); + void init_positions(std::string const& positions) const; std::vector direction_; std::vector text_sizes_; +private: + symbolizer_base::value_type positions_; friend class text_placement_info_simple; }; @@ -53,14 +57,15 @@ class text_placement_info_simple : public text_placement_info { public: text_placement_info_simple(text_placements_simple const* parent, - double scale_factor) - : text_placement_info(parent, scale_factor), - state(0), position_state(0), parent_(parent) {} + std::string const& evaluated_positions, + double scale_factor); bool next() const; protected: bool next_position_only() const; mutable unsigned state; mutable unsigned position_state; + mutable std::vector direction_; + mutable std::vector text_sizes_; text_placements_simple const* parent_; }; diff --git a/include/mapnik/text/renderer.hpp b/include/mapnik/text/renderer.hpp index bc6ee3755..ac8bcb45a 100644 --- a/include/mapnik/text/renderer.hpp +++ b/include/mapnik/text/renderer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include // agg #include @@ -50,7 +50,7 @@ struct glyph_t : image(image_), properties(properties_) {} }; -class text_renderer : private mapnik::noncopyable +class text_renderer : private util::noncopyable { public: text_renderer (halo_rasterizer_e rasterizer, diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 8e13e7793..55561ae91 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/text_layout.hpp b/include/mapnik/text/text_layout.hpp index 89ed96d42..360c518eb 100644 --- a/include/mapnik/text/text_layout.hpp +++ b/include/mapnik/text/text_layout.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/text_line.hpp b/include/mapnik/text/text_line.hpp index 70dcd1adf..dd3cfee1c 100644 --- a/include/mapnik/text/text_line.hpp +++ b/include/mapnik/text/text_line.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,7 +24,7 @@ //stl #include -#include +#include namespace mapnik { @@ -35,7 +35,7 @@ struct glyph_info; // It can be used for rendering but no text processing (like line breaking) // should be done! -class text_line : noncopyable +class text_line : util::noncopyable { public: using glyph_vector = std::vector; diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index 1f28867ef..90711a4e8 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include // stl @@ -63,7 +63,7 @@ struct evaluated_format_properties font_feature_settings ff_settings; }; -struct evaluated_text_properties : noncopyable +struct evaluated_text_properties : util::noncopyable { label_placement_e label_placement; double label_spacing; @@ -84,7 +84,7 @@ struct evaluated_text_properties : noncopyable using evaluated_text_properties_ptr = std::unique_ptr; -enum directions_e +enum directions_e : std::uint8_t { NORTH, EAST, diff --git a/include/mapnik/tiff_io.hpp b/include/mapnik/tiff_io.hpp index 395b9c433..af60309d1 100644 --- a/include/mapnik/tiff_io.hpp +++ b/include/mapnik/tiff_io.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,24 +25,25 @@ #include #include +#include +#include extern "C" { -#ifdef HAVE_GEOTIFF -#include -#include -#define RealTIFFOpen XTIFFClientOpen -#define RealTIFFClose XTIFFClose -#else #include #define RealTIFFOpen TIFFClientOpen #define RealTIFFClose TIFFClose -#endif } +#define TIFF_WRITE_SCANLINE 0 +#define TIFF_WRITE_STRIPPED 1 +#define TIFF_WRITE_TILED 2 + +#include + namespace mapnik { -static tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size) +static inline tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size) { std::ostream* out = reinterpret_cast(fd); std::ios::pos_type pos = out->tellp(); @@ -61,7 +62,7 @@ static tsize_t tiff_write_proc(thandle_t fd, tdata_t buf, tsize_t size) } } -static toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) +static inline toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) { std::ostream* out = reinterpret_cast(fd); @@ -130,14 +131,14 @@ static toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) return static_cast(out->tellp()); } -static int tiff_close_proc(thandle_t fd) +static inline int tiff_close_proc(thandle_t fd) { std::ostream* out = (std::ostream*)fd; out->flush(); return 0; } -static toff_t tiff_size_proc(thandle_t fd) +static inline toff_t tiff_size_proc(thandle_t fd) { std::ostream* out = reinterpret_cast(fd); std::ios::pos_type pos = out->tellp(); @@ -147,27 +148,146 @@ static toff_t tiff_size_proc(thandle_t fd) return static_cast(len); } -static tsize_t tiff_dummy_read_proc(thandle_t , tdata_t , tsize_t) +static inline tsize_t tiff_dummy_read_proc(thandle_t , tdata_t , tsize_t) { return 0; } -static void tiff_dummy_unmap_proc(thandle_t , tdata_t , toff_t) -{ -} +static inline void tiff_dummy_unmap_proc(thandle_t , tdata_t , toff_t) {} -static int tiff_dummy_map_proc(thandle_t , tdata_t*, toff_t* ) +static inline int tiff_dummy_map_proc(thandle_t , tdata_t*, toff_t* ) { return 0; } +struct tiff_config +{ + tiff_config() + : compression(COMPRESSION_ADOBE_DEFLATE), + zlevel(4), + tile_width(0), + tile_height(0), + rows_per_strip(0), + method(TIFF_WRITE_STRIPPED) {} + + int compression; + int zlevel; + int tile_width; // Tile width of zero means tile the width of the image + int tile_height; // Tile height of zero means tile the height of the image + int rows_per_strip; + int method; // The method to use to write the TIFF. + +}; + +struct tag_setter +{ + tag_setter(TIFF * output, tiff_config & config) + : output_(output), + config_(config) {} + + template + void operator() (T const&) const + { + // Assume this would be null type + throw ImageWriterException("Could not write TIFF - unknown image type provided"); + } + + inline void operator() (image_data_rgba8 const&) const + { + TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); + TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 4); + //uint16 extras[] = { EXTRASAMPLE_UNASSALPHA }; + uint16 extras[] = { EXTRASAMPLE_ASSOCALPHA }; + TIFFSetField(output_, TIFFTAG_EXTRASAMPLES, 1, extras); + if (config_.compression == COMPRESSION_DEFLATE + || config_.compression == COMPRESSION_ADOBE_DEFLATE + || config_.compression == COMPRESSION_LZW) + { + TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); + + } + } + inline void operator() (image_data_gray32f const&) const + { + TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); + TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 32); + TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1); + if (config_.compression == COMPRESSION_DEFLATE + || config_.compression == COMPRESSION_ADOBE_DEFLATE + || config_.compression == COMPRESSION_LZW) + { + TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_FLOATINGPOINT); + } + } + inline void operator() (image_data_gray16 const&) const + { + TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 16); + TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1); + if (config_.compression == COMPRESSION_DEFLATE + || config_.compression == COMPRESSION_ADOBE_DEFLATE + || config_.compression == COMPRESSION_LZW) + { + TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); + + } + } + inline void operator() (image_data_gray8 const&) const + { + TIFFSetField(output_, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK); + TIFFSetField(output_, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); + TIFFSetField(output_, TIFFTAG_BITSPERSAMPLE, 8); + TIFFSetField(output_, TIFFTAG_SAMPLESPERPIXEL, 1); + if (config_.compression == COMPRESSION_DEFLATE + || config_.compression == COMPRESSION_ADOBE_DEFLATE + || config_.compression == COMPRESSION_LZW) + { + TIFFSetField(output_, TIFFTAG_PREDICTOR, PREDICTOR_HORIZONTAL); + + } + } + inline void operator() (image_data_null const&) const + { + // Assume this would be null type + throw ImageWriterException("Could not write TIFF - Null image provided"); + } + + private: + TIFF * output_; + tiff_config config_; +}; + +void set_tiff_config(TIFF* output, tiff_config & config) +{ + // Set some constant tiff information that doesn't vary based on type of data + // or image size + TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); + + // Set the compression for the TIFF + TIFFSetField(output, TIFFTAG_COMPRESSION, config.compression); + + if (COMPRESSION_ADOBE_DEFLATE == config.compression + || COMPRESSION_DEFLATE == config.compression + || COMPRESSION_LZW == config.compression) + { + // Set the zip level for the compression + // http://en.wikipedia.org/wiki/DEFLATE#Encoder.2Fcompressor + // Changes the time spent trying to compress + TIFFSetField(output, TIFFTAG_ZIPQUALITY, config.zlevel); + } +} + template -void save_as_tiff(T1 & file, T2 const& image) +void save_as_tiff(T1 & file, T2 const& image, tiff_config & config) { + using pixel_type = typename T2::pixel_type; + const int width = image.width(); const int height = image.height(); - const int scanline_size = sizeof(unsigned char) * width * 3; - TIFF* output = RealTIFFOpen("mapnik_tiff_stream", "wm", @@ -186,13 +306,107 @@ void save_as_tiff(T1 & file, T2 const& image) TIFFSetField(output, TIFFTAG_IMAGEWIDTH, width); TIFFSetField(output, TIFFTAG_IMAGELENGTH, height); - TIFFSetField(output, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE); - TIFFSetField(output, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); - TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); - TIFFSetField(output, TIFFTAG_BITSPERSAMPLE, 8); - TIFFSetField(output, TIFFTAG_SAMPLESPERPIXEL, 3); - TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, 1); + TIFFSetField(output, TIFFTAG_IMAGEDEPTH, 1); + set_tiff_config(output, config); + // Set tags that vary based on the type of data being provided. + tag_setter set(output, config); + set(image); + //util::apply_visitor(set, image); + + // Use specific types of writing methods. + if (TIFF_WRITE_SCANLINE == config.method) + { + // Process Scanline + TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, 1); + + int next_scanline = 0; + std::unique_ptr row (new pixel_type[width]); + while (next_scanline < height) + { + std::copy(image.getRow(next_scanline), image.getRow(next_scanline) + width, row.get()); + TIFFWriteScanline(output, row.get(), next_scanline, 0); + ++next_scanline; + } + } + else if (TIFF_WRITE_STRIPPED == config.method) + { + std::size_t rows_per_strip = config.rows_per_strip; + if (0 == rows_per_strip) + { + rows_per_strip = height; + } + TIFFSetField(output, TIFFTAG_ROWSPERSTRIP, rows_per_strip); + std::size_t strip_size = width * rows_per_strip; + std::unique_ptr strip_buffer(new pixel_type[strip_size]); + int end_y=(height/rows_per_strip+1)*rows_per_strip; + + for (int y=0; y < end_y; y+=rows_per_strip) + { + int ty1 = std::min(height, static_cast(y + rows_per_strip)) - y; + int row = y; + for (int ty = 0; ty < ty1; ++ty, ++row) + { + std::copy(image.getRow(row), image.getRow(row) + width, strip_buffer.get() + ty * width); + } + if (TIFFWriteEncodedStrip(output, TIFFComputeStrip(output, y, 0), strip_buffer.get(), strip_size * sizeof(pixel_type)) == -1) + { + throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed"); + } + } + } + else if (TIFF_WRITE_TILED == config.method) + { + int tile_width = config.tile_width; + int tile_height = config.tile_height; + + if (0 == tile_height) + { + tile_height = height; + if (height % 16 > 0) + { + tile_height = height + 16 - (height % 16); + } + } + if (0 == tile_width) + { + tile_width = width; + if (width % 16 > 0) + { + tile_width = width + 16 - (width % 16); + } + } + TIFFSetField(output, TIFFTAG_TILEWIDTH, tile_width); + TIFFSetField(output, TIFFTAG_TILELENGTH, tile_height); + TIFFSetField(output, TIFFTAG_TILEDEPTH, 1); + std::size_t tile_size = tile_width * tile_height; + std::unique_ptr image_data_out (new pixel_type[tile_size]); + int end_y = (height / tile_height + 1) * tile_height; + int end_x = (width / tile_width + 1) * tile_width; + end_y = std::min(end_y, height); + end_x = std::min(end_x, width); + + for (int y = 0; y < end_y; y += tile_height) + { + int ty1 = std::min(height, y + tile_height) - y; + + for (int x = 0; x < end_x; x += tile_width) + { + // Prefill the entire array with zeros. + std::fill(image_data_out.get(), image_data_out.get() + tile_size, 0); + int tx1 = std::min(width, x + tile_width); + int row = y; + for (int ty = 0; ty < ty1; ++ty, ++row) + { + std::copy(image.getRow(row, x), image.getRow(row, tx1), image_data_out.get() + ty * tile_width); + } + if (TIFFWriteEncodedTile(output, TIFFComputeTile(output, x, y, 0, 0), image_data_out.get(), tile_size * sizeof(pixel_type)) == -1) + { + throw ImageWriterException("Could not write TIFF - TIFF Tile Write failed"); + } + } + } + } // TODO - handle palette images // std::vector const& palette @@ -206,55 +420,6 @@ void save_as_tiff(T1 & file, T2 const& image) // TIFFSetField(output, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE); // TIFFSetField(output, TIFFTAG_COLORMAP, r, g, b); -#ifdef HAVE_GEOTIFF - GTIF* geotiff = GTIFNew(output); - if (! geotiff) - { - // throw ? - } - - GTIFKeySet(geotiff, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic); - GTIFKeySet(geotiff, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsPoint); - GTIFKeySet(geotiff, GeographicTypeGeoKey, TYPE_SHORT, 1, 4326); // parameter needed ! - GTIFKeySet(geotiff, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree); - GTIFKeySet(geotiff, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter); - - double lowerLeftLon = 130.0f; // parameter needed ! - double upperRightLat = 32.0; // parameter needed ! - double tiepoints[] = { 0.0, 0.0, 0.0, lowerLeftLon, upperRightLat, 0.0 }; - TIFFSetField(output, TIFFTAG_GEOTIEPOINTS, sizeof(tiepoints)/sizeof(double), tiepoints); - - double pixelScaleX = 0.0001; // parameter needed ! - double pixelScaleY = 0.0001; // parameter needed ! - double pixscale[] = { pixelScaleX, pixelScaleY, 0.0 }; - TIFFSetField(output, TIFFTAG_GEOPIXELSCALE, sizeof(pixscale)/sizeof(double), pixscale); -#endif - - int next_scanline = 0; - unsigned char* row = reinterpret_cast(::operator new(scanline_size)); - - while (next_scanline < height) - { - const unsigned* imageRow = image.getRow(next_scanline); - - for (int i = 0, index = 0; i < width; ++i) - { - row[index++] = (imageRow[i]) & 0xff; - row[index++] = (imageRow[i] >> 8) & 0xff; - row[index++] = (imageRow[i] >> 16) & 0xff; - } - - TIFFWriteScanline(output, row, next_scanline, 0); - ++next_scanline; - } - - ::operator delete(row); - -#ifdef HAVE_GEOTIFF - GTIFWriteKeys(geotiff); - GTIFFree(geotiff); -#endif - RealTIFFClose(output); } diff --git a/include/mapnik/timer.hpp b/include/mapnik/timer.hpp index d0727b5b4..22a67a339 100644 --- a/include/mapnik/timer.hpp +++ b/include/mapnik/timer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/text/tolerance_iterator.hpp b/include/mapnik/tolerance_iterator.hpp similarity index 98% rename from include/mapnik/text/tolerance_iterator.hpp rename to include/mapnik/tolerance_iterator.hpp index ac83ddd23..041cb114a 100644 --- a/include/mapnik/text/tolerance_iterator.hpp +++ b/include/mapnik/tolerance_iterator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/transform_expression.hpp b/include/mapnik/transform_expression.hpp index c1715aa97..d73554b5a 100644 --- a/include/mapnik/transform_expression.hpp +++ b/include/mapnik/transform_expression.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -192,7 +192,7 @@ inline void clear(transform_node& val) namespace { -struct is_null_transform_node : public mapnik::util::static_visitor +struct is_null_transform_node { bool operator() (value const& val) const { diff --git a/include/mapnik/transform_expression_grammar.hpp b/include/mapnik/transform_expression_grammar.hpp index 220d5126f..6772c80cd 100644 --- a/include/mapnik/transform_expression_grammar.hpp +++ b/include/mapnik/transform_expression_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/transform_expression_grammar_impl.hpp b/include/mapnik/transform_expression_grammar_impl.hpp index b080e200d..59ca57a33 100644 --- a/include/mapnik/transform_expression_grammar_impl.hpp +++ b/include/mapnik/transform_expression_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index 82d210c4e..58f7e7c09 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -46,7 +46,7 @@ struct transform_processor using transform_type = agg::trans_affine; template - struct attribute_collector : util::static_visitor + struct attribute_collector { expression_attributes collect_; @@ -97,7 +97,7 @@ struct transform_processor } }; - struct node_evaluator : util::static_visitor + struct node_evaluator { node_evaluator(transform_type& tr, feature_type const& feat, diff --git a/include/mapnik/unicode.hpp b/include/mapnik/unicode.hpp index 4f84c74e9..89526f5d4 100644 --- a/include/mapnik/unicode.hpp +++ b/include/mapnik/unicode.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,10 +25,10 @@ //mapnik #include -#include +#include #include -// stl +// std #include #include @@ -36,14 +36,13 @@ struct UConverter; namespace mapnik { -class MAPNIK_DECL transcoder : private mapnik::noncopyable +class MAPNIK_DECL transcoder : private util::noncopyable { public: explicit transcoder (std::string const& encoding); mapnik::value_unicode_string transcode(const char* data, std::int32_t length = -1) const; ~transcoder(); private: - bool ok_; UConverter * conv_; }; } diff --git a/include/mapnik/util/container_adapter.hpp b/include/mapnik/util/container_adapter.hpp index e67514dc8..f3ae03c1a 100644 --- a/include/mapnik/util/container_adapter.hpp +++ b/include/mapnik/util/container_adapter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index 0908814f1..de5bd2f93 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/dasharray_parser.hpp b/include/mapnik/util/dasharray_parser.hpp index f22b927e7..e5079b2b1 100644 --- a/include/mapnik/util/dasharray_parser.hpp +++ b/include/mapnik/util/dasharray_parser.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/featureset_buffer.hpp b/include/mapnik/util/featureset_buffer.hpp index 6fc05a4e8..842cc8e1e 100644 --- a/include/mapnik/util/featureset_buffer.hpp +++ b/include/mapnik/util/featureset_buffer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/file_io.hpp b/include/mapnik/util/file_io.hpp index 803c5357d..6c6553340 100644 --- a/include/mapnik/util/file_io.hpp +++ b/include/mapnik/util/file_io.hpp @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include //#include // stl @@ -36,12 +36,12 @@ namespace mapnik { namespace util { -class file : public noncopyable +class file : public util::noncopyable { public: using file_ptr = std::unique_ptr; using data_type = std::unique_ptr; - + explicit file(std::string const& filename) #ifdef _WINDOWS : file_(_wfopen(mapnik::utf8_to_utf16(filename).c_str(), L"rb"), std::fclose), diff --git a/include/mapnik/util/fs.hpp b/include/mapnik/util/fs.hpp index 04775cdeb..3e01b9694 100644 --- a/include/mapnik/util/fs.hpp +++ b/include/mapnik/util/fs.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ // stl #include +#include namespace mapnik { namespace util { @@ -39,6 +40,8 @@ MAPNIK_DECL bool is_relative(std::string const& value); MAPNIK_DECL std::string make_relative(std::string const& filepath, std::string const& base); MAPNIK_DECL std::string make_absolute(std::string const& filepath, std::string const& base); MAPNIK_DECL std::string dirname(std::string const& value); +MAPNIK_DECL std::string basename(std::string const& value); +MAPNIK_DECL std::vector list_directory(std::string const& value); }} diff --git a/include/mapnik/util/geometry_to_ds_type.hpp b/include/mapnik/util/geometry_to_ds_type.hpp index 234d25e02..d1b09d009 100644 --- a/include/mapnik/util/geometry_to_ds_type.hpp +++ b/include/mapnik/util/geometry_to_ds_type.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/geometry_to_geojson.hpp b/include/mapnik/util/geometry_to_geojson.hpp index 3500544df..42f73bc09 100644 --- a/include/mapnik/util/geometry_to_geojson.hpp +++ b/include/mapnik/util/geometry_to_geojson.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/geometry_to_svg.hpp b/include/mapnik/util/geometry_to_svg.hpp index 6e207dbd8..61dd7b796 100644 --- a/include/mapnik/util/geometry_to_svg.hpp +++ b/include/mapnik/util/geometry_to_svg.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/geometry_to_wkb.hpp b/include/mapnik/util/geometry_to_wkb.hpp index 3ec50fc04..ad4ddedf0 100644 --- a/include/mapnik/util/geometry_to_wkb.hpp +++ b/include/mapnik/util/geometry_to_wkb.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -56,7 +56,7 @@ std::string to_hex(const char* blob, unsigned size) return s.str(); } -enum wkbByteOrder { +enum wkbByteOrder : std::uint8_t { wkbXDR=0, wkbNDR=1 }; diff --git a/include/mapnik/util/geometry_to_wkt.hpp b/include/mapnik/util/geometry_to_wkt.hpp index 5d4967fd0..aef1226b3 100644 --- a/include/mapnik/util/geometry_to_wkt.hpp +++ b/include/mapnik/util/geometry_to_wkt.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/hsl.hpp b/include/mapnik/util/hsl.hpp index f669c8880..536f9e7ff 100644 --- a/include/mapnik/util/hsl.hpp +++ b/include/mapnik/util/hsl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/noncopyable.hpp b/include/mapnik/util/noncopyable.hpp similarity index 87% rename from include/mapnik/noncopyable.hpp rename to include/mapnik/util/noncopyable.hpp index f5dfbdc21..e80fb4eb2 100644 --- a/include/mapnik/noncopyable.hpp +++ b/include/mapnik/util/noncopyable.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,10 +20,10 @@ * *****************************************************************************/ -#ifndef MAPNIK_NONCOPYABLE_HPP -#define MAPNIK_NONCOPYABLE_HPP +#ifndef MAPNIK_UTIL_NONCOPYABLE_HPP +#define MAPNIK_UTIL_NONCOPYABLE_HPP -namespace mapnik { +namespace mapnik { namespace util { namespace non_copyable_ { @@ -40,6 +40,6 @@ protected: using noncopyable = non_copyable_::noncopyable; -} // namespace mapnik +}} -#endif // MAPNIK_NONCOPYABLE_HPP +#endif // MAPNIK_UTIL_NONCOPYABLE_HPP diff --git a/include/mapnik/util/path_iterator.hpp b/include/mapnik/util/path_iterator.hpp index f9e60e0b2..11a1b3c0e 100644 --- a/include/mapnik/util/path_iterator.hpp +++ b/include/mapnik/util/path_iterator.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/timer.hpp b/include/mapnik/util/timer.hpp index ee6ccf59d..8f7487812 100644 --- a/include/mapnik/util/timer.hpp +++ b/include/mapnik/util/timer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/trim.hpp b/include/mapnik/util/trim.hpp index 48ec7e018..cc4816dd4 100644 --- a/include/mapnik/util/trim.hpp +++ b/include/mapnik/util/trim.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/util/variant.hpp b/include/mapnik/util/variant.hpp index 55be089b6..9e118f970 100644 --- a/include/mapnik/util/variant.hpp +++ b/include/mapnik/util/variant.hpp @@ -35,7 +35,8 @@ #include #include "recursive_wrapper.hpp" -#include + +#include // spirit support #ifdef _MSC_VER // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx @@ -59,7 +60,19 @@ // translates to 100 #define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) -namespace mapnik { namespace util { namespace detail { +namespace mapnik { namespace util { + +// static visitor +template +struct static_visitor +{ + using result_type = R; +protected: + static_visitor() {} + ~static_visitor() {} +}; + +namespace detail { static constexpr std::size_t invalid_value = std::size_t(-1); @@ -134,18 +147,38 @@ struct select_type<0, T, Types...> using type = T; }; -} // namespace detail -// static visitor -template -struct static_visitor +template +struct enable_if_type { using type = R; }; + +template +struct result_of_unary_visit { - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} + using type = typename std::result_of::type; }; +template +struct result_of_unary_visit::type > +{ + using type = typename F::result_type; +}; + +template +struct result_of_binary_visit +{ + using type = typename std::result_of::type; +}; + + +template +struct result_of_binary_visit::type > +{ + using type = typename F::result_type; +}; + + +} // namespace detail + template struct static_max; @@ -244,13 +277,13 @@ struct unwrapper> }; -template +template struct dispatcher; -template -struct dispatcher +template +struct dispatcher { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const& v, F f) { if (v.get_type_index() == sizeof...(Types)) @@ -259,7 +292,7 @@ struct dispatcher } else { - return dispatcher::apply_const(v, f); + return dispatcher::apply_const(v, f); } } @@ -271,15 +304,15 @@ struct dispatcher } else { - return dispatcher::apply(v, f); + return dispatcher::apply(v, f); } } }; -template -struct dispatcher +template +struct dispatcher { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, F) { throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); @@ -292,13 +325,13 @@ struct dispatcher }; -template +template struct binary_dispatcher_rhs; -template -struct binary_dispatcher_rhs +template +struct binary_dispatcher_rhs { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) { if (rhs.get_type_index() == sizeof...(Types)) // call binary functor @@ -308,7 +341,7 @@ struct binary_dispatcher_rhs } else { - return binary_dispatcher_rhs::apply_const(lhs, rhs, f); + return binary_dispatcher_rhs::apply_const(lhs, rhs, f); } } @@ -321,16 +354,16 @@ struct binary_dispatcher_rhs } else { - return binary_dispatcher_rhs::apply(lhs, rhs, f); + return binary_dispatcher_rhs::apply(lhs, rhs, f); } } }; -template -struct binary_dispatcher_rhs +template +struct binary_dispatcher_rhs { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -342,13 +375,13 @@ struct binary_dispatcher_rhs }; -template +template struct binary_dispatcher_lhs; -template -struct binary_dispatcher_lhs +template +struct binary_dispatcher_lhs { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) { if (lhs.get_type_index() == sizeof...(Types)) // call binary functor @@ -357,7 +390,7 @@ struct binary_dispatcher_lhs } else { - return binary_dispatcher_lhs::apply_const(lhs, rhs, f); + return binary_dispatcher_lhs::apply_const(lhs, rhs, f); } } @@ -369,16 +402,16 @@ struct binary_dispatcher_lhs } else { - return binary_dispatcher_lhs::apply(lhs, rhs, f); + return binary_dispatcher_lhs::apply(lhs, rhs, f); } } }; -template -struct binary_dispatcher_lhs +template +struct binary_dispatcher_lhs { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -390,13 +423,13 @@ struct binary_dispatcher_lhs } }; -template +template struct binary_dispatcher; -template -struct binary_dispatcher +template +struct binary_dispatcher { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) { if (v0.get_type_index() == sizeof...(Types)) @@ -407,14 +440,14 @@ struct binary_dispatcher } else { - return binary_dispatcher_rhs::apply_const(v0, v1, f); + return binary_dispatcher_rhs::apply_const(v0, v1, f); } } else if (v1.get_type_index() == sizeof...(Types)) { - return binary_dispatcher_lhs::apply_const(v0, v1, f); + return binary_dispatcher_lhs::apply_const(v0, v1, f); } - return binary_dispatcher::apply_const(v0, v1, f); + return binary_dispatcher::apply_const(v0, v1, f); } VARIANT_INLINE static result_type apply(V & v0, V & v1, F f) @@ -427,21 +460,21 @@ struct binary_dispatcher } else { - return binary_dispatcher_rhs::apply(v0, v1, f); + return binary_dispatcher_rhs::apply(v0, v1, f); } } else if (v1.get_type_index() == sizeof...(Types)) { - return binary_dispatcher_lhs::apply(v0, v1, f); + return binary_dispatcher_lhs::apply(v0, v1, f); } - return binary_dispatcher::apply(v0, v1, f); + return binary_dispatcher::apply(v0, v1, f); } }; -template -struct binary_dispatcher +template +struct binary_dispatcher { - using result_type = typename F::result_type; + using result_type = R; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -473,7 +506,7 @@ struct less_comp }; template -class comparer : public static_visitor +class comparer { public: explicit comparer(Variant const& lhs) noexcept @@ -492,7 +525,7 @@ private: // operator<< helper template -class printer : public static_visitor<> +class printer { public: explicit printer(Out & out) @@ -528,9 +561,11 @@ private: data_type data; public: + // tell spirit that this is an adapted variant struct adapted_variant_tag; using types = boost::mpl::vector; + VARIANT_INLINE variant() : type_index(sizeof...(Types) - 1) { @@ -540,6 +575,7 @@ public: VARIANT_INLINE variant(no_init) : type_index(detail::invalid_value) {} + // http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers template ::type, Types...>::value>::type> VARIANT_INLINE variant(T && val) noexcept @@ -649,17 +685,23 @@ public: template auto VARIANT_INLINE static visit(V const& v, F f) - -> decltype(detail::dispatcher::apply_const(v, f)) + -> decltype(detail::dispatcher::type>::type, Types...>::apply_const(v, f)) { - return detail::dispatcher::apply_const(v, f); + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply_const(v, f); } // non-const template auto VARIANT_INLINE static visit(V & v, F f) - -> decltype(detail::dispatcher::apply(v, f)) + -> decltype(detail::dispatcher::type>::type, Types...>::apply(v, f)) { - return detail::dispatcher::apply(v, f); + using R = typename detail::result_of_unary_visit::type>::type; + return detail::dispatcher::apply(v, f); } // binary @@ -667,17 +709,23 @@ public: template auto VARIANT_INLINE static binary_visit(V const& v0, V const& v1, F f) - -> decltype(detail::binary_dispatcher::apply_const(v0, v1, f)) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply_const(v0, v1, f)) { - return detail::binary_dispatcher::apply_const(v0, v1, f); + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply_const(v0, v1, f); } // non-const template auto VARIANT_INLINE static binary_visit(V& v0, V& v1, F f) - -> decltype(detail::binary_dispatcher::apply(v0, v1, f)) + -> decltype(detail::binary_dispatcher::type>::type, Types...>::apply(v0, v1, f)) { - return detail::binary_dispatcher::apply(v0, v1, f); + using R = typename detail::result_of_binary_visit::type>::type; + return detail::binary_dispatcher::apply(v0, v1, f); } ~variant() noexcept @@ -749,6 +797,7 @@ ResultType const& get(T const& var) return var.template get(); } + // operator<< template VARIANT_INLINE std::basic_ostream& diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp index d6961d950..c43bebf37 100644 --- a/include/mapnik/utils.hpp +++ b/include/mapnik/utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 9a946233f..29d4000bc 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -72,7 +72,7 @@ using value_base = util::variant + { bool operator() (value_integer lhs, value_double rhs) const { @@ -124,7 +124,7 @@ struct equals }; struct not_equals - : public util::static_visitor + { template bool operator() (const T &, const U &) const @@ -186,7 +186,7 @@ struct not_equals }; struct greater_than - : public util::static_visitor + { template bool operator()(const T &, const U &) const @@ -222,7 +222,7 @@ struct greater_than }; struct greater_or_equal - : public util::static_visitor + { template bool operator()(const T &, const U &) const @@ -258,7 +258,7 @@ struct greater_or_equal }; struct less_than - : public util::static_visitor + { template bool operator()(const T &, const U &) const @@ -295,7 +295,7 @@ struct less_than }; struct less_or_equal - : public util::static_visitor + { template bool operator()(const T &, const U &) const @@ -332,7 +332,7 @@ struct less_or_equal }; template -struct add : public util::static_visitor +struct add { using value_type = V; value_type operator() (value_unicode_string const& lhs , @@ -398,7 +398,7 @@ struct add : public util::static_visitor }; template -struct sub : public util::static_visitor +struct sub { using value_type = V; template @@ -436,7 +436,7 @@ struct sub : public util::static_visitor }; template -struct mult : public util::static_visitor +struct mult { using value_type = V; template @@ -473,7 +473,7 @@ struct mult : public util::static_visitor }; template -struct div: public util::static_visitor +struct div { using value_type = V; template @@ -514,7 +514,7 @@ struct div: public util::static_visitor }; template -struct mod: public util::static_visitor +struct mod { using value_type = V; template @@ -558,7 +558,7 @@ struct mod: public util::static_visitor }; template -struct negate : public util::static_visitor +struct negate { using value_type = V; @@ -589,7 +589,7 @@ template struct convert {}; template <> -struct convert : public util::static_visitor +struct convert { value_bool operator() (value_bool val) const { @@ -614,7 +614,7 @@ struct convert : public util::static_visitor }; template <> -struct convert : public util::static_visitor +struct convert { value_double operator() (value_double val) const { @@ -653,7 +653,7 @@ struct convert : public util::static_visitor }; template <> -struct convert : public util::static_visitor +struct convert { value_integer operator() (value_integer val) const { @@ -692,7 +692,7 @@ struct convert : public util::static_visitor }; template <> -struct convert : public util::static_visitor +struct convert { template std::string operator() (T val) const @@ -723,7 +723,7 @@ struct convert : public util::static_visitor } }; -struct to_unicode : public util::static_visitor +struct to_unicode { template @@ -753,7 +753,7 @@ struct to_unicode : public util::static_visitor } }; -struct to_expression_string : public util::static_visitor +struct to_expression_string { explicit to_expression_string(char quote = '\'') : quote_(quote) {} @@ -947,7 +947,7 @@ using value_adl_barrier::operator<<; namespace detail { -struct is_null_visitor : public util::static_visitor +struct is_null_visitor { bool operator() (value const& val) const { diff --git a/include/mapnik/value_error.hpp b/include/mapnik/value_error.hpp index aca3c3239..1edc5419b 100644 --- a/include/mapnik/value_error.hpp +++ b/include/mapnik/value_error.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/value_hash.hpp b/include/mapnik/value_hash.hpp index 1a72108b4..0933f06d3 100644 --- a/include/mapnik/value_hash.hpp +++ b/include/mapnik/value_hash.hpp @@ -42,7 +42,7 @@ inline void hash_combine(std::size_t & seed, T const& v) seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2); } -struct value_hasher: public util::static_visitor +struct value_hasher { std::size_t operator() (value_null val) const { diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index c4f5e55ac..ffe021869 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/version.hpp b/include/mapnik/version.hpp index cfb3bd0e3..8030c5c92 100644 --- a/include/mapnik/version.hpp +++ b/include/mapnik/version.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/vertex.hpp b/include/mapnik/vertex.hpp index 877c13067..597526d7b 100644 --- a/include/mapnik/vertex.hpp +++ b/include/mapnik/vertex.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,11 +24,12 @@ #define MAPNIK_VERTEX_HPP #include +#include namespace mapnik { -enum CommandType { +enum CommandType : std::uint8_t { SEG_END = 0, SEG_MOVETO = 1, SEG_LINETO = 2, @@ -44,7 +45,7 @@ struct vertex { template struct vertex { - enum no_init_t { no_init }; + enum no_init_t : std::uint8_t { no_init }; using coord_type = T; coord_type x; diff --git a/include/mapnik/text/vertex_cache.hpp b/include/mapnik/vertex_cache.hpp similarity index 97% rename from include/mapnik/text/vertex_cache.hpp rename to include/mapnik/vertex_cache.hpp index 277936032..e557d4b30 100644 --- a/include/mapnik/text/vertex_cache.hpp +++ b/include/mapnik/vertex_cache.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ #include #include #include -#include +#include // agg #include "agg_basics.h" @@ -43,7 +43,7 @@ class vertex_cache; using vertex_cache_ptr = std::unique_ptr; // Caches all path points and their lengths. Allows easy moving in both directions. -class MAPNIK_DECL vertex_cache : noncopyable +class MAPNIK_DECL vertex_cache : util::noncopyable { struct segment { @@ -81,7 +81,7 @@ public: pixel_position const& position() const { return current_position; } }; - class scoped_state : noncopyable + class scoped_state : util::noncopyable { public: scoped_state(vertex_cache &pp) : pp_(pp), state_(pp.save_state()), restored_(false) {} @@ -97,12 +97,14 @@ public: /////////////////////////////////////////////////////////////////////// template vertex_cache(T &path); + vertex_cache(vertex_cache && rhs); double length() const { return current_subpath_->length; } pixel_position const& current_position() const { return current_position_; } double angle(double width=0.); + double current_segment_angle(); double linear_position() const { return position_; } @@ -141,7 +143,6 @@ private: void rewind_subpath(); bool next_segment(); bool previous_segment(); - double current_segment_angle(); void find_line_circle_intersection( double cx, double cy, double radius, double x1, double y1, double x2, double y2, diff --git a/include/mapnik/vertex_converters.hpp b/include/mapnik/vertex_converters.hpp index 0f0e36299..8207af6d0 100644 --- a/include/mapnik/vertex_converters.hpp +++ b/include/mapnik/vertex_converters.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include @@ -319,7 +319,7 @@ struct converters_helper }; template -struct dispatcher : mapnik::noncopyable +struct dispatcher : util::noncopyable { using this_type = dispatcher; using args_type = Args; @@ -337,7 +337,7 @@ struct dispatcher : mapnik::noncopyable }; template -struct arguments : mapnik::noncopyable +struct arguments : util::noncopyable { using processor_type = Processor; arguments(Processor & proc, box2d const& bbox, symbolizer_base const& sym, view_transform const& tr, @@ -367,7 +367,7 @@ struct arguments : mapnik::noncopyable } template -struct vertex_converter : private mapnik::noncopyable +struct vertex_converter : private util::noncopyable { using bbox_type = box2d; using processor_type = Processor; diff --git a/include/mapnik/vertex_vector.hpp b/include/mapnik/vertex_vector.hpp index 198865cc5..a25afc22e 100644 --- a/include/mapnik/vertex_vector.hpp +++ b/include/mapnik/vertex_vector.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,7 @@ // mapnik #include -#include +#include // stl #include @@ -40,7 +40,7 @@ namespace mapnik { template -class vertex_vector : private mapnik::noncopyable +class vertex_vector : private util::noncopyable { using coord_type = T; enum block_e { diff --git a/include/mapnik/view_transform.hpp b/include/mapnik/view_transform.hpp index 683e97947..d692c7ce1 100644 --- a/include/mapnik/view_transform.hpp +++ b/include/mapnik/view_transform.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/warp.hpp b/include/mapnik/warp.hpp index 7e53ca08f..262164ea7 100644 --- a/include/mapnik/warp.hpp +++ b/include/mapnik/warp.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,6 +26,7 @@ // mapnik #include #include +#include namespace mapnik { @@ -33,12 +34,17 @@ class raster; class proj_transform; MAPNIK_DECL void reproject_and_scale_raster(raster & target, - raster const& source, - proj_transform const& prj_trans, - double offset_x, double offset_y, - unsigned mesh_size, - scaling_method_e scaling_method); + raster const& source, + proj_transform const& prj_trans, + double offset_x, double offset_y, + unsigned mesh_size, + scaling_method_e scaling_method); + +template +MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans, + box2d const& target_ext, box2d const& source_ext, + double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor); } #endif // MAPNIK_WARP_HPP diff --git a/include/mapnik/webp_io.hpp b/include/mapnik/webp_io.hpp index 268963502..eecd65e70 100644 --- a/include/mapnik/webp_io.hpp +++ b/include/mapnik/webp_io.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -98,11 +98,11 @@ inline int import_image_data(T2 const& image, else { // need to copy: https://github.com/mapnik/mapnik/issues/2024 - image_data_32 im(image.width(),image.height()); + image_data_rgba8 im(image.width(),image.height()); for (unsigned y = 0; y < image.height(); ++y) { typename T2::pixel_type const * row_from = image.getRow(y); - image_data_32::pixel_type * row_to = im.getRow(y); + image_data_rgba8::pixel_type * row_to = im.getRow(y); std::copy(row_from, row_from + stride, row_to); } if (alpha) @@ -121,11 +121,11 @@ inline int import_image_data(T2 const& image, } template <> -inline int import_image_data(image_data_32 const& im, +inline int import_image_data(image_data_rgba8 const& im, WebPPicture & pic, bool alpha) { - int stride = sizeof(image_data_32::pixel_type) * im.width(); + int stride = sizeof(image_data_rgba8::pixel_type) * im.width(); if (alpha) { return WebPPictureImportRGBA(&pic, im.getBytes(), stride); diff --git a/include/mapnik/well_known_srs.hpp b/include/mapnik/well_known_srs.hpp index 5efab629b..2c0d40e1e 100644 --- a/include/mapnik/well_known_srs.hpp +++ b/include/mapnik/well_known_srs.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,7 @@ namespace mapnik { -enum well_known_srs_enum { +enum well_known_srs_enum : std::uint8_t { WGS_84, G_MERC, well_known_srs_enum_MAX diff --git a/include/mapnik/wkb.hpp b/include/mapnik/wkb.hpp index 2f3052c66..fe6a36b25 100644 --- a/include/mapnik/wkb.hpp +++ b/include/mapnik/wkb.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include namespace mapnik { @@ -42,14 +42,14 @@ namespace mapnik * the Open Geospatial Consortium (OGC) and described in their Simple Feature * Access and Coordinate Transformation Service specifications. */ -enum wkbFormat +enum wkbFormat : std::uint8_t { wkbAuto=1, wkbGeneric=2, wkbSpatiaLite=3 }; -class MAPNIK_DECL geometry_utils : private mapnik::noncopyable +class MAPNIK_DECL geometry_utils : private util::noncopyable { public: diff --git a/include/mapnik/wkt/wkt_factory.hpp b/include/mapnik/wkt/wkt_factory.hpp index 934781f5d..01949eb0f 100644 --- a/include/mapnik/wkt/wkt_factory.hpp +++ b/include/mapnik/wkt/wkt_factory.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/wkt/wkt_generator_grammar.hpp b/include/mapnik/wkt/wkt_generator_grammar.hpp index 9c6337c25..e2ea7df14 100644 --- a/include/mapnik/wkt/wkt_generator_grammar.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp index e4051a73b..d1d339dc9 100644 --- a/include/mapnik/wkt/wkt_generator_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_generator_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/wkt/wkt_grammar.hpp b/include/mapnik/wkt/wkt_grammar.hpp index ff004faa2..072d4a986 100644 --- a/include/mapnik/wkt/wkt_grammar.hpp +++ b/include/mapnik/wkt/wkt_grammar.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/wkt/wkt_grammar_impl.hpp b/include/mapnik/wkt/wkt_grammar_impl.hpp index 8cf6f7f0b..5ebee461f 100644 --- a/include/mapnik/wkt/wkt_grammar_impl.hpp +++ b/include/mapnik/wkt/wkt_grammar_impl.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/xml_attribute_cast.hpp b/include/mapnik/xml_attribute_cast.hpp index 37188534a..6d2e4ae25 100644 --- a/include/mapnik/xml_attribute_cast.hpp +++ b/include/mapnik/xml_attribute_cast.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/xml_loader.hpp b/include/mapnik/xml_loader.hpp index b102b61eb..2bc8f4af3 100644 --- a/include/mapnik/xml_loader.hpp +++ b/include/mapnik/xml_loader.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/xml_node.hpp b/include/mapnik/xml_node.hpp index 59498e056..28be9ff0c 100644 --- a/include/mapnik/xml_node.hpp +++ b/include/mapnik/xml_node.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/include/mapnik/xml_tree.hpp b/include/mapnik/xml_tree.hpp index 68d980b28..9cb29a8cc 100644 --- a/include/mapnik/xml_tree.hpp +++ b/include/mapnik/xml_tree.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 76b577011..5cbc8d336 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/csv/csv_datasource.hpp b/plugins/input/csv/csv_datasource.hpp index b5b695b29..f433b17a9 100644 --- a/plugins/input/csv/csv_datasource.hpp +++ b/plugins/input/csv/csv_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/csv/csv_utils.hpp b/plugins/input/csv/csv_utils.hpp index a07346268..3ec8c9fcb 100644 --- a/plugins/input/csv/csv_utils.hpp +++ b/plugins/input/csv/csv_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,7 +51,7 @@ namespace csv_utils wrapping_char = "\""; j_idx = j_idx_double; post_idx = csv_line.find("}\""); - + } else if (j_idx_single != std::string::npos) { @@ -89,7 +89,7 @@ namespace csv_utils csv_line = pre_json + json_chunk + post_json; } } - } + } } } diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index ed714019c..48577dac5 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,6 @@ #include #include #include -#include #include @@ -110,7 +109,7 @@ gdal_datasource::gdal_datasource(parameters const& params) nbands_ = dataset->GetRasterCount(); width_ = dataset->GetRasterXSize(); height_ = dataset->GetRasterYSize(); - desc_.add_descriptor(mapnik::attribute_descriptor("nodata", mapnik::Integer)); + desc_.add_descriptor(mapnik::attribute_descriptor("nodata", mapnik::Double)); double tr[6]; bool bbox_override = false; diff --git a/plugins/input/gdal/gdal_datasource.hpp b/plugins/input/gdal/gdal_datasource.hpp index bb43b95bd..68536b2d8 100644 --- a/plugins/input/gdal/gdal_datasource.hpp +++ b/plugins/input/gdal/gdal_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index f250cac8a..1e276cc2a 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -104,6 +104,7 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) GDALRasterBand * blue = 0; GDALRasterBand * alpha = 0; GDALRasterBand * grey = 0; + CPLErr raster_io_error = CE_None; /* #ifdef MAPNIK_LOG @@ -198,31 +199,38 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) if (im_width > 0 && im_height > 0) { - mapnik::raster_ptr raster = std::make_shared(intersect, im_width, im_height, filter_factor); - feature->set_raster(raster); - mapnik::image_data_32 & image = raster->data_; - image.set(0xffffffff); - MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Image Size=(" << im_width << "," << im_height << ")"; MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: Reading band=" << band_; - if (band_ > 0) // we are querying a single band { + mapnik::image_data_gray16 image(im_width, im_height); + image.set(std::numeric_limits::max()); if (band_ > nbands_) { std::ostringstream s; s << "GDAL Plugin: " << band_ << " is an invalid band, dataset only has " << nbands_ << "bands"; throw datasource_exception(s.str()); } - float* imageData = (float*)image.getBytes(); + GDALRasterBand * band = dataset_.GetRasterBand(band_); raster_nodata = band->GetNoDataValue(&raster_has_nodata); - band->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = band->RasterIO(GF_Read, x_off, y_off, width, height, + image.getData(), image.width(), image.height(), + GDT_Int16, 0, 0); + if (raster_io_error == CE_Failure) + { + throw datasource_exception(CPLGetLastErrorMsg()); + } + mapnik::raster_ptr raster = std::make_shared(intersect, image, filter_factor); + // set nodata value to be used in raster colorizer + if (nodata_value_) raster->set_nodata(*nodata_value_); + else raster->set_nodata(raster_nodata); + feature->set_raster(raster); } else // working with all bands { + mapnik::image_data_rgba8 image(im_width, im_height); + image.set(std::numeric_limits::max()); for (int i = 0; i < nbands_; ++i) { GDALRasterBand * band = dataset_.GetRasterBand(i + 1); @@ -309,9 +317,12 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) // TODO - we assume here the nodata value for the red band applies to all bands // more details about this at http://trac.osgeo.org/gdal/ticket/2734 float* imageData = (float*)image.getBytes(); - red->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, + imageData, image.width(), image.height(), + GDT_Float32, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { @@ -325,12 +336,21 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) } } } - red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + raster_io_error = red->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = green->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 1, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } + raster_io_error = blue->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 2, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } } else if (grey) { @@ -344,9 +364,13 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: applying nodata value for layer=" << apply_nodata; // first read the data in and create an alpha channel from the nodata values float* imageData = (float*)image.getBytes(); - grey->RasterIO(GF_Read, x_off, y_off, width, height, - imageData, image.width(), image.height(), - GDT_Float32, 0, 0); + raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, + imageData, image.width(), image.height(), + GDT_Float32, 0, 0); + if (raster_io_error == CE_Failure) + { + throw datasource_exception(CPLGetLastErrorMsg()); + } int len = image.width() * image.height(); for (int i = 0; i < len; ++i) { @@ -360,12 +384,28 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) } } } - grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); - grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + + raster_io_error = grey->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 0, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) + { + throw datasource_exception(CPLGetLastErrorMsg()); + } + + raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 1, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) + { + throw datasource_exception(CPLGetLastErrorMsg()); + } + + raster_io_error = grey->RasterIO(GF_Read,x_off, y_off, width, height, image.getBytes() + 2, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + + if (raster_io_error == CE_Failure) + { + throw datasource_exception(CPLGetLastErrorMsg()); + } if (color_table) { @@ -396,23 +436,22 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) MAPNIK_LOG_DEBUG(gdal) << "gdal_featureset: processing alpha band..."; if (!raster_has_nodata) { - alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3, - image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + raster_io_error = alpha->RasterIO(GF_Read, x_off, y_off, width, height, image.getBytes() + 3, + image.width(), image.height(), GDT_Byte, 4, 4 * image.width()); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } } else { MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; } } - } - // set nodata value to be used in raster colorizer - if (nodata_value_) - { - raster->set_nodata(*nodata_value_); - } - else - { - raster->set_nodata(raster_nodata); + mapnik::raster_ptr raster = std::make_shared(intersect, image, filter_factor); + // set nodata value to be used in raster colorizer + if (nodata_value_) raster->set_nodata(*nodata_value_); + else raster->set_nodata(raster_nodata); + feature->set_raster(raster); } // report actual/original source nodata in feature attributes if (raster_has_nodata) @@ -428,6 +467,8 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) { + CPLErr raster_io_error = CE_None; + if (band_ > 0) { unsigned raster_xsize = dataset_.GetRasterXSize(); @@ -455,7 +496,10 @@ feature_ptr gdal_featureset::get_feature_at_point(mapnik::coord2d const& pt) int raster_has_nodata; double nodata = band->GetNoDataValue(&raster_has_nodata); double value; - band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0); + raster_io_error = band->RasterIO(GF_Read, x, y, 1, 1, &value, 1, 1, GDT_Float64, 0, 0); + if (raster_io_error == CE_Failure) { + throw datasource_exception(CPLGetLastErrorMsg()); + } if (! raster_has_nodata || value != nodata) { // construct feature diff --git a/plugins/input/gdal/gdal_featureset.hpp b/plugins/input/gdal/gdal_featureset.hpp index a10a3f0f3..04f24ed0f 100644 --- a/plugins/input/gdal/gdal_featureset.hpp +++ b/plugins/input/gdal/gdal_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ using gdal_query = mapnik::util::variant; class gdal_featureset : public mapnik::Featureset { - struct query_dispatch : public mapnik::util::static_visitor + struct query_dispatch { query_dispatch( gdal_featureset & featureset) : featureset_(featureset) {} diff --git a/plugins/input/geojson/geojson_datasource.cpp b/plugins/input/geojson/geojson_datasource.cpp index 21c71603c..065226f01 100644 --- a/plugins/input/geojson/geojson_datasource.cpp +++ b/plugins/input/geojson/geojson_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -53,7 +53,7 @@ using mapnik::parameters; DATASOURCE_PLUGIN(geojson_datasource) -struct attr_value_converter : public mapnik::util::static_visitor +struct attr_value_converter { mapnik::eAttributeType operator() (mapnik::value_integer) const { @@ -127,7 +127,7 @@ geojson_datasource::geojson_datasource(parameters const& params) mapnik::util::file file(filename_); if (!file.open()) { - throw mapnik::datasource_exception("TopoJSON Plugin: could not open: '" + filename_ + "'"); + throw mapnik::datasource_exception("GeoJSON Plugin: could not open: '" + filename_ + "'"); } std::string file_buffer; file_buffer.resize(file.size()); @@ -147,7 +147,10 @@ void geojson_datasource::parse_geojson(T const& buffer) { boost::spirit::standard_wide::space_type space; mapnik::context_ptr ctx = std::make_shared(); - bool result = boost::spirit::qi::phrase_parse(buffer.begin(), buffer.end(), (fc_grammar)(boost::phoenix::ref(ctx)), space, features_); + std::size_t start_id = 1; + bool result = boost::spirit::qi::phrase_parse(buffer.begin(), buffer.end(), (fc_grammar) + (boost::phoenix::ref(ctx),boost::phoenix::ref(start_id)), + space, features_); if (!result) { if (!inline_string_.empty()) throw mapnik::datasource_exception("geojson_datasource: Failed parse GeoJSON file from in-memory string"); diff --git a/plugins/input/geojson/geojson_datasource.hpp b/plugins/input/geojson/geojson_datasource.hpp index c5194ec76..1437d3664 100644 --- a/plugins/input/geojson/geojson_datasource.hpp +++ b/plugins/input/geojson/geojson_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -73,7 +73,12 @@ struct options_type > choose_by_content_diff_tag, split_default_tag, linear_tag, +#if BOOST_VERSION >= 105700 + node_variant_static_tag>; +#else node_s_mem_static_tag>; + +#endif }; }}}}} diff --git a/plugins/input/geojson/geojson_featureset.cpp b/plugins/input/geojson/geojson_featureset.cpp index 722108dc1..3254cb2e8 100644 --- a/plugins/input/geojson/geojson_featureset.cpp +++ b/plugins/input/geojson/geojson_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/geojson/geojson_featureset.hpp b/plugins/input/geojson/geojson_featureset.hpp index 1f6898bf8..1af2da7ae 100644 --- a/plugins/input/geojson/geojson_featureset.hpp +++ b/plugins/input/geojson/geojson_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_datasource.cpp b/plugins/input/occi/occi_datasource.cpp index 364817b3c..a39c6b259 100644 --- a/plugins/input/occi/occi_datasource.cpp +++ b/plugins/input/occi/occi_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_datasource.hpp b/plugins/input/occi/occi_datasource.hpp index 0aa6f3891..8601fb4de 100644 --- a/plugins/input/occi/occi_datasource.hpp +++ b/plugins/input/occi/occi_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_featureset.cpp b/plugins/input/occi/occi_featureset.cpp index 33f89e833..e2d2ecd52 100644 --- a/plugins/input/occi/occi_featureset.cpp +++ b/plugins/input/occi/occi_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_featureset.hpp b/plugins/input/occi/occi_featureset.hpp index 88f9cfb22..abe21716c 100644 --- a/plugins/input/occi/occi_featureset.hpp +++ b/plugins/input/occi/occi_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_types.cpp b/plugins/input/occi/occi_types.cpp index 0545b80fa..6fb69aa3e 100644 --- a/plugins/input/occi/occi_types.cpp +++ b/plugins/input/occi/occi_types.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/occi/occi_types.hpp b/plugins/input/occi/occi_types.hpp index 066704c14..752246abd 100644 --- a/plugins/input/occi/occi_types.hpp +++ b/plugins/input/occi/occi_types.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software, you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_converter.cpp b/plugins/input/ogr/ogr_converter.cpp index 341ab0473..7a64d87d7 100644 --- a/plugins/input/ogr/ogr_converter.cpp +++ b/plugins/input/ogr/ogr_converter.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_converter.hpp b/plugins/input/ogr/ogr_converter.hpp index a52ab66ce..a633784e2 100644 --- a/plugins/input/ogr/ogr_converter.hpp +++ b/plugins/input/ogr/ogr_converter.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_datasource.cpp b/plugins/input/ogr/ogr_datasource.cpp index 3e76dd94c..c317b75dc 100644 --- a/plugins/input/ogr/ogr_datasource.cpp +++ b/plugins/input/ogr/ogr_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_datasource.hpp b/plugins/input/ogr/ogr_datasource.hpp index 5691fd845..853e2f447 100644 --- a/plugins/input/ogr/ogr_datasource.hpp +++ b/plugins/input/ogr/ogr_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_featureset.cpp b/plugins/input/ogr/ogr_featureset.cpp index 7383c7f86..a0a6a112f 100644 --- a/plugins/input/ogr/ogr_featureset.cpp +++ b/plugins/input/ogr/ogr_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_featureset.hpp b/plugins/input/ogr/ogr_featureset.hpp index 861ff27fd..9dfd7290c 100644 --- a/plugins/input/ogr/ogr_featureset.hpp +++ b/plugins/input/ogr/ogr_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_index.hpp b/plugins/input/ogr/ogr_index.hpp index ff793c622..b30c92a35 100644 --- a/plugins/input/ogr/ogr_index.hpp +++ b/plugins/input/ogr/ogr_index.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_index_featureset.cpp b/plugins/input/ogr/ogr_index_featureset.cpp index f72a5a647..e095ed1ea 100644 --- a/plugins/input/ogr/ogr_index_featureset.cpp +++ b/plugins/input/ogr/ogr_index_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_index_featureset.hpp b/plugins/input/ogr/ogr_index_featureset.hpp index 83645da00..440743e31 100644 --- a/plugins/input/ogr/ogr_index_featureset.hpp +++ b/plugins/input/ogr/ogr_index_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/ogr/ogr_layer_ptr.hpp b/plugins/input/ogr/ogr_layer_ptr.hpp index 81fe3dcc4..07c55c352 100644 --- a/plugins/input/ogr/ogr_layer_ptr.hpp +++ b/plugins/input/ogr/ogr_layer_ptr.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/Makefile.example b/plugins/input/osm/Makefile.example deleted file mode 100644 index b89658478..000000000 --- a/plugins/input/osm/Makefile.example +++ /dev/null @@ -1,9 +0,0 @@ -CXXFLAGS = `xml2-config --cflags` -I/usr/local/include/mapnik -I/usr/include/boost -I/usr/include/freetype2 -I/home/nick/mapnik-osm/agg/include -g -LDFLAGS = `xml2-config --libs` -L/usr/local/lib -LDFLAGS5 = `xml2-config --libs` -L/usr/local/lib -lmapnik -OBJ = test.o osm.o osmparser.o -test: $(OBJ) - g++ -o test $(OBJ) $(LDFLAGS) -render: render.o - g++ -o render render.o $(LDFLAGS5) - diff --git a/plugins/input/osm/basiccurl.cpp b/plugins/input/osm/basiccurl.cpp index ece3aca22..77cab5eba 100755 --- a/plugins/input/osm/basiccurl.cpp +++ b/plugins/input/osm/basiccurl.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/dataset_deliverer.cpp b/plugins/input/osm/dataset_deliverer.cpp index caaadb8ac..4920cab90 100644 --- a/plugins/input/osm/dataset_deliverer.cpp +++ b/plugins/input/osm/dataset_deliverer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/libMakefile b/plugins/input/osm/libMakefile deleted file mode 100644 index d072ba2f1..000000000 --- a/plugins/input/osm/libMakefile +++ /dev/null @@ -1,4 +0,0 @@ -CXXFLAGS = `xml2-config --cflags` -I/usr/local/include/mapnik -I/usr/include/boost -I/usr/include/freetype2 -I/home/nick/mapnik-osm/agg/include -fPIC -g -MAPNIK_OSM_OBJ = osmparser.o osm.o osm_datasource.o osm_featureset.o -osm.input: $(MAPNIK_OSM_OBJ) - g++ -shared -o osm.input $(MAPNIK_OSM_OBJ) diff --git a/plugins/input/osm/osm.cpp b/plugins/input/osm/osm.cpp index d5fe09670..f822a3177 100644 --- a/plugins/input/osm/osm.cpp +++ b/plugins/input/osm/osm.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/osm_datasource.cpp b/plugins/input/osm/osm_datasource.cpp index 65a66a8aa..4dd4c348e 100644 --- a/plugins/input/osm/osm_datasource.cpp +++ b/plugins/input/osm/osm_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/osm_datasource.hpp b/plugins/input/osm/osm_datasource.hpp index fb9fcb3fa..2662dedec 100644 --- a/plugins/input/osm/osm_datasource.hpp +++ b/plugins/input/osm/osm_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/osm_featureset.cpp b/plugins/input/osm/osm_featureset.cpp index 99be92be0..ca81575d2 100644 --- a/plugins/input/osm/osm_featureset.cpp +++ b/plugins/input/osm/osm_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/osm_featureset.hpp b/plugins/input/osm/osm_featureset.hpp index ebf11c755..48c0ff508 100644 --- a/plugins/input/osm/osm_featureset.hpp +++ b/plugins/input/osm/osm_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/osm/render.cpp b/plugins/input/osm/render.cpp deleted file mode 100644 index 707ac1285..000000000 --- a/plugins/input/osm/render.cpp +++ /dev/null @@ -1,75 +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 - * - *****************************************************************************/ - -// stl -#include -#include - -// mapnik -#include -#include -#include -#include -#include -#include -#include -#include -#include - -int main(int argc,char *argv[]) -{ - if (argc < 6) - { - std::cerr << "Usage: render XMLfile w s e n [OSMfile]" << std::endl; - exit(0); - } - - mapnik::datasource_cache::instance().register_datasources("/usr/local/lib/mapnik/input"); - mapnik::freetype_engine::register_font("/usr/local/lib/mapnik/fonts/DejaVuSans.ttf"); - - mapnik::Map m(800, 800); - mapnik::load_map(m, argv[1]); - - if (argc > 6) - { - mapnik::parameters p; - p["type"] = "osm"; - p["file"] = argv[6]; - for (int count = 0; count < m.layer_count(); count++) - { - mapnik::parameters q = m.get_layer(count).datasource()->params(); - m.get_layer(count).set_datasource(mapnik::datasource_cache::instance().create(p)); - } - } - - mapnik::box2d bbox (atof(argv[2]), atof(argv[3]), atof(argv[4]), atof(argv[5])); - - m.zoom_to_box(bbox); - - mapnik::image_32 buf (m.width(), m.height()); - mapnik::agg_renderer r(m, buf); - r.apply(); - - mapnik::save_to_file(buf.data(), "blah.png", "png"); - - return 0; -} diff --git a/plugins/input/pgraster/pgraster_datasource.cpp b/plugins/input/pgraster/pgraster_datasource.cpp index f4a8a9d12..7a144dca0 100644 --- a/plugins/input/pgraster/pgraster_datasource.cpp +++ b/plugins/input/pgraster/pgraster_datasource.cpp @@ -355,12 +355,22 @@ pgraster_datasource::pgraster_datasource(parameters const& params) shared_ptr rs = conn->executeQuery(s.str()); while (rs->next()) { - overviews_.resize(overviews_.size()+1); - pgraster_overview& ov = overviews_.back(); - ov.schema = rs->getValue("sch"); + pgraster_overview ov = pgraster_overview(); + + ov.schema = rs->getValue("sch"); ov.table = rs->getValue("tab"); ov.column = rs->getValue("col"); ov.scale = atof(rs->getValue("scl")); + + if(ov.scale == 0.0f) + { + MAPNIK_LOG_WARN(pgraster) << "pgraster_datasource: found invalid overview " + << ov.schema << "." << ov.table << "." << ov.column << " with scale " << ov.scale; + continue; + } + + overviews_.push_back(ov); + MAPNIK_LOG_DEBUG(pgraster) << "pgraster_datasource: found overview " << ov.schema << "." << ov.table << "." << ov.column << " with scale " << ov.scale; } rs->close(); diff --git a/plugins/input/pgraster/pgraster_featureset.cpp b/plugins/input/pgraster/pgraster_featureset.cpp index ee36cc4e6..497652561 100644 --- a/plugins/input/pgraster/pgraster_featureset.cpp +++ b/plugins/input/pgraster/pgraster_featureset.cpp @@ -28,6 +28,7 @@ #include "pgraster_wkb_reader.hpp" #include "../postgis/resultset.hpp" #include "../postgis/cursorresultset.hpp" +#include "../postgis/numeric2string.hpp" // mapnik #include @@ -64,8 +65,6 @@ pgraster_featureset::pgraster_featureset(std::shared_ptr const& rs, { } -std::string numeric2string(const char* buf); - feature_ptr pgraster_featureset::next() { while (rs_->next()) @@ -241,115 +240,3 @@ pgraster_featureset::~pgraster_featureset() { rs_->close(); } - -std::string numeric2string(const char* buf) -{ - std::int16_t ndigits = int2net(buf); - std::int16_t weight = int2net(buf+2); - std::int16_t sign = int2net(buf+4); - std::int16_t dscale = int2net(buf+6); - - std::unique_ptr digits(new std::int16_t[ndigits]); - for (int n=0; n < ndigits ;++n) - { - digits[n] = int2net(buf+8+n*2); - } - - std::ostringstream ss; - - if (sign == 0x4000) ss << "-"; - - int i = std::max(weight,std::int16_t(0)); - int d = 0; - - // Each numeric "digit" is actually a value between 0000 and 9999 stored in a 16 bit field. - // For example, the number 1234567809990001 is stored as four digits: [1234] [5678] [999] [1]. - // Note that the last two digits show that the leading 0's are lost when the number is split. - // We must be careful to re-insert these 0's when building the string. - - while ( i >= 0) - { - if (i <= weight && d < ndigits) - { - // All digits after the first must be padded to make the field 4 characters long - if (d != 0) - { -#ifdef _WINDOWS - int dig = digits[d]; - if (dig < 10) - { - ss << "000"; // 0000 - 0009 - } - else if (dig < 100) - { - ss << "00"; // 0010 - 0099 - } - else - { - ss << "0"; // 0100 - 0999; - } -#else - switch(digits[d]) - { - case 0 ... 9: - ss << "000"; // 0000 - 0009 - break; - case 10 ... 99: - ss << "00"; // 0010 - 0099 - break; - case 100 ... 999: - ss << "0"; // 0100 - 0999 - break; - } -#endif - } - ss << digits[d++]; - } - else - { - if (d == 0) - ss << "0"; - else - ss << "0000"; - } - - i--; - } - if (dscale > 0) - { - ss << '.'; - // dscale counts the number of decimal digits following the point, not the numeric digits - while (dscale > 0) - { - int value; - if (i <= weight && d < ndigits) - value = digits[d++]; - else - value = 0; - - // Output up to 4 decimal digits for this value - if (dscale > 0) { - ss << (value / 1000); - value %= 1000; - dscale--; - } - if (dscale > 0) { - ss << (value / 100); - value %= 100; - dscale--; - } - if (dscale > 0) { - ss << (value / 10); - value %= 10; - dscale--; - } - if (dscale > 0) { - ss << value; - dscale--; - } - - i--; - } - } - return ss.str(); -} diff --git a/plugins/input/pgraster/pgraster_featureset.hpp b/plugins/input/pgraster/pgraster_featureset.hpp index d7f200158..55aba597a 100644 --- a/plugins/input/pgraster/pgraster_featureset.hpp +++ b/plugins/input/pgraster/pgraster_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/pgraster/pgraster_wkb_reader.cpp b/plugins/input/pgraster/pgraster_wkb_reader.cpp index 109438ab9..d2e77048c 100644 --- a/plugins/input/pgraster/pgraster_wkb_reader.cpp +++ b/plugins/input/pgraster/pgraster_wkb_reader.cpp @@ -178,25 +178,20 @@ typedef enum { } -using mapnik::box2d; - template -void read_data_band(mapnik::raster_ptr raster, +mapnik::raster_ptr read_data_band(mapnik::box2d const& bbox, uint16_t width, uint16_t height, bool hasnodata, T reader) { - mapnik::image_data_32 & image = raster->data_; - + mapnik::image_data_gray32f image(width, height); + //image.set(std::numeric_limits::max()); // Start with plain white (ABGR or RGBA depending on endiannes) // TODO: set to transparent instead? image.set(0xffffffff); - raster->premultiplied_alpha_ = true; - - float* data = (float*)image.getBytes(); + float* data = image.getData(); double val; val = reader(); // nodata value, need to read anyway - if ( hasnodata ) raster->set_nodata(val); for (int y=0; y(bbox, image, 1.0, true); + if ( hasnodata ) raster->set_nodata(val); + return raster; } -void -pgraster_wkb_reader::read_indexed(mapnik::raster_ptr raster) +mapnik::raster_ptr pgraster_wkb_reader::read_indexed(mapnik::box2d const& bbox, + uint16_t width, uint16_t height) { - mapnik::image_data_32 & image = raster->data_; - - // Start with all zeroes - image.set(0); - uint8_t type = read_uint8(&ptr_); int pixtype = BANDTYPE_PIXTYPE(type); @@ -227,7 +220,7 @@ pgraster_wkb_reader::read_indexed(mapnik::raster_ptr raster) if ( offline ) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: offline band " " unsupported"; - return; + return mapnik::raster_ptr(); } MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: reading " << height_ << "x" << width_ << " pixels"; @@ -240,27 +233,27 @@ pgraster_wkb_reader::read_indexed(mapnik::raster_ptr raster) case PT_8BSI: // mapnik does not support signed anyway case PT_8BUI: - read_data_band(raster, width_, height_, hasnodata, + return read_data_band(bbox, width_, height_, hasnodata, boost::bind(read_uint8, &ptr_)); break; case PT_16BSI: // mapnik does not support signed anyway case PT_16BUI: - read_data_band(raster, width_, height_, hasnodata, + return read_data_band(bbox, width_, height_, hasnodata, boost::bind(read_uint16, &ptr_, endian_)); break; case PT_32BSI: // mapnik does not support signed anyway case PT_32BUI: - read_data_band(raster, width_, height_, hasnodata, + return read_data_band(bbox, width_, height_, hasnodata, boost::bind(read_uint32, &ptr_, endian_)); break; case PT_32BF: - read_data_band(raster, width_, height_, hasnodata, + return read_data_band(bbox, width_, height_, hasnodata, boost::bind(read_float32, &ptr_, endian_)); break; case PT_64BF: - read_data_band(raster, width_, height_, hasnodata, + return read_data_band(bbox, width_, height_, hasnodata, boost::bind(read_float64, &ptr_, endian_)); break; default: @@ -270,28 +263,25 @@ pgraster_wkb_reader::read_indexed(mapnik::raster_ptr raster) //MAPNIK_LOG_WARN(pgraster) << err.str(); throw mapnik::datasource_exception(err.str()); } - + return mapnik::raster_ptr(); } template -void read_grayscale_band(mapnik::raster_ptr raster, +mapnik::raster_ptr read_grayscale_band(mapnik::box2d const& bbox, uint16_t width, uint16_t height, bool hasnodata, T reader) { - mapnik::image_data_32 & image = raster->data_; - + mapnik::image_data_rgba8 image(width,height); // Start with plain white (ABGR or RGBA depending on endiannes) // TODO: set to transparent instead? image.set(0xffffffff); - raster->premultiplied_alpha_ = true; int val; uint8_t * data = image.getBytes(); int ps = 4; // sizeof(image_data::pixel_type) int off; val = reader(); // nodata value, need to read anyway - if ( hasnodata ) raster->set_nodata(val); for (int y=0; y(bbox, image, 1.0, true); + if ( hasnodata ) raster->set_nodata(val); + return raster; } -void -pgraster_wkb_reader::read_grayscale(mapnik::raster_ptr raster) +mapnik::raster_ptr pgraster_wkb_reader::read_grayscale(mapnik::box2d const& bbox, + uint16_t width, uint16_t height) { uint8_t type = read_uint8(&ptr_); @@ -320,7 +313,7 @@ pgraster_wkb_reader::read_grayscale(mapnik::raster_ptr raster) if ( offline ) { MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: offline band " " unsupported"; - return; + return mapnik::raster_ptr(); } switch (pixtype) { @@ -331,19 +324,19 @@ pgraster_wkb_reader::read_grayscale(mapnik::raster_ptr raster) case PT_8BSI: // mapnik does not support signed anyway case PT_8BUI: - read_grayscale_band(raster, width_, height_, hasnodata, + return read_grayscale_band(bbox, width_, height_, hasnodata, boost::bind(read_uint8, &ptr_)); break; case PT_16BSI: // mapnik does not support signed anyway case PT_16BUI: - read_grayscale_band(raster, width_, height_, hasnodata, + return read_grayscale_band(bbox, width_, height_, hasnodata, boost::bind(read_uint16, &ptr_, endian_)); break; case PT_32BSI: // mapnik does not support signed anyway case PT_32BUI: - read_grayscale_band(raster, width_, height_, hasnodata, + return read_grayscale_band(bbox, width_, height_, hasnodata, boost::bind(read_uint32, &ptr_, endian_)); break; default: @@ -353,19 +346,15 @@ pgraster_wkb_reader::read_grayscale(mapnik::raster_ptr raster) //MAPNIK_LOG_WARN(pgraster) << err.str(); throw mapnik::datasource_exception(err.str()); } - + return mapnik::raster_ptr(); } -void -pgraster_wkb_reader::read_rgba(mapnik::raster_ptr raster) +mapnik::raster_ptr pgraster_wkb_reader::read_rgba(mapnik::box2d const& bbox, + uint16_t width, uint16_t height) { - mapnik::image_data_32 & image = raster->data_; - + mapnik::image_data_rgba8 image(width, height); // Start with plain white (ABGR or RGBA depending on endiannes) image.set(0xffffffff); - //raster->set_nodata(0xffffffff); - - raster->premultiplied_alpha_ = true; uint8_t nodataval; for (int bn=0; bn(bbox, image, 1.0, true); + raster->set_nodata(0xffffffff); + return raster; } mapnik::raster_ptr @@ -458,28 +450,30 @@ pgraster_wkb_reader::get_raster() { return mapnik::raster_ptr(); } - box2d ext(ipX,ipY,ipX+(width_*scaleX),ipY+(height_*scaleY)); + mapnik::box2d ext(ipX,ipY,ipX+(width_*scaleX),ipY+(height_*scaleY)); MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: Raster extent=" << ext; - mapnik::raster_ptr raster = std::make_shared(ext, width_, height_, 1.0); - - if ( bandno_ ) { - if ( bandno_ != 1 ) { - MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: " + if ( bandno_ ) + { + if ( bandno_ != 1 ) + { + MAPNIK_LOG_WARN(pgraster) << "pgraster_wkb_reader: " "reading bands other than 1st as indexed is unsupported"; - return mapnik::raster_ptr(); + return mapnik::raster_ptr(); } MAPNIK_LOG_DEBUG(pgraster) << "pgraster_wkb_reader: requested band " << bandno_; - read_indexed(raster); + return read_indexed(ext, width_, height_); } - else { - switch (numBands_) { + else + { + switch (numBands_) + { case 1: - read_grayscale(raster); + return read_grayscale(ext, width_, height_); break; case 3: case 4: - read_rgba(raster); + return read_rgba(ext, width_, height_); break; default: std::ostringstream err; @@ -491,7 +485,5 @@ pgraster_wkb_reader::get_raster() { return mapnik::raster_ptr(); } } - - return raster; - + return mapnik::raster_ptr(); } diff --git a/plugins/input/pgraster/pgraster_wkb_reader.hpp b/plugins/input/pgraster/pgraster_wkb_reader.hpp index 21f163bbd..b0ec7f8f9 100644 --- a/plugins/input/pgraster/pgraster_wkb_reader.hpp +++ b/plugins/input/pgraster/pgraster_wkb_reader.hpp @@ -29,6 +29,7 @@ // mapnik #include // for raster_ptr +#include enum pgraster_color_interp { // Automatic color interpretation: @@ -65,9 +66,9 @@ public: } private: - void read_indexed(mapnik::raster_ptr raster); - void read_grayscale(mapnik::raster_ptr raster); - void read_rgba(mapnik::raster_ptr raster); + mapnik::raster_ptr read_indexed(mapnik::box2d const& bbox, uint16_t width, uint16_t height); + mapnik::raster_ptr read_grayscale(mapnik::box2d const& bbox, uint16_t width, uint16_t height); + mapnik::raster_ptr read_rgba(mapnik::box2d const& bbox, uint16_t width, uint16_t height); //int wkbsize_; //const uint8_t* wkb_; diff --git a/plugins/input/postgis/asyncresultset.hpp b/plugins/input/postgis/asyncresultset.hpp index 0db1079f8..b1bc9126d 100644 --- a/plugins/input/postgis/asyncresultset.hpp +++ b/plugins/input/postgis/asyncresultset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,7 +34,7 @@ class postgis_processor_context; using postgis_processor_context_ptr = std::shared_ptr; -class AsyncResultSet : public IResultSet, private mapnik::noncopyable +class AsyncResultSet : public IResultSet, private mapnik::util::noncopyable { public: AsyncResultSet(postgis_processor_context_ptr const& ctx, diff --git a/plugins/input/postgis/connection.hpp b/plugins/input/postgis/connection.hpp index 479472109..8f3e6bfbb 100644 --- a/plugins/input/postgis/connection.hpp +++ b/plugins/input/postgis/connection.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/postgis/connection_manager.hpp b/plugins/input/postgis/connection_manager.hpp index 4437c1ebc..64271900a 100644 --- a/plugins/input/postgis/connection_manager.hpp +++ b/plugins/input/postgis/connection_manager.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/postgis/cursorresultset.hpp b/plugins/input/postgis/cursorresultset.hpp index 87f4df215..fa071b3a5 100644 --- a/plugins/input/postgis/cursorresultset.hpp +++ b/plugins/input/postgis/cursorresultset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include "connection.hpp" #include "resultset.hpp" -class CursorResultSet : public IResultSet, private mapnik::noncopyable +class CursorResultSet : public IResultSet, private mapnik::util::noncopyable { public: CursorResultSet(std::shared_ptr const &conn, std::string cursorName, int fetch_count) diff --git a/plugins/input/postgis/numeric2string.hpp b/plugins/input/postgis/numeric2string.hpp new file mode 100644 index 000000000..0f988c9c6 --- /dev/null +++ b/plugins/input/postgis/numeric2string.hpp @@ -0,0 +1,144 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_NUMERIC_2_STRING_HPP +#define MAPNIK_NUMERIC_2_STRING_HPP + +#include +#include +#include +#include +#include + +static inline std::string numeric2string(const char* buf) +{ + std::int16_t ndigits = int2net(buf); + std::int16_t weight = int2net(buf+2); + std::int16_t sign = int2net(buf+4); + std::int16_t dscale = int2net(buf+6); + + std::unique_ptr digits(new std::int16_t[ndigits]); + for (int n=0; n < ndigits ;++n) + { + digits[n] = int2net(buf+8+n*2); + } + + std::ostringstream ss; + + if (sign == 0x4000) ss << "-"; + + int i = std::max(weight,std::int16_t(0)); + int d = 0; + + // Each numeric "digit" is actually a value between 0000 and 9999 stored in a 16 bit field. + // For example, the number 1234567809990001 is stored as four digits: [1234] [5678] [999] [1]. + // Note that the last two digits show that the leading 0's are lost when the number is split. + // We must be careful to re-insert these 0's when building the string. + + while ( i >= 0) + { + if (i <= weight && d < ndigits) + { + // All digits after the first must be padded to make the field 4 characters long + if (d != 0) + { +#ifdef _WINDOWS + int dig = digits[d]; + if (dig < 10) + { + ss << "000"; // 0000 - 0009 + } + else if (dig < 100) + { + ss << "00"; // 0010 - 0099 + } + else + { + ss << "0"; // 0100 - 0999; + } +#else + switch(digits[d]) + { + case 0 ... 9: + ss << "000"; // 0000 - 0009 + break; + case 10 ... 99: + ss << "00"; // 0010 - 0099 + break; + case 100 ... 999: + ss << "0"; // 0100 - 0999 + break; + } +#endif + } + ss << digits[d++]; + } + else + { + if (d == 0) + ss << "0"; + else + ss << "0000"; + } + + i--; + } + if (dscale > 0) + { + ss << '.'; + // dscale counts the number of decimal digits following the point, not the numeric digits + while (dscale > 0) + { + int value; + if (i <= weight && d < ndigits) + value = digits[d++]; + else + value = 0; + + // Output up to 4 decimal digits for this value + if (dscale > 0) { + ss << (value / 1000); + value %= 1000; + dscale--; + } + if (dscale > 0) { + ss << (value / 100); + value %= 100; + dscale--; + } + if (dscale > 0) { + ss << (value / 10); + value %= 10; + dscale--; + } + if (dscale > 0) { + ss << value; + dscale--; + } + + i--; + } + } + return ss.str(); +} + +#endif diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 95cb80873..908b939b8 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index ebe87d7ad..0fb8e11ad 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 8569a03e3..7d9f47589 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@ #include "postgis_featureset.hpp" #include "resultset.hpp" #include "cursorresultset.hpp" + #include "numeric2string.hpp" // mapnik #include @@ -59,8 +60,6 @@ postgis_featureset::postgis_featureset(std::shared_ptr const& rs, { } -std::string numeric2string(const char* buf); - feature_ptr postgis_featureset::next() { while (rs_->next()) @@ -226,115 +225,3 @@ postgis_featureset::~postgis_featureset() { rs_->close(); } - -std::string numeric2string(const char* buf) -{ - std::int16_t ndigits = int2net(buf); - std::int16_t weight = int2net(buf+2); - std::int16_t sign = int2net(buf+4); - std::int16_t dscale = int2net(buf+6); - - const std::unique_ptr digits(new std::int16_t[ndigits]); - for (int n=0; n < ndigits ;++n) - { - digits[n] = int2net(buf+8+n*2); - } - - std::ostringstream ss; - - if (sign == 0x4000) ss << "-"; - - int i = std::max(weight,std::int16_t(0)); - int d = 0; - - // Each numeric "digit" is actually a value between 0000 and 9999 stored in a 16 bit field. - // For example, the number 1234567809990001 is stored as four digits: [1234] [5678] [999] [1]. - // Note that the last two digits show that the leading 0's are lost when the number is split. - // We must be careful to re-insert these 0's when building the string. - - while ( i >= 0) - { - if (i <= weight && d < ndigits) - { - // All digits after the first must be padded to make the field 4 characters long - if (d != 0) - { -#ifdef _WINDOWS - int dig = digits[d]; - if (dig < 10) - { - ss << "000"; // 0000 - 0009 - } - else if (dig < 100) - { - ss << "00"; // 0010 - 0099 - } - else - { - ss << "0"; // 0100 - 0999; - } -#else - switch(digits[d]) - { - case 0 ... 9: - ss << "000"; // 0000 - 0009 - break; - case 10 ... 99: - ss << "00"; // 0010 - 0099 - break; - case 100 ... 999: - ss << "0"; // 0100 - 0999 - break; - } -#endif - } - ss << digits[d++]; - } - else - { - if (d == 0) - ss << "0"; - else - ss << "0000"; - } - - i--; - } - if (dscale > 0) - { - ss << '.'; - // dscale counts the number of decimal digits following the point, not the numeric digits - while (dscale > 0) - { - int value; - if (i <= weight && d < ndigits) - value = digits[d++]; - else - value = 0; - - // Output up to 4 decimal digits for this value - if (dscale > 0) { - ss << (value / 1000); - value %= 1000; - dscale--; - } - if (dscale > 0) { - ss << (value / 100); - value %= 100; - dscale--; - } - if (dscale > 0) { - ss << (value / 10); - value %= 10; - dscale--; - } - if (dscale > 0) { - ss << value; - dscale--; - } - - i--; - } - } - return ss.str(); -} diff --git a/plugins/input/postgis/postgis_featureset.hpp b/plugins/input/postgis/postgis_featureset.hpp index a3a2cbf1e..6f5fff44a 100644 --- a/plugins/input/postgis/postgis_featureset.hpp +++ b/plugins/input/postgis/postgis_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/postgis/resultset.hpp b/plugins/input/postgis/resultset.hpp index 600fc96dd..b93ce64dd 100644 --- a/plugins/input/postgis/resultset.hpp +++ b/plugins/input/postgis/resultset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,7 +45,7 @@ public: virtual const char* getValue(const char* name) const = 0; }; -class ResultSet : public IResultSet, private mapnik::noncopyable +class ResultSet : public IResultSet, private mapnik::util::noncopyable { public: ResultSet(PGresult *res) diff --git a/plugins/input/raster/raster_datasource.cpp b/plugins/input/raster/raster_datasource.cpp index 13d996e9e..b70b6f25a 100644 --- a/plugins/input/raster/raster_datasource.cpp +++ b/plugins/input/raster/raster_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -84,6 +84,16 @@ raster_datasource::raster_datasource(parameters const& params) { extent_initialized_ = extent_.from_string(*ext); } + else //bounding box from image_reader + { + std::unique_ptr reader(mapnik::get_image_reader(*file)); + auto bbox = reader->bounding_box(); + if (bbox) + { + extent_ = *bbox; + extent_initialized_ = true; + } + } if (! extent_initialized_) { diff --git a/plugins/input/raster/raster_datasource.hpp b/plugins/input/raster/raster_datasource.hpp index 96bcaf16b..435f8e5c7 100644 --- a/plugins/input/raster/raster_datasource.hpp +++ b/plugins/input/raster/raster_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/raster/raster_featureset.cpp b/plugins/input/raster/raster_featureset.cpp index b396abb8a..6f5fa0376 100644 --- a/plugins/input/raster/raster_featureset.cpp +++ b/plugins/input/raster/raster_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ #include #include #include +#include // boost #pragma GCC diagnostic push @@ -42,7 +43,7 @@ using mapnik::query; using mapnik::image_reader; using mapnik::feature_ptr; -using mapnik::image_data_32; +using mapnik::image_data_rgba8; using mapnik::raster; using mapnik::feature_factory; @@ -113,9 +114,8 @@ feature_ptr raster_featureset::next() rem.maxx() + x_off + width, rem.maxy() + y_off + height); intersect = t.backward(feature_raster_extent); - - mapnik::raster_ptr raster = std::make_shared(intersect, width, height, 1.0); - reader->read(x_off, y_off, raster->data_); + mapnik::image_data_any data = reader->read(x_off, y_off, width, height); + mapnik::raster_ptr raster = std::make_shared(intersect, std::move(data), 1.0); raster->premultiplied_alpha_ = reader->premultiplied_alpha(); feature->set_raster(raster); } diff --git a/plugins/input/raster/raster_featureset.hpp b/plugins/input/raster/raster_featureset.hpp index 18e3ebcef..fed7bbaea 100644 --- a/plugins/input/raster/raster_featureset.hpp +++ b/plugins/input/raster/raster_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/raster/raster_info.cpp b/plugins/input/raster/raster_info.cpp index 10bd79775..9b04983e7 100644 --- a/plugins/input/raster/raster_info.cpp +++ b/plugins/input/raster/raster_info.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/raster/raster_info.hpp b/plugins/input/raster/raster_info.hpp index 4de948528..2bf5ba96c 100644 --- a/plugins/input/raster/raster_info.hpp +++ b/plugins/input/raster/raster_info.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/rasterlite/build.py b/plugins/input/rasterlite/build.py index 4b463831b..7100b1e5f 100644 --- a/plugins/input/rasterlite/build.py +++ b/plugins/input/rasterlite/build.py @@ -38,6 +38,15 @@ libraries = [env['PLUGINS']['rasterlite']['lib']] libraries.append(env['ICU_LIB_NAME']) libraries.append('boost_system%s' % env['BOOST_APPEND']) +if env['RUNTIME_LINK'] == 'static': + libraries.append('geotiff') + libraries.append('spatialite') + libraries.append('sqlite3') + libraries.append('geos_c') + libraries.append('geos') + libraries.append('proj') + libraries.append('z') + if env['PLUGIN_LINKING'] == 'shared': libraries.append(env['MAPNIK_NAME']) diff --git a/plugins/input/rasterlite/rasterlite_datasource.cpp b/plugins/input/rasterlite/rasterlite_datasource.cpp index b6e07556f..b851bebd3 100644 --- a/plugins/input/rasterlite/rasterlite_datasource.cpp +++ b/plugins/input/rasterlite/rasterlite_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/rasterlite/rasterlite_datasource.hpp b/plugins/input/rasterlite/rasterlite_datasource.hpp index da5257766..df6c03d91 100644 --- a/plugins/input/rasterlite/rasterlite_datasource.hpp +++ b/plugins/input/rasterlite/rasterlite_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/rasterlite/rasterlite_featureset.cpp b/plugins/input/rasterlite/rasterlite_featureset.cpp index 517e9a75e..2e3c6bb40 100644 --- a/plugins/input/rasterlite/rasterlite_featureset.cpp +++ b/plugins/input/rasterlite/rasterlite_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -114,19 +114,11 @@ feature_ptr rasterlite_featureset::get_feature(mapnik::query const& q) { if (size > 0) { - mapnik::raster_ptr rasterp = std::make_shared(intersect, width, height, 1.0); - mapnik::image_data_32 & image = rasterp->data_; - image.set(0xffffffff); - + mapnik::image_data_rgba8 image(width,height); unsigned char* raster_data = static_cast(raster); unsigned char* image_data = image.getBytes(); - std::memcpy(image_data, raster_data, size); - - feature->set_raster(rasterp); - - free (raster); - + feature->set_raster(std::make_shared(intersect, std::move(image), 1.0)); MAPNIK_LOG_DEBUG(rasterlite) << "rasterlite_featureset: Done"; } else diff --git a/plugins/input/rasterlite/rasterlite_featureset.hpp b/plugins/input/rasterlite/rasterlite_featureset.hpp index 63be0dbe8..cf7973f15 100644 --- a/plugins/input/rasterlite/rasterlite_featureset.hpp +++ b/plugins/input/rasterlite/rasterlite_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,7 @@ using rasterlite_query = mapnik::util::variant; class rasterlite_featureset : public mapnik::Featureset { - struct query_dispatch : public mapnik::util::static_visitor + struct query_dispatch { query_dispatch( rasterlite_featureset & featureset) : featureset_(featureset) {} diff --git a/plugins/input/rasterlite/rasterlite_include.hpp b/plugins/input/rasterlite/rasterlite_include.hpp index b94eb482a..4662e845d 100644 --- a/plugins/input/rasterlite/rasterlite_include.hpp +++ b/plugins/input/rasterlite/rasterlite_include.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/dbf_test.cpp b/plugins/input/shape/dbf_test.cpp index c521dc710..b9917a931 100644 --- a/plugins/input/shape/dbf_test.cpp +++ b/plugins/input/shape/dbf_test.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/dbfile.cpp b/plugins/input/shape/dbfile.cpp index cada1733b..5b1c76e46 100644 --- a/plugins/input/shape/dbfile.cpp +++ b/plugins/input/shape/dbfile.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/dbfile.hpp b/plugins/input/shape/dbfile.hpp index 29aaefa74..75e77d323 100644 --- a/plugins/input/shape/dbfile.hpp +++ b/plugins/input/shape/dbfile.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,7 @@ // mapnik #include -#include +#include #include #ifdef SHAPE_MEMORY_MAPPED_FILE #include @@ -52,7 +52,7 @@ struct field_descriptor }; -class dbf_file : private mapnik::noncopyable +class dbf_file : private mapnik::util::noncopyable { private: int num_records_; diff --git a/plugins/input/shape/shape_datasource.cpp b/plugins/input/shape/shape_datasource.cpp index a649c75e3..dbf8edd4f 100644 --- a/plugins/input/shape/shape_datasource.cpp +++ b/plugins/input/shape/shape_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_datasource.hpp b/plugins/input/shape/shape_datasource.hpp index ae1894dbd..9795370a4 100644 --- a/plugins/input/shape/shape_datasource.hpp +++ b/plugins/input/shape/shape_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_featureset.cpp b/plugins/input/shape/shape_featureset.cpp index 7ae4a6494..2c4d90cd4 100644 --- a/plugins/input/shape/shape_featureset.cpp +++ b/plugins/input/shape/shape_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_featureset.hpp b/plugins/input/shape/shape_featureset.hpp index a71e59e65..4ce235e8e 100644 --- a/plugins/input/shape/shape_featureset.hpp +++ b/plugins/input/shape/shape_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_index_featureset.cpp b/plugins/input/shape/shape_index_featureset.cpp index 2ff18cd9f..c05d9ee79 100644 --- a/plugins/input/shape/shape_index_featureset.cpp +++ b/plugins/input/shape/shape_index_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_index_featureset.hpp b/plugins/input/shape/shape_index_featureset.hpp index cc1715b21..d62d8ed6a 100644 --- a/plugins/input/shape/shape_index_featureset.hpp +++ b/plugins/input/shape/shape_index_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_io.cpp b/plugins/input/shape/shape_io.cpp index ec1e134bc..d05b6416b 100644 --- a/plugins/input/shape/shape_io.cpp +++ b/plugins/input/shape/shape_io.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,6 @@ #include #include #include - // boost using mapnik::datasource_exception; @@ -147,34 +146,53 @@ void shape_io::read_polyline( shape_file::record_type & record, mapnik::geometry } } +template +bool is_clockwise(T const& points, int start, int end) +{ + int num_points = end - start; + double area = 0.0; + for (int i = 0; i < num_points; ++i) + { + auto const& p0 = points[start + i]; + auto const& p1 = points[start + (i + 1) % num_points]; + area += std::get<0>(p0) * std::get<1>(p1) - std::get<1>(p0) * std::get<0>(p1); + } + return ( area < 0.0) ? true : false; +} + void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_container & geom) { int num_parts = record.read_ndr_integer(); int num_points = record.read_ndr_integer(); std::vector parts(num_parts); + using points_cont = std::vector >; + points_cont points; + points.reserve(num_points); + for (int i = 0; i < num_parts; ++i) { parts[i] = record.read_ndr_integer(); } + for (int k = 0; k < num_points; ++k) + { + double x = record.read_double(); + double y = record.read_double(); + points.emplace_back(x,y); + } + std::unique_ptr poly(new geometry_type(mapnik::geometry_type::types::Polygon)); for (int k = 0; k < num_parts; ++k) { int start = parts[k]; int end; - if (k == num_parts - 1) - { - end = num_points; - } - else - { - end = parts[k + 1]; - } - - double x = record.read_double(); - double y = record.read_double(); - if (k > 0 && !hit_test_first(*poly, x, y)) + if (k == num_parts - 1) end = num_points; + else end = parts[k + 1]; + auto const& pt = points[start]; + double x = std::get<0>(pt); + double y = std::get<1>(pt); + if ( k > 0 && is_clockwise(points, start, end)) { geom.push_back(poly.release()); poly.reset(new geometry_type(mapnik::geometry_type::types::Polygon)); @@ -182,8 +200,9 @@ void shape_io::read_polygon(shape_file::record_type & record, mapnik::geometry_c poly->move_to(x, y); for (int j = start + 1; j < end; ++j) { - x = record.read_double(); - y = record.read_double(); + auto const& pt = points[j]; + x = std::get<0>(pt); + y = std::get<1>(pt); poly->line_to(x, y); } poly->close_path(); diff --git a/plugins/input/shape/shape_io.hpp b/plugins/input/shape/shape_io.hpp index 727310c0e..15797e9fb 100644 --- a/plugins/input/shape/shape_io.hpp +++ b/plugins/input/shape/shape_io.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,7 +26,7 @@ // mapnik #include #include -#include +#include // boost #include @@ -37,7 +37,7 @@ #include "dbfile.hpp" #include "shapefile.hpp" -struct shape_io : mapnik::noncopyable +struct shape_io : mapnik::util::noncopyable { public: enum shapeType diff --git a/plugins/input/shape/shape_utils.cpp b/plugins/input/shape/shape_utils.cpp index 0f90878db..9495fda87 100644 --- a/plugins/input/shape/shape_utils.cpp +++ b/plugins/input/shape/shape_utils.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shape_utils.hpp b/plugins/input/shape/shape_utils.hpp index f113d3d1a..eda62a8b2 100644 --- a/plugins/input/shape/shape_utils.hpp +++ b/plugins/input/shape/shape_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/shape/shapefile.hpp b/plugins/input/shape/shapefile.hpp index bd2740a7c..c53d467b7 100644 --- a/plugins/input/shape/shapefile.hpp +++ b/plugins/input/shape/shapefile.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,7 +38,7 @@ #include #include #endif -#include +#include using mapnik::box2d; using mapnik::read_int32_ndr; @@ -131,7 +131,7 @@ struct shape_record } }; -class shape_file : mapnik::noncopyable +class shape_file : mapnik::util::noncopyable { public: diff --git a/plugins/input/shape/shp_index.hpp b/plugins/input/shape/shp_index.hpp index 1d69b5d7a..bb033e95f 100644 --- a/plugins/input/shape/shp_index.hpp +++ b/plugins/input/shape/shp_index.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_connection.hpp b/plugins/input/sqlite/sqlite_connection.hpp index 244c577d1..c7bd11fb7 100644 --- a/plugins/input/sqlite/sqlite_connection.hpp +++ b/plugins/input/sqlite/sqlite_connection.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 25f727b24..21db6edfe 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_datasource.hpp b/plugins/input/sqlite/sqlite_datasource.hpp index db0bcfa07..4461c962e 100644 --- a/plugins/input/sqlite/sqlite_datasource.hpp +++ b/plugins/input/sqlite/sqlite_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_featureset.cpp b/plugins/input/sqlite/sqlite_featureset.cpp index 11530809d..39b37aff8 100644 --- a/plugins/input/sqlite/sqlite_featureset.cpp +++ b/plugins/input/sqlite/sqlite_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_featureset.hpp b/plugins/input/sqlite/sqlite_featureset.hpp index 6fc53602f..12f3ee0ee 100644 --- a/plugins/input/sqlite/sqlite_featureset.hpp +++ b/plugins/input/sqlite/sqlite_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_prepared.hpp b/plugins/input/sqlite/sqlite_prepared.hpp index e05e5db62..cf81842ab 100644 --- a/plugins/input/sqlite/sqlite_prepared.hpp +++ b/plugins/input/sqlite/sqlite_prepared.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,7 @@ #include #include #include -#include +#include // boost #include @@ -43,7 +43,7 @@ extern "C" { #include } -class prepared_index_statement : mapnik::noncopyable +class prepared_index_statement : mapnik::util::noncopyable { public: diff --git a/plugins/input/sqlite/sqlite_resultset.hpp b/plugins/input/sqlite/sqlite_resultset.hpp index e8e6a16fe..aebd031a1 100644 --- a/plugins/input/sqlite/sqlite_resultset.hpp +++ b/plugins/input/sqlite/sqlite_resultset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/sqlite/sqlite_utils.hpp b/plugins/input/sqlite/sqlite_utils.hpp index 06832f6e0..0d63e82bb 100644 --- a/plugins/input/sqlite/sqlite_utils.hpp +++ b/plugins/input/sqlite/sqlite_utils.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -684,8 +684,8 @@ public: desc.add_descriptor(mapnik::attribute_descriptor(fld_name, mapnik::String)); } else if (boost::algorithm::contains(fld_type, "real") || - boost::algorithm::contains(fld_type, "float") || - boost::algorithm::contains(fld_type, "double")) + boost::algorithm::contains(fld_type, "floa") || + boost::algorithm::contains(fld_type, "doub")) { desc.add_descriptor(mapnik::attribute_descriptor(fld_name, mapnik::Double)); } @@ -701,14 +701,17 @@ public: // "Column Affinity" says default to "Numeric" but for now we pass.. //desc_.add_descriptor(attribute_descriptor(fld_name,mapnik::Double)); + desc.add_descriptor(mapnik::attribute_descriptor(fld_name, mapnik::String)); + #ifdef MAPNIK_LOG // Do not fail when we specify geometry_field in XML file if (field.empty()) { MAPNIK_LOG_DEBUG(sqlite) << "Column '" << std::string(fld_name) - << "' unhandled due to unknown type: " - << fld_type; + << "' unhandled due to unknown type: '" + << fld_type + << "', using String"; } #endif } diff --git a/plugins/input/topojson/topojson_datasource.cpp b/plugins/input/topojson/topojson_datasource.cpp index 8e92245f5..23b3b2376 100644 --- a/plugins/input/topojson/topojson_datasource.cpp +++ b/plugins/input/topojson/topojson_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,7 +44,7 @@ using mapnik::parameters; DATASOURCE_PLUGIN(topojson_datasource) -struct attr_value_converter : public mapnik::util::static_visitor +struct attr_value_converter { mapnik::eAttributeType operator() (mapnik::value_integer /*val*/) const { @@ -82,7 +82,7 @@ struct attr_value_converter : public mapnik::util::static_visitor +struct geometry_type_visitor { int operator() (mapnik::topojson::point const&) const { @@ -114,7 +114,7 @@ struct geometry_type_visitor : public mapnik::util::static_visitor } }; -struct collect_attributes_visitor : public mapnik::util::static_visitor +struct collect_attributes_visitor { mapnik::layer_descriptor & desc_; collect_attributes_visitor(mapnik::layer_descriptor & desc): diff --git a/plugins/input/topojson/topojson_datasource.hpp b/plugins/input/topojson/topojson_datasource.hpp index cb7e046da..bcf32f702 100644 --- a/plugins/input/topojson/topojson_datasource.hpp +++ b/plugins/input/topojson/topojson_datasource.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/plugins/input/topojson/topojson_featureset.cpp b/plugins/input/topojson/topojson_featureset.cpp index b1231a04d..898c7db8c 100644 --- a/plugins/input/topojson/topojson_featureset.cpp +++ b/plugins/input/topojson/topojson_featureset.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -51,7 +51,7 @@ BOOST_GEOMETRY_REGISTER_LINESTRING(std::vector) namespace mapnik { namespace topojson { struct attribute_value_visitor - : mapnik::util::static_visitor + { public: attribute_value_visitor(mapnik::transcoder const& tr) @@ -84,7 +84,7 @@ void assign_properties(mapnik::feature_impl & feature, T const& geom, mapnik::tr } template -struct feature_generator : public mapnik::util::static_visitor +struct feature_generator { feature_generator(Context & ctx, mapnik::transcoder const& tr, topology const& topo, std::size_t feature_id) : ctx_(ctx), diff --git a/plugins/input/topojson/topojson_featureset.hpp b/plugins/input/topojson/topojson_featureset.hpp index 78ab136c9..f6dc224c6 100644 --- a/plugins/input/topojson/topojson_featureset.hpp +++ b/plugins/input/topojson/topojson_featureset.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/run_tests b/run_tests index 5dab76b2a..7ae774a35 100755 --- a/run_tests +++ b/run_tests @@ -5,15 +5,20 @@ failures=0 source ./localize.sh PYTHON=${PYTHON:-python} -echo "*** Running visual tests..." -$PYTHON tests/visual_tests/test.py -q +echo "*** Running Next Gen C++ tests..." +./tests/cxx/run failures=$((failures+$?)) +echo -echo "*** Running C++ tests..." +echo "*** Running Old C++ tests..." ./tests/cpp_tests/run failures=$((failures+$?)) echo +echo "*** Running visual tests..." +$PYTHON tests/visual_tests/test.py -q +failures=$((failures+$?)) + echo "*** Running python tests..." $PYTHON tests/run_tests.py -q failures=$((failures+$?)) diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index 129765195..d1ce80ca0 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -412,7 +412,7 @@ void agg_renderer::render_marker(pixel_position const& pos, agg::image_filter_bilinear filter_kernel; agg::image_filter_lut filter(filter_kernel, false); - image_data_32 const& src = **marker.get_bitmap_data(); + image_data_rgba8 const& src = **marker.get_bitmap_data(); agg::rendering_buffer marker_buf((unsigned char *)src.getBytes(), src.width(), src.height(), diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 9d0baeb63..7a693454f 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_debug_symbolizer.cpp b/src/agg/process_debug_symbolizer.cpp index ecd37907a..fb1d2e90b 100644 --- a/src/agg/process_debug_symbolizer.cpp +++ b/src/agg/process_debug_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_dot_symbolizer.cpp b/src/agg/process_dot_symbolizer.cpp new file mode 100644 index 000000000..4b53d3ced --- /dev/null +++ b/src/agg/process_dot_symbolizer.cpp @@ -0,0 +1,105 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// agg +#include "agg_ellipse.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" +#include "agg_scanline_u.h" +#include "agg_renderer_scanline.h" +#include "agg_color_rgba.h" +#include "agg_renderer_base.h" + +namespace mapnik { + +template +void agg_renderer::process(dot_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + double width = 0.0; + double height = 0.0; + bool has_width = has_key(sym,keys::width); + bool has_height = has_key(sym,keys::height); + if (has_width && has_height) + { + width = get(sym, keys::width, feature, common_.vars_, 0.0); + height = get(sym, keys::height, feature, common_.vars_, 0.0); + } + else if (has_width) + { + width = height = get(sym, keys::width, feature, common_.vars_, 0.0); + } + else if (has_height) + { + width = height = get(sym, keys::height, feature, common_.vars_, 0.0); + } + double rx = width/2.0; + double ry = height/2.0; + double opacity = get(sym, keys::opacity, feature, common_.vars_, 1.0); + color const& fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); + ras_ptr->reset(); + agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(),current_buffer_->width() * 4); + using blender_type = agg::comp_op_adaptor_rgba_pre; + using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba; + using renderer_base = agg::renderer_base; + using renderer_type = agg::renderer_scanline_aa_solid; + pixfmt_comp_type pixf(buf); + pixf.comp_op(static_cast(get(sym, keys::comp_op, feature, common_.vars_, src_over))); + renderer_base renb(pixf); + renderer_type ren(renb); + agg::scanline_u8 sl; + ren.color(agg::rgba8_pre(fill.red(), fill.green(), fill.blue(), int(fill.alpha() * opacity))); + agg::ellipse el(0,0,rx,ry); + unsigned num_steps = el.num_steps(); + for (geometry_type const& geom : feature.paths()) { + double x,y,z = 0; + unsigned cmd = 1; + geom.rewind(0); + while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) { + if (cmd == SEG_CLOSE) continue; + prj_trans.backward(x,y,z); + common_.t_.forward(&x,&y); + el.init(x,y,rx,ry,num_steps); + ras_ptr->add_path(el); + agg::render_scanlines(*ras_ptr, sl, ren); + } + } +} + +template void agg_renderer::process(dot_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index 1d823288d..d8b2d3868 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,7 +48,7 @@ namespace mapnik { * to render it, and the boxes themselves should already be * in the detector from the placement_finder. */ -struct thunk_renderer : public util::static_visitor<> +struct thunk_renderer { using renderer_type = agg_renderer; using buffer_type = renderer_type::buffer_type; diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 412b4d55d..110a52e2e 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index a2eca2417..e35f1000b 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index ecfaac4f1..31555bc6e 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -125,7 +125,7 @@ struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch; using renderer_base = agg::renderer_base; - raster_markers_rasterizer_dispatch(image_data_32 & src, + raster_markers_rasterizer_dispatch(image_data_rgba8 & src, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, diff --git a/src/agg/process_point_symbolizer.cpp b/src/agg/process_point_symbolizer.cpp index 96d041068..950e9cb58 100644 --- a/src/agg/process_point_symbolizer.cpp +++ b/src/agg/process_point_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -53,7 +53,7 @@ void agg_renderer::process(point_symbolizer const& sym, render_point_symbolizer( sym, feature, prj_trans, common_, - [&](pixel_position const& pos, marker const& marker, + [&](pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity) { render_marker(pos, marker, tr, opacity, comp_op); }); diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index ea58d8b1c..abcbdf7bd 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 5a5fb492e..d02ead68c 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_raster_symbolizer.cpp b/src/agg/process_raster_symbolizer.cpp index e79664f3b..4af75bbd6 100644 --- a/src/agg/process_raster_symbolizer.cpp +++ b/src/agg/process_raster_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -52,7 +52,7 @@ void agg_renderer::process(raster_symbolizer const& sym, { render_raster_symbolizer( sym, feature, prj_trans, common_, - [&](image_data_32 & target, composite_mode_e comp_op, double opacity, + [&](image_data_rgba8 & target, composite_mode_e comp_op, double opacity, int start_x, int start_y) { composite(current_buffer_->data(), target, comp_op, opacity, start_x, start_y, false); diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index ad86e41ad..cd039d9b7 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index bb45bed85..b7ed299d4 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/box2d.cpp b/src/box2d.cpp index 209fdece4..a812042f0 100644 --- a/src/box2d.cpp +++ b/src/box2d.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/build.py b/src/build.py index 4b1932833..0f32bce0b 100644 --- a/src/build.py +++ b/src/build.py @@ -204,8 +204,8 @@ source = Split( svg/svg_transform_parser.cpp warp.cpp css_color_grammar.cpp + vertex_cache.cpp text/font_library.cpp - text/vertex_cache.cpp text/text_layout.cpp text/text_line.cpp text/itemizer.cpp @@ -243,6 +243,7 @@ source = Split( if env['PLUGIN_LINKING'] == 'static': hit = False + lib_env.AppendUnique(CPPPATH='../plugins/') for plugin in env['REQUESTED_PLUGINS']: details = env['PLUGINS'][plugin] if details['lib'] in env['LIBS'] or not details['lib']: @@ -300,6 +301,7 @@ for cpp in enabled_imaging_libraries: source += Split( """ agg/agg_renderer.cpp + agg/process_dot_symbolizer.cpp agg/process_building_symbolizer.cpp agg/process_line_symbolizer.cpp agg/process_line_pattern_symbolizer.cpp diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index 41056b056..8f2c60a61 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -337,7 +337,7 @@ void cairo_context::set_gradient(cairo_gradient const& pattern, const box2d -struct thunk_renderer : public util::static_visitor<> +struct thunk_renderer { using renderer_type = cairo_renderer; @@ -104,7 +104,7 @@ struct thunk_renderer : public util::static_visitor<> glyphs->marker()->transform, thunk.opacity_, thunk.comp_op_); } - context_.add_text(*glyphs, face_manager_, common_.font_manager_, src_over, src_over, common_.scale_factor_); + context_.add_text(*glyphs, face_manager_, src_over, src_over, common_.scale_factor_); }); } diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp index 22e4f80d0..d741c64f1 100644 --- a/src/cairo/process_markers_symbolizer.cpp +++ b/src/cairo/process_markers_symbolizer.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ class proj_transform; namespace detail { template -struct vector_markers_dispatch_cairo : public vector_markers_dispatch +struct vector_markers_dispatch_cairo : public vector_markers_dispatch { vector_markers_dispatch_cairo(svg_path_ptr const& src, svg::svg_path_adapter & path, @@ -86,7 +86,7 @@ private: template struct raster_markers_dispatch_cairo : public raster_markers_dispatch { - raster_markers_dispatch_cairo(mapnik::image_data_32 & src, + raster_markers_dispatch_cairo(mapnik::image_data_rgba8 & src, agg::trans_affine const& marker_trans, markers_symbolizer const& sym, Detector & detector, diff --git a/src/cairo/process_raster_symbolizer.cpp b/src/cairo/process_raster_symbolizer.cpp index c9bfcaf8a..36daee737 100644 --- a/src/cairo/process_raster_symbolizer.cpp +++ b/src/cairo/process_raster_symbolizer.cpp @@ -43,7 +43,7 @@ void cairo_renderer::process(raster_symbolizer const& sym, cairo_save_restore guard(context_); render_raster_symbolizer( sym, feature, prj_trans, common_, - [&](image_data_32 &target, composite_mode_e comp_op, double opacity, + [&](image_data_rgba8 &target, composite_mode_e comp_op, double opacity, int start_x, int start_y) { context_.set_operator(comp_op); context_.add_image(start_x, start_y, target, opacity); diff --git a/src/cairo/process_text_symbolizer.cpp b/src/cairo/process_text_symbolizer.cpp index 3493ac15b..365e5f662 100644 --- a/src/cairo/process_text_symbolizer.cpp +++ b/src/cairo/process_text_symbolizer.cpp @@ -64,7 +64,7 @@ void cairo_renderer::process(shield_symbolizer const& sym, glyphs->marker()->transform, opacity); } - context_.add_text(*glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + context_.add_text(*glyphs, face_manager_, comp_op, halo_comp_op, common_.scale_factor_); } } @@ -94,7 +94,7 @@ void cairo_renderer::process(text_symbolizer const& sym, placements_list const& placements = helper.get(); for (glyph_positions_ptr glyphs : placements) { - context_.add_text(*glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + context_.add_text(*glyphs, face_manager_, comp_op, halo_comp_op, common_.scale_factor_); } } diff --git a/src/color.cpp b/src/color.cpp index 5cc33b72b..f1146e815 100644 --- a/src/color.cpp +++ b/src/color.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,7 +39,7 @@ #include #include #pragma GCC diagnostic pop - + // stl #include diff --git a/src/color_factory.cpp b/src/color_factory.cpp index c509c7f85..38257ec22 100644 --- a/src/color_factory.cpp +++ b/src/color_factory.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/conversions.cpp b/src/conversions.cpp index da79ae0de..250378e0e 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index cafb8c978..946a03d6f 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,7 +34,6 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedef" -#include #include #include #pragma GCC diagnostic pop @@ -171,18 +170,9 @@ bool datasource_cache::register_datasources(std::string const& dir, bool recurse bool success = false; try { - boost::filesystem::directory_iterator end_itr; -#ifdef _WINDOWS - std::wstring wide_dir(mapnik::utf8_to_utf16(dir)); - for (boost::filesystem::directory_iterator itr(wide_dir); itr != end_itr; ++itr) + for (std::string const& file_name : mapnik::util::list_directory(dir)) { - std::string file_name = mapnik::utf16_to_utf8(itr->path().wstring()); -#else - for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr) - { - std::string file_name = itr->path().string(); -#endif - if (boost::filesystem::is_directory(*itr) && recurse) + if (mapnik::util::is_directory(file_name) && recurse) { if (register_datasources(file_name, true)) { @@ -191,7 +181,7 @@ bool datasource_cache::register_datasources(std::string const& dir, bool recurse } else { - std::string base_name = itr->path().filename().string(); + std::string base_name = mapnik::util::basename(file_name); if (!boost::algorithm::starts_with(base_name,".") && mapnik::util::is_regular_file(file_name) && is_input_plugin(file_name)) diff --git a/src/datasource_cache_static.cpp b/src/datasource_cache_static.cpp index 459460a94..578b2f990 100644 --- a/src/datasource_cache_static.cpp +++ b/src/datasource_cache_static.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,46 +38,46 @@ // static plugin linkage #ifdef MAPNIK_STATIC_PLUGINS #if defined(MAPNIK_STATIC_PLUGIN_CSV) - #include "plugins/input/csv/csv_datasource.hpp" + #include "input/csv/csv_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_GDAL) - #include "plugins/input/gdal/gdal_datasource.hpp" + #include "input/gdal/gdal_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_GEOJSON) - #include "plugins/input/geojson/geojson_datasource.hpp" + #include "input/geojson/geojson_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_GEOS) - #include "plugins/input/geos/geos_datasource.hpp" + #include "input/geos/geos_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_KISMET) - #include "plugins/input/kismet/kismet_datasource.hpp" + #include "input/kismet/kismet_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_OCCI) - #include "plugins/input/occi/occi_datasource.hpp" + #include "input/occi/occi_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_OGR) - #include "plugins/input/ogr/ogr_datasource.hpp" + #include "input/ogr/ogr_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_OSM) - #include "plugins/input/osm/osm_datasource.hpp" + #include "input/osm/osm_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_POSTGIS) - #include "plugins/input/postgis/postgis_datasource.hpp" + #include "input/postgis/postgis_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_PYTHON) - #include "plugins/input/python/python_datasource.hpp" + #include "input/python/python_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_RASTER) - #include "plugins/input/raster/raster_datasource.hpp" + #include "input/raster/raster_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_RASTERLITE) - #include "plugins/input/rasterlite/rasterlite_datasource.hpp" + #include "input/rasterlite/rasterlite_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_SHAPE) - #include "plugins/input/shape/shape_datasource.hpp" + #include "input/shape/shape_datasource.hpp" #endif #if defined(MAPNIK_STATIC_PLUGIN_SQLITE) - #include "plugins/input/sqlite/sqlite_datasource.hpp" + #include "input/sqlite/sqlite_datasource.hpp" #endif #endif @@ -90,7 +90,7 @@ datasource_ptr ds_generator(parameters const& params) return std::make_shared(params); } -using params) = datasource_ptr (*ds_generator_ptr)(parameters const&; +typedef datasource_ptr (*ds_generator_ptr)(parameters const& params); using datasource_map = boost::unordered_map; static datasource_map ds_map = boost::assign::map_list_of diff --git a/src/debug.cpp b/src/debug.cpp index 44a125005..4a519cd71 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/expression.cpp b/src/expression.cpp index 3f01fe205..c8798774b 100644 --- a/src/expression.cpp +++ b/src/expression.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,12 +40,18 @@ expression_ptr parse_expression(std::string const& str) auto node = std::make_shared(); std::string::const_iterator itr = str.begin(); std::string::const_iterator end = str.end(); - bool r = boost::spirit::qi::phrase_parse(itr, end, g, space, *node); - if (r && itr == end) - { - return node; + try { + bool r = boost::spirit::qi::phrase_parse(itr, end, g, space, *node); + if (r && itr == end) + { + return node; + } + else + { + throw config_error("Failed to parse expression: \"" + str + "\""); + } } - else + catch (std::exception const&) // boost::spirit::qi::expectation_failure { throw config_error("Failed to parse expression: \"" + str + "\""); } diff --git a/src/expression_node.cpp b/src/expression_node.cpp index 69cb53074..3eef36057 100644 --- a/src/expression_node.cpp +++ b/src/expression_node.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,7 +22,7 @@ #include #include -#include +#include #if defined(BOOST_REGEX_HAS_ICU) #include @@ -33,7 +33,7 @@ namespace mapnik { -struct _regex_match_impl : noncopyable { +struct _regex_match_impl : util::noncopyable { #if defined(BOOST_REGEX_HAS_ICU) _regex_match_impl(value_unicode_string const& ustr) : pattern_(boost::make_u32regex(ustr)) {} @@ -45,7 +45,7 @@ struct _regex_match_impl : noncopyable { #endif }; -struct _regex_replace_impl : noncopyable { +struct _regex_replace_impl : util::noncopyable { #if defined(BOOST_REGEX_HAS_ICU) _regex_replace_impl(value_unicode_string const& ustr, value_unicode_string const& f) : pattern_(boost::make_u32regex(ustr)), @@ -153,4 +153,4 @@ std::string regex_replace_node::to_string() const return str_; } -} \ No newline at end of file +} diff --git a/src/expression_string.cpp b/src/expression_string.cpp index a5d1386b7..6fe39209e 100644 --- a/src/expression_string.cpp +++ b/src/expression_string.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ namespace mapnik { -struct expression_string : util::static_visitor +struct expression_string { explicit expression_string(std::string & str) : str_(str) {} diff --git a/src/feature_kv_iterator.cpp b/src/feature_kv_iterator.cpp index ed0c90566..ae2543d93 100644 --- a/src/feature_kv_iterator.cpp +++ b/src/feature_kv_iterator.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index a9af0dc5a..42fad26a5 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index 87752261b..4ee54e200 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index f4c33c95b..412b59511 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,7 +35,6 @@ #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedef" #include -#include #include #pragma GCC diagnostic pop @@ -66,11 +65,10 @@ bool freetype_engine::is_font_file(std::string const& file_name) std::transform(fn.begin(), fn.end(), fn.begin(), ::tolower); return boost::algorithm::ends_with(fn,std::string(".ttf")) || boost::algorithm::ends_with(fn,std::string(".otf")) || + boost::algorithm::ends_with(fn,std::string(".woff"))|| boost::algorithm::ends_with(fn,std::string(".ttc")) || boost::algorithm::ends_with(fn,std::string(".pfa")) || boost::algorithm::ends_with(fn,std::string(".pfb")) || - boost::algorithm::ends_with(fn,std::string(".ttc")) || - boost::algorithm::ends_with(fn,std::string(".woff"))|| // Plus OSX custom ext boost::algorithm::ends_with(fn,std::string(".dfont")); } @@ -190,18 +188,9 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, bool success = false; try { - boost::filesystem::directory_iterator end_itr; -#ifdef _WINDOWS - std::wstring wide_dir(mapnik::utf8_to_utf16(dir)); - for (boost::filesystem::directory_iterator itr(wide_dir); itr != end_itr; ++itr) + for (std::string const& file_name : mapnik::util::list_directory(dir)) { - std::string file_name = mapnik::utf16_to_utf8(itr->path().wstring()); -#else - for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr) - { - std::string file_name = itr->path().string(); -#endif - if (boost::filesystem::is_directory(*itr) && recurse) + if (mapnik::util::is_directory(file_name) && recurse) { if (register_fonts_impl(file_name, library, font_file_mapping, true)) { @@ -210,7 +199,7 @@ bool freetype_engine::register_fonts_impl(std::string const& dir, } else { - std::string base_name = itr->path().filename().string(); + std::string base_name = mapnik::util::basename(file_name); if (!boost::algorithm::starts_with(base_name,".") && mapnik::util::is_regular_file(file_name) && is_font_file(file_name)) @@ -327,9 +316,9 @@ face_ptr freetype_engine::create_face(std::string const& family_name, itr = global_font_file_mapping.find(family_name); if (itr != global_font_file_mapping.end()) { - auto mem_font_itr = global_memory_fonts_.find(itr->second.second); + auto mem_font_itr = global_memory_fonts.find(itr->second.second); // if font already in memory, use it - if (mem_font_itr != global_memory_fonts_.end()) + if (mem_font_itr != global_memory_fonts.end()) { FT_Face face; FT_Error error = FT_New_Memory_Face(library.get(), @@ -351,7 +340,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name, #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - auto result = global_memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(file.data()),file.size())); + auto result = global_memory_fonts.emplace(itr->second.second, std::make_pair(std::move(file.data()),file.size())); FT_Face face; FT_Error error = FT_New_Memory_Face(library.get(), reinterpret_cast(result.first->second.first.get()), // data @@ -361,7 +350,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name, if (error) { // we can't load font, erase it. - global_memory_fonts_.erase(result.first); + global_memory_fonts.erase(result.first); return face_ptr(); } return std::make_shared(face); diff --git a/src/font_set.cpp b/src/font_set.cpp index c99f8045c..89f46b0fb 100644 --- a/src/font_set.cpp +++ b/src/font_set.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/fs.cpp b/src/fs.cpp index 247c4a4d8..655472487 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,7 +25,8 @@ #include // boost -#include +#include // for absolute, exists, etc +#include // for path, operator/ // stl #include @@ -81,7 +82,6 @@ namespace util { return (! child_path.has_root_directory() && ! child_path.has_root_name()); } - std::string make_relative(std::string const& filepath, std::string const& base) { #ifdef _WINDOWS @@ -109,6 +109,32 @@ namespace util { return bp.parent_path().string(); } + std::string basename(std::string const& value) + { + boost::filesystem::path bp(value); + return bp.filename().string(); + } + + std::vector list_directory(std::string const& dir) + { + std::vector listing; + boost::filesystem::directory_iterator end_itr; +#ifdef _WINDOWS + std::wstring wide_dir(mapnik::utf8_to_utf16(dir)); + for (boost::filesystem::directory_iterator itr(wide_dir); itr != end_itr; ++itr) + { + listing.emplace_back(mapnik::utf16_to_utf8(itr->path().wstring())); + } +#else + for (boost::filesystem::directory_iterator itr(dir); itr != end_itr; ++itr) + { + listing.emplace_back(itr->path().string()); + } +#endif + return listing; + } + + } // end namespace util } // end namespace mapnik diff --git a/src/gradient.cpp b/src/gradient.cpp index 41612833b..912739eba 100644 --- a/src/gradient.cpp +++ b/src/gradient.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,28 +45,26 @@ static const char * gradient_unit_strings[] = { IMPLEMENT_ENUM( gradient_unit_e, gradient_unit_strings ) gradient::gradient() -: gradient_type_(NO_GRADIENT), - stops_(), - x1_(0), - y1_(0), - x2_(0), - y2_(0), - r_(0), - units_(OBJECT_BOUNDING_BOX), - transform_() -{} +: transform_(), + x1_(0), + y1_(0), + x2_(0), + y2_(0), + r_(0), + stops_(), + units_(OBJECT_BOUNDING_BOX), + gradient_type_(NO_GRADIENT) {} gradient::gradient(gradient const& other) - : gradient_type_(other.gradient_type_), - stops_(other.stops_), + : transform_(other.transform_), x1_(other.x1_), y1_(other.y1_), x2_(other.x2_), y2_(other.y2_), r_(other.r_), + stops_(other.stops_), units_(other.units_), - transform_(other.transform_) -{} + gradient_type_(other.gradient_type_) {} gradient & gradient::operator=(const gradient& rhs) { diff --git a/src/graphics.cpp b/src/graphics.cpp index 31d4536ca..850df6514 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,73 +39,29 @@ namespace mapnik { image_32::image_32(int width,int height) - :width_(width), - height_(height), - data_(width,height), + : data_(width,height), painted_(false), premultiplied_(false) {} -image_32::image_32(const image_32& rhs) - :width_(rhs.width_), - height_(rhs.height_), - data_(rhs.data_), + +image_32::image_32(image_32 const& rhs) + : data_(rhs.data_), painted_(rhs.painted_), premultiplied_(rhs.premultiplied_) {} -#ifdef HAVE_CAIRO -image_32::image_32(cairo_surface_ptr const& surface) - :width_(cairo_image_surface_get_width(&*surface)), - height_(cairo_image_surface_get_height(&*surface)), - data_(width_, height_), - premultiplied_(false) -{ - painted_ = true; - if ( cairo_image_surface_get_format(&*surface) != CAIRO_FORMAT_ARGB32) - { - MAPNIK_LOG_WARN(graphics) << "Unable to convert this Cairo format"; - throw; - } - - int stride = cairo_image_surface_get_stride(&*surface) / 4; - - const std::unique_ptr out_row(new unsigned int[width_]); - const unsigned int *in_row = (const unsigned int *)cairo_image_surface_get_data(&*surface); - - for (unsigned int row = 0; row < height_; row++, in_row += stride) - { - for (unsigned int column = 0; column < width_; column++) - { - unsigned int in = in_row[column]; - unsigned int a = (in >> 24) & 0xff; - unsigned int r = (in >> 16) & 0xff; - unsigned int g = (in >> 8) & 0xff; - unsigned int b = (in >> 0) & 0xff; - -#define DE_ALPHA(x) do { \ - if (a == 0) x = 0; \ - else x = x * 255 / a; \ - if (x > 255) x = 255; \ - } while(0) - - DE_ALPHA(r); - DE_ALPHA(g); - DE_ALPHA(b); - - out_row[column] = color(r, g, b, a).rgba(); - } - data_.setRow(row, out_row.get(), width_); - } -} -#endif +image_32::image_32(image_data_rgba8 && data) + : data_(std::move(data)), + painted_(false), + premultiplied_(false) {} image_32::~image_32() {} void image_32::set_grayscale_to_alpha() { - for (unsigned int y = 0; y < height_; ++y) + for (unsigned int y = 0; y < data_.height(); ++y) { unsigned int* row_from = data_.getRow(y); - for (unsigned int x = 0; x < width_; ++x) + for (unsigned int x = 0; x < data_.width(); ++x) { unsigned rgba = row_from[x]; unsigned r = rgba & 0xff; @@ -122,10 +78,10 @@ void image_32::set_grayscale_to_alpha() void image_32::set_color_to_alpha(const color& c) { - for (unsigned y = 0; y < height_; ++y) + for (unsigned y = 0; y < data_.height(); ++y) { unsigned int* row_from = data_.getRow(y); - for (unsigned x = 0; x < width_; ++x) + for (unsigned x = 0; x < data_.width(); ++x) { unsigned rgba = row_from[x]; unsigned r = rgba & 0xff; @@ -141,10 +97,10 @@ void image_32::set_color_to_alpha(const color& c) void image_32::set_alpha(float opacity) { - for (unsigned int y = 0; y < height_; ++y) + for (unsigned int y = 0; y < data_.height(); ++y) { unsigned int* row_to = data_.getRow(y); - for (unsigned int x = 0; x < width_; ++x) + for (unsigned int x = 0; x < data_.width(); ++x) { unsigned rgba = row_to[x]; unsigned a0 = (rgba >> 24) & 0xff; @@ -174,7 +130,7 @@ boost::optional const& image_32::get_background() const void image_32::premultiply() { - agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4); + agg::rendering_buffer buffer(data_.getBytes(),data_.width(),data_.height(),data_.width() * 4); agg::pixfmt_rgba32 pixf(buffer); pixf.premultiply(); premultiplied_ = true; @@ -182,7 +138,7 @@ void image_32::premultiply() void image_32::demultiply() { - agg::rendering_buffer buffer(data_.getBytes(),width_,height_,width_ * 4); + agg::rendering_buffer buffer(data_.getBytes(),data_.width(),data_.height(),data_.width() * 4); agg::pixfmt_rgba32_pre pixf(buffer); pixf.demultiply(); premultiplied_ = false; diff --git a/src/grid/grid.cpp b/src/grid/grid.cpp index 208fe663e..434e1bca9 100644 --- a/src/grid/grid.cpp +++ b/src/grid/grid.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index a9a4fc6b2..c72f9d1ca 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -165,7 +165,7 @@ void grid_renderer::render_marker(mapnik::feature_impl const& feature, pixel_ } else { - image_data_32 const& data = **marker.get_bitmap_data(); + image_data_rgba8 const& data = **marker.get_bitmap_data(); double width = data.width(); double height = data.height(); double cx = 0.5 * width; @@ -179,13 +179,13 @@ void grid_renderer::render_marker(mapnik::feature_impl const& feature, pixel_ } else { - image_data_32 target(data.width(), data.height()); - mapnik::scale_image_agg(target, - data, - SCALING_NEAR, - 1, - 1, - 0.0, 0.0, 1.0); // TODO: is 1.0 a valid default here, and do we even care in grid_renderer what the image looks like? + image_data_rgba8 target(data.width(), data.height()); + mapnik::scale_image_agg(target, + data, + SCALING_NEAR, + 1, + 1, + 0.0, 0.0, 1.0); // TODO: is 1.0 a valid default here, and do we even care in grid_renderer what the image looks like? pixmap_.set_rectangle(feature.id(), target, boost::math::iround(pos.x - cx), boost::math::iround(pos.y - cy)); diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index 319e1a28e..cc31772a0 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_group_symbolizer.cpp b/src/grid/process_group_symbolizer.cpp index 252b8c267..2188c0340 100644 --- a/src/grid/process_group_symbolizer.cpp +++ b/src/grid/process_group_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -58,7 +58,7 @@ namespace mapnik { * in the detector from the placement_finder. */ template -struct thunk_renderer : public util::static_visitor<> +struct thunk_renderer { using renderer_type = grid_renderer; using buffer_type = typename renderer_type::buffer_type; diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index 9505987fb..e46bf931d 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index a54738eae..2b5d03b36 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index a6225ca85..2d7fa49f9 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -146,7 +146,7 @@ struct raster_markers_rasterizer_dispatch : public raster_markers_dispatch::type; using PixMapType = typename std::tuple_element<2,RendererContext>::type; - raster_markers_rasterizer_dispatch(image_data_32 & src, + raster_markers_rasterizer_dispatch(image_data_rgba8 & src, agg::trans_affine const& marker_trans, markers_symbolizer const& sym, Detector & detector, diff --git a/src/grid/process_point_symbolizer.cpp b/src/grid/process_point_symbolizer.cpp index aa749a532..ded85034a 100644 --- a/src/grid/process_point_symbolizer.cpp +++ b/src/grid/process_point_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index affe399bf..4fdb12bf0 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_polygon_symbolizer.cpp b/src/grid/process_polygon_symbolizer.cpp index f06893e96..b659dc0cd 100644 --- a/src/grid/process_polygon_symbolizer.cpp +++ b/src/grid/process_polygon_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_raster_symbolizer.cpp b/src/grid/process_raster_symbolizer.cpp index b22947259..aff12a419 100644 --- a/src/grid/process_raster_symbolizer.cpp +++ b/src/grid/process_raster_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index ca10dc6e1..42f42dcd2 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 1c768c32d..921ce1d71 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/group/group_layout_manager.cpp b/src/group/group_layout_manager.cpp index 7799d5fda..7c6f7b8c6 100644 --- a/src/group/group_layout_manager.cpp +++ b/src/group/group_layout_manager.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ namespace mapnik { // This visitor will process offsets for the given layout -struct process_layout : public util::static_visitor<> +struct process_layout { // The vector containing the existing, centered item bounding boxes vector const& member_boxes_; diff --git a/src/group/group_rule.cpp b/src/group/group_rule.cpp index e3c5a6f5a..4ea7d9c34 100644 --- a/src/group/group_rule.cpp +++ b/src/group/group_rule.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -56,4 +56,3 @@ void group_rule::append(const mapnik::symbolizer &sym) } } - diff --git a/src/group/group_symbolizer_helper.cpp b/src/group/group_symbolizer_helper.cpp index faa5e4ae4..56fd8a730 100644 --- a/src/group/group_symbolizer_helper.cpp +++ b/src/group/group_symbolizer_helper.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,8 +29,8 @@ #include #include #include -#include -#include +#include +#include //agg #include "agg_conv_clip_polyline.h" diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index 3c71bc8b2..75e9884d2 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,8 +38,10 @@ #include "agg_scanline_u.h" #include "agg_renderer_scanline.h" #include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" + namespace mapnik { @@ -120,9 +122,33 @@ For example, if you generate some pattern with AGG (premultiplied) and would lik */ +namespace detail { -template -void composite(T1 & dst, T2 & src, composite_mode_e mode, +// non-mutable rendering_buffer implementation +template +struct rendering_buffer +{ + using image_data_type = T; + using pixel_type = typename image_data_type::pixel_type; + using row_data = agg::const_row_info; + + rendering_buffer(T const& data) + : data_(data) {} + + uint8_t const* buf() const { return data_.getBytes(); } + unsigned width() const { return data_.width();} + unsigned height() const { return data_.height();} + int stride() const { return data_.width() * sizeof(pixel_type);} + uint8_t const* row_ptr(int, int y, unsigned) {return row_ptr(y);} + uint8_t const* row_ptr(int y) const { return reinterpret_cast(data_.getRow(y)); } + row_data row (int y) const { return row_data(0, data_.width() - 1, row_ptr(y)); } + image_data_type const& data_; +}; + +} + +template <> +MAPNIK_DECL void composite(image_data_rgba8 & dst, image_data_rgba8 const& src, composite_mode_e mode, float opacity, int dx, int dy, @@ -130,28 +156,39 @@ void composite(T1 & dst, T2 & src, composite_mode_e mode, { using color = agg::rgba8; using order = agg::order_rgba; + using const_rendering_buffer = detail::rendering_buffer; using blender_type = agg::comp_op_adaptor_rgba_pre; using pixfmt_type = agg::pixfmt_custom_blend_rgba; using renderer_type = agg::renderer_base; agg::rendering_buffer dst_buffer(dst.getBytes(),dst.width(),dst.height(),dst.width() * 4); - agg::rendering_buffer src_buffer(src.getBytes(),src.width(),src.height(),src.width() * 4); - + const_rendering_buffer src_buffer(src); pixfmt_type pixf(dst_buffer); pixf.comp_op(static_cast(mode)); - - agg::pixfmt_rgba32 pixf_mask(src_buffer); + agg::pixfmt_alpha_blend_rgba pixf_mask(src_buffer); if (premultiply_src) pixf_mask.premultiply(); renderer_type ren(pixf); ren.blend_from(pixf_mask,0,dx,dy,unsigned(255*opacity)); } -template void composite(mapnik::image_data_32&, - mapnik::image_data_32&, - composite_mode_e, - float, - int, - int, - bool); +template <> +MAPNIK_DECL void composite(image_data_gray32f & dst, image_data_gray32f const& src, composite_mode_e mode, + float opacity, + int dx, + int dy, + bool premultiply_src) +{ + using const_rendering_buffer = detail::rendering_buffer; + using src_pixfmt_type = agg::pixfmt_alpha_blend_gray, const_rendering_buffer, 1, 0>; + using dst_pixfmt_type = agg::pixfmt_alpha_blend_gray, agg::rendering_buffer, 1, 0>; + using renderer_type = agg::renderer_base; + + agg::rendering_buffer dst_buffer(dst.getBytes(),dst.width(),dst.height(),dst.width()); + const_rendering_buffer src_buffer(src); + dst_pixfmt_type pixf(dst_buffer); + src_pixfmt_type pixf_mask(src_buffer); + renderer_type ren(pixf); + ren.copy_from(pixf_mask,0,dx,dy); +} } diff --git a/src/image_filter_types.cpp b/src/image_filter_types.cpp index 702c56672..0b28b07c0 100644 --- a/src/image_filter_types.cpp +++ b/src/image_filter_types.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/image_reader.cpp b/src/image_reader.cpp index 036a0510f..df876ff8f 100644 --- a/src/image_reader.cpp +++ b/src/image_reader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/image_scaling.cpp b/src/image_scaling.cpp index c122e89c3..7edf13e6e 100644 --- a/src/image_scaling.cpp +++ b/src/image_scaling.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,6 +23,7 @@ // mapnik #include #include +#include // does not handle alpha correctly //#include @@ -37,12 +38,14 @@ // agg #include "agg_image_accessors.h" #include "agg_pixfmt_rgba.h" +#include "agg_pixfmt_gray.h" #include "agg_color_rgba.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_renderer_scanline.h" #include "agg_rendering_buffer.h" #include "agg_scanline_u.h" #include "agg_span_allocator.h" +#include "agg_span_image_filter_gray.h" #include "agg_span_image_filter_rgba.h" #include "agg_span_interpolator_linear.h" #include "agg_trans_affine.h" @@ -94,37 +97,39 @@ boost::optional scaling_method_to_string(scaling_method_e scaling_m return mode; } -template -void scale_image_agg(Image & target, - Image const& source, - scaling_method_e scaling_method, - double image_ratio_x, - double image_ratio_y, - double x_off_f, - double y_off_f, + +template +void scale_image_agg(T & target, T const& source, scaling_method_e scaling_method, + double image_ratio_x, double image_ratio_y, double x_off_f, double y_off_f, double filter_factor) { // "the image filters should work namely in the premultiplied color space" // http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html // "Yes, you need to use premultiplied images only. Only in this case the simple weighted averaging works correctly in the image fitering." // http://permalink.gmane.org/gmane.comp.graphics.agg/3443 - using pixfmt_pre = agg::pixfmt_rgba32_pre; + using image_data_type = T; + using pixel_type = typename image_data_type::pixel_type; + using pixfmt_pre = typename detail::agg_scaling_traits::pixfmt_pre; + using color_type = typename detail::agg_scaling_traits::color_type; + using img_src_type = typename detail::agg_scaling_traits::img_src_type; + using interpolator_type = typename detail::agg_scaling_traits::interpolator_type; using renderer_base_pre = agg::renderer_base; + constexpr std::size_t pixel_size = sizeof(pixel_type); // define some stuff we'll use soon agg::rasterizer_scanline_aa<> ras; agg::scanline_u8 sl; - agg::span_allocator sa; - agg::image_filter_lut filter; + agg::span_allocator sa; // initialize source AGG buffer - agg::rendering_buffer rbuf_src((unsigned char*)source.getBytes(), source.width(), source.height(), source.width() * 4); + agg::rendering_buffer rbuf_src(const_cast(source.getBytes()), + source.width(), source.height(), source.width() * pixel_size); pixfmt_pre pixf_src(rbuf_src); - using img_src_type = agg::image_accessor_clone; + img_src_type img_src(pixf_src); // initialize destination AGG buffer (with transparency) - agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4); + agg::rendering_buffer rbuf_dst(target.getBytes(), target.width(), target.height(), target.width() * pixel_size); pixfmt_pre pixf_dst(rbuf_dst); renderer_base_pre rb_dst_pre(pixf_dst); @@ -133,9 +138,7 @@ void scale_image_agg(Image & target, img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y); // create a linear interpolator for our scaling matrix - using interpolator_type = agg::span_interpolator_linear<>; interpolator_type interpolator(img_mtx); - // draw an anticlockwise polygon to render our image into double scaled_width = target.width(); double scaled_height = target.height(); @@ -145,73 +148,33 @@ void scale_image_agg(Image & target, ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height); ras.line_to_d(x_off_f, y_off_f + scaled_height); - switch(scaling_method) + if (scaling_method == SCALING_NEAR) { - case SCALING_NEAR: - { - using span_gen_type = agg::span_image_filter_rgba_nn; + using span_gen_type = typename detail::agg_scaling_traits::span_image_filter; span_gen_type sg(img_src, interpolator); agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg); - return; } - case SCALING_BILINEAR: - filter.calculate(agg::image_filter_bilinear(), true); break; - case SCALING_BICUBIC: - filter.calculate(agg::image_filter_bicubic(), true); break; - case SCALING_SPLINE16: - filter.calculate(agg::image_filter_spline16(), true); break; - case SCALING_SPLINE36: - filter.calculate(agg::image_filter_spline36(), true); break; - case SCALING_HANNING: - filter.calculate(agg::image_filter_hanning(), true); break; - case SCALING_HAMMING: - filter.calculate(agg::image_filter_hamming(), true); break; - case SCALING_HERMITE: - filter.calculate(agg::image_filter_hermite(), true); break; - case SCALING_KAISER: - filter.calculate(agg::image_filter_kaiser(), true); break; - case SCALING_QUADRIC: - filter.calculate(agg::image_filter_quadric(), true); break; - case SCALING_CATROM: - filter.calculate(agg::image_filter_catrom(), true); break; - case SCALING_GAUSSIAN: - filter.calculate(agg::image_filter_gaussian(), true); break; - case SCALING_BESSEL: - filter.calculate(agg::image_filter_bessel(), true); break; - case SCALING_MITCHELL: - filter.calculate(agg::image_filter_mitchell(), true); break; - case SCALING_SINC: - filter.calculate(agg::image_filter_sinc(filter_factor), true); break; - case SCALING_LANCZOS: - filter.calculate(agg::image_filter_lanczos(filter_factor), true); break; - case SCALING_BLACKMAN: - filter.calculate(agg::image_filter_blackman(filter_factor), true); break; + else + { + using span_gen_type = typename detail::agg_scaling_traits::span_image_resample_affine; + agg::image_filter_lut filter; + detail::set_scaling_method(filter, scaling_method, filter_factor); + span_gen_type sg(img_src, interpolator, filter); + agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg); } - // details on various resampling considerations - // http://old.nabble.com/Re%3A-Newbie---texture-p5057255.html - // high quality resampler - using span_gen_type = agg::span_image_resample_rgba_affine; - - // faster, lower quality - //using span_gen_type = agg::span_image_filter_rgba; - - // local, modified agg::span_image_resample_rgba_affine - // dating back to when we were not handling alpha correctly - // and this file helped work around symptoms - // https://github.com/mapnik/mapnik/issues/1489 - //using span_gen_type = mapnik::span_image_resample_rgba_affine; - span_gen_type sg(img_src, interpolator, filter); - agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg); } -template void scale_image_agg(image_data_32& target, - const image_data_32& source, - scaling_method_e scaling_method, - double image_ratio_x, - double image_ratio_y, - double x_off_f, - double y_off_f, - double filter_factor); +template MAPNIK_DECL void scale_image_agg(image_data_rgba8 &, image_data_rgba8 const&, scaling_method_e, + double, double , double, double , double); + +template MAPNIK_DECL void scale_image_agg(image_data_gray8 &, image_data_gray8 const&, scaling_method_e, + double, double , double, double , double); + +template MAPNIK_DECL void scale_image_agg(image_data_gray16 &, image_data_gray16 const&, scaling_method_e, + double, double , double, double , double); + +template MAPNIK_DECL void scale_image_agg(image_data_gray32f &, image_data_gray32f const&, scaling_method_e, + double, double , double, double , double); } diff --git a/src/image_util.cpp b/src/image_util.cpp index 3de9b4599..de81f9a90 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -46,7 +46,6 @@ extern "C" #include #include -#include #include #include #include @@ -255,6 +254,127 @@ void handle_png_options(std::string const& type, } #endif +#if defined(HAVE_TIFF) +void handle_tiff_options(std::string const& type, + tiff_config & config) +{ + if (type == "tiff") + { + return; + } + if (type.length() > 4) + { + boost::char_separator sep(":"); + boost::tokenizer< boost::char_separator > tokens(type, sep); + for (auto const& t : tokens) + { + if (t == "tiff") + { + continue; + } + else if (boost::algorithm::starts_with(t, "compression=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (val == "deflate") + { + config.compression = COMPRESSION_DEFLATE; + } + else if (val == "adobedeflate") + { + config.compression = COMPRESSION_ADOBE_DEFLATE; + } + else if (val == "lzw") + { + config.compression = COMPRESSION_LZW; + } + else if (val == "none") + { + config.compression = COMPRESSION_NONE; + } + else + { + throw ImageWriterException("invalid tiff compression: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "method=")) + { + std::string val = t.substr(7); + if (!val.empty()) + { + if (val == "scanline") + { + config.method = TIFF_WRITE_SCANLINE; + } + else if (val == "strip" || val == "stripped") + { + config.method = TIFF_WRITE_STRIPPED; + } + else if (val == "tiled") + { + config.method = TIFF_WRITE_TILED; + } + else + { + throw ImageWriterException("invalid tiff method: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "zlevel=")) + { + std::string val = t.substr(7); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.zlevel) || config.zlevel < 0 || config.zlevel > 9) + { + throw ImageWriterException("invalid tiff zlevel: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "tile_height=")) + { + std::string val = t.substr(12); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.tile_height) || config.tile_height < 0 ) + { + throw ImageWriterException("invalid tiff tile_height: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "tile_width=")) + { + std::string val = t.substr(11); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.tile_width) || config.tile_width < 0 ) + { + throw ImageWriterException("invalid tiff tile_width: '" + val + "'"); + } + } + } + else if (boost::algorithm::starts_with(t, "rows_per_strip=")) + { + std::string val = t.substr(15); + if (!val.empty()) + { + if (!mapnik::util::string2int(val,config.rows_per_strip) || config.rows_per_strip < 0 ) + { + throw ImageWriterException("invalid tiff rows_per_strip: '" + val + "'"); + } + } + } + else + { + throw ImageWriterException("unhandled tiff option: " + t); + } + } + } +} +#endif + #if defined(HAVE_WEBP) void handle_webp_options(std::string const& type, WebPConfig & config, @@ -621,7 +741,9 @@ void save_to_stream(T const& image, else if (boost::algorithm::starts_with(t, "tif")) { #if defined(HAVE_TIFF) - save_as_tiff(stream, image); + tiff_config config; + handle_tiff_options(t, config); + save_as_tiff(stream, image, config); #else throw ImageWriterException("tiff output is not enabled in your build of Mapnik"); #endif @@ -769,83 +891,50 @@ void save_to_cairo_file(mapnik::Map const& map, #endif -template void save_to_file(image_data_32 const&, +template void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&); -template void save_to_file(image_data_32 const&, +template void save_to_file(image_data_rgba8 const&, std::string const&, std::string const&, rgba_palette const& palette); -template void save_to_file(image_data_32 const&, +template void save_to_file(image_data_rgba8 const&, std::string const&); -template void save_to_file(image_data_32 const&, +template void save_to_file(image_data_rgba8 const&, std::string const&, rgba_palette const& palette); -template std::string save_to_string(image_data_32 const&, +template std::string save_to_string(image_data_rgba8 const&, std::string const&); -template std::string save_to_string(image_data_32 const&, +template std::string save_to_string(image_data_rgba8 const&, std::string const&, rgba_palette const& palette); -template void save_to_file > (image_view const&, +template void save_to_file > (image_view const&, std::string const&, std::string const&); -template void save_to_file > (image_view const&, +template void save_to_file > (image_view const&, std::string const&, std::string const&, rgba_palette const& palette); -template void save_to_file > (image_view const&, +template void save_to_file > (image_view const&, std::string const&); -template void save_to_file > (image_view const&, +template void save_to_file > (image_view const&, std::string const&, rgba_palette const& palette); -template std::string save_to_string > (image_view const&, +template std::string save_to_string > (image_view const&, std::string const&); -template std::string save_to_string > (image_view const&, +template std::string save_to_string > (image_view const&, std::string const&, rgba_palette const& palette); -void save_to_file(image_32 const& image,std::string const& file) -{ - save_to_file(image.data(), file); -} - -void save_to_file (image_32 const& image, - std::string const& file, - std::string const& type) -{ - save_to_file(image.data(), file, type); -} - -void save_to_file (image_32 const& image, - std::string const& file, - std::string const& type, - rgba_palette const& palette) -{ - save_to_file(image.data(), file, type, palette); -} - -std::string save_to_string(image_32 const& image, - std::string const& type) -{ - return save_to_string(image.data(), type); -} - -std::string save_to_string(image_32 const& image, - std::string const& type, - rgba_palette const& palette) -{ - return save_to_string(image.data(), type, palette); -} - } diff --git a/src/jpeg_reader.cpp b/src/jpeg_reader.cpp index af2d40083..48ac83e19 100644 --- a/src/jpeg_reader.cpp +++ b/src/jpeg_reader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -81,11 +81,13 @@ public: explicit jpeg_reader(std::string const& file_name); explicit jpeg_reader(char const* data, size_t size); ~jpeg_reader(); - unsigned width() const; - unsigned height() const; - inline bool has_alpha() const { return false; } - inline bool premultiplied_alpha() const { return true; } - void read(unsigned x,unsigned y,image_data_32& image); + unsigned width() const final; + unsigned height() const final; + boost::optional > bounding_box() const final; + inline bool has_alpha() const final { return false; } + inline bool premultiplied_alpha() const final { return true; } + void read(unsigned x,unsigned y,image_data_rgba8& image) final; + image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) final; private: void init(); static void on_error(j_common_ptr cinfo); @@ -258,7 +260,13 @@ unsigned jpeg_reader::height() const } template -void jpeg_reader::read(unsigned x0, unsigned y0, image_data_32& image) +boost::optional > jpeg_reader::bounding_box() const +{ + return boost::optional >(); +} + +template +void jpeg_reader::read(unsigned x0, unsigned y0, image_data_rgba8& image) { stream_.clear(); stream_.seekg(0, std::ios_base::beg); @@ -312,4 +320,12 @@ void jpeg_reader::read(unsigned x0, unsigned y0, image_data_32& image) jpeg_finish_decompress(&cinfo); } +template +image_data_any jpeg_reader::read(unsigned x, unsigned y, unsigned width, unsigned height) +{ + image_data_rgba8 data(width,height); + read(x, y, data); + return image_data_any(std::move(data)); +} + } diff --git a/src/json/mapnik_json_generator_grammar.cpp b/src/json/mapnik_json_generator_grammar.cpp index bc7bc5f37..0f45df122 100644 --- a/src/json/mapnik_json_generator_grammar.cpp +++ b/src/json/mapnik_json_generator_grammar.cpp @@ -24,9 +24,12 @@ #include #include #include +#include #include using sink_type = std::back_insert_iterator; -template struct mapnik::json::feature_generator_grammar; + +template struct mapnik::json::properties_generator_grammar; +template struct mapnik::json::feature_generator_grammar; template struct mapnik::json::geometry_generator_grammar; template struct mapnik::json::multi_geometry_generator_grammar; diff --git a/src/json/mapnik_json_geometry_grammar.cpp b/src/json/mapnik_json_geometry_grammar.cpp index dff5bc47b..7df858bb2 100644 --- a/src/json/mapnik_json_geometry_grammar.cpp +++ b/src/json/mapnik_json_geometry_grammar.cpp @@ -24,4 +24,4 @@ #include using iterator_type = std::string::const_iterator; -template struct mapnik::json::geometry_grammar; \ No newline at end of file +template struct mapnik::json::geometry_grammar; diff --git a/src/layer.cpp b/src/layer.cpp index dd66f2621..a5180a7d8 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/libxml2_loader.cpp b/src/libxml2_loader.cpp index 5c03f8762..70ca728e8 100644 --- a/src/libxml2_loader.cpp +++ b/src/libxml2_loader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include // libxml @@ -43,7 +43,7 @@ namespace mapnik { -class libxml2_loader : mapnik::noncopyable +class libxml2_loader : util::noncopyable { public: libxml2_loader(const char *encoding = nullptr, int options = DEFAULT_OPTIONS, const char *url = nullptr) : diff --git a/src/load_map.cpp b/src/load_map.cpp index 74f7b3824..c2d7fa4a1 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -50,7 +50,7 @@ #include #include #include -#include +#include #include #include #include @@ -84,7 +84,7 @@ constexpr unsigned name2int(const char *str, int off = 0) return !str[off] ? 5381 : (name2int(str, off+1)*33) ^ str[off]; } -class map_parser : mapnik::noncopyable +class map_parser : util::noncopyable { public: map_parser(Map & map, bool strict, std::string const& filename = "") : @@ -119,6 +119,7 @@ private: void parse_markers_symbolizer(rule & rule, xml_node const& node); void parse_group_symbolizer(rule &rule, xml_node const& node); void parse_debug_symbolizer(rule & rule, xml_node const& node); + void parse_dot_symbolizer(rule & rule, xml_node const& node); void parse_group_rule(group_symbolizer_properties &prop, xml_node const& node); void parse_simple_layout(group_symbolizer_properties &prop, xml_node const& node); void parse_pair_layout(group_symbolizer_properties &prop, xml_node const& node); @@ -377,25 +378,15 @@ void map_parser::parse_map_include(Map & map, xml_node const& node) { if (p.is("Parameter")) { - bool is_string = true; - boost::optional type = p.get_opt_attr("type"); - if (type) - { - if (*type == "int") - { - is_string = false; - params[p.get_attr("name")] = p.get_value(); - } - else if (*type == "float") - { - is_string = false; - params[p.get_attr("name")] = p.get_value(); - } - } - if (is_string) - { - params[p.get_attr("name")] = p.get_text(); - } + std::string val = p.get_text(); + std::string key = p.get_attr("name"); + mapnik::value_bool b; + mapnik::value_integer i; + mapnik::value_double d; + if (mapnik::util::string2bool(val,b)) params[key] = b; + else if (mapnik::util::string2int(val,i)) params[key] = i; + else if (mapnik::util::string2double(val,d)) params[key] = d; + else params[key] = val; } } } @@ -863,6 +854,11 @@ void map_parser::parse_symbolizers(rule & rule, xml_node const & node) parse_debug_symbolizer(rule, sym_node); sym_node.set_processed(true); break; + case name2int("DotSymbolizer"): + parse_dot_symbolizer(rule, sym_node); + sym_node.set_processed(true); + break; + default: break; } @@ -918,6 +914,25 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & node) } } +void map_parser::parse_dot_symbolizer(rule & rule, xml_node const & node) +{ + try + { + dot_symbolizer sym; + set_symbolizer_property(sym, keys::fill, node); + set_symbolizer_property(sym, keys::opacity, node); + set_symbolizer_property(sym, keys::width, node); + set_symbolizer_property(sym, keys::height, node); + set_symbolizer_property(sym, keys::comp_op, node); + rule.append(std::move(sym)); + } + catch (config_error const& ex) + { + ex.append_context(node); + throw; + } +} + void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node) { try diff --git a/src/map.cpp b/src/map.cpp index 764f82dd3..c8e1da191 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -340,6 +340,9 @@ void Map::remove_all() { layers_.clear(); styles_.clear(); + fontsets_.clear(); + font_file_mapping_.clear(); + font_memory_cache_.clear(); } layer const& Map::get_layer(size_t index) const diff --git a/src/mapped_memory_cache.cpp b/src/mapped_memory_cache.cpp index 36b2aa8d0..f296c2253 100644 --- a/src/mapped_memory_cache.cpp +++ b/src/mapped_memory_cache.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 024be9c27..c7d1b005f 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -62,7 +62,7 @@ marker_cache::marker_cache() "" "" ""); - boost::optional bitmap_data = boost::optional(std::make_shared(4,4)); + boost::optional bitmap_data = boost::optional(std::make_shared(4,4)); (*bitmap_data)->set(0xff000000); marker_ptr mark = std::make_shared(bitmap_data); marker_cache_.emplace("image://square",mark); @@ -210,7 +210,7 @@ boost::optional marker_cache::find(std::string const& uri, unsigned width = reader->width(); unsigned height = reader->height(); BOOST_ASSERT(width > 0 && height > 0); - mapnik::image_ptr image(std::make_shared(width,height)); + mapnik::image_ptr image(std::make_shared(width,height)); reader->read(0,0,*image); if (!reader->premultiplied_alpha()) { diff --git a/src/marker_helpers.cpp b/src/marker_helpers.cpp index c801af790..bdc70fab0 100644 --- a/src/marker_helpers.cpp +++ b/src/marker_helpers.cpp @@ -79,14 +79,18 @@ bool push_explicit_style(svg_attribute_type const& src, bool success = false; for(unsigned i = 0; i < src.size(); ++i) { - success = true; dst.push_back(src[i]); mapnik::svg::path_attributes & attr = dst.last(); - if (attr.stroke_flag) + if (!attr.visibility_flag) + continue; + success = true; + + if (!attr.stroke_none) { if (stroke_width) { attr.stroke_width = *stroke_width; + attr.stroke_flag = true; } if (stroke_color) { @@ -95,13 +99,15 @@ bool push_explicit_style(svg_attribute_type const& src, s_color.green()/255.0, s_color.blue()/255.0, s_color.alpha()/255.0); + attr.stroke_flag = true; } if (stroke_opacity) { attr.stroke_opacity = *stroke_opacity; + attr.stroke_flag = true; } } - if (attr.fill_flag) + if (!attr.fill_none) { if (fill_color) { @@ -110,10 +116,12 @@ bool push_explicit_style(svg_attribute_type const& src, f_color.green()/255.0, f_color.blue()/255.0, f_color.alpha()/255.0); + attr.fill_flag = true; } if (fill_opacity) { attr.fill_opacity = *fill_opacity; + attr.fill_flag = true; } } } diff --git a/src/memory.cpp b/src/memory.cpp index bb45b70b4..6f4351de3 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/memory_datasource.cpp b/src/memory_datasource.cpp index 7ffe12b74..6bcc7aea0 100644 --- a/src/memory_datasource.cpp +++ b/src/memory_datasource.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/miniz_png.cpp b/src/miniz_png.cpp index 5426fb63a..d968d1dae 100644 --- a/src/miniz_png.cpp +++ b/src/miniz_png.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -361,11 +361,11 @@ const mz_uint8 PNGWriter::IEND_tpl[] = { 'I', 'E', 'N', 'D' // "IEND" }; -template void PNGWriter::writeIDAT(image_data_8 const& image); -template void PNGWriter::writeIDAT >(image_view const& image); -template void PNGWriter::writeIDAT(image_data_32 const& image); -template void PNGWriter::writeIDAT >(image_view const& image); -template void PNGWriter::writeIDATStripAlpha(image_data_32 const& image); -template void PNGWriter::writeIDATStripAlpha >(image_view const& image); +template void PNGWriter::writeIDAT(image_data_gray8 const& image); +template void PNGWriter::writeIDAT >(image_view const& image); +template void PNGWriter::writeIDAT(image_data_rgba8 const& image); +template void PNGWriter::writeIDAT >(image_view const& image); +template void PNGWriter::writeIDATStripAlpha(image_data_rgba8 const& image); +template void PNGWriter::writeIDATStripAlpha >(image_view const& image); }} diff --git a/src/palette.cpp b/src/palette.cpp index 282386575..803e0efe2 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/params.cpp b/src/params.cpp index d45f419bd..39b36fdbd 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/parse_path.cpp b/src/parse_path.cpp index 643d48ea1..0064f3ab3 100644 --- a/src/parse_path.cpp +++ b/src/parse_path.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -53,7 +53,7 @@ path_expression_ptr parse_path(std::string const& str) namespace path_processor_detail { - struct path_visitor_ : util::static_visitor + struct path_visitor_ { path_visitor_ (std::string & filename, feature_impl const& f) : filename_(filename), @@ -75,7 +75,7 @@ namespace path_processor_detail feature_impl const& feature_; }; - struct to_string_ : util::static_visitor + struct to_string_ { to_string_ (std::string & str) : str_(str) {} @@ -95,7 +95,7 @@ namespace path_processor_detail std::string & str_; }; - struct collect_ : util::static_visitor + struct collect_ { collect_ (std::set & cont) : cont_(cont) {} diff --git a/src/parse_transform.cpp b/src/parse_transform.cpp index 9ea153773..c9403014c 100644 --- a/src/parse_transform.cpp +++ b/src/parse_transform.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/plugin.cpp b/src/plugin.cpp index fe6bb9d09..3e66d1aaf 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,8 +30,12 @@ #define dlsym GetProcAddress #define dlclose FreeLibrary #define dlerror GetLastError + #define MAPNIK_SUPPORTS_DLOPEN #else - #include + #ifdef MAPNIK_HAS_DLCFN + #include + #define MAPNIK_SUPPORTS_DLOPEN + #endif #define handle void * #endif @@ -52,21 +56,32 @@ PluginInfo::PluginInfo(std::string const& filename, { #ifdef _WINDOWS if (module_) module_->dl = LoadLibraryA(filename.c_str()); -#else - if (module_) module_->dl = dlopen(filename.c_str(),RTLD_LAZY); -#endif if (module_ && module_->dl) { name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); if (name) name_ = name(); } +#else + #ifdef MAPNIK_HAS_DLCFN + if (module_) module_->dl = dlopen(filename.c_str(),RTLD_LAZY); + if (module_ && module_->dl) + { + name_func name = reinterpret_cast(dlsym(module_->dl, library_name.c_str())); + if (name) name_ = name(); + } + #else + throw std::runtime_error("no support for loading dynamic objects (Mapnik not compiled with -DMAPNIK_HAS_DLCFN)"); + #endif +#endif } PluginInfo::~PluginInfo() { if (module_) { +#ifdef MAPNIK_SUPPORTS_DLOPEN if (module_->dl) dlclose(module_->dl),module_->dl=0; +#endif delete module_; } } @@ -74,7 +89,11 @@ PluginInfo::~PluginInfo() void * PluginInfo::get_symbol(std::string const& sym_name) const { +#ifdef MAPNIK_SUPPORTS_DLOPEN return static_cast(dlsym(module_->dl, sym_name.c_str())); +#else + return NULL; +#endif } std::string const& PluginInfo::name() const @@ -84,7 +103,9 @@ std::string const& PluginInfo::name() const bool PluginInfo::valid() const { +#ifdef MAPNIK_SUPPORTS_DLOPEN if (module_ && module_->dl && !name_.empty()) return true; +#endif return false; } diff --git a/src/png_reader.cpp b/src/png_reader.cpp index 80a8ec957..318a67b47 100644 --- a/src/png_reader.cpp +++ b/src/png_reader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -76,11 +76,13 @@ public: explicit png_reader(std::string const& file_name); png_reader(char const* data, std::size_t size); ~png_reader(); - unsigned width() const; - unsigned height() const; - inline bool has_alpha() const { return has_alpha_; } - bool premultiplied_alpha() const { return false; } //http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html - void read(unsigned x,unsigned y,image_data_32& image); + unsigned width() const final; + unsigned height() const final; + boost::optional > bounding_box() const final; + inline bool has_alpha() const final { return has_alpha_; } + bool premultiplied_alpha() const final { return false; } //http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html + void read(unsigned x,unsigned y,image_data_rgba8& image) final; + image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) final; private: void init(); static void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length); @@ -219,7 +221,13 @@ unsigned png_reader::height() const } template -void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) +boost::optional > png_reader::bounding_box() const +{ + return boost::optional >(); +} + +template +void png_reader::read(unsigned x0, unsigned y0,image_data_rgba8& image) { stream_.clear(); stream_.seekg(0, std::ios_base::beg); @@ -300,4 +308,14 @@ void png_reader::read(unsigned x0, unsigned y0,image_data_32& image) } png_read_end(png_ptr,0); } + + +template +image_data_any png_reader::read(unsigned x, unsigned y, unsigned width, unsigned height) +{ + image_data_rgba8 data(width,height); + read(x, y, data); + return image_data_any(std::move(data)); +} + } diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index f3cd2e852..95776fc12 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/projection.cpp b/src/projection.cpp index 06dc5e4c8..a660884ae 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/rapidxml_loader.cpp b/src/rapidxml_loader.cpp index ea2479378..841fa9fd2 100644 --- a/src/rapidxml_loader.cpp +++ b/src/rapidxml_loader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,7 +32,7 @@ #include #include #include -#include +#include // stl #include @@ -42,7 +42,7 @@ namespace rapidxml = boost::property_tree::detail::rapidxml; namespace mapnik { -class rapidxml_loader : mapnik::noncopyable +class rapidxml_loader : util::noncopyable { public: rapidxml_loader() : diff --git a/src/raster_colorizer.cpp b/src/raster_colorizer.cpp index 6bc0c052b..9bed5500a 100644 --- a/src/raster_colorizer.cpp +++ b/src/raster_colorizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -122,23 +122,27 @@ bool raster_colorizer::add_stop(colorizer_stop const& stop) return true; } -void raster_colorizer::colorize(raster_ptr const& raster, feature_impl const& f) const +template +void raster_colorizer::colorize(image_data_rgba8 & out, T const& in, + boost::optional const& nodata, + feature_impl const& f) const { - unsigned *imageData = raster->data_.getData(); - - int len = raster->data_.width() * raster->data_.height(); - boost::optional const& nodata = raster->nodata(); + using image_data_type = T; + using pixel_type = typename image_data_type::pixel_type; + // TODO: assuming in/out have the same width/height for now + std::uint32_t * out_data = out.getData(); + pixel_type const* in_data = in.getData(); + int len = out.width() * out.height(); for (int i=0; i (&imageData[i]); + pixel_type value = in_data[i]; if (nodata && (std::fabs(value - *nodata) < epsilon_)) { - imageData[i] = 0; + out_data[i] = 0; // rgba(0,0,0,0) } else { - imageData[i] = get_color(value); + out_data[i] = get_color(value); } } } @@ -153,7 +157,7 @@ unsigned raster_colorizer::get_color(float value) const int stopCount = stops_.size(); //use default color if no stops - if(stopCount == 0) + if (stopCount == 0) { return default_color_.rgba(); } @@ -282,5 +286,14 @@ unsigned raster_colorizer::get_color(float value) const } -} +template void raster_colorizer::colorize(image_data_rgba8 & out, image_data_gray8 const& in, + boost::optionalconst& nodata, + feature_impl const& f) const; +template void raster_colorizer::colorize(image_data_rgba8 & out, image_data_gray16 const& in, + boost::optionalconst& nodata, + feature_impl const& f) const; +template void raster_colorizer::colorize(image_data_rgba8 & out, image_data_gray32f const& in, + boost::optionalconst& nodata, + feature_impl const& f) const; +} diff --git a/src/renderer_common.cpp b/src/renderer_common.cpp index 17111bb73..ecba13655 100644 --- a/src/renderer_common.cpp +++ b/src/renderer_common.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 0fae35166..669de0d09 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,7 +39,7 @@ vector_marker_render_thunk::vector_marker_render_thunk(svg_path_ptr const& src, comp_op_(comp_op), snap_to_pixels_(snap_to_pixels) {} -raster_marker_render_thunk::raster_marker_render_thunk(image_data_32 & src, +raster_marker_render_thunk::raster_marker_render_thunk(image_data_rgba8 & src, agg::trans_affine const& marker_trans, double opacity, composite_mode_e comp_op, @@ -97,7 +97,7 @@ private: template struct raster_marker_thunk_dispatch : public raster_markers_dispatch { - raster_marker_thunk_dispatch(image_data_32 & src, + raster_marker_thunk_dispatch(image_data_rgba8 & src, agg::trans_affine const& marker_trans, symbolizer_base const& sym, Detector & detector, diff --git a/src/renderer_common/render_pattern.cpp b/src/renderer_common/render_pattern.cpp index f149c134a..bb404cdb0 100644 --- a/src/renderer_common/render_pattern.cpp +++ b/src/renderer_common/render_pattern.cpp @@ -35,7 +35,7 @@ namespace mapnik { -std::shared_ptr render_pattern(rasterizer & ras, +std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr, double opacity) @@ -51,7 +51,7 @@ std::shared_ptr render_pattern(rasterizer & ras, mtx.translate(0.5 * bbox.width(), 0.5 * bbox.height()); mtx = tr * mtx; - std::shared_ptr image = std::make_shared(bbox.width(), bbox.height()); + std::shared_ptr image = std::make_shared(bbox.width(), bbox.height()); agg::rendering_buffer buf(image->getBytes(), image->width(), image->height(), image->width() * 4); pixfmt pixf(buf); renderer_base renb(pixf); diff --git a/src/request.cpp b/src/request.cpp index b99f533de..46fc220cc 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/rule.cpp b/src/rule.cpp index 3dfab5535..55a1ba256 100644 --- a/src/rule.cpp +++ b/src/rule.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/save_map.cpp b/src/save_map.cpp index 27eb75518..31fe20718 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -135,7 +135,7 @@ void serialize_group_symbolizer_properties(ptree & sym_node, bool explicit_defaults); template -class serialize_symbolizer_property : public util::static_visitor<> +class serialize_symbolizer_property { public: serialize_symbolizer_property(Meta const& meta, @@ -225,7 +225,7 @@ private: bool explicit_defaults_; }; -class serialize_symbolizer : public util::static_visitor<> +class serialize_symbolizer { public: serialize_symbolizer( ptree & r , bool explicit_defaults) @@ -255,7 +255,7 @@ private: bool explicit_defaults_; }; -class serialize_group_layout : public util::static_visitor<> +class serialize_group_layout { public: serialize_group_layout(ptree & parent_node, bool explicit_defaults) @@ -488,36 +488,6 @@ void serialize_datasource( ptree & layer_node, datasource_ptr datasource) } } -class serialize_type : public util::static_visitor<> -{ -public: - serialize_type( boost::property_tree::ptree & node): - node_(node) {} - - void operator () ( mapnik::value_integer ) const - { - node_.put(".type", "int" ); - } - - void operator () ( mapnik::value_double ) const - { - node_.put(".type", "float" ); - } - - void operator () ( std::string const& ) const - { - node_.put(".type", "string" ); - } - - void operator () ( mapnik::value_null ) const - { - node_.put(".type", "string" ); - } - -private: - boost::property_tree::ptree & node_; -}; - void serialize_parameters( ptree & map_node, mapnik::parameters const& params) { if (params.size()) { @@ -531,7 +501,6 @@ void serialize_parameters( ptree & map_node, mapnik::parameters const& params) boost::property_tree::ptree()))->second; param_node.put(".name", p.first ); param_node.put_value( p.second ); - util::apply_visitor(serialize_type(param_node),p.second); } } } diff --git a/src/scale_denominator.cpp b/src/scale_denominator.cpp index 35e8f94d7..f7a622088 100644 --- a/src/scale_denominator.cpp +++ b/src/scale_denominator.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/output/process_line_symbolizer.cpp b/src/svg/output/process_line_symbolizer.cpp index e99bfbe59..4640a370d 100644 --- a/src/svg/output/process_line_symbolizer.cpp +++ b/src/svg/output/process_line_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -54,4 +54,3 @@ template void svg_renderer >::process(line_symbolize } #endif - diff --git a/src/svg/output/process_polygon_symbolizer.cpp b/src/svg/output/process_polygon_symbolizer.cpp index 77d8d5e05..18bfaae1a 100644 --- a/src/svg/output/process_polygon_symbolizer.cpp +++ b/src/svg/output/process_polygon_symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/output/process_symbolizers.cpp b/src/svg/output/process_symbolizers.cpp index 765ec3fdf..8b57c4fa5 100644 --- a/src/svg/output/process_symbolizers.cpp +++ b/src/svg/output/process_symbolizers.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,7 +37,7 @@ namespace mapnik { -struct symbol_type_dispatch : public util::static_visitor +struct symbol_type_dispatch { template bool operator()(Symbolizer const&) const diff --git a/src/svg/output/svg_generator.cpp b/src/svg/output/svg_generator.cpp index 422a9368a..a02c84f69 100644 --- a/src/svg/output/svg_generator.cpp +++ b/src/svg/output/svg_generator.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -116,4 +116,3 @@ namespace mapnik { namespace svg { }} #endif - diff --git a/src/svg/output/svg_output_attributes.cpp b/src/svg/output/svg_output_attributes.cpp index 972fbb766..fb0b6a783 100644 --- a/src/svg/output/svg_output_attributes.cpp +++ b/src/svg/output/svg_output_attributes.cpp @@ -1,9 +1,8 @@ - /***************************************************************************** * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -292,4 +291,3 @@ namespace mapnik { namespace svg { }} #endif - diff --git a/src/svg/output/svg_output_grammars.cpp b/src/svg/output/svg_output_grammars.cpp index 30ed5f90d..cc0d51439 100644 --- a/src/svg/output/svg_output_grammars.cpp +++ b/src/svg/output/svg_output_grammars.cpp @@ -28,4 +28,4 @@ template struct mapnik::svg::svg_path_attributes_grammar >; template struct mapnik::svg::svg_path_dash_array_grammar >; template struct mapnik::svg::svg_rect_attributes_grammar >; -template struct mapnik::svg::svg_root_attributes_grammar >; \ No newline at end of file +template struct mapnik::svg::svg_root_attributes_grammar >; diff --git a/src/svg/output/svg_renderer.cpp b/src/svg/output/svg_renderer.cpp index aeeace05f..4525caead 100644 --- a/src/svg/output/svg_renderer.cpp +++ b/src/svg/output/svg_renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/svg_parser.cpp b/src/svg/svg_parser.cpp index b1ec83bfe..a6fa1ee5b 100644 --- a/src/svg/svg_parser.cpp +++ b/src/svg/svg_parser.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/svg_path_parser.cpp b/src/svg/svg_path_parser.cpp index 86684e610..d69473425 100644 --- a/src/svg/svg_path_parser.cpp +++ b/src/svg/svg_path_parser.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/svg_points_parser.cpp b/src/svg/svg_points_parser.cpp index af97c4109..b02dafac7 100644 --- a/src/svg/svg_points_parser.cpp +++ b/src/svg/svg_points_parser.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/svg/svg_transform_parser.cpp b/src/svg/svg_transform_parser.cpp index eee7a6464..ed6e7f6bb 100644 --- a/src/svg/svg_transform_parser.cpp +++ b/src/svg/svg_transform_parser.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/symbolizer.cpp b/src/symbolizer.cpp index 7107fe706..bce44a161 100644 --- a/src/symbolizer.cpp +++ b/src/symbolizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/symbolizer_enumerations.cpp b/src/symbolizer_enumerations.cpp index 6f290f1f0..bd79562b4 100644 --- a/src/symbolizer_enumerations.cpp +++ b/src/symbolizer_enumerations.cpp @@ -160,6 +160,7 @@ static const char * text_transform_strings[] = { "uppercase", "lowercase", "capitalize", + "reverse", "" }; diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index bc81756ec..b22fa2ed0 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/face.cpp b/src/text/face.cpp index dbe088fe6..3e14aa62b 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/base.cpp b/src/text/formatting/base.cpp index b1e9c2ab9..a1e16db38 100644 --- a/src/text/formatting/base.cpp +++ b/src/text/formatting/base.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/format.cpp b/src/text/formatting/format.cpp index 524abcf72..e8c14e10b 100644 --- a/src/text/formatting/format.cpp +++ b/src/text/formatting/format.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/layout.cpp b/src/text/formatting/layout.cpp index d0372ef5e..a5b59a85a 100644 --- a/src/text/formatting/layout.cpp +++ b/src/text/formatting/layout.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/list.cpp b/src/text/formatting/list.cpp index 1d6f7b9ed..c8f444fe7 100644 --- a/src/text/formatting/list.cpp +++ b/src/text/formatting/list.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/registry.cpp b/src/text/formatting/registry.cpp index 4d28dd09a..bf49c5653 100644 --- a/src/text/formatting/registry.cpp +++ b/src/text/formatting/registry.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/formatting/text.cpp b/src/text/formatting/text.cpp index 51c7086d1..8247bd26a 100644 --- a/src/text/formatting/text.cpp +++ b/src/text/formatting/text.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ #include #include #include +#include // boost #include @@ -53,21 +54,28 @@ node_ptr text_node::from_xml(xml_node const& xml, fontset_map const& fontsets) void text_node::apply(evaluated_format_properties_ptr const& p, feature_impl const& feature, attributes const& vars, text_layout &output) const { mapnik::value_unicode_string text_str = util::apply_visitor(evaluate(feature,vars), *text_).to_unicode(); - if (p->text_transform == UPPERCASE) + switch (p->text_transform) { - text_str = text_str.toUpper(); - } - else if (p->text_transform == LOWERCASE) - { - text_str = text_str.toLower(); - } + case UPPERCASE: + text_str.toUpper(); + break; + case LOWERCASE: + text_str.toLower(); + break; + case REVERSE: + text_str.reverse(); + break; + case CAPITALIZE: #if !UCONFIG_NO_BREAK_ITERATION - else if (p->text_transform == CAPITALIZE) - { // note: requires BreakIterator support in ICU which is optional - text_str = text_str.toTitle(nullptr); - } + text_str.toTitle(nullptr); +#else + MAPNIK_LOG_DEBUG(text_node) << "text capitalize (toTitle) disabled because ICU was built without UCONFIG_NO_BREAK_ITERATION"; #endif + break; + default: + break; + } if (text_str.length() > 0) { output.add_text(text_str, p); } diff --git a/src/text/glyph_positions.cpp b/src/text/glyph_positions.cpp index 1f42ec69e..4717b99a7 100644 --- a/src/text/glyph_positions.cpp +++ b/src/text/glyph_positions.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/itemizer.cpp b/src/text/itemizer.cpp index 876c192cc..5058bfde4 100644 --- a/src/text/itemizer.cpp +++ b/src/text/itemizer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index f63d6db1e..df67dc09e 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,7 +29,7 @@ #include #include #include -#include +#include // agg #include "agg_conv_clip_polyline.h" @@ -328,7 +328,9 @@ double placement_finder::normalize_angle(double angle) { angle += 2.0 * M_PI; } - return angle; + // y axis is inverted. + // See note about coordinate systems in placement_finder::find_point_placement(). + return -angle; } double placement_finder::get_spacing(double path_length, double layout_width) const diff --git a/src/text/placements/base.cpp b/src/text/placements/base.cpp index 8b9c36b6d..0e70b1cf8 100644 --- a/src/text/placements/base.cpp +++ b/src/text/placements/base.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/placements/dummy.cpp b/src/text/placements/dummy.cpp index 59f1221a6..569b5df48 100644 --- a/src/text/placements/dummy.cpp +++ b/src/text/placements/dummy.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,7 +33,7 @@ bool text_placement_info_dummy::next() const } text_placement_info_ptr text_placements_dummy::get_placement_info( - double scale_factor) const + double scale_factor, feature_impl const& feature, attributes const& vars) const { return std::make_shared(this, scale_factor); } diff --git a/src/text/placements/list.cpp b/src/text/placements/list.cpp index 1fec71af3..1c40b68cf 100644 --- a/src/text/placements/list.cpp +++ b/src/text/placements/list.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -65,7 +65,7 @@ text_symbolizer_properties & text_placements_list::get(unsigned i) } -text_placement_info_ptr text_placements_list::get_placement_info(double scale_factor) const +text_placement_info_ptr text_placements_list::get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const { return std::make_shared(this, scale_factor); } diff --git a/src/text/placements/registry.cpp b/src/text/placements/registry.cpp index 535f842ff..c7a655b6b 100644 --- a/src/text/placements/registry.cpp +++ b/src/text/placements/registry.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/placements/simple.cpp b/src/text/placements/simple.cpp index edcdad236..693b0bacd 100644 --- a/src/text/placements/simple.cpp +++ b/src/text/placements/simple.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include // boost #pragma GCC diagnostic push @@ -47,14 +51,86 @@ namespace phoenix = boost::phoenix; using phoenix::push_back; using phoenix::ref; +struct direction_name : qi::symbols +{ + direction_name() + { + add + ("N" , NORTH) + ("E" , EAST) + ("S" , SOUTH) + ("W" , WEST) + ("NE", NORTHEAST) + ("SE", SOUTHEAST) + ("NW", NORTHWEST) + ("SW", SOUTHWEST) + ("X" , EXACT_POSITION) + ; + } + +}; + +// Position string: [POS][SIZE] +// [POS] is any combination of +// N, E, S, W, NE, SE, NW, SW, X (exact position) (separated by commas) +// [SIZE] is a list of font sizes, separated by commas. The first font size +// is always the one given in the TextSymbolizer's parameters. +// First all directions are tried, then font size is reduced +// and all directions are tried again. The process ends when a placement is +// found or the last fontsize is tried without success. +// Example: N,S,15,10,8 (tries placement above, then below and if +// that fails it tries the additional font sizes 15, 10 and 8. + +bool parse_positions(std::string const& evaluated_positions, + std::vector & direction, + std::vector & text_sizes) +{ + direction_name names; + boost::spirit::ascii::space_type space; + qi::_1_type _1; + qi::float_type float_; + std::string::const_iterator first = evaluated_positions.begin(); + std::string::const_iterator last = evaluated_positions.end(); + bool r = qi::phrase_parse(first, last, + (names[push_back(phoenix::ref(direction), _1)] % ',') + >> *(',' >> float_[push_back(phoenix::ref(text_sizes), _1)]), + space); + if (first != last) + { + return false; + } + return r; +} + + +text_placement_info_simple::text_placement_info_simple(text_placements_simple const* parent, + std::string const& evaluated_positions, + double scale_factor) +: text_placement_info(parent, scale_factor), + state(0), + position_state(0), + direction_(parent->direction_), + text_sizes_(parent->text_sizes_), + parent_(parent) +{ + if (direction_.empty() && !parse_positions(evaluated_positions,direction_,text_sizes_)) + { + MAPNIK_LOG_ERROR(text_placements) << "Could not parse text_placement_simple placement string ('" << evaluated_positions << "')"; + if (direction_.size() == 0) + { + MAPNIK_LOG_ERROR(text_placements) << "text_placements_simple with no valid placements! ('"<< evaluated_positions <<"')"; + } + } +} + bool text_placement_info_simple::next() const { while (true) { if (state > 0) { - if (state > parent_->text_sizes_.size()) return false; - properties.format_defaults.text_size = value_double(parent_->text_sizes_[state-1]); + if (state > text_sizes_.size()) return false; + properties.format_defaults.text_size = value_double(text_sizes_[state-1]); } if (!next_position_only()) { @@ -68,90 +144,112 @@ bool text_placement_info_simple::next() const bool text_placement_info_simple::next_position_only() const { - if (position_state >= parent_->direction_.size()) return false; - //directions_e dir = parent_->direction_[position_state]; - properties.layout_defaults.dir = parent_->direction_[position_state]; + if (position_state >= direction_.size()) return false; + properties.layout_defaults.dir = direction_[position_state]; ++position_state; return true; } -text_placement_info_ptr text_placements_simple::get_placement_info(double scale_factor) const +text_placement_info_ptr text_placements_simple::get_placement_info(double scale_factor, feature_impl const& feature, attributes const& vars) const { - return std::make_shared(this, scale_factor); + std::string evaluated_positions = util::apply_visitor(extract_value(feature,vars), positions_); + return std::make_shared(this, evaluated_positions, scale_factor); } -// Position string: [POS][SIZE] -// [POS] is any combination of -// N, E, S, W, NE, SE, NW, SW, X (exact position) (separated by commas) -// [SIZE] is a list of font sizes, separated by commas. The first font size -// is always the one given in the TextSymbolizer's parameters. -// First all directions are tried, then font size is reduced -// and all directions are tried again. The process ends when a placement is -// found or the last fontsize is tried without success. -// Example: N,S,15,10,8 (tries placement above, then below and if -// that fails it tries the additional font sizes 15, 10 and 8. +text_placements_simple::text_placements_simple(symbolizer_base::value_type const& positions) + : direction_(), + text_sizes_(), + positions_(positions) { } -void text_placements_simple::set_positions(std::string const& positions) -{ - positions_ = positions; - struct direction_name_ : qi::symbols +text_placements_simple::text_placements_simple(symbolizer_base::value_type const& positions, + std::vector && direction, + std::vector && text_sizes) + : direction_(direction), + text_sizes_(text_sizes), + positions_(positions) { } + +namespace detail { + struct serialize_positions { - direction_name_() + serialize_positions() {} + + std::string operator() (expression_ptr const& expr) const { - add - ("N" , NORTH) - ("E" , EAST) - ("S" , SOUTH) - ("W" , WEST) - ("NE", NORTHEAST) - ("SE", SOUTHEAST) - ("NW", NORTHWEST) - ("SW", SOUTHWEST) - ("X" , EXACT_POSITION) - ; + if (expr) return to_expression_string(*expr); + return ""; } - } direction_name; - boost::spirit::ascii::space_type space; - qi::_1_type _1; - qi::float_type float_; + std::string operator() (std::string const val) const + { + return val; + } - std::string::const_iterator first = positions.begin(), last = positions.end(); - qi::phrase_parse(first, last, - (direction_name[push_back(phoenix::ref(direction_), _1)] % ',') - >> *(',' >> float_[push_back(phoenix::ref(text_sizes_), _1)]), - space); - if (first != last) - { - MAPNIK_LOG_WARN(text_placements) << "Could not parse text_placement_simple placement string ('" << positions << "')"; - } - if (direction_.size() == 0) - { - MAPNIK_LOG_WARN(text_placements) << "text_placements_simple with no valid placements! ('"<< positions<<"')"; - } + template + std::string operator() (T const& val) const + { + return ""; + } + }; } -text_placements_simple::text_placements_simple() +std::string text_placements_simple::get_positions() const { - set_positions("X"); -} - -text_placements_simple::text_placements_simple(std::string const& positions) -{ - set_positions(positions); -} - -std::string text_placements_simple::get_positions() -{ - return positions_; //TODO: Build string from data in direction_ and text_sizes_ + return util::apply_visitor(detail::serialize_positions(), positions_); } text_placements_ptr text_placements_simple::from_xml(xml_node const& xml, fontset_map const& fontsets, bool is_shield) { - text_placements_ptr ptr = std::make_shared( - xml.get_attr("placements", "X")); - ptr->defaults.from_xml(xml, fontsets, is_shield); - return ptr; + // TODO - handle X cleaner + std::string placements_string = xml.get_attr("placements", "X"); + // like set_property_from_xml in properties_util.hpp + if (!placements_string.empty()) + { + if (placements_string == "X") + { + text_placements_ptr ptr = std::make_shared(placements_string); + ptr->defaults.from_xml(xml, fontsets, is_shield); + return ptr; + } + else + { + try + { + // we don't use parse_expression(placements_string) directly here to benefit from the cache in the xml_node + boost::optional val = xml.get_opt_attr("placements"); + if (val) + { + text_placements_ptr ptr = std::make_shared(*val); + ptr->defaults.from_xml(xml, fontsets, is_shield); + return ptr; + } + } + catch (std::exception const& ex) + { + // otherwise ensure it is valid + std::vector direction; + std::vector text_sizes; + if (!parse_positions(placements_string,direction,text_sizes)) + { + MAPNIK_LOG_ERROR(text_placements) << "Could not parse text_placement_simple placement string ('" << placements_string << "')"; + if (direction.size() == 0) + { + MAPNIK_LOG_ERROR(text_placements) << "text_placements_simple with no valid placements! ('"<< placements_string <<"')"; + } + return text_placements_ptr(); + } + else + { + text_placements_ptr ptr = std::make_shared(placements_string,std::move(direction),std::move(text_sizes)); + ptr->defaults.from_xml(xml, fontsets, is_shield); + return ptr; + } + } + text_placements_ptr ptr = std::make_shared(placements_string); + ptr->defaults.from_xml(xml, fontsets, is_shield); + return ptr; + } + } + return text_placements_ptr(); } } //ns mapnik diff --git a/src/text/properties_util.cpp b/src/text/properties_util.cpp index 873534f1e..ca76efd02 100644 --- a/src/text/properties_util.cpp +++ b/src/text/properties_util.cpp @@ -28,7 +28,7 @@ namespace mapnik { namespace detail { -struct property_serializer : public util::static_visitor<> +struct property_serializer { property_serializer(std::string const& name, boost::property_tree::ptree & node) : name_(name), diff --git a/src/text/renderer.cpp b/src/text/renderer.cpp index c5826115a..b57c2d8ef 100644 --- a/src/text/renderer.cpp +++ b/src/text/renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 5d29bf020..36b6478a7 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -58,7 +58,7 @@ base_symbolizer_helper::base_symbolizer_helper( dims_(0, 0, width, height), query_extent_(query_extent), scale_factor_(scale_factor), - info_ptr_(mapnik::get(sym_, keys::text_placements_)->get_placement_info(scale_factor)), + info_ptr_(mapnik::get(sym_, keys::text_placements_)->get_placement_info(scale_factor,feature_,vars_)), text_props_(evaluate_text_properties(info_ptr_->properties,feature_,vars_)) { initialize_geometries(); diff --git a/src/text/text_layout.cpp b/src/text/text_layout.cpp index 2250d975d..fbaebe958 100644 --- a/src/text/text_layout.cpp +++ b/src/text/text_layout.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -303,7 +303,7 @@ void text_layout::break_line_icu(std::pair && line_limits) } } -struct line_breaker : mapnik::noncopyable +struct line_breaker : util::noncopyable { line_breaker(value_unicode_string const& ustr, char wrap_char) : ustr_(ustr), diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index e14fd157c..f66af1b78 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 2126b8ecd..b1e9dd748 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/tiff_reader.cpp b/src/tiff_reader.cpp index bb73712be..b81df4b68 100644 --- a/src/tiff_reader.cpp +++ b/src/tiff_reader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -42,9 +42,9 @@ extern "C" namespace mapnik { namespace impl { -static toff_t tiff_seek_proc(thandle_t fd, toff_t off, int whence) +static toff_t tiff_seek_proc(thandle_t handle, toff_t off, int whence) { - std::istream* in = reinterpret_cast(fd); + std::istream* in = reinterpret_cast(handle); switch(whence) { @@ -66,9 +66,9 @@ static int tiff_close_proc(thandle_t) return 0; } -static toff_t tiff_size_proc(thandle_t fd) +static toff_t tiff_size_proc(thandle_t handle) { - std::istream* in = reinterpret_cast(fd); + std::istream* in = reinterpret_cast(handle); std::ios::pos_type pos = in->tellg(); in->seekg(0, std::ios::end); std::ios::pos_type len = in->tellg(); @@ -76,9 +76,9 @@ static toff_t tiff_size_proc(thandle_t fd) return static_cast(len); } -static tsize_t tiff_read_proc(thandle_t fd, tdata_t buf, tsize_t size) +static tsize_t tiff_read_proc(thandle_t handle, tdata_t buf, tsize_t size) { - std::istream * in = reinterpret_cast(fd); + std::istream * in = reinterpret_cast(handle); std::streamsize request_size = size; if (static_cast(request_size) != size) return static_cast(-1); @@ -123,15 +123,23 @@ class tiff_reader : public image_reader private: source_type source_; input_stream stream_; + tiff_ptr tif_; int read_method_; - std::size_t width_; - std::size_t height_; int rows_per_strip_; int tile_width_; int tile_height_; - tiff_ptr tif_; + std::size_t width_; + std::size_t height_; + boost::optional > bbox_; + unsigned bps_; + unsigned photometric_; + unsigned bands_; + unsigned planar_config_; + unsigned compression_; bool premultiplied_alpha_; bool has_alpha_; + bool is_tiled_; + public: enum TiffType { generic=1, @@ -141,18 +149,35 @@ public: explicit tiff_reader(std::string const& file_name); tiff_reader(char const* data, std::size_t size); virtual ~tiff_reader(); - unsigned width() const; - unsigned height() const; - inline bool has_alpha() const { return has_alpha_; } - bool premultiplied_alpha() const; - void read(unsigned x,unsigned y,image_data_32& image); + unsigned width() const final; + unsigned height() const final; + boost::optional > bounding_box() const final; + inline bool has_alpha() const final { return has_alpha_; } + bool premultiplied_alpha() const final; + void read(unsigned x,unsigned y,image_data_rgba8& image) final; + image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) final; + // methods specific to tiff reader + unsigned bits_per_sample() const { return bps_; } + unsigned photometric() const { return photometric_; } + bool is_tiled() const { return is_tiled_; } + unsigned tile_width() const { return tile_width_; } + unsigned tile_height() const { return tile_height_; } + unsigned rows_per_strip() const { return rows_per_strip_; } + unsigned planar_config() const { return planar_config_; } + unsigned compression() const { return compression_; } private: tiff_reader(const tiff_reader&); tiff_reader& operator=(const tiff_reader&); void init(); - void read_generic(unsigned x,unsigned y,image_data_32& image); - void read_stripped(unsigned x,unsigned y,image_data_32& image); - void read_tiled(unsigned x,unsigned y,image_data_32& image); + void read_generic(unsigned x,unsigned y,image_data_rgba8& image); + void read_stripped(unsigned x,unsigned y,image_data_rgba8& image); + + template + void read_tiled(unsigned x,unsigned y, ImageData & image); + + template + image_data_any read_any_gray(unsigned x, unsigned y, unsigned width, unsigned height); + TIFF* open(std::istream & input); }; @@ -178,14 +203,21 @@ template tiff_reader::tiff_reader(std::string const& file_name) : source_(file_name, std::ios_base::in | std::ios_base::binary), stream_(source_), + tif_(nullptr), read_method_(generic), - width_(0), - height_(0), rows_per_strip_(0), tile_width_(0), tile_height_(0), + width_(0), + height_(0), + bps_(0), + photometric_(0), + bands_(1), + planar_config_(PLANARCONFIG_CONTIG), + compression_(COMPRESSION_NONE), premultiplied_alpha_(false), - has_alpha_(false) + has_alpha_(false), + is_tiled_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open file "+ file_name); init(); @@ -195,16 +227,24 @@ template tiff_reader::tiff_reader(char const* data, std::size_t size) : source_(data, size), stream_(source_), + tif_(nullptr), read_method_(generic), - width_(0), - height_(0), rows_per_strip_(0), tile_width_(0), tile_height_(0), + width_(0), + height_(0), + bps_(0), + photometric_(0), + bands_(1), + planar_config_(PLANARCONFIG_CONTIG), + compression_(COMPRESSION_NONE), premultiplied_alpha_(false), - has_alpha_(false) + has_alpha_(false), + is_tiled_(false) { if (!stream_) throw image_reader_exception("TIFF reader: cannot open image stream "); + stream_.rdbuf()->pubsetbuf(0, 0); stream_.seekg(0, std::ios::beg); init(); } @@ -220,39 +260,97 @@ void tiff_reader::init() if (!tif) throw image_reader_exception("Can't open tiff file"); - char msg[1024]; + TIFFGetField(tif,TIFFTAG_BITSPERSAMPLE,&bps_); + TIFFGetField(tif,TIFFTAG_PHOTOMETRIC,&photometric_); + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &bands_); - if (TIFFRGBAImageOK(tif,msg)) + MAPNIK_LOG_DEBUG(tiff_reader) << "bits per sample: " << bps_; + MAPNIK_LOG_DEBUG(tiff_reader) << "photometric: " << photometric_; + MAPNIK_LOG_DEBUG(tiff_reader) << "bands: " << bands_; + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_); + + if (width_ > 10000 || height_ > 10000) { - TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width_); - TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height_); - if (TIFFIsTiled(tif)) + throw image_reader_exception("Can't allocate tiff > 10000x10000"); + } + + TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config_); + TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression_ ); + TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rows_per_strip_); + + std::uint16_t orientation; + if (TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation) == 0) + { + orientation = 1; + } + MAPNIK_LOG_DEBUG(tiff_reader) << "orientation: " << orientation; + + is_tiled_ = TIFFIsTiled(tif); + + if (is_tiled_) + { + TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width_); + TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height_); + MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is tiled"; + read_method_ = tiled; + } + else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0) + { + MAPNIK_LOG_DEBUG(tiff_reader) << "tiff is stripped"; + read_method_ = stripped; + } + //TIFFTAG_EXTRASAMPLES + uint16 extrasamples = 0; + uint16* sampleinfo = nullptr; + if (TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, + &extrasamples, &sampleinfo)) + { + has_alpha_ = true; + if (extrasamples == 1 && + sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA) { - TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tile_width_); - TIFFGetField(tif, TIFFTAG_TILELENGTH, &tile_height_); - read_method_=tiled; - } - else if (TIFFGetField(tif,TIFFTAG_ROWSPERSTRIP,&rows_per_strip_)!=0) - { - read_method_=stripped; - } - //TIFFTAG_EXTRASAMPLES - uint16 extrasamples = 0; - uint16* sampleinfo = nullptr; - if (TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, - &extrasamples, &sampleinfo)) - { - has_alpha_ = true; - if (extrasamples == 1 && - sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA) - { - premultiplied_alpha_ = true; - } + premultiplied_alpha_ = true; } } - else + // Try extracting bounding box from geoTIFF tags { - throw image_reader_exception(msg); + uint16 count = 0; + double *pixelscale; + double *tilepoint; + if (TIFFGetField(tif, 33550, &count, &pixelscale) == 1 && count == 3 + && TIFFGetField(tif, 33922 , &count, &tilepoint) == 1 && count == 6) + { + MAPNIK_LOG_DEBUG(tiff_reader) << "PixelScale:" << pixelscale[0] << "," << pixelscale[1] << "," << pixelscale[2]; + MAPNIK_LOG_DEBUG(tiff_reader) << "TilePoint:" << tilepoint[0] << "," << tilepoint[1] << "," << tilepoint[2]; + MAPNIK_LOG_DEBUG(tiff_reader) << " " << tilepoint[3] << "," << tilepoint[4] << "," << tilepoint[5]; + + // assuming upper-left + double lox = tilepoint[3]; + double loy = tilepoint[4]; + double hix = lox + pixelscale[0] * width_; + double hiy = loy - pixelscale[1] * height_; + bbox_.reset(box2d(lox, loy, hix, hiy)); + MAPNIK_LOG_DEBUG(tiff_reader) << "Bounding Box:" << *bbox_; + } + + } + if (!is_tiled_ && + compression_ == COMPRESSION_NONE && + planar_config_ == PLANARCONFIG_CONTIG) + { + if (height_ > 128 * 1024 * 1024) + { + std::size_t line_size = (bands_ * width_ * bps_ + 7) / 8; + std::size_t default_strip_height = 8192 / line_size; + if (default_strip_height == 0) default_strip_height = 1; + std::size_t num_strips = height_ / default_strip_height; + if (num_strips > 128 * 1024 * 1024) + { + throw image_reader_exception("Can't allocate tiff"); + } + } } } @@ -273,6 +371,12 @@ unsigned tiff_reader::height() const return height_; } +template +boost::optional > tiff_reader::bounding_box() const +{ + return bbox_; +} + template bool tiff_reader::premultiplied_alpha() const { @@ -280,7 +384,7 @@ bool tiff_reader::premultiplied_alpha() const } template -void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) +void tiff_reader::read(unsigned x,unsigned y,image_data_rgba8& image) { if (read_method_==stripped) { @@ -297,96 +401,279 @@ void tiff_reader::read(unsigned x,unsigned y,image_data_32& image) } template -void tiff_reader::read_generic(unsigned, unsigned, image_data_32&) +template +image_data_any tiff_reader::read_any_gray(unsigned x0, unsigned y0, unsigned width, unsigned height) +{ + using image_data_type = ImageData; + using pixel_type = typename image_data_type::pixel_type; + if (read_method_ == tiled) + { + image_data_type data(width,height); + read_tiled(x0, y0, data); + return image_data_any(std::move(data)); + } + else + { + TIFF* tif = open(stream_); + if (tif) + { + image_data_type data(width, height); + std::size_t block_size = rows_per_strip_ > 0 ? rows_per_strip_ : tile_height_ ; + std::ptrdiff_t start_y = y0 - y0 % block_size; + std::ptrdiff_t end_y = std::min(y0 + height, static_cast(height_)); + std::ptrdiff_t start_x = x0; + std::ptrdiff_t end_x = std::min(x0 + width, static_cast(width_)); + std::size_t element_size = sizeof(pixel_type); + std::size_t size_to_allocate = (TIFFScanlineSize(tif) + element_size - 1)/element_size; + const std::unique_ptr scanline(new pixel_type[size_to_allocate]); + for (std::size_t y = start_y; y < end_y; ++y) + { + if (-1 != TIFFReadScanline(tif, scanline.get(), y) && (y >= y0)) + { + pixel_type * row = data.getRow(y - y0); + std::transform(scanline.get() + start_x, scanline.get() + end_x, row, [](pixel_type const& p) { return p;}); + } + } + return image_data_any(std::move(data)); + } + } + return image_data_any(); +} + + +namespace detail { + +struct rgb8 +{ + std::uint8_t r; + std::uint8_t g; + std::uint8_t b; +}; + +struct rgb8_to_rgba8 +{ + std::uint32_t operator() (rgb8 const& in) const + { + return ((255 << 24) | (in.r) | (in.g << 8) | (in.b << 16)); + } +}; + +template +struct tiff_reader_traits +{ + using image_data_type = T; + using pixel_type = typename image_data_type::pixel_type; + static bool read_tile(TIFF * tif, unsigned x, unsigned y, pixel_type* buf, std::size_t tile_width, std::size_t tile_height) + { + return (TIFFReadEncodedTile(tif, TIFFComputeTile(tif, x,y,0,0), buf, tile_width * tile_height * sizeof(pixel_type)) != -1); + } +}; + +// default specialization that expands into RGBA +template <> +struct tiff_reader_traits +{ + using pixel_type = std::uint32_t; + static bool read_tile(TIFF * tif, unsigned x0, unsigned y0, pixel_type* buf, std::size_t tile_width, std::size_t tile_height) + { + if (TIFFReadRGBATile(tif, x0, y0, buf) != -1) + { + for (unsigned y = 0; y < tile_height/2; ++y) + { + std::swap_ranges(buf + y * tile_width, buf + (y + 1) * tile_width, buf + (tile_height - y - 1) * tile_width); + } + return true; + } + return false; + } +}; + +} + +template +image_data_any tiff_reader::read(unsigned x0, unsigned y0, unsigned width, unsigned height) +{ + switch (photometric_) + { + case PHOTOMETRIC_MINISBLACK: + case PHOTOMETRIC_MINISWHITE: + { + switch (bps_) + { + case 8: + { + return read_any_gray(x0, y0, width, height); + } + case 16: + { + return read_any_gray(x0, y0, width, height); + } + case 32: + { + return read_any_gray(x0, y0, width, height); + } + } + } +// read PHOTOMETRIC_RGB expand using RGBA interface +/* + case PHOTOMETRIC_RGB: + { + switch (bps_) + { + case 8: + { + TIFF* tif = open(stream_); + if (tif) + { + image_data_rgba8 data(width, height); + std::size_t element_size = sizeof(detail::rgb8); + std::size_t size_to_allocate = (TIFFScanlineSize(tif) + element_size - 1)/element_size; + const std::unique_ptr scanline(new detail::rgb8[size_to_allocate]); + std::ptrdiff_t start_y = y0 - y0 % rows_per_strip_; + std::ptrdiff_t end_y = std::min(y0 + height, static_cast(height_)); + std::ptrdiff_t start_x = x0; + std::ptrdiff_t end_x = std::min(x0 + width, static_cast(width_)); + for (std::size_t y = start_y; y < end_y; ++y) + { + if (-1 != TIFFReadScanline(tif, scanline.get(), y)) + { + if (y >= y0) + { + image_data_rgba8::pixel_type * row = data.getRow(y - y0); + std::transform(scanline.get() + start_x, scanline.get() + end_x, row, detail::rgb8_to_rgba8()); + } + } + } + return image_data_any(std::move(data)); + } + return image_data_any(); + } + case 16: + { + image_data_rgba8 data(width,height); + read(x0, y0, data); + return image_data_any(std::move(data)); + } + case 32: + { + image_data_rgba8 data(width,height); + read(x0, y0, data); + return image_data_any(std::move(data)); + } + } + } +*/ + default: + { + //PHOTOMETRIC_PALETTE = 3; + //PHOTOMETRIC_MASK = 4; + //PHOTOMETRIC_SEPARATED = 5; + //PHOTOMETRIC_YCBCR = 6; + //PHOTOMETRIC_CIELAB = 8; + //PHOTOMETRIC_ICCLAB = 9; + //PHOTOMETRIC_ITULAB = 10; + //PHOTOMETRIC_LOGL = 32844; + //PHOTOMETRIC_LOGLUV = 32845; + image_data_rgba8 data(width,height); + read(x0, y0, data); + return image_data_any(std::move(data)); + } + } + return image_data_any(); +} + +template +void tiff_reader::read_generic(unsigned, unsigned, image_data_rgba8& image) { TIFF* tif = open(stream_); if (tif) { - MAPNIK_LOG_DEBUG(tiff_reader) << "tiff_reader: TODO - tiff is not stripped or tiled"; + throw std::runtime_error("tiff_reader: TODO - tiff is not stripped or tiled"); } } template -void tiff_reader::read_tiled(unsigned x0,unsigned y0,image_data_32& image) +template +void tiff_reader::read_tiled(unsigned x0,unsigned y0, ImageData & image) { + using pixel_type = typename detail::tiff_reader_traits::pixel_type; + TIFF* tif = open(stream_); if (tif) { - uint32* buf = (uint32*)_TIFFmalloc(tile_width_*tile_height_*sizeof(uint32)); - int width=image.width(); - int height=image.height(); + std::unique_ptr buf(new pixel_type[tile_width_*tile_height_]); + int width = image.width(); + int height = image.height(); + int start_y = (y0 / tile_height_) * tile_height_; + int end_y = ((y0 + height) / tile_height_ + 1) * tile_height_; + int start_x = (x0 / tile_width_) * tile_width_; + int end_x = ((x0 + width) / tile_width_ + 1) * tile_width_; + end_y = std::min(end_y, int(height_)); + end_x = std::min(end_x, int(width_)); - int start_y=(y0/tile_height_)*tile_height_; - int end_y=((y0+height)/tile_height_+1)*tile_height_; - - int start_x=(x0/tile_width_)*tile_width_; - int end_x=((x0+width)/tile_width_+1)*tile_width_; - int row,tx0,tx1,ty0,ty1; - - for (int y=start_y;y(y)) - y; + int ty1 = std::min(height + y0, static_cast(y + tile_height_)) - y; - int n0=tile_height_-ty1; - int n1=tile_height_-ty0-1; - - for (int x=start_x;x=n0;--n) + if (!detail::tiff_reader_traits::read_tile(tif, x, y, buf.get(), tile_width_, tile_height_)) { - image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*tile_width_+tx0-x]); - ++row; + std::clog << "read_tile(...) failed at " << x << "/" << y << " for " << width_ << "/" << height_ << "\n"; + break; + } + int tx0 = std::max(x0, static_cast(x)); + int tx1 = std::min(width + x0, static_cast(x + tile_width_)); + int row = y + ty0 - y0; + for (int ty = ty0; ty < ty1; ++ty, ++row) + { + image.setRow(row, tx0 - x0, tx1 - x0, &buf[ty * tile_width_ + tx0 - x]); } } } - _TIFFfree(buf); } } + template -void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_32& image) +void tiff_reader::read_stripped(unsigned x0,unsigned y0,image_data_rgba8& image) { TIFF* tif = open(stream_); if (tif) { - uint32* buf = (uint32*)_TIFFmalloc(width_*rows_per_strip_*sizeof(uint32)); - + image_data_rgba8 strip(width_,rows_per_strip_,false); int width=image.width(); int height=image.height(); unsigned start_y=(y0/rows_per_strip_)*rows_per_strip_; unsigned end_y=((y0+height)/rows_per_strip_+1)*rows_per_strip_; - bool laststrip=((unsigned)end_y > height_)?true:false; + bool laststrip=(static_cast(end_y) > height_)?true:false; int row,tx0,tx1,ty0,ty1; tx0=x0; - tx1=std::min(width+x0,(unsigned)width_); + tx1=std::min(width+x0,static_cast(width_)); for (unsigned y=start_y; y < end_y; y+=rows_per_strip_) { ty0 = std::max(y0,y)-y; ty1 = std::min(height+y0,y+rows_per_strip_)-y; - if (!TIFFReadRGBAStrip(tif,y,buf)) break; - + if (!TIFFReadRGBAStrip(tif,y,strip.getData())) + { + std::clog << "TIFFReadRGBAStrip failed at " << y << " for " << width_ << "/" << height_ << "\n"; + break; + } row=y+ty0-y0; int n0=laststrip ? 0:(rows_per_strip_-ty1); int n1=laststrip ? (ty1-ty0-1):(rows_per_strip_-ty0-1); for (int n=n1;n>=n0;--n) { - image.setRow(row,tx0-x0,tx1-x0,(const unsigned*)&buf[n*width_+tx0]); + image.setRow(row,tx0-x0,tx1-x0,&strip.getData()[n*width_+tx0]); ++row; } } - _TIFFfree(buf); } } @@ -395,7 +682,7 @@ TIFF* tiff_reader::open(std::istream & input) { if (!tif_) { - tif_ = tiff_ptr(TIFFClientOpen("tiff_input_stream", "rm", + tif_ = tiff_ptr(TIFFClientOpen("tiff_input_stream", "rcm", reinterpret_cast(&input), impl::tiff_read_proc, impl::tiff_write_proc, diff --git a/src/transform_expression.cpp b/src/transform_expression.cpp index eff6548ed..e065ddc7e 100644 --- a/src/transform_expression.cpp +++ b/src/transform_expression.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,7 +30,7 @@ namespace mapnik { struct transform_node_to_expression_string - : public util::static_visitor + { std::ostringstream& os_; diff --git a/src/unicode.cpp b/src/unicode.cpp index 4c703a2cb..f6c059f60 100644 --- a/src/unicode.cpp +++ b/src/unicode.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,9 +24,8 @@ #include #include -// stl -#include -#include +// std +#include // icu #include @@ -34,13 +33,15 @@ namespace mapnik { transcoder::transcoder (std::string const& encoding) - : ok_(false), - conv_(0) + : conv_(0) { UErrorCode err = U_ZERO_ERROR; conv_ = ucnv_open(encoding.c_str(),&err); - if (U_SUCCESS(err)) ok_ = true; - // TODO ?? + if (!U_SUCCESS(err)) + { + // NOT: conv_ should be null on error so no need to call ucnv_close + throw std::runtime_error(std::string("could not create converter for ") + encoding); + } } mapnik::value_unicode_string transcoder::transcode(const char* data, std::int32_t length) const diff --git a/src/utils.cpp b/src/utils.cpp index 668a0bf05..f694faa18 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/text/vertex_cache.cpp b/src/vertex_cache.cpp similarity index 91% rename from src/text/vertex_cache.cpp rename to src/vertex_cache.cpp index 8a2fb2b89..d5a18a316 100644 --- a/src/text/vertex_cache.cpp +++ b/src/vertex_cache.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -21,23 +21,36 @@ *****************************************************************************/ // mapnik #include -#include +#include #include #include namespace mapnik { +vertex_cache::vertex_cache(vertex_cache && rhs) + : current_position_(std::move(rhs.current_position_)), + segment_starting_point_(std::move(rhs.segment_starting_point_)), + subpaths_(std::move(rhs.subpaths_)), + position_in_segment_(std::move(rhs.position_in_segment_)), + angle_(std::move(rhs.angle_)), + angle_valid_(std::move(rhs.angle_valid_)), + offseted_lines_(std::move(rhs.offseted_lines_)), + position_(std::move(rhs.position_)) +{ + // The C++11 standard doesn't guarantee iterators are valid when container is moved. + // We can create them from indexes but we don't need to. Just let them uninitialized. + initialized_ = false; +} + double vertex_cache::current_segment_angle() { - return std::atan2(-(current_segment_->pos.y - segment_starting_point_.y), - current_segment_->pos.x - segment_starting_point_.x); + return std::atan2(current_segment_->pos.y - segment_starting_point_.y, + current_segment_->pos.x - segment_starting_point_.x); } double vertex_cache::angle(double width) { - // IMPORTANT NOTE: See note about coordinate systems in placement_finder::find_point_placement() - // for imformation about why the y axis is inverted! double tmp = width + position_in_segment_; if ((tmp <= current_segment_->length) && (tmp >= 0)) { @@ -53,8 +66,8 @@ double vertex_cache::angle(double width) if (move(width)) { pixel_position const& old_pos = s.get_state().position(); - return std::atan2(-(current_position_.y - old_pos.y), - current_position_.x - old_pos.x); + return std::atan2(current_position_.y - old_pos.y, + current_position_.x - old_pos.x); } else { diff --git a/src/warp.cpp b/src/warp.cpp index a7bb21ad6..16a81492d 100644 --- a/src/warp.cpp +++ b/src/warp.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -47,105 +48,68 @@ namespace mapnik { -void reproject_and_scale_raster(raster & target, raster const& source, - proj_transform const& prj_trans, - double offset_x, double offset_y, - unsigned mesh_size, - scaling_method_e scaling_method) +template +MAPNIK_DECL void warp_image (T & target, T const& source, proj_transform const& prj_trans, + box2d const& target_ext, box2d const& source_ext, + double offset_x, double offset_y, unsigned mesh_size, scaling_method_e scaling_method, double filter_factor) { - view_transform ts(source.data_.width(), source.data_.height(), - source.ext_); - view_transform tt(target.data_.width(), target.data_.height(), - target.ext_, offset_x, offset_y); + using image_data_type = T; + using pixel_type = typename image_data_type::pixel_type; + using pixfmt_pre = typename detail::agg_scaling_traits::pixfmt_pre; + using color_type = typename detail::agg_scaling_traits::color_type; + using renderer_base = agg::renderer_base; + using interpolator_type = typename detail::agg_scaling_traits::interpolator_type; - unsigned mesh_nx = std::ceil(source.data_.width()/double(mesh_size) + 1); - unsigned mesh_ny = std::ceil(source.data_.height()/double(mesh_size) + 1); + constexpr std::size_t pixel_size = sizeof(pixel_type); + + view_transform ts(source.width(), source.height(), + source_ext); + view_transform tt(target.width(), target.height(), + target_ext, offset_x, offset_y); + + std::size_t mesh_nx = std::ceil(source.width()/double(mesh_size) + 1); + std::size_t mesh_ny = std::ceil(source.height()/double(mesh_size) + 1); image_data xs(mesh_nx, mesh_ny); image_data ys(mesh_nx, mesh_ny); // Precalculate reprojected mesh - for(unsigned j=0; j; - agg::rasterizer_scanline_aa<> rasterizer; agg::scanline_bin scanline; - agg::rendering_buffer buf((unsigned char*)target.data_.getData(), - target.data_.width(), - target.data_.height(), - target.data_.width()*4); - pixfmt pixf(buf); + agg::rendering_buffer buf(target.getBytes(), + target.width(), + target.height(), + target.width() * pixel_size); + pixfmt_pre pixf(buf); renderer_base rb(pixf); - rasterizer.clip_box(0, 0, target.data_.width(), target.data_.height()); + rasterizer.clip_box(0, 0, target.width(), target.height()); agg::rendering_buffer buf_tile( - (unsigned char*)source.data_.getData(), - source.data_.width(), - source.data_.height(), - source.data_.width() * 4); + const_cast(source.getBytes()), + source.width(), + source.height(), + source.width() * pixel_size); - pixfmt pixf_tile(buf_tile); + pixfmt_pre pixf_tile(buf_tile); - using img_accessor_type = agg::image_accessor_clone; + using img_accessor_type = agg::image_accessor_clone; img_accessor_type ia(pixf_tile); agg::span_allocator sa; - - // Initialize filter - agg::image_filter_lut filter; - switch(scaling_method) - { - case SCALING_NEAR: break; - case SCALING_BILINEAR: - filter.calculate(agg::image_filter_bilinear(), true); break; - case SCALING_BICUBIC: - filter.calculate(agg::image_filter_bicubic(), true); break; - case SCALING_SPLINE16: - filter.calculate(agg::image_filter_spline16(), true); break; - case SCALING_SPLINE36: - filter.calculate(agg::image_filter_spline36(), true); break; - case SCALING_HANNING: - filter.calculate(agg::image_filter_hanning(), true); break; - case SCALING_HAMMING: - filter.calculate(agg::image_filter_hamming(), true); break; - case SCALING_HERMITE: - filter.calculate(agg::image_filter_hermite(), true); break; - case SCALING_KAISER: - filter.calculate(agg::image_filter_kaiser(), true); break; - case SCALING_QUADRIC: - filter.calculate(agg::image_filter_quadric(), true); break; - case SCALING_CATROM: - filter.calculate(agg::image_filter_catrom(), true); break; - case SCALING_GAUSSIAN: - filter.calculate(agg::image_filter_gaussian(), true); break; - case SCALING_BESSEL: - filter.calculate(agg::image_filter_bessel(), true); break; - case SCALING_MITCHELL: - filter.calculate(agg::image_filter_mitchell(), true); break; - case SCALING_SINC: - filter.calculate(agg::image_filter_sinc(source.get_filter_factor()), true); break; - case SCALING_LANCZOS: - filter.calculate(agg::image_filter_lanczos(source.get_filter_factor()), true); break; - case SCALING_BLACKMAN: - filter.calculate(agg::image_filter_blackman(source.get_filter_factor()), true); break; - } - // Project mesh cells into target interpolating raster inside each one - for(unsigned j=0; j; interpolator_type interpolator(tr); - if (scaling_method == SCALING_NEAR) { - using span_gen_type = agg::span_image_filter_rgba_nn - ; + using span_gen_type = typename detail::agg_scaling_traits::span_image_filter; span_gen_type sg(ia, interpolator); - agg::render_scanlines_bin(rasterizer, scanline, rb, - sa, sg); + agg::render_scanlines_bin(rasterizer, scanline, rb, sa, sg); } else { - using span_gen_type = agg::span_image_resample_rgba_affine - ; + using span_gen_type = typename detail::agg_scaling_traits::span_image_resample_affine; + agg::image_filter_lut filter; + detail::set_scaling_method(filter, scaling_method, filter_factor); span_gen_type sg(ia, interpolator, filter); - agg::render_scanlines_bin(rasterizer, scanline, rb, - sa, sg); + agg::render_scanlines_bin(rasterizer, scanline, rb, sa, sg); } } } } } + +namespace detail { + +struct warp_image_visitor +{ + warp_image_visitor (raster & target_raster, proj_transform const& prj_trans, box2d const& source_ext, + double offset_x, double offset_y, unsigned mesh_size, + scaling_method_e scaling_method, double filter_factor) + : target_raster_(target_raster), + prj_trans_(prj_trans), + source_ext_(source_ext), + offset_x_(offset_x), + offset_y_(offset_y), + mesh_size_(mesh_size), + scaling_method_(scaling_method), + filter_factor_(filter_factor) {} + + void operator() (image_data_null const&) {} + + template + void operator() (T const& source) + { + using image_data_type = T; + //source and target image data types must match + if (target_raster_.data_.template is()) + { + image_data_type & target = util::get(target_raster_.data_); + warp_image (target, source, prj_trans_, target_raster_.ext_, source_ext_, + offset_x_, offset_y_, mesh_size_, scaling_method_, filter_factor_); + } + } + + raster & target_raster_; + proj_transform const& prj_trans_; + box2d const& source_ext_; + double offset_x_; + double offset_y_; + unsigned mesh_size_; + scaling_method_e scaling_method_; + double filter_factor_; +}; + +} + +void reproject_and_scale_raster(raster & target, raster const& source, + proj_transform const& prj_trans, + double offset_x, double offset_y, + unsigned mesh_size, + scaling_method_e scaling_method) +{ + detail::warp_image_visitor warper(target, prj_trans, source.ext_, offset_x, offset_y, mesh_size, + scaling_method, source.get_filter_factor()); + util::apply_visitor(warper, source.data_); +} + +template MAPNIK_DECL void warp_image (image_data_rgba8&, image_data_rgba8 const&, proj_transform const&, + box2d const&, box2d const&, double, double, unsigned, scaling_method_e, double); + +template MAPNIK_DECL void warp_image (image_data_gray8&, image_data_gray8 const&, proj_transform const&, + box2d const&, box2d const&, double, double, unsigned, scaling_method_e, double); + +template MAPNIK_DECL void warp_image (image_data_gray16&, image_data_gray16 const&, proj_transform const&, + box2d const&, box2d const&, double, double, unsigned, scaling_method_e, double); + +template MAPNIK_DECL void warp_image (image_data_gray32f&, image_data_gray32f const&, proj_transform const&, + box2d const&, box2d const&, double, double, unsigned, scaling_method_e, double); + + }// namespace mapnik diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index bd34d2355..6add17485 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -120,11 +120,13 @@ public: explicit webp_reader(char const* data, std::size_t size); explicit webp_reader(std::string const& filename); ~webp_reader(); - unsigned width() const; - unsigned height() const; - inline bool has_alpha() const { return has_alpha_; } - bool premultiplied_alpha() const { return false; } - void read(unsigned x,unsigned y,image_data_32& image); + unsigned width() const final; + unsigned height() const final; + boost::optional > bounding_box() const final; + inline bool has_alpha() const final { return has_alpha_; } + bool premultiplied_alpha() const final { return false; } + void read(unsigned x,unsigned y,image_data_rgba8& image) final; + image_data_any read(unsigned x, unsigned y, unsigned width, unsigned height) final; private: void init(); }; @@ -229,7 +231,13 @@ unsigned webp_reader::height() const } template -void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) +boost::optional > webp_reader::bounding_box() const +{ + return boost::optional >(); +} + +template +void webp_reader::read(unsigned x0, unsigned y0,image_data_rgba8& image) { WebPDecoderConfig config; config_guard guard(config); @@ -241,8 +249,8 @@ void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) config.options.use_cropping = 1; config.options.crop_left = x0; config.options.crop_top = y0; - config.options.crop_width = std::min(width_ - x0, image.width()); - config.options.crop_height = std::min(height_ - y0, image.height()); + config.options.crop_width = std::min(static_cast(width_ - x0), image.width()); + config.options.crop_height = std::min(static_cast(height_ - y0), image.height()); if (WebPGetFeatures(buffer_->data(), buffer_->size(), &config.input) != VP8_STATUS_OK) { @@ -250,7 +258,7 @@ void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) } config.output.colorspace = MODE_RGBA; - config.output.u.RGBA.rgba = (uint8_t *)image.getBytes(); + config.output.u.RGBA.rgba = reinterpret_cast(image.getBytes()); config.output.u.RGBA.stride = 4 * image.width(); config.output.u.RGBA.size = image.width() * image.height() * 4; config.output.is_external_memory = 1; @@ -260,4 +268,12 @@ void webp_reader::read(unsigned x0, unsigned y0,image_data_32& image) } } +template +image_data_any webp_reader::read(unsigned x, unsigned y, unsigned width, unsigned height) +{ + image_data_rgba8 data(width,height); + read(x, y, data); + return image_data_any(std::move(data)); +} + } diff --git a/src/well_known_srs.cpp b/src/well_known_srs.cpp index c3163df0d..8aaf7ab18 100644 --- a/src/well_known_srs.cpp +++ b/src/well_known_srs.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/wkb.cpp b/src/wkb.cpp index 1a31d7ce0..8e7bf62d7 100644 --- a/src/wkb.cpp +++ b/src/wkb.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,14 +28,14 @@ #include #include #include -#include +#include namespace mapnik { using CoordinateArray = coord_array; -struct wkb_reader : mapnik::noncopyable +struct wkb_reader : util::noncopyable { private: enum wkbByteOrder { diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index b03dd915a..e46f6a4f2 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2012 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/tests/cpp_tests/agg_blend_src_over_test.cpp b/tests/cpp_tests/agg_blend_src_over_test.cpp index 0b4648f46..eb86e4cad 100644 --- a/tests/cpp_tests/agg_blend_src_over_test.cpp +++ b/tests/cpp_tests/agg_blend_src_over_test.cpp @@ -153,11 +153,10 @@ int main(int argc, char** argv) BOOST_TEST_EQ( to_string(blend(white,black)), to_string(white) ); BOOST_TEST_EQ( to_string(blend(black,white)), to_string(black) ); - // https://github.com/mapnik/mapnik/issues/1452#issuecomment-8154646 color near_white(254,254,254,254); // Source color near_trans(1,1,1,1); // Dest - color expected_color(252,252,252,255); // expected result - BOOST_TEST_EQ( to_string(blend(near_white,near_trans)), to_string(color(252,252,252,254)) ); + color expected_color(253,253,253,255); // expected result + BOOST_TEST_EQ( to_string(blend(near_white,near_trans)), to_string(color(253,253,253,254)) ); BOOST_TEST_EQ( to_string(blend(near_white,near_trans)), to_string(expected_color) ); BOOST_TEST_EQ( to_string(normal_blend(near_white,near_trans)), to_string(expected_color) ); diff --git a/tests/cpp_tests/build.py b/tests/cpp_tests/build.py index 731123028..88ea7b3af 100644 --- a/tests/cpp_tests/build.py +++ b/tests/cpp_tests/build.py @@ -12,6 +12,8 @@ if not env['CPP_TESTS']: else: test_env['LIBS'] = [env['MAPNIK_NAME']] test_env.AppendUnique(LIBS=copy(env['LIBMAPNIK_LIBS'])) + test_env.AppendUnique(LIBS='mapnik-wkt') + test_env.AppendUnique(LIBS='mapnik-json') if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux': test_env.AppendUnique(LIBS='dl') test_env.AppendUnique(CXXFLAGS='-g') @@ -43,6 +45,8 @@ else: source_files += glob.glob('../../plugins/input/csv/' + '*.cpp') test_program = test_env_local.Program(name, source=source_files) Depends(test_program, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) + Depends(test_program, env.subst('../../src/json/libmapnik-json${LIBSUFFIX}')) + Depends(test_program, env.subst('../../src/wkt/libmapnik-wkt${LIBSUFFIX}')) # build locally if installing if 'install' in COMMAND_LINE_TARGETS: env.Alias('install',test_program) diff --git a/tests/cpp_tests/exceptions_test.cpp b/tests/cpp_tests/exceptions_test.cpp index cc731fd9f..1bfc826e0 100644 --- a/tests/cpp_tests/exceptions_test.cpp +++ b/tests/cpp_tests/exceptions_test.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,13 @@ int main(int argc, char** argv) BOOST_TEST(true); } + try { + mapnik::transcoder tr("bogus encoding"); + BOOST_TEST(false); + } catch (...) { + BOOST_TEST(true); + } + mapnik::Map map(256,256); mapnik::rule r; r.set_filter(mapnik::parse_expression("[foo]='bar'")); diff --git a/tests/cpp_tests/geometry_converters_test.cpp b/tests/cpp_tests/geometry_converters_test.cpp index 23ff74d99..1bc115617 100644 --- a/tests/cpp_tests/geometry_converters_test.cpp +++ b/tests/cpp_tests/geometry_converters_test.cpp @@ -13,10 +13,8 @@ #include #include #include -#include #include #include -#include #include #include diff --git a/tests/cpp_tests/image_io_test.cpp b/tests/cpp_tests/image_io_test.cpp index 8ed34eacd..f7cb158f6 100644 --- a/tests/cpp_tests/image_io_test.cpp +++ b/tests/cpp_tests/image_io_test.cpp @@ -1,10 +1,16 @@ #include #include +#include +#include #include #include #include #include #include +#if defined(HAVE_CAIRO) +#include +#include +#endif #include "utils.hpp" @@ -21,15 +27,7 @@ int main(int argc, char** argv) boost::optional type; try { - mapnik::image_data_32 im(256,256); - mapnik::image_data_32::pixel_type * data = im.getData(); - mapnik::image_data_32 * im_ptr = new mapnik::image_data_32(im.width(),im.height(),data); - mapnik::image_data_32::pixel_type * same_data = im_ptr->getData(); - BOOST_TEST(data == same_data); - delete im_ptr; - BOOST_TEST(data == same_data); BOOST_TEST(set_working_dir(args)); - #if defined(HAVE_JPEG) should_throw = "./tests/cpp_tests/data/blank.jpg"; BOOST_TEST( mapnik::util::exists( should_throw ) ); @@ -46,6 +44,38 @@ int main(int argc, char** argv) } #endif + try + { + mapnik::image_32 im(-10,-10); // should throw rather than overflow + BOOST_TEST( im.width() < 10 ); // should not get here, but if we did this test should fail + } + catch (std::exception const& ex) + { + BOOST_TEST( true ); // should hit bad alloc here + } + + try + { + mapnik::image_data_rgba8 im(-10,-10); // should throw rather than overflow + BOOST_TEST( im.width() < 10 ); // should not get here, but if we did this test should fail + } + catch (std::exception const& ex) + { + BOOST_TEST( true ); // should hit bad alloc here + } + +#if defined(HAVE_CAIRO) + mapnik::cairo_surface_ptr image_surface( + cairo_image_surface_create(CAIRO_FORMAT_ARGB32,256,257), + mapnik::cairo_surface_closer()); + mapnik::image_data_rgba8 im_data(cairo_image_surface_get_width(&*image_surface), cairo_image_surface_get_height(&*image_surface)); + im_data.set(1); + BOOST_TEST( (unsigned)im_data(0,0) == unsigned(1) ); + // Should set back to fully transparent + mapnik::cairo_image_to_rgba8(im_data, image_surface); + BOOST_TEST( (unsigned)im_data(0,0) == unsigned(0) ); +#endif + #if defined(HAVE_PNG) should_throw = "./tests/cpp_tests/data/blank.png"; BOOST_TEST( mapnik::util::exists( should_throw ) ); diff --git a/tests/cpp_tests/line_offset_test.cpp b/tests/cpp_tests/line_offset_test.cpp index 9e5732be1..d8dce5847 100644 --- a/tests/cpp_tests/line_offset_test.cpp +++ b/tests/cpp_tests/line_offset_test.cpp @@ -1,6 +1,6 @@ // mapnik #include -#include +#include // boost #include diff --git a/tests/cpp_tests/map_request_test.cpp b/tests/cpp_tests/map_request_test.cpp index 6af08c08e..b7f2deb64 100644 --- a/tests/cpp_tests/map_request_test.cpp +++ b/tests/cpp_tests/map_request_test.cpp @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include @@ -39,8 +41,8 @@ bool compare_images(std::string const& src_fn,std::string const& dest_fn) std::shared_ptr image_ptr2 = std::make_shared(reader2->width(),reader2->height()); reader2->read(0,0,image_ptr2->data()); - image_data_32 const& dest = image_ptr1->data(); - image_data_32 const& src = image_ptr2->data(); + image_data_rgba8 const& dest = image_ptr1->data(); + image_data_rgba8 const& src = image_ptr2->data(); unsigned int width = src.width(); unsigned int height = src.height(); @@ -65,9 +67,6 @@ int main(int argc, char** argv) args.push_back(argv[i]); } bool quiet = std::find(args.begin(), args.end(), "-q")!=args.end(); - // TODO - re-enable if we can control the freetype/cairo versions used - // https://github.com/mapnik/mapnik/issues/1868 - /* std::string expected("./tests/cpp_tests/support/map-request-marker-text-line-expected.png"); std::string expected_cairo("./tests/cpp_tests/support/map-request-marker-text-line-expected-cairo.png"); try { @@ -86,9 +85,11 @@ int main(int argc, char** argv) mapnik::agg_renderer renderer1(m,im,scale_factor); renderer1.apply(); std::string actual1("/tmp/map-request-marker-text-line-actual1.png"); - //mapnik::save_to_file(im,expected); - mapnik::save_to_file(im,actual1); - BOOST_TEST(compare_images(actual1,expected)); + //mapnik::save_to_file(im.data(),expected); + mapnik::save_to_file(im.data(),actual1); + // TODO - re-enable if we can control the freetype/cairo versions used + // https://github.com/mapnik/mapnik/issues/1868 + //BOOST_TEST(compare_images(actual1,expected)); // reset image im.clear(); @@ -98,17 +99,20 @@ int main(int argc, char** argv) req.set_buffer_size(m.buffer_size()); // render using apply() and mapnik::request - mapnik::agg_renderer renderer2(m,req,im,scale_factor); + mapnik::attributes vars; + mapnik::agg_renderer renderer2(m,req,vars,im,scale_factor); renderer2.apply(); std::string actual2("/tmp/map-request-marker-text-line-actual2.png"); - mapnik::save_to_file(im,actual2); - BOOST_TEST(compare_images(actual2,expected)); + mapnik::save_to_file(im.data(),actual2); + // TODO - re-enable if we can control the freetype/cairo versions used + // https://github.com/mapnik/mapnik/issues/1868 + //BOOST_TEST(compare_images(actual2,expected)); // reset image im.clear(); // render with apply_to_layer api and mapnik::request params passed to apply_to_layer - mapnik::agg_renderer renderer3(m,req,im,scale_factor); + mapnik::agg_renderer renderer3(m,req,vars,im,scale_factor); renderer3.start_map_processing(m); mapnik::projection map_proj(m.srs(),true); double scale_denom = mapnik::scale_denominator(req.scale(),map_proj.is_geographic()); @@ -133,8 +137,10 @@ int main(int argc, char** argv) } renderer3.end_map_processing(m); std::string actual3("/tmp/map-request-marker-text-line-actual3.png"); - mapnik::save_to_file(im,actual3); - BOOST_TEST(compare_images(actual3,expected)); + mapnik::save_to_file(im.data(),actual3); + // TODO - re-enable if we can control the freetype/cairo versions used + // https://github.com/mapnik/mapnik/issues/1868 + //BOOST_TEST(compare_images(actual3,expected)); // also test cairo #if defined(HAVE_CAIRO) @@ -142,19 +148,20 @@ int main(int argc, char** argv) cairo_image_surface_create(CAIRO_FORMAT_ARGB32,req.width(),req.height()), mapnik::cairo_surface_closer()); mapnik::cairo_ptr image_context = (mapnik::create_context(image_surface)); - mapnik::cairo_renderer png_render(m,req,image_context,scale_factor); + mapnik::cairo_renderer png_render(m,req,vars,image_context,scale_factor); png_render.apply(); //cairo_surface_write_to_png(&*image_surface, expected_cairo.c_str()); std::string actual_cairo("/tmp/map-request-marker-text-line-actual4.png"); cairo_surface_write_to_png(&*image_surface, actual_cairo.c_str()); - BOOST_TEST(compare_images(actual_cairo,expected_cairo)); + // TODO - re-enable if we can control the freetype/cairo versions used + // https://github.com/mapnik/mapnik/issues/1868 + //BOOST_TEST(compare_images(actual_cairo,expected_cairo)); #endif // TODO - test grid_renderer } catch (std::exception const& ex) { std::clog << ex.what() << "\n"; } - */ if (!::boost::detail::test_errors()) { if (quiet) std::clog << "\x1b[1;32m.\x1b[0m"; else std::clog << "C++ Map Request rendering hook: \x1b[1;32m✓ \x1b[0m\n"; diff --git a/tests/cpp_tests/simplify_converters_test.cpp b/tests/cpp_tests/simplify_converters_test.cpp index 4f6d32be1..b3923d0fc 100644 --- a/tests/cpp_tests/simplify_converters_test.cpp +++ b/tests/cpp_tests/simplify_converters_test.cpp @@ -7,9 +7,7 @@ #include #include -#include #include -#include #include #include diff --git a/tests/cxx/README.md b/tests/cxx/README.md new file mode 100644 index 000000000..273cade25 --- /dev/null +++ b/tests/cxx/README.md @@ -0,0 +1,11 @@ + +Catch C++ tests + +### Building + + python scons/scons.py tests/cxx/run + + +### Running + + ./tests/cxx/run \ No newline at end of file diff --git a/tests/cxx/build.py b/tests/cxx/build.py new file mode 100644 index 000000000..6626f03c4 --- /dev/null +++ b/tests/cxx/build.py @@ -0,0 +1,32 @@ +import os +import glob +from copy import copy + +Import ('env') + +test_env = env.Clone() + +if not env['CPP_TESTS']: + for cpp_test_bin in glob.glob('*-bin'): + os.unlink(cpp_test_bin) +else: + test_env['LIBS'] = [env['MAPNIK_NAME']] + test_env.AppendUnique(LIBS=copy(env['LIBMAPNIK_LIBS'])) + test_env.AppendUnique(LIBS='mapnik-wkt') + test_env.AppendUnique(LIBS='mapnik-json') + if env['RUNTIME_LINK'] == 'static' and env['PLATFORM'] == 'Linux': + test_env.AppendUnique(LIBS='dl') + test_env.AppendUnique(CXXFLAGS='-g') + test_env['CXXFLAGS'] = copy(test_env['LIBMAPNIK_CXXFLAGS']) + test_env.Append(CPPDEFINES = env['LIBMAPNIK_DEFINES']) + if test_env['HAS_CAIRO']: + test_env.PrependUnique(CPPPATH=test_env['CAIRO_CPPPATHS']) + test_env.Append(CPPDEFINES = '-DHAVE_CAIRO') + test_env_local = test_env.Clone() + test_program = test_env_local.Program("run", source=glob.glob('*.cpp')) + Depends(test_program, env.subst('../../src/%s' % env['MAPNIK_LIB_NAME'])) + Depends(test_program, env.subst('../../src/json/libmapnik-json${LIBSUFFIX}')) + Depends(test_program, env.subst('../../src/wkt/libmapnik-wkt${LIBSUFFIX}')) + # build locally if installing + if 'install' in COMMAND_LINE_TARGETS: + env.Alias('install',test_program) diff --git a/tests/cxx/catch.hpp b/tests/cxx/catch.hpp new file mode 100644 index 000000000..6b8dfb5eb --- /dev/null +++ b/tests/cxx/catch.hpp @@ -0,0 +1,8997 @@ +/* + * CATCH v1.0 build 53 (master branch) + * Generated: 2014-08-20 08:08:19.533804 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + +#define TWOBLUECUBES_CATCH_HPP_INCLUDED + +// #included from: internal/catch_suppress_warnings.h + +#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc99-extensions" +#pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#elif defined __GNUC__ +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpadded" +#endif + +#ifdef CATCH_CONFIG_MAIN +# define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// #included from: internal/catch_notimplemented_exception.h +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED + +// #included from: catch_common.h +#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED + +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) + +#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr +#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) + +#include +#include +#include + +// #included from: catch_compiler_capabilities.h +#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED + +// Much of the following code is based on Boost (1.53) + +#ifdef __clang__ + +# if __has_feature(cxx_nullptr) +# define CATCH_CONFIG_CPP11_NULLPTR +# endif + +# if __has_feature(cxx_noexcept) +# define CATCH_CONFIG_CPP11_NOEXCEPT +# endif + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Borland +#ifdef __BORLANDC__ + +#if (__BORLANDC__ > 0x582 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __BORLANDC__ + +//////////////////////////////////////////////////////////////////////////////// +// EDG +#ifdef __EDG_VERSION__ + +#if (__EDG_VERSION__ > 238 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __EDG_VERSION__ + +//////////////////////////////////////////////////////////////////////////////// +// Digital Mars +#ifdef __DMC__ + +#if (__DMC__ > 0x840 ) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // __DMC__ + +//////////////////////////////////////////////////////////////////////////////// +// GCC +#ifdef __GNUC__ + +#if __GNUC__ < 3 + +#if (__GNUC_MINOR__ >= 96 ) +//#define CATCH_CONFIG_SFINAE +#endif + +#elif __GNUC__ >= 3 + +// #define CATCH_CONFIG_SFINAE // Taking this out completely for now + +#endif // __GNUC__ < 3 + +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) + +#define CATCH_CONFIG_CPP11_NULLPTR +#endif + +#endif // __GNUC__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +#if (_MSC_VER >= 1310 ) // (VC++ 7.0+) +//#define CATCH_CONFIG_SFINAE // Not confirmed +#endif + +#endif // _MSC_VER + +// Use variadic macros if the compiler supports them +#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ + ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ + ( defined __GNUC__ && __GNUC__ >= 3 ) || \ + ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) + +#ifndef CATCH_CONFIG_NO_VARIADIC_MACROS +#define CATCH_CONFIG_VARIADIC_MACROS +#endif + +#endif + +//////////////////////////////////////////////////////////////////////////////// +// C++ language feature support + +// detect language version: +#if (__cplusplus == 201103L) +# define CATCH_CPP11 +# define CATCH_CPP11_OR_GREATER +#elif (__cplusplus >= 201103L) +# define CATCH_CPP11_OR_GREATER +#endif + +// noexcept support: +#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) +# define CATCH_NOEXCEPT noexcept +# define CATCH_NOEXCEPT_IS(x) noexcept(x) +#else +# define CATCH_NOEXCEPT throw() +# define CATCH_NOEXCEPT_IS(x) +#endif + +namespace Catch { + + class NonCopyable { + NonCopyable( NonCopyable const& ); + void operator = ( NonCopyable const& ); + protected: + NonCopyable() {} + virtual ~NonCopyable(); + }; + + class SafeBool { + public: + typedef void (SafeBool::*type)() const; + + static type makeSafe( bool value ) { + return value ? &SafeBool::trueValue : 0; + } + private: + void trueValue() const {} + }; + + template + inline void deleteAll( ContainerT& container ) { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete *it; + } + template + inline void deleteAllValues( AssociativeContainerT& container ) { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + delete it->second; + } + + bool startsWith( std::string const& s, std::string const& prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; + + struct SourceLineInfo { + + SourceLineInfo(); + SourceLineInfo( char const* _file, std::size_t _line ); + SourceLineInfo( SourceLineInfo const& other ); +# ifdef CATCH_CPP11_OR_GREATER + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; +# endif + bool empty() const; + bool operator == ( SourceLineInfo const& other ) const; + + std::string file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // This is just here to avoid compiler warnings with macro constants and boolean literals + inline bool isTrue( bool value ){ return value; } + inline bool alwaysTrue() { return true; } + inline bool alwaysFalse() { return false; } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() { + return std::string(); + } + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) +#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); + +#include + +namespace Catch { + + class NotImplementedException : public std::exception + { + public: + NotImplementedException( SourceLineInfo const& lineInfo ); + NotImplementedException( NotImplementedException const& ) {} + + virtual ~NotImplementedException() CATCH_NOEXCEPT {} + + virtual const char* what() const CATCH_NOEXCEPT; + + private: + std::string m_what; + SourceLineInfo m_lineInfo; + }; + +} // end namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) + +// #included from: internal/catch_context.h +#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED + +// #included from: catch_interfaces_generators.h +#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED + +#include + +namespace Catch { + + struct IGeneratorInfo { + virtual ~IGeneratorInfo(); + virtual bool moveNext() = 0; + virtual std::size_t getCurrentIndex() const = 0; + }; + + struct IGeneratorsForTest { + virtual ~IGeneratorsForTest(); + + virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; + virtual bool moveNext() = 0; + }; + + IGeneratorsForTest* createGeneratorsForTest(); + +} // end namespace Catch + +// #included from: catch_ptr.hpp +#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + // An intrusive reference counting smart pointer. + // T must implement addRef() and release() methods + // typically implementing the IShared interface + template + class Ptr { + public: + Ptr() : m_p( NULL ){} + Ptr( T* p ) : m_p( p ){ + if( m_p ) + m_p->addRef(); + } + Ptr( Ptr const& other ) : m_p( other.m_p ){ + if( m_p ) + m_p->addRef(); + } + ~Ptr(){ + if( m_p ) + m_p->release(); + } + void reset() { + if( m_p ) + m_p->release(); + m_p = NULL; + } + Ptr& operator = ( T* p ){ + Ptr temp( p ); + swap( temp ); + return *this; + } + Ptr& operator = ( Ptr const& other ){ + Ptr temp( other ); + swap( temp ); + return *this; + } + void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } + T* get() { return m_p; } + const T* get() const{ return m_p; } + T& operator*() const { return *m_p; } + T* operator->() const { return m_p; } + bool operator !() const { return m_p == NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + + private: + T* m_p; + }; + + struct IShared : NonCopyable { + virtual ~IShared(); + virtual void addRef() const = 0; + virtual void release() const = 0; + }; + + template + struct SharedImpl : T { + + SharedImpl() : m_rc( 0 ){} + + virtual void addRef() const { + ++m_rc; + } + virtual void release() const { + if( --m_rc == 0 ) + delete this; + } + + mutable unsigned int m_rc; + }; + +} // end namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#include +#include +#include + +namespace Catch { + + class TestCase; + class Stream; + struct IResultCapture; + struct IRunner; + struct IGeneratorsForTest; + struct IConfig; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; + virtual bool advanceGeneratorsForCurrentTest() = 0; + virtual Ptr getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( Ptr const& config ) = 0; + }; + + IContext& getCurrentContext(); + IMutableContext& getCurrentMutableContext(); + void cleanUpContext(); + Stream createStream( std::string const& streamName ); + +} + +// #included from: internal/catch_test_registry.hpp +#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED + +// #included from: catch_interfaces_testcase.h +#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED + +#include + +namespace Catch { + + class TestSpec; + + struct ITestCase : IShared { + virtual void invoke () const = 0; + protected: + virtual ~ITestCase(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const = 0; + + }; +} + +namespace Catch { + +template +class MethodTestCase : public SharedImpl { + +public: + MethodTestCase( void (C::*method)() ) : m_method( method ) {} + + virtual void invoke() const { + C obj; + (obj.*m_method)(); + } + +private: + virtual ~MethodTestCase() {} + + void (C::*m_method)(); +}; + +typedef void(*TestFunction)(); + +struct NameAndDesc { + NameAndDesc( const char* _name = "", const char* _description= "" ) + : name( _name ), description( _description ) + {} + + const char* name; + const char* description; +}; + +struct AutoReg { + + AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + + template + AutoReg( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + registerTestCase( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } + + void registerTestCase( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + + ~AutoReg(); + +private: + AutoReg( AutoReg const& ); + void operator= ( AutoReg const& ); +}; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( ... ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#else + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + namespace{ \ + struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + } \ + void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + +#endif + +// #included from: internal/catch_capture.hpp +#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED + +// #included from: catch_result_builder.h +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED + +// #included from: catch_result_type.h +#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2 + + }; }; + + inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x00, + + ContinueOnFailure = 0x01, // Failures fail test, but execution continues + FalseTest = 0x02, // Prefix expression with ! + SuppressFail = 0x04 // Failures are reported but do not fail the test + }; }; + + inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch + +// #included from: catch_assertionresult.h +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED + +#include + +namespace Catch { + + struct AssertionInfo + { + AssertionInfo() {} + AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ); + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + ResultDisposition::Flags resultDisposition; + }; + + struct AssertionResultData + { + AssertionResultData() : resultType( ResultWas::Unknown ) {} + + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + + class AssertionResult { + public: + AssertionResult(); + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + ~AssertionResult(); +# ifdef CATCH_CPP11_OR_GREATER + AssertionResult( AssertionResult const& ) = default; + AssertionResult( AssertionResult && ) = default; + AssertionResult& operator = ( AssertionResult const& ) = default; + AssertionResult& operator = ( AssertionResult && ) = default; +# endif + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + std::string getTestMacroName() const; + + protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +namespace Catch { + + struct TestFailureException{}; + + template class ExpressionLhs; + + struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; + + struct CopyableStream { + CopyableStream() {} + CopyableStream( CopyableStream const& other ) { + oss << other.oss.str(); + } + CopyableStream& operator=( CopyableStream const& other ) { + oss.str(""); + oss << other.oss.str(); + return *this; + } + std::ostringstream oss; + }; + + class ResultBuilder { + public: + ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ); + + template + ExpressionLhs operator->* ( T const& operand ); + ExpressionLhs operator->* ( bool value ); + + template + ResultBuilder& operator << ( T const& value ) { + m_stream.oss << value; + return *this; + } + + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + + ResultBuilder& setResultType( ResultWas::OfType result ); + ResultBuilder& setResultType( bool result ); + ResultBuilder& setLhs( std::string const& lhs ); + ResultBuilder& setRhs( std::string const& rhs ); + ResultBuilder& setOp( std::string const& op ); + + void endExpression(); + + std::string reconstructExpression() const; + AssertionResult build() const; + + void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); + void captureResult( ResultWas::OfType resultType ); + void captureExpression(); + void react(); + bool shouldDebugBreak() const; + bool allowThrows() const; + + private: + AssertionInfo m_assertionInfo; + AssertionResultData m_data; + struct ExprComponents { + ExprComponents() : testFalse( false ) {} + bool testFalse; + std::string lhs, rhs, op; + } m_exprComponents; + CopyableStream m_stream; + + bool m_shouldDebugBreak; + bool m_shouldThrow; + }; + +} // namespace Catch + +// Include after due to circular dependency: +// #included from: catch_expression_lhs.hpp +#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED + +// #included from: catch_evaluate.hpp +#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#endif + +#include + +namespace Catch { +namespace Internal { + + enum Operator { + IsEqualTo, + IsNotEqualTo, + IsLessThan, + IsGreaterThan, + IsLessThanOrEqualTo, + IsGreaterThanOrEqualTo + }; + + template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; + template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; + template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; + template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; + + template + inline T& opCast(T const& t) { return const_cast(t); } + +// nullptr_t support based on pull request #154 from Konstantin Baumann +#ifdef CATCH_CONFIG_CPP11_NULLPTR + inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } +#endif // CATCH_CONFIG_CPP11_NULLPTR + + // So the compare overloads can be operator agnostic we convey the operator as a template + // enum, which is used to specialise an Evaluator for doing the comparison. + template + class Evaluator{}; + + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs) { + return opCast( lhs ) == opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) != opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) < opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) > opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) >= opCast( rhs ); + } + }; + template + struct Evaluator { + static bool evaluate( T1 const& lhs, T2 const& rhs ) { + return opCast( lhs ) <= opCast( rhs ); + } + }; + + template + bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // This level of indirection allows us to specialise for integer types + // to avoid signed/ unsigned warnings + + // "base" overload + template + bool compare( T1 const& lhs, T2 const& rhs ) { + return Evaluator::evaluate( lhs, rhs ); + } + + // unsigned X to int + template bool compare( unsigned int lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, int rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // unsigned X to long + template bool compare( unsigned int lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned long lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + template bool compare( unsigned char lhs, long rhs ) { + return applyEvaluator( lhs, static_cast( rhs ) ); + } + + // int to unsigned X + template bool compare( int lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( int lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // long to unsigned X + template bool compare( long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long (when comparing against NULL) + template bool compare( long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + + // pointer to int (when comparing against NULL) + template bool compare( int lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, int rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } + +#ifdef CATCH_CONFIG_CPP11_NULLPTR + // pointer to nullptr_t (when comparing against nullptr) + template bool compare( std::nullptr_t, T* rhs ) { + return Evaluator::evaluate( NULL, rhs ); + } + template bool compare( T* lhs, std::nullptr_t ) { + return Evaluator::evaluate( lhs, NULL ); + } +#endif // CATCH_CONFIG_CPP11_NULLPTR + +} // end of namespace Internal +} // end of namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// #included from: catch_tostring.h +#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED + +// #included from: catch_sfinae.hpp +#define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED + +// Try to detect if the current compiler supports SFINAE + +namespace Catch { + + struct TrueType { + static const bool value = true; + typedef void Enable; + char sizer[1]; + }; + struct FalseType { + static const bool value = false; + typedef void Disable; + char sizer[2]; + }; + +#ifdef CATCH_CONFIG_SFINAE + + template struct NotABooleanExpression; + + template struct If : NotABooleanExpression {}; + template<> struct If : TrueType {}; + template<> struct If : FalseType {}; + + template struct SizedIf; + template<> struct SizedIf : TrueType {}; + template<> struct SizedIf : FalseType {}; + +#endif // CATCH_CONFIG_SFINAE + +} // end namespace Catch + +#include +#include +#include +#include +#include + +#ifdef __OBJC__ +// #included from: catch_objc_arc.hpp +#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +#endif + +namespace Catch { +namespace Detail { + +// SFINAE is currently disabled by default for all compilers. +// If the non SFINAE version of IsStreamInsertable is ambiguous for you +// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE +#ifdef CATCH_CONFIG_SFINAE + + template + class IsStreamInsertableHelper { + template struct TrueIfSizeable : TrueType {}; + + template + static TrueIfSizeable dummy(T2*); + static FalseType dummy(...); + + public: + typedef SizedIf type; + }; + + template + struct IsStreamInsertable : IsStreamInsertableHelper::type {}; + +#else + + struct BorgType { + template BorgType( T const& ); + }; + + TrueType& testStreamable( std::ostream& ); + FalseType testStreamable( FalseType ); + + FalseType operator<<( std::ostream const&, BorgType const& ); + + template + struct IsStreamInsertable { + static std::ostream &s; + static T const&t; + enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; + }; + +#endif + + template + struct StringMakerBase { + template + static std::string convert( T const& ) { return "{?}"; } + }; + + template<> + struct StringMakerBase { + template + static std::string convert( T const& _value ) { + std::ostringstream oss; + oss << _value; + return oss.str(); + } + }; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + inline std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + +} // end namespace Detail + +template +std::string toString( T const& value ); + +template +struct StringMaker : + Detail::StringMakerBase::value> {}; + +template +struct StringMaker { + template + static std::string convert( U* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +template +struct StringMaker { + static std::string convert( R C::* p ) { + if( !p ) + return INTERNAL_CATCH_STRINGIFY( NULL ); + else + return Detail::rawMemoryToString( p ); + } +}; + +namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ); +} + +template +struct StringMaker > { + static std::string convert( std::vector const& v ) { + return Detail::rangeToString( v.begin(), v.end() ); + } +}; + +namespace Detail { + template + std::string makeString( T const& value ) { + return StringMaker::convert( value ); + } +} // end namespace Detail + +/// \brief converts any type to a string +/// +/// The default template forwards on to ostringstream - except when an +/// ostringstream overload does not exist - in which case it attempts to detect +/// that and writes {?}. +/// Overload (not specialise) this template for custom typs that you don't want +/// to provide an ostream overload for. +template +std::string toString( T const& value ) { + return StringMaker::convert( value ); +} + +// Built in overloads + +std::string toString( std::string const& value ); +std::string toString( std::wstring const& value ); +std::string toString( const char* const value ); +std::string toString( char* const value ); +std::string toString( const wchar_t* const value ); +std::string toString( wchar_t* const value ); +std::string toString( int value ); +std::string toString( unsigned long value ); +std::string toString( unsigned int value ); +std::string toString( const double value ); +std::string toString( const float value ); +std::string toString( bool value ); +std::string toString( char value ); +std::string toString( signed char value ); +std::string toString( unsigned char value ); + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ); +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ); + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); + std::string toString( NSObject* const& nsObject ); +#endif + + namespace Detail { + template + std::string rangeToString( InputIterator first, InputIterator last ) { + std::ostringstream oss; + oss << "{ "; + if( first != last ) { + oss << toString( *first ); + for( ++first ; first != last ; ++first ) { + oss << ", " << toString( *first ); + } + } + oss << " }"; + return oss.str(); + } +} + +} // end namespace Catch + +namespace Catch { + +// Wraps the LHS of an expression and captures the operator and RHS (if any) - +// wrapping them all in a ResultBuilder object +template +class ExpressionLhs { + ExpressionLhs& operator = ( ExpressionLhs const& ); +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs& operator = ( ExpressionLhs && ) = delete; +# endif + +public: + ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} +# ifdef CATCH_CPP11_OR_GREATER + ExpressionLhs( ExpressionLhs const& ) = default; + ExpressionLhs( ExpressionLhs && ) = default; +# endif + + template + ResultBuilder& operator == ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator != ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator < ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator > ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator <= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + template + ResultBuilder& operator >= ( RhsT const& rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator == ( bool rhs ) { + return captureExpression( rhs ); + } + + ResultBuilder& operator != ( bool rhs ) { + return captureExpression( rhs ); + } + + void endExpression() { + bool value = m_lhs ? true : false; + m_rb + .setLhs( Catch::toString( value ) ) + .setResultType( value ) + .endExpression(); + } + + // Only simple binary expressions are allowed on the LHS. + // If more complex compositions are required then place the sub expression in parentheses + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& ); + template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& ); + +private: + template + ResultBuilder& captureExpression( RhsT const& rhs ) { + return m_rb + .setResultType( Internal::compare( m_lhs, rhs ) ) + .setLhs( Catch::toString( m_lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); + } + +private: + ResultBuilder& m_rb; + T m_lhs; +}; + +} // end namespace Catch + + +namespace Catch { + + template + inline ExpressionLhs ResultBuilder::operator->* ( T const& operand ) { + return ExpressionLhs( *this, operand ); + } + + inline ExpressionLhs ResultBuilder::operator->* ( bool value ) { + return ExpressionLhs( *this, value ); + } + +} // namespace Catch + +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + struct MessageBuilder { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + : m_info( macroName, lineInfo, type ) + {} + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + std::ostringstream m_stream; + }; + + class ScopedMessage { + public: + ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage const& other ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// #included from: catch_interfaces_capture.h +#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct MessageInfo; + class ScopedMessageBuilder; + struct Counts; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual void assertionEnded( AssertionResult const& result ) = 0; + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + }; + + IResultCapture& getResultCapture(); +} + +// #included from: catch_debugger.h +#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED + +// #included from: catch_platform.h +#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED + +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define CATCH_PLATFORM_IPHONE +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CATCH_PLATFORM_WINDOWS +#endif + +#include + +namespace Catch{ + + bool isDebuggerActive(); + void writeToDebugConsole( std::string const& text ); +} + +#ifdef CATCH_PLATFORM_MAC + + // The following code snippet based on: + // http://cocoawithlove.com/2008/03/break-into-debugger.html + #ifdef DEBUG + #if defined(__ppc64__) || defined(__ppc__) + #define CATCH_BREAK_INTO_DEBUGGER() \ + if( Catch::isDebuggerActive() ) { \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ); \ + } + #else + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} + #endif + #endif + +#elif defined(_MSC_VER) + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); } +#endif + +#ifndef CATCH_BREAK_INTO_DEBUGGER +#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); +#endif + +// #included from: catch_interfaces_runner.h +#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED + +namespace Catch { + class TestCase; + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +/////////////////////////////////////////////////////////////////////////////// +// In the event of a failure works out if the debugger needs to be invoked +// and/or an exception thrown and takes appropriate action. +// This needs to be done as a macro so the debugger will stop in the user +// source code rather than in Catch library code +#define INTERNAL_CATCH_REACT( resultBuilder ) \ + if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ + resultBuilder.react(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + ( __catchResult->*expr ).endExpression(); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ + INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ + if( !Catch::getResultCapture().getLastResult()->succeeded() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( ... ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + if( __catchResult.allowThrows() ) \ + try { \ + expr; \ + __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ + } \ + catch( exceptionType ) { \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + } \ + catch( ... ) { \ + __catchResult.useActiveException( resultDisposition ); \ + } \ + else \ + __catchResult.captureResult( Catch::ResultWas::Ok ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +/////////////////////////////////////////////////////////////////////////////// +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#else + #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + __catchResult << log + ::Catch::StreamEndStop(); \ + __catchResult.captureResult( messageType ); \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) +#endif + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( log, macroName ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ + do { \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ + try { \ + std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + __catchResult \ + .setLhs( Catch::toString( arg ) ) \ + .setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ + .setOp( "matches" ) \ + .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + __catchResult.captureExpression(); \ + } catch( ... ) { \ + __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ + } \ + INTERNAL_CATCH_REACT( __catchResult ) \ + } while( Catch::alwaysFalse() ) + +// #included from: internal/catch_section.h +#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED + +// #included from: catch_section_info.h +#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// #included from: catch_totals.hpp +#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED + +#include + +namespace Catch { + + struct Counts { + Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} + + Counts operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + Counts& operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t total() const { + return passed + failed + failedButOk; + } + bool allPassed() const { + return failed == 0 && failedButOk == 0; + } + + std::size_t passed; + std::size_t failed; + std::size_t failedButOk; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + + Totals& operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Counts assertions; + Counts testCases; + }; +} + +// #included from: catch_timer.h +#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED + +#ifdef CATCH_PLATFORM_WINDOWS +typedef unsigned long long uint64_t; +#else +#include +#endif + +namespace Catch { + + class Timer { + public: + Timer() : m_ticks( 0 ) {} + void start(); + unsigned int getElapsedNanoseconds() const; + unsigned int getElapsedMilliseconds() const; + double getElapsedSeconds() const; + + private: + uint64_t m_ticks; + }; + +} // namespace Catch + +#include + +namespace Catch { + + class Section { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + operator bool() const; + + private: +#ifdef CATCH_CPP11_OR_GREATER + Section( Section const& ) = delete; + Section( Section && ) = delete; + Section& operator = ( Section const& ) = delete; + Section& operator = ( Section && ) = delete; +#else + Section( Section const& info ); + Section& operator = ( Section const& ); +#endif + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) +#else + #define INTERNAL_CATCH_SECTION( name, desc ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) +#endif + +// #included from: internal/catch_generators.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + +template +struct IGenerator { + virtual ~IGenerator() {} + virtual T getValue( std::size_t index ) const = 0; + virtual std::size_t size () const = 0; +}; + +template +class BetweenGenerator : public IGenerator { +public: + BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} + + virtual T getValue( std::size_t index ) const { + return m_from+static_cast( index ); + } + + virtual std::size_t size() const { + return static_cast( 1+m_to-m_from ); + } + +private: + + T m_from; + T m_to; +}; + +template +class ValuesGenerator : public IGenerator { +public: + ValuesGenerator(){} + + void add( T value ) { + m_values.push_back( value ); + } + + virtual T getValue( std::size_t index ) const { + return m_values[index]; + } + + virtual std::size_t size() const { + return m_values.size(); + } + +private: + std::vector m_values; +}; + +template +class CompositeGenerator { +public: + CompositeGenerator() : m_totalSize( 0 ) {} + + // *** Move semantics, similar to auto_ptr *** + CompositeGenerator( CompositeGenerator& other ) + : m_fileInfo( other.m_fileInfo ), + m_totalSize( 0 ) + { + move( other ); + } + + CompositeGenerator& setFileInfo( const char* fileInfo ) { + m_fileInfo = fileInfo; + return *this; + } + + ~CompositeGenerator() { + deleteAll( m_composed ); + } + + operator T () const { + size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); + + typename std::vector*>::const_iterator it = m_composed.begin(); + typename std::vector*>::const_iterator itEnd = m_composed.end(); + for( size_t index = 0; it != itEnd; ++it ) + { + const IGenerator* generator = *it; + if( overallIndex >= index && overallIndex < index + generator->size() ) + { + return generator->getValue( overallIndex-index ); + } + index += generator->size(); + } + CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); + return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so + } + + void add( const IGenerator* generator ) { + m_totalSize += generator->size(); + m_composed.push_back( generator ); + } + + CompositeGenerator& then( CompositeGenerator& other ) { + move( other ); + return *this; + } + + CompositeGenerator& then( T value ) { + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( value ); + add( valuesGen ); + return *this; + } + +private: + + void move( CompositeGenerator& other ) { + std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) ); + m_totalSize += other.m_totalSize; + other.m_composed.clear(); + } + + std::vector*> m_composed; + std::string m_fileInfo; + size_t m_totalSize; +}; + +namespace Generators +{ + template + CompositeGenerator between( T from, T to ) { + CompositeGenerator generators; + generators.add( new BetweenGenerator( from, to ) ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3 ){ + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + generators.add( valuesGen ); + return generators; + } + + template + CompositeGenerator values( T val1, T val2, T val3, T val4 ) { + CompositeGenerator generators; + ValuesGenerator* valuesGen = new ValuesGenerator(); + valuesGen->add( val1 ); + valuesGen->add( val2 ); + valuesGen->add( val3 ); + valuesGen->add( val4 ); + generators.add( valuesGen ); + return generators; + } + +} // end namespace Generators + +using namespace Generators; + +} // end namespace Catch + +#define INTERNAL_CATCH_LINESTR2( line ) #line +#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) + +#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) + +// #included from: internal/catch_interfaces_exception.h +#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED + +#include +// #included from: catch_interfaces_registry_hub.h +#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED + +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + + +namespace Catch { + + typedef std::string(*exceptionTranslateFunction)(); + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate() const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + virtual std::string translate() const { + try { + throw; + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ + static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) + +// #included from: internal/catch_approx.hpp +#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + public: + explicit Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_scale( 1.0 ), + m_value( value ) + {} + + Approx( Approx const& other ) + : m_epsilon( other.m_epsilon ), + m_scale( other.m_scale ), + m_value( other.m_value ) + {} + + static Approx custom() { + return Approx( 0 ); + } + + Approx operator()( double value ) { + Approx approx( value ); + approx.epsilon( m_epsilon ); + approx.scale( m_scale ); + return approx; + } + + friend bool operator == ( double lhs, Approx const& rhs ) { + // Thanks to Richard Harris for his help refining this formula + return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) ); + } + + friend bool operator == ( Approx const& lhs, double rhs ) { + return operator==( rhs, lhs ); + } + + friend bool operator != ( double lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + friend bool operator != ( Approx const& lhs, double rhs ) { + return !operator==( rhs, lhs ); + } + + Approx& epsilon( double newEpsilon ) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale( double newScale ) { + m_scale = newScale; + return *this; + } + + std::string toString() const { + std::ostringstream oss; + oss << "Approx( " << Catch::toString( m_value ) << " )"; + return oss.str(); + } + + private: + double m_epsilon; + double m_scale; + double m_value; + }; +} + +template<> +inline std::string toString( Detail::Approx const& value ) { + return value.toString(); +} + +} // end namespace Catch + +// #included from: internal/catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct Equals : MatcherImpl { + Equals( std::string const& str ) : m_str( str ){} + Equals( Equals const& other ) : m_str( other.m_str ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_str == expr; + } + virtual std::string toString() const { + return "equals: \"" + m_str + "\""; + } + + std::string m_str; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr ) : m_substr( substr ){} + Contains( Contains const& other ) : m_substr( other.m_substr ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr ) : m_substr( substr ){} + StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr ) : m_substr( substr ){} + EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return expr.find( m_substr ) == expr.size() - m_substr.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_substr + "\""; + } + + std::string m_substr; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str ) { + return Impl::StdString::Equals( str ); + } + inline Impl::StdString::Equals Equals( const char* str ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + } + inline Impl::StdString::Contains Contains( std::string const& substr ) { + return Impl::StdString::Contains( substr ); + } + inline Impl::StdString::Contains Contains( const char* substr ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + +// #included from: internal/catch_interfaces_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED + +// #included from: catch_tag_alias.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED + +#include + +namespace Catch { + + struct TagAlias { + TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} + + std::string tag; + SourceLineInfo lineInfo; + }; + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } +// #included from: catch_option.hpp +#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( NULL ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = NULL; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != NULL; } + bool none() const { return nullableValue == NULL; } + + bool operator !() const { return nullableValue == NULL; } + operator SafeBool::type() const { + return SafeBool::makeSafe( some() ); + } + + private: + T* nullableValue; + char storage[sizeof(T)]; + }; + +} // end namespace Catch + +namespace Catch { + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + virtual Option find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// #included from: internal/catch_test_case_info.h +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED + +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestCase; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ); + + TestCaseInfo( TestCaseInfo const& other ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string name; + std::string className; + std::string description; + std::set tags; + std::set lcaseTags; + std::string tagsAsString; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestCase* testCase, TestCaseInfo const& info ); + TestCase( TestCase const& other ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + void swap( TestCase& other ); + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + TestCase& operator = ( TestCase const& other ); + + private: + Ptr test; + }; + + TestCase makeTestCase( ITestCase* testCase, + std::string const& className, + std::string const& name, + std::string const& description, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + +#ifdef __OBJC__ +// #included from: internal/catch_objc.hpp +#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public SharedImpl { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline size_t registerTestMethods() { + size_t noTestMethods = 0; + int noClasses = objc_getClassList( NULL, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + template + struct StringHolder : MatcherImpl{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + NSString* m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + virtual std::string toString() const { + return "equals string: " + Catch::toString( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + virtual std::string toString() const { + return "contains string: " + Catch::toString( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + virtual std::string toString() const { + return "starts with: " + Catch::toString( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + virtual bool match( ExpressionType const& str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + virtual std::string toString() const { + return "ends with: " + Catch::toString( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_TEST_CASE( name, desc )\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ +{\ +return @ name; \ +}\ ++(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ +{ \ +return @ desc; \ +} \ +-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) + +#endif + +#ifdef CATCH_CONFIG_RUNNER +// #included from: internal/catch_impl.hpp +#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED + +// Collect all the implementation files together here +// These are the equivalent of what would usually be cpp files + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// #included from: catch_runner.hpp +#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED + +// #included from: internal/catch_commandline.hpp +#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED + +// #included from: catch_config.hpp +#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED + +// #included from: catch_test_spec_parser.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// #included from: catch_test_spec.hpp +#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern : SharedImpl<> { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + class NamePattern : public Pattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { + if( startsWith( m_name, "*" ) ) { + m_name = m_name.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_name, "*" ) ) { + m_name = m_name.substr( 0, m_name.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_name == toLower( testCase.name ); + case WildcardAtStart: + return endsWith( toLower( testCase.name ), m_name ); + case WildcardAtEnd: + return startsWith( toLower( testCase.name ), m_name ); + case WildcardAtBothEnds: + return contains( toLower( testCase.name ), m_name ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string m_name; + WildcardPosition m_wildcard; + }; + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { + return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); + } + private: + std::string m_tag; + }; + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + private: + Ptr m_underlyingPattern; + }; + + struct Filter { + std::vector > m_patterns; + + bool matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) + if( !(*it)->matches( testCase ) ) + return false; + return true; + } + }; + + public: + bool hasFilters() const { + return !m_filters.empty(); + } + bool matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) + if( it->matches( testCase ) ) + return true; + return false; + } + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag }; + Mode m_mode; + bool m_exclusion; + std::size_t m_start, m_pos; + std::string m_arg; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec testSpec() { + addFilter(); + return m_testSpec; + } + private: + void visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + } + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + template + void addPattern() { + std::string token = subString(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + Ptr pattern = new T( token ); + if( m_exclusion ) + pattern = new TestSpec::ExcludedPattern( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + void addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + }; + inline TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// #included from: catch_interfaces_config.h +#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct Verbosity { enum Level { + NoOutput = 0, + Quiet, + Normal + }; }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + + class TestSpec; + + struct IConfig : IShared { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + }; +} + +// #included from: catch_stream.h +#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED + +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + class Stream { + public: + Stream(); + Stream( std::streambuf* _streamBuf, bool _isOwned ); + void release(); + + std::streambuf* streamBuf; + + private: + bool isOwned; + }; +} + +#include +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct ConfigData { + + ConfigData() + : listTests( false ), + listTags( false ), + listReporters( false ), + listTestNamesOnly( false ), + showSuccessfulTests( false ), + shouldDebugBreak( false ), + noThrow( false ), + showHelp( false ), + showInvisibles( false ), + abortAfter( -1 ), + verbosity( Verbosity::Normal ), + warnings( WarnAbout::Nothing ), + showDurations( ShowDurations::DefaultForReporter ) + {} + + bool listTests; + bool listTags; + bool listReporters; + bool listTestNamesOnly; + + bool showSuccessfulTests; + bool shouldDebugBreak; + bool noThrow; + bool showHelp; + bool showInvisibles; + + int abortAfter; + + Verbosity::Level verbosity; + WarnAbout::What warnings; + ShowDurations::OrNot showDurations; + + std::string reporterName; + std::string outputFilename; + std::string name; + std::string processName; + + std::vector testsOrTags; + }; + + class Config : public SharedImpl { + private: + Config( Config const& other ); + Config& operator = ( Config const& other ); + virtual void dummy(); + public: + + Config() + : m_os( std::cout.rdbuf() ) + {} + + Config( ConfigData const& data ) + : m_data( data ), + m_os( std::cout.rdbuf() ) + { + if( !data.testsOrTags.empty() ) { + TestSpecParser parser( ITagAliasRegistry::get() ); + for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) + parser.parse( data.testsOrTags[i] ); + m_testSpec = parser.testSpec(); + } + } + + virtual ~Config() { + m_os.rdbuf( std::cout.rdbuf() ); + m_stream.release(); + } + + void setFilename( std::string const& filename ) { + m_data.outputFilename = filename; + } + + std::string const& getFilename() const { + return m_data.outputFilename ; + } + + bool listTests() const { return m_data.listTests; } + bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool listTags() const { return m_data.listTags; } + bool listReporters() const { return m_data.listReporters; } + + std::string getProcessName() const { return m_data.processName; } + + bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } + + void setStreamBuf( std::streambuf* buf ) { + m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); + } + + void useStream( std::string const& streamName ) { + Stream stream = createStream( streamName ); + setStreamBuf( stream.streamBuf ); + m_stream.release(); + m_stream = stream; + } + + std::string getReporterName() const { return m_data.reporterName; } + + int abortAfter() const { return m_data.abortAfter; } + + TestSpec const& testSpec() const { return m_testSpec; } + + bool showHelp() const { return m_data.showHelp; } + bool showInvisibles() const { return m_data.showInvisibles; } + + // IConfig interface + virtual bool allowThrows() const { return !m_data.noThrow; } + virtual std::ostream& stream() const { return m_os; } + virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } + virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } + + private: + ConfigData m_data; + + Stream m_stream; + mutable std::ostream m_os; + TestSpec m_testSpec; + }; + +} // end namespace Catch + +// #included from: catch_clara.h +#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH +#undef CLARA_CONFIG_CONSOLE_WIDTH +#endif +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +// Declare Clara inside the Catch namespace +#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { +// #included from: ../external/clara.h + +// Only use header guard if we are not using an outer namespace +#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) + +#ifndef STITCH_CLARA_OPEN_NAMESPACE +#define TWOBLUECUBES_CLARA_H_INCLUDED +#define STITCH_CLARA_OPEN_NAMESPACE +#define STITCH_CLARA_CLOSE_NAMESPACE +#else +#define STITCH_CLARA_CLOSE_NAMESPACE } +#endif + +#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE + +// ----------- #included from tbc_text_format.h ----------- + +// Only use header guard if we are not using an outer namespace +#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) +#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +#define TBC_TEXT_FORMAT_H_INCLUDED +#endif + +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TBC_TEXT_FORMAT_H_INCLUDED + +// ----------- end of #include from tbc_text_format.h ----------- +// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h + +#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE + +#include +#include +#include +#include + +// Use optional outer namespace +#ifdef STITCH_CLARA_OPEN_NAMESPACE +STITCH_CLARA_OPEN_NAMESPACE +#endif + +namespace Clara { + + struct UnpositionalTag {}; + + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif + + namespace Detail { + +#ifdef CLARA_CONSOLE_WIDTH + const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + using namespace Tbc; + + inline bool startsWith( std::string const& str, std::string const& prefix ) { + return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; + } + + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + template struct RemoveConstRef{ typedef T type; }; + + template struct IsBool { static const bool value = false; }; + template<> struct IsBool { static const bool value = true; }; + + template + void convertInto( std::string const& _source, T& _dest ) { + std::stringstream ss; + ss << _source; + ss >> _dest; + if( ss.fail() ) + throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); + } + inline void convertInto( std::string const& _source, std::string& _dest ) { + _dest = _source; + } + inline void convertInto( std::string const& _source, bool& _dest ) { + std::string sourceLC = _source; + std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower ); + if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) + _dest = true; + else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) + _dest = false; + else + throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); + } + inline void convertInto( bool _source, bool& _dest ) { + _dest = _source; + } + template + inline void convertInto( bool, T& ) { + throw std::runtime_error( "Invalid conversion" ); + } + + template + struct IArgFunction { + virtual ~IArgFunction() {} +# ifdef CATCH_CPP11_OR_GREATER + IArgFunction() = default; + IArgFunction( IArgFunction const& ) = default; +# endif + virtual void set( ConfigT& config, std::string const& value ) const = 0; + virtual void setFlag( ConfigT& config ) const = 0; + virtual bool takesArg() const = 0; + virtual IArgFunction* clone() const = 0; + }; + + template + class BoundArgFunction { + public: + BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction& operator = ( BoundArgFunction const& other ) { + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + delete functionObj; + functionObj = newFunctionObj; + return *this; + } + ~BoundArgFunction() { delete functionObj; } + + void set( ConfigT& config, std::string const& value ) const { + functionObj->set( config, value ); + } + void setFlag( ConfigT& config ) const { + functionObj->setFlag( config ); + } + bool takesArg() const { return functionObj->takesArg(); } + + bool isSet() const { + return functionObj != NULL; + } + private: + IArgFunction* functionObj; + }; + + template + struct NullBinder : IArgFunction{ + virtual void set( C&, std::string const& ) const {} + virtual void setFlag( C& ) const {} + virtual bool takesArg() const { return true; } + virtual IArgFunction* clone() const { return new NullBinder( *this ); } + }; + + template + struct BoundDataMember : IArgFunction{ + BoundDataMember( M C::* _member ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + convertInto( stringValue, p.*member ); + } + virtual void setFlag( C& p ) const { + convertInto( true, p.*member ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } + M C::* member; + }; + template + struct BoundUnaryMethod : IArgFunction{ + BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + (p.*member)( value ); + } + virtual void setFlag( C& p ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + (p.*member)( value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } + void (C::*member)( M ); + }; + template + struct BoundNullaryMethod : IArgFunction{ + BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} + virtual void set( C& p, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + (p.*member)(); + } + virtual void setFlag( C& p ) const { + (p.*member)(); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } + void (C::*member)(); + }; + + template + struct BoundUnaryFunction : IArgFunction{ + BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + bool value; + convertInto( stringValue, value ); + if( value ) + function( obj ); + } + virtual void setFlag( C& p ) const { + function( p ); + } + virtual bool takesArg() const { return false; } + virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } + void (*function)( C& ); + }; + + template + struct BoundBinaryFunction : IArgFunction{ + BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} + virtual void set( C& obj, std::string const& stringValue ) const { + typename RemoveConstRef::type value; + convertInto( stringValue, value ); + function( obj, value ); + } + virtual void setFlag( C& obj ) const { + typename RemoveConstRef::type value; + convertInto( true, value ); + function( obj, value ); + } + virtual bool takesArg() const { return !IsBool::value; } + virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } + void (*function)( C&, T ); + }; + + } // namespace Detail + + struct Parser { + Parser() : separators( " \t=:" ) {} + + struct Token { + enum Type { Positional, ShortOpt, LongOpt }; + Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} + Type type; + std::string data; + }; + + void parseIntoTokens( int argc, char const * const * argv, std::vector& tokens ) const { + const std::string doubleDash = "--"; + for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) + parseIntoTokens( argv[i] , tokens); + } + void parseIntoTokens( std::string arg, std::vector& tokens ) const { + while( !arg.empty() ) { + Parser::Token token( Parser::Token::Positional, arg ); + arg = ""; + if( token.data[0] == '-' ) { + if( token.data.size() > 1 && token.data[1] == '-' ) { + token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); + } + else { + token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); + if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { + arg = "-" + token.data.substr( 1 ); + token.data = token.data.substr( 0, 1 ); + } + } + } + if( token.type != Parser::Token::Positional ) { + std::size_t pos = token.data.find_first_of( separators ); + if( pos != std::string::npos ) { + arg = token.data.substr( pos+1 ); + token.data = token.data.substr( 0, pos ); + } + } + tokens.push_back( token ); + } + } + std::string separators; + }; + + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string detail; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + void validate() const { + if( !boundField.isSet() ) + throw std::logic_error( "option not bound" ); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + + template + class CommandLine { + + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD + + std::string dbgName() const { + if( !longName.empty() ) + return "--" + longName; + if( !shortNames.empty() ) + return "-" + shortNames[0]; + return "positional args"; + } + std::string commands() const { + std::ostringstream oss; + bool first = true; + std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); + for(; it != itEnd; ++it ) { + if( first ) + first = false; + else + oss << ", "; + oss << "-" << *it; + } + if( !longName.empty() ) { + if( !first ) + oss << ", "; + oss << "--" << longName; + } + if( !placeholder.empty() ) + oss << " <" << placeholder << ">"; + return oss.str(); + } + }; + + // NOTE: std::auto_ptr is deprecated in c++11/c++0x +#if defined(__cplusplus) && __cplusplus > 199711L + typedef std::unique_ptr ArgAutoPtr; +#else + typedef std::auto_ptr ArgAutoPtr; +#endif + + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { + public: + ArgBuilder( Arg* arg ) : m_arg( arg ) {} + + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + m_arg->placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg->boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + m_arg->placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::* unaryMethod)( bool ) ) { + m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::* nullaryMethod)() ) { + m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (* unaryFunction)( C& ) ) { + m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); + m_arg->placeholder = placeholder; + } + + ArgBuilder& describe( std::string const& description ) { + m_arg->description = description; + return *this; + } + ArgBuilder& detail( std::string const& detail ) { + m_arg->detail = detail; + return *this; + } + + protected: + Arg* m_arg; + }; + + class OptBuilder : public ArgBuilder { + public: + OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} + OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} + + OptBuilder& operator[]( std::string const& optName ) { + addOptName( *ArgBuilder::m_arg, optName ); + return *this; + } + }; + + public: + + CommandLine() + : m_boundProcessName( new Detail::NullBinder() ), + m_highestSpecifiedArgPosition( 0 ), + m_throwOnUnrecognisedTokens( false ) + {} + CommandLine( CommandLine const& other ) + : m_boundProcessName( other.m_boundProcessName ), + m_options ( other.m_options ), + m_positionalArgs( other.m_positionalArgs ), + m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), + m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) + { + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); + } + + CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { + m_throwOnUnrecognisedTokens = shouldThrow; + return *this; + } + + OptBuilder operator[]( std::string const& optName ) { + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( &m_options.back() ); + return builder; + } + + ArgBuilder operator[]( int position ) { + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( &m_positionalArgs[position] ); + return builder; + } + + // Invoke this with the _ instance + ArgBuilder operator[]( UnpositionalTag ) { + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( m_floatingArg.get() ); + return builder; + } + + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { + typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; + std::size_t maxWidth = 0; + for( it = itBegin; it != itEnd; ++it ) + maxWidth = (std::max)( maxWidth, it->commands().size() ); + + for( it = itBegin; it != itEnd; ++it ) { + Detail::Text usage( it->commands(), Detail::TextAttributes() + .setWidth( maxWidth+indent ) + .setIndent( indent ) ); + Detail::Text desc( it->description, Detail::TextAttributes() + .setWidth( width - maxWidth - 3 ) ); + + for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { + std::string usageCol = i < usage.size() ? usage[i] : ""; + os << usageCol; + + if( i < desc.size() && !desc[i].empty() ) + os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) + << desc[i]; + os << "\n"; + } + } + } + std::string optUsage() const { + std::ostringstream oss; + optUsage( oss ); + return oss.str(); + } + + void argSynopsis( std::ostream& os ) const { + for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { + if( i > 1 ) + os << " "; + typename std::map::const_iterator it = m_positionalArgs.find( i ); + if( it != m_positionalArgs.end() ) + os << "<" << it->second.placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; + else + throw std::logic_error( "non consecutive positional arguments with no floating args" ); + } + // !TBD No indication of mandatory args + if( m_floatingArg.get() ) { + if( m_highestSpecifiedArgPosition > 1 ) + os << " "; + os << "[<" << m_floatingArg->placeholder << "> ...]"; + } + } + std::string argSynopsis() const { + std::ostringstream oss; + argSynopsis( oss ); + return oss.str(); + } + + void usage( std::ostream& os, std::string const& procName ) const { + validate(); + os << "usage:\n " << procName << " "; + argSynopsis( os ); + if( !m_options.empty() ) { + os << " [options]\n\nwhere options are: \n"; + optUsage( os, 2 ); + } + os << "\n"; + } + std::string usage( std::string const& procName ) const { + std::ostringstream oss; + usage( oss, procName ); + return oss.str(); + } + + ConfigT parse( int argc, char const * const * argv ) const { + ConfigT config; + parseInto( argc, argv, config ); + return config; + } + + std::vector parseInto( int argc, char const * const * argv, ConfigT& config ) const { + std::string processName = argv[0]; + std::size_t lastSlash = processName.find_last_of( "/\\" ); + if( lastSlash != std::string::npos ) + processName = processName.substr( lastSlash+1 ); + m_boundProcessName.set( config, processName ); + std::vector tokens; + Parser parser; + parser.parseIntoTokens( argc, argv, tokens ); + return populate( tokens, config ); + } + + std::vector populate( std::vector const& tokens, ConfigT& config ) const { + validate(); + std::vector unusedTokens = populateOptions( tokens, config ); + unusedTokens = populateFixedArgs( unusedTokens, config ); + unusedTokens = populateFloatingArgs( unusedTokens, config ); + return unusedTokens; + } + + std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + std::vector errors; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); + for(; it != itEnd; ++it ) { + Arg const& arg = *it; + + try { + if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || + ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { + if( arg.takesArg() ) { + if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) + errors.push_back( "Expected argument to option: " + token.data ); + else + arg.boundField.set( config, tokens[++i].data ); + } + else { + arg.boundField.setFlag( config ); + } + break; + } + } + catch( std::exception& ex ) { + errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); + } + } + if( it == itEnd ) { + if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) + unusedTokens.push_back( token ); + else if( m_throwOnUnrecognisedTokens ) + errors.push_back( "unrecognised option: " + token.data ); + } + } + if( !errors.empty() ) { + std::ostringstream oss; + for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); + it != itEnd; + ++it ) { + if( it != errors.begin() ) + oss << "\n"; + oss << *it; + } + throw std::runtime_error( oss.str() ); + } + return unusedTokens; + } + std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { + std::vector unusedTokens; + int position = 1; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + typename std::map::const_iterator it = m_positionalArgs.find( position ); + if( it != m_positionalArgs.end() ) + it->second.boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + if( token.type == Parser::Token::Positional ) + position++; + } + return unusedTokens; + } + std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { + if( !m_floatingArg.get() ) + return tokens; + std::vector unusedTokens; + for( std::size_t i = 0; i < tokens.size(); ++i ) { + Parser::Token const& token = tokens[i]; + if( token.type == Parser::Token::Positional ) + m_floatingArg->boundField.set( config, token.data ); + else + unusedTokens.push_back( token ); + } + return unusedTokens; + } + + void validate() const + { + if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) + throw std::logic_error( "No options or arguments specified" ); + + for( typename std::vector::const_iterator it = m_options.begin(), + itEnd = m_options.end(); + it != itEnd; ++it ) + it->validate(); + } + + private: + Detail::BoundArgFunction m_boundProcessName; + std::vector m_options; + std::map m_positionalArgs; + ArgAutoPtr m_floatingArg; + int m_highestSpecifiedArgPosition; + bool m_throwOnUnrecognisedTokens; + }; + +} // end namespace Clara + +STITCH_CLARA_CLOSE_NAMESPACE +#undef STITCH_CLARA_OPEN_NAMESPACE +#undef STITCH_CLARA_CLOSE_NAMESPACE + +#endif // TWOBLUECUBES_CLARA_H_INCLUDED +#undef STITCH_CLARA_OPEN_NAMESPACE + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#include + +namespace Catch { + + inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } + inline void abortAfterX( ConfigData& config, int x ) { + if( x < 1 ) + throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); + config.abortAfter = x; + } + inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + + inline void addWarning( ConfigData& config, std::string const& _warning ) { + if( _warning == "NoAssertions" ) + config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); + else + throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); + + } + inline void setVerbosity( ConfigData& config, int level ) { + // !TBD: accept strings? + config.verbosity = static_cast( level ); + } + inline void setShowDurations( ConfigData& config, bool _showDurations ) { + config.showDurations = _showDurations + ? ShowDurations::Always + : ShowDurations::Never; + } + inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { + std::ifstream f( _filename.c_str() ); + if( !f.is_open() ) + throw std::domain_error( "Unable to load input file: " + _filename ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, "#" ) ) + addTestOrTags( config, "\"" + line + "\"," ); + } + } + + inline Clara::CommandLine makeCommandLineParser() { + + using namespace Clara; + CommandLine cli; + + cli.bindProcessName( &ConfigData::processName ); + + cli["-?"]["-h"]["--help"] + .describe( "display usage information" ) + .bind( &ConfigData::showHelp ); + + cli["-l"]["--list-tests"] + .describe( "list all/matching test cases" ) + .bind( &ConfigData::listTests ); + + cli["-t"]["--list-tags"] + .describe( "list all/matching tags" ) + .bind( &ConfigData::listTags ); + + cli["-s"]["--success"] + .describe( "include successful tests in output" ) + .bind( &ConfigData::showSuccessfulTests ); + + cli["-b"]["--break"] + .describe( "break into debugger on failure" ) + .bind( &ConfigData::shouldDebugBreak ); + + cli["-e"]["--nothrow"] + .describe( "skip exception tests" ) + .bind( &ConfigData::noThrow ); + + cli["-i"]["--invisibles"] + .describe( "show invisibles (tabs, newlines)" ) + .bind( &ConfigData::showInvisibles ); + + cli["-o"]["--out"] + .describe( "output filename" ) + .bind( &ConfigData::outputFilename, "filename" ); + + cli["-r"]["--reporter"] +// .placeholder( "name[:filename]" ) + .describe( "reporter to use (defaults to console)" ) + .bind( &ConfigData::reporterName, "name" ); + + cli["-n"]["--name"] + .describe( "suite name" ) + .bind( &ConfigData::name, "name" ); + + cli["-a"]["--abort"] + .describe( "abort at first failure" ) + .bind( &abortAfterFirst ); + + cli["-x"]["--abortx"] + .describe( "abort after x failures" ) + .bind( &abortAfterX, "no. failures" ); + + cli["-w"]["--warn"] + .describe( "enable warnings" ) + .bind( &addWarning, "warning name" ); + +// - needs updating if reinstated +// cli.into( &setVerbosity ) +// .describe( "level of verbosity (0=no output)" ) +// .shortOpt( "v") +// .longOpt( "verbosity" ) +// .placeholder( "level" ); + + cli[_] + .describe( "which test or tests to use" ) + .bind( &addTestOrTags, "test name, pattern or tags" ); + + cli["-d"]["--durations"] + .describe( "show test durations" ) + .bind( &setShowDurations, "yes/no" ); + + cli["-f"]["--input-file"] + .describe( "load test names to run from a file" ) + .bind( &loadTestNamesFromFile, "filename" ); + + // Less common commands which don't have a short form + cli["--list-test-names-only"] + .describe( "list all/matching test cases names only" ) + .bind( &ConfigData::listTestNamesOnly ); + + cli["--list-reporters"] + .describe( "list all reporters" ) + .bind( &ConfigData::listReporters ); + + return cli; + } + +} // end namespace Catch + +// #included from: internal/catch_list.hpp +#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED + +// #included from: catch_text.h +#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED + +#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH + +#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch +// #included from: ../external/tbc_text_format.h +// Only use header guard if we are not using an outer namespace +#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +# endif +# else +# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED +# endif +#endif +#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#include +#include +#include + +// Use optional outer namespace +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { +#endif + +namespace Tbc { + +#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH + const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; +#else + const unsigned int consoleWidth = 80; +#endif + + struct TextAttributes { + TextAttributes() + : initialIndent( std::string::npos ), + indent( 0 ), + width( consoleWidth-1 ), + tabChar( '\t' ) + {} + + TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } + TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } + TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } + TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } + + std::size_t initialIndent; // indent of first line, or npos + std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos + std::size_t width; // maximum width of text, including indent. Longer text will wrap + char tabChar; // If this char is seen the indent is changed to current pos + }; + + class Text { + public: + Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) + : attr( _attr ) + { + std::string wrappableChars = " [({.,/|\\-"; + std::size_t indent = _attr.initialIndent != std::string::npos + ? _attr.initialIndent + : _attr.indent; + std::string remainder = _str; + + while( !remainder.empty() ) { + if( lines.size() >= 1000 ) { + lines.push_back( "... message truncated due to excessive size" ); + return; + } + std::size_t tabPos = std::string::npos; + std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); + std::size_t pos = remainder.find_first_of( '\n' ); + if( pos <= width ) { + width = pos; + } + pos = remainder.find_last_of( _attr.tabChar, width ); + if( pos != std::string::npos ) { + tabPos = pos; + if( remainder[width] == '\n' ) + width--; + remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); + } + + if( width == remainder.size() ) { + spliceLine( indent, remainder, width ); + } + else if( remainder[width] == '\n' ) { + spliceLine( indent, remainder, width ); + if( width <= 1 || remainder.size() != 1 ) + remainder = remainder.substr( 1 ); + indent = _attr.indent; + } + else { + pos = remainder.find_last_of( wrappableChars, width ); + if( pos != std::string::npos && pos > 0 ) { + spliceLine( indent, remainder, pos ); + if( remainder[0] == ' ' ) + remainder = remainder.substr( 1 ); + } + else { + spliceLine( indent, remainder, width-1 ); + lines.back() += "-"; + } + if( lines.size() == 1 ) + indent = _attr.indent; + if( tabPos != std::string::npos ) + indent += tabPos; + } + } + } + + void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { + lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); + _remainder = _remainder.substr( _pos ); + } + + typedef std::vector::const_iterator const_iterator; + + const_iterator begin() const { return lines.begin(); } + const_iterator end() const { return lines.end(); } + std::string const& last() const { return lines.back(); } + std::size_t size() const { return lines.size(); } + std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } + std::string toString() const { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + + inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { + for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); + it != itEnd; ++it ) { + if( it != _text.begin() ) + _stream << "\n"; + _stream << *it; + } + return _stream; + } + + private: + std::string str; + TextAttributes attr; + std::vector lines; + }; + +} // end namespace Tbc + +#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE +} // end outer namespace +#endif + +#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED +#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE + +namespace Catch { + using Tbc::Text; + using Tbc::TextAttributes; +} + +// #included from: catch_console_colour.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED + +namespace Catch { + + namespace Detail { + struct IColourImpl; + } + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + + // By intention + FileName = LightGrey, + Warning = Yellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = Yellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour const& other ); + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + static Detail::IColourImpl* impl(); + bool m_moved; + }; + + inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } + +} // end namespace Catch + +// #included from: catch_interfaces_reporter.h +#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED + +#include +#include +#include +#include + +namespace Catch +{ + struct ReporterConfig { + explicit ReporterConfig( Ptr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& stream() const { return *m_stream; } + Ptr fullConfig() const { return m_fullConfig; } + + private: + std::ostream* m_stream; + Ptr m_fullConfig; + }; + + struct ReporterPreferences { + ReporterPreferences() + : shouldRedirectStdOut( false ) + {} + + bool shouldRedirectStdOut; + }; + + template + struct LazyStat : Option { + LazyStat() : used( false ) {} + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ) : name( _name ) {} + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + virtual ~AssertionStats(); + +# ifdef CATCH_CPP11_OR_GREATER + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; +# endif + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + virtual ~SectionStats(); +# ifdef CATCH_CPP11_OR_GREATER + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; +# endif + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + virtual ~TestCaseStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; +# endif + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + virtual ~TestGroupStats(); + +# ifdef CATCH_CPP11_OR_GREATER + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; +# endif + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + virtual ~TestRunStats(); + +# ifndef CATCH_CPP11_OR_GREATER + TestRunStats( TestRunStats const& _other ) + : runInfo( _other.runInfo ), + totals( _other.totals ), + aborting( _other.aborting ) + {} +# else + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; +# endif + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct IStreamingReporter : IShared { + virtual ~IStreamingReporter(); + + // Implementing class must also provide the following static method: + // static std::string getDescription(); + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + }; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + + struct IReporterRegistry { + typedef std::map FactoryMap; + + virtual ~IReporterRegistry(); + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + }; + +} + +#include +#include + +namespace Catch { + + inline std::size_t listTests( Config const& config ) { + + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Matching test cases:\n"; + else { + std::cout << "All available test cases:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::size_t matchedTests = 0; + TextAttributes nameAttr, tagsAttr; + nameAttr.setInitialIndent( 2 ).setIndent( 4 ); + tagsAttr.setIndent( 6 ); + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; + if( !testCaseInfo.tags.empty() ) + std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; + } + + if( !config.testSpec().hasFilters() ) + std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; + else + std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; + return matchedTests; + } + + inline std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( !config.testSpec().hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + matchedTests++; + TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); + std::cout << testCaseInfo.name << std::endl; + } + return matchedTests; + } + + struct TagInfo { + TagInfo() : count ( 0 ) {} + void add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + std::string all() const { + std::string out; + for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); + it != itEnd; + ++it ) + out += "[" + *it + "]"; + return out; + } + std::set spellings; + std::size_t count; + }; + + inline std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.testSpec().hasFilters() ) + std::cout << "Tags for matching test cases:\n"; + else { + std::cout << "All available tags:\n"; + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); + } + + std::map tagCounts; + + std::vector matchedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); + it != itEnd; + ++it ) { + for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), + tagItEnd = it->getTestCaseInfo().tags.end(); + tagIt != tagItEnd; + ++tagIt ) { + std::string tagName = *tagIt; + std::string lcaseTagName = toLower( tagName ); + std::map::iterator countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( std::map::const_iterator countIt = tagCounts.begin(), + countItEnd = tagCounts.end(); + countIt != countItEnd; + ++countIt ) { + std::ostringstream oss; + oss << " " << std::setw(2) << countIt->second.count << " "; + Text wrapper( countIt->second.all(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( oss.str().size() ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); + std::cout << oss.str() << wrapper << "\n"; + } + std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; + return tagCounts.size(); + } + + inline std::size_t listReporters( Config const& /*config*/ ) { + std::cout << "Available reports:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; + std::size_t maxNameLen = 0; + for(it = itBegin; it != itEnd; ++it ) + maxNameLen = (std::max)( maxNameLen, it->first.size() ); + + for(it = itBegin; it != itEnd; ++it ) { + Text wrapper( it->second->getDescription(), TextAttributes() + .setInitialIndent( 0 ) + .setIndent( 7+maxNameLen ) + .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); + std::cout << " " + << it->first + << ":" + << std::string( maxNameLen - it->first.size() + 2, ' ' ) + << wrapper << "\n"; + } + std::cout << std::endl; + return factories.size(); + } + + inline Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch + +// #included from: internal/catch_runner_impl.hpp +#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED + +// #included from: catch_test_case_tracker.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { +namespace SectionTracking { + + class TrackedSection { + + typedef std::map TrackedSections; + + public: + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + Completed + }; + + TrackedSection( std::string const& name, TrackedSection* parent ) + : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + {} + + RunState runState() const { return m_runState; } + + TrackedSection* findChild( std::string const& childName ) { + TrackedSections::iterator it = m_children.find( childName ); + return it != m_children.end() + ? &it->second + : NULL; + } + TrackedSection* acquireChild( std::string const& childName ) { + if( TrackedSection* child = findChild( childName ) ) + return child; + m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); + return findChild( childName ); + } + void enter() { + if( m_runState == NotStarted ) + m_runState = Executing; + } + void leave() { + for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); + it != itEnd; + ++it ) + if( it->second.runState() != Completed ) { + m_runState = ExecutingChildren; + return; + } + m_runState = Completed; + } + TrackedSection* getParent() { + return m_parent; + } + bool hasChildren() const { + return !m_children.empty(); + } + + private: + std::string m_name; + RunState m_runState; + TrackedSections m_children; + TrackedSection* m_parent; + + }; + + class TestCaseTracker { + public: + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), + m_completedASectionThisRun( false ) + {} + + bool enterSection( std::string const& name ) { + TrackedSection* child = m_currentSection->acquireChild( name ); + if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) + return false; + + m_currentSection = child; + m_currentSection->enter(); + return true; + } + void leaveSection() { + m_currentSection->leave(); + m_currentSection = m_currentSection->getParent(); + assert( m_currentSection != NULL ); + m_completedASectionThisRun = true; + } + + bool currentSectionHasChildren() const { + return m_currentSection->hasChildren(); + } + bool isCompleted() const { + return m_testCase.runState() == TrackedSection::Completed; + } + + class Guard { + public: + Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + Guard( Guard const& ); + void operator = ( Guard const& ); + TestCaseTracker& m_tracker; + }; + + private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + + TrackedSection m_testCase; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; + }; + +} // namespace SectionTracking + +using SectionTracking::TestCaseTracker; + +} // namespace Catch + +#include +#include + +namespace Catch { + + class StreamRedirect { + + public: + StreamRedirect( std::ostream& stream, std::string& targetString ) + : m_stream( stream ), + m_prevBuf( stream.rdbuf() ), + m_targetString( targetString ) + { + stream.rdbuf( m_oss.rdbuf() ); + } + + ~StreamRedirect() { + m_targetString += m_oss.str(); + m_stream.rdbuf( m_prevBuf ); + } + + private: + std::ostream& m_stream; + std::streambuf* m_prevBuf; + std::ostringstream m_oss; + std::string& m_targetString; + }; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + RunContext( RunContext const& ); + void operator =( RunContext const& ); + + public: + + explicit RunContext( Ptr const& config, Ptr const& reporter ) + : m_runInfo( config->name() ), + m_context( getCurrentMutableContext() ), + m_activeTestCase( NULL ), + m_config( config ), + m_reporter( reporter ), + m_prevRunner( m_context.getRunner() ), + m_prevResultCapture( m_context.getResultCapture() ), + m_prevConfig( m_context.getConfig() ) + { + m_context.setRunner( this ); + m_context.setConfig( m_config ); + m_context.setResultCapture( this ); + m_reporter->testRunStarting( m_runInfo ); + } + + virtual ~RunContext() { + m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); + m_context.setRunner( m_prevRunner ); + m_context.setConfig( NULL ); + m_context.setResultCapture( m_prevResultCapture ); + m_context.setConfig( m_prevConfig ); + } + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); + } + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { + m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); + } + + Totals runTest( TestCase const& testCase ) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + TestCaseInfo testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting( testInfo ); + + m_activeTestCase = &testCase; + m_testCaseTracker = TestCaseTracker( testInfo.name ); + + do { + do { + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( !m_testCaseTracker->isCompleted() && !aborting() ); + } + while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); + + Totals deltaTotals = m_totals.delta( prevTotals ); + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded( TestCaseStats( testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting() ) ); + + m_activeTestCase = NULL; + m_testCaseTracker.reset(); + + return deltaTotals; + } + + Ptr config() const { + return m_config; + } + + private: // IResultCapture + + virtual void assertionEnded( AssertionResult const& result ) { + if( result.getResultType() == ResultWas::Ok ) { + m_totals.assertions.passed++; + } + else if( !result.isOk() ) { + m_totals.assertions.failed++; + } + + if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) ) + m_messages.clear(); + + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_lastResult = result; + } + + virtual bool sectionStarted ( + SectionInfo const& sectionInfo, + Counts& assertions + ) + { + std::ostringstream oss; + oss << sectionInfo.name << "@" << sectionInfo.lineInfo; + + if( !m_testCaseTracker->enterSection( oss.str() ) ) + return false; + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting( sectionInfo ); + + assertions = m_totals.assertions; + + return true; + } + bool testForMissingAssertions( Counts& assertions ) { + if( assertions.total() != 0 || + !m_config->warnAboutMissingAssertions() || + m_testCaseTracker->currentSectionHasChildren() ) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { + if( std::uncaught_exception() ) { + m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); + return; + } + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + m_testCaseTracker->leaveSection(); + + m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_messages.clear(); + } + + virtual void pushScopedMessage( MessageInfo const& message ) { + m_messages.push_back( message ); + } + + virtual void popScopedMessage( MessageInfo const& message ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); + } + + virtual std::string getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : ""; + } + + virtual const AssertionResult* getLastResult() const { + return &m_lastResult; + } + + public: + // !TBD We need to do this another way! + bool aborting() const { + return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); + } + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { + TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); + m_reporter->sectionStarting( testCaseSection ); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + try { + m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); + TestCaseTracker::Guard guard( *m_testCaseTracker ); + + Timer timer; + timer.start(); + if( m_reporter->getPreferences().shouldRedirectStdOut ) { + StreamRedirect coutRedir( std::cout, redirectedCout ); + StreamRedirect cerrRedir( std::cerr, redirectedCerr ); + m_activeTestCase->invoke(); + } + else { + m_activeTestCase->invoke(); + } + duration = timer.getElapsedSeconds(); + } + catch( TestFailureException& ) { + // This just means the test was aborted due to failure + } + catch(...) { + ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(), + m_lastAssertionInfo.lineInfo, + m_lastAssertionInfo.capturedExpression.c_str(), + m_lastAssertionInfo.resultDisposition ); + exResult.useActiveException(); + } + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it ) + sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + m_unfinishedSections.clear(); + m_messages.clear(); + + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions( assertions ); + + if( testCaseInfo.okToFail() ) { + std::swap( assertions.failedButOk, assertions.failed ); + m_totals.assertions.failed -= assertions.failedButOk; + m_totals.assertions.failedButOk += assertions.failedButOk; + } + + SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); + m_reporter->sectionEnded( testCaseSectionStats ); + } + + private: + struct UnfinishedSections { + UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) + : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo info; + Counts prevAssertions; + double durationInSeconds; + }; + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase; + Option m_testCaseTracker; + AssertionResult m_lastResult; + + Ptr m_config; + Totals m_totals; + Ptr m_reporter; + std::vector m_messages; + IRunner* m_prevRunner; + IResultCapture* m_prevResultCapture; + Ptr m_prevConfig; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + }; + + IResultCapture& getResultCapture() { + if( IResultCapture* capture = getCurrentContext().getResultCapture() ) + return *capture; + else + throw std::logic_error( "No result capture instance" ); + } + +} // end namespace Catch + +// #included from: internal/catch_version.h +#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED + +namespace Catch { + + // Versioning information + struct Version { + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _buildNumber, + char const* const _branchName ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + buildNumber( _buildNumber ), + branchName( _branchName ) + {} + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const buildNumber; + char const* const branchName; + + private: + void operator=( Version const& ); + }; + + extern Version libraryVersion; +} + +#include +#include +#include + +namespace Catch { + + class Runner { + + public: + Runner( Ptr const& config ) + : m_config( config ) + { + openStream(); + makeReporter(); + } + + Totals runTests() { + + RunContext context( m_config.get(), m_reporter ); + + Totals totals; + + context.testGroupStarting( "", 1, 1 ); // deprecated? + + TestSpec testSpec = m_config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); + + int testsRunForGroup = 0; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + testsRunForGroup++; + if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + m_testsAlreadyRun.insert( *it ); + } + } + context.testGroupEnded( "", totals, 1, 1 ); + return totals; + } + + private: + void openStream() { + // Open output file, if specified + if( !m_config->getFilename().empty() ) { + m_ofs.open( m_config->getFilename().c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << m_config->getFilename() << "'"; + throw std::domain_error( oss.str() ); + } + m_config->setStreamBuf( m_ofs.rdbuf() ); + } + } + void makeReporter() { + std::string reporterName = m_config->getReporterName().empty() + ? "console" + : m_config->getReporterName(); + + m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); + if( !m_reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); + } + } + + private: + Ptr m_config; + std::ofstream m_ofs; + Ptr m_reporter; + std::set m_testsAlreadyRun; + }; + + class Session { + static bool alreadyInstantiated; + + public: + + struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; + + Session() + : m_cli( makeCommandLineParser() ) { + if( alreadyInstantiated ) { + std::string msg = "Only one instance of Catch::Session can ever be used"; + std::cerr << msg << std::endl; + throw std::logic_error( msg ); + } + alreadyInstantiated = true; + } + ~Session() { + Catch::cleanUp(); + } + + void showHelp( std::string const& processName ) { + std::cout << "\nCatch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " build " + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + std::cout << " (" << libraryVersion.branchName << " branch)"; + std::cout << "\n"; + + m_cli.usage( std::cout, processName ); + std::cout << "For more detail usage please see the project docs\n" << std::endl; + } + + int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + try { + m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); + m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + if( m_configData.showHelp ) + showHelp( m_configData.processName ); + m_config.reset(); + } + catch( std::exception& ex ) { + { + Colour colourGuard( Colour::Red ); + std::cerr << "\nError(s) in input:\n" + << Text( ex.what(), TextAttributes().setIndent(2) ) + << "\n\n"; + } + m_cli.usage( std::cout, m_configData.processName ); + return (std::numeric_limits::max)(); + } + return 0; + } + + void useConfigData( ConfigData const& _configData ) { + m_configData = _configData; + m_config.reset(); + } + + int run( int argc, char* const argv[] ) { + + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + + int run() { + if( m_configData.showHelp ) + return 0; + + try + { + config(); // Force config to be constructed + Runner runner( m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + return static_cast( runner.runTests().assertions.failed ); + } + catch( std::exception& ex ) { + std::cerr << ex.what() << std::endl; + return (std::numeric_limits::max)(); + } + } + + Clara::CommandLine const& cli() const { + return m_cli; + } + std::vector const& unusedTokens() const { + return m_unusedTokens; + } + ConfigData& configData() { + return m_configData; + } + Config& config() { + if( !m_config ) + m_config = new Config( m_configData ); + return *m_config; + } + + private: + Clara::CommandLine m_cli; + std::vector m_unusedTokens; + ConfigData m_configData; + Ptr m_config; + }; + + bool Session::alreadyInstantiated = false; + +} // end namespace Catch + +// #included from: catch_registry_hub.hpp +#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED + +// #included from: catch_test_case_registry_impl.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class TestRegistry : public ITestCaseRegistry { + public: + TestRegistry() : m_unnamedCount( 0 ) {} + virtual ~TestRegistry(); + + virtual void registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name == "" ) { + std::ostringstream oss; + oss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( oss.str() ) ); + } + + if( m_functions.find( testCase ) == m_functions.end() ) { + m_functions.insert( testCase ); + m_functionsInOrder.push_back( testCase ); + if( !testCase.isHidden() ) + m_nonHiddenFunctions.push_back( testCase ); + } + else { + TestCase const& prev = *m_functions.find( testCase ); + { + Colour colourGuard( Colour::Red ); + std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; + } + exit(1); + } + } + + virtual std::vector const& getAllTests() const { + return m_functionsInOrder; + } + + virtual std::vector const& getAllNonHiddenTests() const { + return m_nonHiddenFunctions; + } + + virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases ) const { + for( std::vector::const_iterator it = m_functionsInOrder.begin(), + itEnd = m_functionsInOrder.end(); + it != itEnd; + ++it ) { + if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) + matchingTestCases.push_back( *it ); + } + } + + private: + + std::set m_functions; + std::vector m_functionsInOrder; + std::vector m_nonHiddenFunctions; + size_t m_unnamedCount; + }; + + /////////////////////////////////////////////////////////////////////////// + + class FreeFunctionTestCase : public SharedImpl { + public: + + FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} + + virtual void invoke() const { + m_fun(); + } + + private: + virtual ~FreeFunctionTestCase(); + + TestFunction m_fun; + }; + + inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, "&" ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + + /////////////////////////////////////////////////////////////////////////// + + AutoReg::AutoReg( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + + AutoReg::~AutoReg() {} + + void AutoReg::registerTestCase( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + +} // end namespace Catch + +// #included from: catch_reporter_registry.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + virtual ~ReporterRegistry() { + deleteAllValues( m_factories ); + } + + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + FactoryMap::const_iterator it = m_factories.find( name ); + if( it == m_factories.end() ) + return NULL; + return it->second->create( ReporterConfig( config ) ); + } + + void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_factories.insert( std::make_pair( name, factory ) ); + } + + FactoryMap const& getFactories() const { + return m_factories; + } + + private: + FactoryMap m_factories; + }; +} + +// #included from: catch_exception_translator_registry.hpp +#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED + +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry() { + deleteAll( m_translators ); + } + + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( translator ); + } + + virtual std::string translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + throw; + } + @catch (NSException *exception) { + return toString( [exception description] ); + } +#else + throw; +#endif + } + catch( TestFailureException& ) { + throw; + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return tryTranslators( m_translators.begin() ); + } + } + + std::string tryTranslators( std::vector::const_iterator it ) const { + if( it == m_translators.end() ) + return "Unknown exception"; + + try { + return (*it)->translate(); + } + catch(...) { + return tryTranslators( it+1 ); + } + } + + private: + std::vector m_translators; + }; +} + +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub { + + RegistryHub( RegistryHub const& ); + void operator=( RegistryHub const& ); + + public: // IRegistryHub + RegistryHub() { + } + virtual IReporterRegistry const& getReporterRegistry() const { + return m_reporterRegistry; + } + virtual ITestCaseRegistry const& getTestCaseRegistry() const { + return m_testCaseRegistry; + } + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + return m_exceptionTranslatorRegistry; + } + + public: // IMutableRegistryHub + virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + m_reporterRegistry.registerReporter( name, factory ); + } + virtual void registerTest( TestCase const& testInfo ) { + m_testCaseRegistry.registerTest( testInfo ); + } + virtual void registerTranslator( const IExceptionTranslator* translator ) { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + }; + + // Single, global, instance + inline RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = NULL; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = NULL; + cleanUpContext(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch + +// #included from: catch_notimplemented_exception.hpp +#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED + +#include + +namespace Catch { + + NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) + : m_lineInfo( lineInfo ) { + std::ostringstream oss; + oss << lineInfo << ": function "; + oss << "not implemented"; + m_what = oss.str(); + } + + const char* NotImplementedException::what() const CATCH_NOEXCEPT { + return m_what.c_str(); + } + +} // end namespace Catch + +// #included from: catch_context_impl.hpp +#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED + +// #included from: catch_stream.hpp +#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED + +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED + +#include + +namespace Catch { + + class StreamBufBase : public std::streambuf { + public: + virtual ~StreamBufBase() CATCH_NOEXCEPT; + }; +} + +#include +#include + +namespace Catch { + + template + class StreamBufImpl : public StreamBufBase { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() CATCH_NOEXCEPT { + sync(); + } + + private: + int overflow( int c ) { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + Stream::Stream() + : streamBuf( NULL ), isOwned( false ) + {} + + Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) + : streamBuf( _streamBuf ), isOwned( _isOwned ) + {} + + void Stream::release() { + if( isOwned ) { + delete streamBuf; + streamBuf = NULL; + isOwned = false; + } + } +} + +namespace Catch { + + class Context : public IMutableContext { + + Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context( Context const& ); + void operator=( Context const& ); + + public: // IContext + virtual IResultCapture* getResultCapture() { + return m_resultCapture; + } + virtual IRunner* getRunner() { + return m_runner; + } + virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { + return getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + virtual bool advanceGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } + + virtual Ptr getConfig() const { + return m_config; + } + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) { + m_runner = runner; + } + virtual void setConfig( Ptr const& config ) { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IGeneratorsForTest* findGeneratorsForCurrentTest() { + std::string testName = getResultCapture()->getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + + IGeneratorsForTest& getGeneratorsForCurrentTest() { + IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) { + std::string testName = getResultCapture()->getCurrentTestName(); + generators = createGeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + private: + Ptr m_config; + IRunner* m_runner; + IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; + }; + + namespace { + Context* currentContext = NULL; + } + IMutableContext& getCurrentMutableContext() { + if( !currentContext ) + currentContext = new Context(); + return *currentContext; + } + IContext& getCurrentContext() { + return getCurrentMutableContext(); + } + + Stream createStream( std::string const& streamName ) { + if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); + if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); + if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); + + throw std::domain_error( "Unknown stream: " + streamName ); + } + + void cleanUpContext() { + delete currentContext; + currentContext = NULL; + } +} + +// #included from: catch_console_colour_impl.hpp +#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED + +namespace Catch { namespace Detail { + struct IColourImpl { + virtual ~IColourImpl() {} + virtual void use( Colour::Code _colourCode ) = 0; + }; +}} + +#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +namespace Catch { +namespace { + + class Win32ColourImpl : public Detail::IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalAttributes = csbiInfo.wAttributes; + } + + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + } + HANDLE stdoutHandle; + WORD originalAttributes; + }; + + inline bool shouldUseColourForPlatform() { + return true; + } + + static Detail::IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#else // Not Windows - assumed to be POSIX compatible ////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public Detail::IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0:34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + + case Colour::Bright: throw std::logic_error( "not a colour" ); + } + } + private: + void setColour( const char* _escapeCode ) { + std::cout << '\033' << _escapeCode; + } + }; + + inline bool shouldUseColourForPlatform() { + return isatty(STDOUT_FILENO); + } + + static Detail::IColourImpl* platformColourInstance() { + static PosixColourImpl s_instance; + return &s_instance; + } + +} // end anon namespace +} // end namespace Catch + +#endif // not Windows + +namespace Catch { + + namespace { + struct NoColourImpl : Detail::IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + static bool shouldUseColour() { + return shouldUseColourForPlatform() && !isDebuggerActive(); + } + } + + Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } + Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } + Colour::~Colour(){ if( !m_moved ) use( None ); } + void Colour::use( Code _colourCode ) { + impl()->use( _colourCode ); + } + + Detail::IColourImpl* Colour::impl() { + return shouldUseColour() + ? platformColourInstance() + : NoColourImpl::instance(); + } + +} // end namespace Catch + +// #included from: catch_generators_impl.hpp +#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED + +#include +#include +#include + +namespace Catch { + + struct GeneratorInfo : IGeneratorInfo { + + GeneratorInfo( std::size_t size ) + : m_size( size ), + m_currentIndex( 0 ) + {} + + bool moveNext() { + if( ++m_currentIndex == m_size ) { + m_currentIndex = 0; + return false; + } + return true; + } + + std::size_t getCurrentIndex() const { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + /////////////////////////////////////////////////////////////////////////// + + class GeneratorsForTest : public IGeneratorsForTest { + + public: + ~GeneratorsForTest() { + deleteAll( m_generatorsInOrder ); + } + + IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) { + IGeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + bool moveNext() { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.end(); + for(; it != itEnd; ++it ) { + if( (*it)->moveNext() ) + return true; + } + return false; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + }; + + IGeneratorsForTest* createGeneratorsForTest() + { + return new GeneratorsForTest(); + } + +} // end namespace Catch + +// #included from: catch_assertionresult.hpp +#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED + +namespace Catch { + + AssertionInfo::AssertionInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + std::string const& _capturedExpression, + ResultDisposition::Flags _resultDisposition ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + capturedExpression( _capturedExpression ), + resultDisposition( _resultDisposition ) + {} + + AssertionResult::AssertionResult() {} + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + AssertionResult::~AssertionResult() {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return !m_info.capturedExpression.empty(); + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!" + m_info.capturedExpression; + else + return m_info.capturedExpression; + } + std::string AssertionResult::getExpressionInMacro() const { + if( m_info.macroName.empty() ) + return m_info.capturedExpression; + else + return m_info.macroName + "( " + m_info.capturedExpression + " )"; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + return m_resultData.reconstructedExpression; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + std::string AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch + +// #included from: catch_test_case_info.hpp +#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED + +namespace Catch { + + inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( tag == "." || + tag == "hide" || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else + return TestCaseInfo::None; + } + inline bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] ); + } + inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + if( isReservedTag( tag ) ) { + { + Colour colourGuard( Colour::Red ); + std::cerr + << "Tag name [" << tag << "] not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n"; + } + { + Colour colourGuard( Colour::FileName ); + std::cerr << _lineInfo << std::endl; + } + exit(1); + } + } + + TestCase makeTestCase( ITestCase* _testCase, + std::string const& _className, + std::string const& _name, + std::string const& _descOrTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden( startsWith( _name, "./" ) ); // Legacy support + + // Parse out tags + std::set tags; + std::string desc, tag; + bool inTag = false; + for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { + char c = _descOrTags[i]; + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + enforceNotReservedTag( tag, _lineInfo ); + + inTag = false; + if( tag == "hide" || tag == "." ) + isHidden = true; + else + tags.insert( tag ); + tag.clear(); + } + else + tag += c; + } + } + if( isHidden ) { + tags.insert( "hide" ); + tags.insert( "." ); + } + + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, info ); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::set const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + tags( _tags ), + lineInfo( _lineInfo ), + properties( None ) + { + std::ostringstream oss; + for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); + lcaseTags.insert( lcaseTag ); + } + tagsAsString = oss.str(); + } + + TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) + : name( other.name ), + className( other.className ), + description( other.description ), + tags( other.tags ), + lcaseTags( other.lcaseTags ), + tagsAsString( other.tagsAsString ), + lineInfo( other.lineInfo ), + properties( other.properties ) + {} + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} + + TestCase::TestCase( TestCase const& other ) + : TestCaseInfo( other ), + test( other.test ) + {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::swap( TestCase& other ) { + test.swap( other.test ); + name.swap( other.name ); + className.swap( other.className ); + description.swap( other.description ); + tags.swap( other.tags ); + lcaseTags.swap( other.lcaseTags ); + tagsAsString.swap( other.tagsAsString ); + std::swap( TestCaseInfo::properties, static_cast( other ).properties ); + std::swap( lineInfo, other.lineInfo ); + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + TestCase& TestCase::operator = ( TestCase const& other ) { + TestCase temp( other ); + swap( temp ); + return *this; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch + +// #included from: catch_version.hpp +#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED + +namespace Catch { + + // These numbers are maintained by a script + Version libraryVersion( 1, 0, 53, "master" ); +} + +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + ScopedMessage::ScopedMessage( ScopedMessage const& other ) + : m_info( other.m_info ) + {} + + ScopedMessage::~ScopedMessage() { + getResultCapture().popScopedMessage( m_info ); + } + +} // end namespace Catch + +// #included from: catch_legacy_reporter_adapter.hpp +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED + +// #included from: catch_legacy_reporter_adapter.h +#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED + +namespace Catch +{ + // Deprecated + struct IReporter : IShared { + virtual ~IReporter(); + + virtual bool shouldRedirectStdout() const = 0; + + virtual void StartTesting() = 0; + virtual void EndTesting( Totals const& totals ) = 0; + virtual void StartGroup( std::string const& groupName ) = 0; + virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; + virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; + virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; + virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; + virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; + virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; + virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; + virtual void Aborted() = 0; + virtual void Result( AssertionResult const& result ) = 0; + }; + + class LegacyReporterAdapter : public SharedImpl + { + public: + LegacyReporterAdapter( Ptr const& legacyReporter ); + virtual ~LegacyReporterAdapter(); + + virtual ReporterPreferences getPreferences() const; + virtual void noMatchingTestCases( std::string const& ); + virtual void testRunStarting( TestRunInfo const& ); + virtual void testGroupStarting( GroupInfo const& groupInfo ); + virtual void testCaseStarting( TestCaseInfo const& testInfo ); + virtual void sectionStarting( SectionInfo const& sectionInfo ); + virtual void assertionStarting( AssertionInfo const& ); + virtual bool assertionEnded( AssertionStats const& assertionStats ); + virtual void sectionEnded( SectionStats const& sectionStats ); + virtual void testCaseEnded( TestCaseStats const& testCaseStats ); + virtual void testGroupEnded( TestGroupStats const& testGroupStats ); + virtual void testRunEnded( TestRunStats const& testRunStats ); + + private: + Ptr m_legacyReporter; + }; +} + +namespace Catch +{ + LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) + : m_legacyReporter( legacyReporter ) + {} + LegacyReporterAdapter::~LegacyReporterAdapter() {} + + ReporterPreferences LegacyReporterAdapter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); + return prefs; + } + + void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} + void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { + m_legacyReporter->StartTesting(); + } + void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { + m_legacyReporter->StartGroup( groupInfo.name ); + } + void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { + m_legacyReporter->StartTestCase( testInfo ); + } + void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { + m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); + } + void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { + // Not on legacy interface + } + + bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { + for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); + it != itEnd; + ++it ) { + if( it->type == ResultWas::Info ) { + ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); + rb << it->message; + rb.setResultType( ResultWas::Info ); + AssertionResult result = rb.build(); + m_legacyReporter->Result( result ); + } + } + } + m_legacyReporter->Result( assertionStats.assertionResult ); + return true; + } + void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { + if( sectionStats.missingAssertions ) + m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); + m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); + } + void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { + m_legacyReporter->EndTestCase + ( testCaseStats.testInfo, + testCaseStats.totals, + testCaseStats.stdOut, + testCaseStats.stdErr ); + } + void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { + if( testGroupStats.aborting ) + m_legacyReporter->Aborted(); + m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); + } + void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { + m_legacyReporter->EndTesting( testRunStats.totals ); + } +} + +// #included from: catch_timer.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++11-long-long" +#endif + +#ifdef CATCH_PLATFORM_WINDOWS +#include +#else +#include +#endif + +namespace Catch { + + namespace { +#ifdef CATCH_PLATFORM_WINDOWS + uint64_t getCurrentTicks() { + static uint64_t hz=0, hzo=0; + if (!hz) { + QueryPerformanceFrequency((LARGE_INTEGER*)&hz); + QueryPerformanceCounter((LARGE_INTEGER*)&hzo); + } + uint64_t t; + QueryPerformanceCounter((LARGE_INTEGER*)&t); + return ((t-hzo)*1000000)/hz; + } +#else + uint64_t getCurrentTicks() { + timeval t; + gettimeofday(&t,NULL); + return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); + } +#endif + } + + void Timer::start() { + m_ticks = getCurrentTicks(); + } + unsigned int Timer::getElapsedNanoseconds() const { + return static_cast(getCurrentTicks() - m_ticks); + } + unsigned int Timer::getElapsedMilliseconds() const { + return static_cast((getCurrentTicks() - m_ticks)/1000); + } + double Timer::getElapsedSeconds() const { + return (getCurrentTicks() - m_ticks)/1000000.0; + } + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +// #included from: catch_common.hpp +#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), ::tolower ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << " " << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << "s"; + return os; + } + + SourceLineInfo::SourceLineInfo() : line( 0 ){} + SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) + : file( _file ), + line( _line ) + {} + SourceLineInfo::SourceLineInfo( SourceLineInfo const& other ) + : file( other.file ), + line( other.line ) + {} + bool SourceLineInfo::empty() const { + return file.empty(); + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { + return line == other.line && file == other.file; + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << "(" << info.line << ")"; +#else + os << info.file << ":" << info.line; +#endif + return os; + } + + void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { + std::ostringstream oss; + oss << locationInfo << ": Internal Catch error: '" << message << "'"; + if( alwaysTrue() ) + throw std::logic_error( oss.str() ); + } +} + +// #included from: catch_section.hpp +#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) + getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch + +// #included from: catch_debugger.hpp +#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED + +#include + +#ifdef CATCH_PLATFORM_MAC + + #include + #include + #include + #include + #include + + namespace Catch{ + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + inline bool isDebuggerActive() { return false; } + } +#endif // Platform + +#ifdef CATCH_PLATFORM_WINDOWS + extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* ); + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } +#else + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + std::cout << text; + } + } +#endif // Platform + +// #included from: catch_tostring.hpp +#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED + +namespace Catch { + +namespace Detail { + + namespace { + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) + { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + os << std::setw(2) << static_cast(bytes[i]); + return os.str(); + } +} + +std::string toString( std::string const& value ) { + std::string s = value; + if( getCurrentContext().getConfig()->showInvisibles() ) { + for(size_t i = 0; i < s.size(); ++i ) { + std::string subs; + switch( s[i] ) { + case '\n': subs = "\\n"; break; + case '\t': subs = "\\t"; break; + default: break; + } + if( !subs.empty() ) { + s = s.substr( 0, i ) + subs + s.substr( i+1 ); + ++i; + } + } + } + return "\"" + s + "\""; +} +std::string toString( std::wstring const& value ) { + + std::string s; + s.reserve( value.size() ); + for(size_t i = 0; i < value.size(); ++i ) + s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; + return toString( s ); +} + +std::string toString( const char* const value ) { + return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); +} + +std::string toString( char* const value ) { + return Catch::toString( static_cast( value ) ); +} + +std::string toString( const wchar_t* const value ) +{ + return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); +} + +std::string toString( wchar_t* const value ) +{ + return Catch::toString( static_cast( value ) ); +} + +std::string toString( int value ) { + std::ostringstream oss; + oss << value; + return oss.str(); +} + +std::string toString( unsigned long value ) { + std::ostringstream oss; + if( value > 8192 ) + oss << "0x" << std::hex << value; + else + oss << value; + return oss.str(); +} + +std::string toString( unsigned int value ) { + return toString( static_cast( value ) ); +} + +template +std::string fpToString( T value, int precision ) { + std::ostringstream oss; + oss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = oss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +std::string toString( const double value ) { + return fpToString( value, 10 ); +} +std::string toString( const float value ) { + return fpToString( value, 5 ) + "f"; +} + +std::string toString( bool value ) { + return value ? "true" : "false"; +} + +std::string toString( char value ) { + return value < ' ' + ? toString( static_cast( value ) ) + : Detail::makeString( value ); +} + +std::string toString( signed char value ) { + return toString( static_cast( value ) ); +} + +std::string toString( unsigned char value ) { + return toString( static_cast( value ) ); +} + +#ifdef CATCH_CONFIG_CPP11_NULLPTR +std::string toString( std::nullptr_t ) { + return "nullptr"; +} +#endif + +#ifdef __OBJC__ + std::string toString( NSString const * const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { + if( !nsstring ) + return "nil"; + return "@" + toString([nsstring UTF8String]); + } + std::string toString( NSObject* const& nsObject ) { + return toString( [nsObject description] ); + } +#endif + +} // end namespace Catch + +// #included from: catch_result_builder.hpp +#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED + +namespace Catch { + + ResultBuilder::ResultBuilder( char const* macroName, + SourceLineInfo const& lineInfo, + char const* capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + m_shouldDebugBreak( false ), + m_shouldThrow( false ) + {} + + ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { + m_data.resultType = result; + return *this; + } + ResultBuilder& ResultBuilder::setResultType( bool result ) { + m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; + return *this; + } + ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) { + m_exprComponents.lhs = lhs; + return *this; + } + ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) { + m_exprComponents.rhs = rhs; + return *this; + } + ResultBuilder& ResultBuilder::setOp( std::string const& op ) { + m_exprComponents.op = op; + return *this; + } + + void ResultBuilder::endExpression() { + m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition ); + captureExpression(); + } + + void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + m_stream.oss << Catch::translateActiveException(); + captureResult( ResultWas::ThrewException ); + } + + void ResultBuilder::captureResult( ResultWas::OfType resultType ) { + setResultType( resultType ); + captureExpression(); + } + + void ResultBuilder::captureExpression() { + AssertionResult result = build(); + getResultCapture().assertionEnded( result ); + + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) + m_shouldThrow = true; + } + } + void ResultBuilder::react() { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } + bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } + + AssertionResult ResultBuilder::build() const + { + assert( m_data.resultType != ResultWas::Unknown ); + + AssertionResultData data = m_data; + + // Flip bool results if testFalse is set + if( m_exprComponents.testFalse ) { + if( data.resultType == ResultWas::Ok ) + data.resultType = ResultWas::ExpressionFailed; + else if( data.resultType == ResultWas::ExpressionFailed ) + data.resultType = ResultWas::Ok; + } + + data.message = m_stream.oss.str(); + data.reconstructedExpression = reconstructExpression(); + if( m_exprComponents.testFalse ) { + if( m_exprComponents.op == "" ) + data.reconstructedExpression = "!" + data.reconstructedExpression; + else + data.reconstructedExpression = "!(" + data.reconstructedExpression + ")"; + } + return AssertionResult( m_assertionInfo, data ); + } + std::string ResultBuilder::reconstructExpression() const { + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 && + m_exprComponents.lhs.find("\n") == std::string::npos && + m_exprComponents.rhs.find("\n") == std::string::npos ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else + return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs; + } + else + return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}"; + } + +} // end namespace Catch + +// #included from: catch_tag_alias_registry.hpp +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED + +// #included from: catch_tag_alias_registry.h +#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED + +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + virtual ~TagAliasRegistry(); + virtual Option find( std::string const& alias ) const; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; + void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + static TagAliasRegistry& get(); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +#include +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + Option TagAliasRegistry::find( std::string const& alias ) const { + std::map::const_iterator it = m_registry.find( alias ); + if( it != m_registry.end() ) + return it->second; + else + return Option(); + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); + it != itEnd; + ++it ) { + std::size_t pos = expandedTestSpec.find( it->first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + it->second.tag + + expandedTestSpec.substr( pos + it->first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + + if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { + std::ostringstream oss; + oss << "error: tag alias, \"" << alias << "\" already registered.\n" + << "\tFirst seen at " << find(alias)->lineInfo << "\n" + << "\tRedefined at " << lineInfo; + throw std::domain_error( oss.str().c_str() ); + } + } + + TagAliasRegistry& TagAliasRegistry::get() { + static TagAliasRegistry instance; + return instance; + + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); } + + RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { + try { + TagAliasRegistry::get().add( alias, tag, lineInfo ); + } + catch( std::exception& ex ) { + Colour colourGuard( Colour::Red ); + std::cerr << ex.what() << std::endl; + exit(1); + } + } + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_xml.hpp +#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED + +// #included from: catch_reporter_bases.hpp +#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED + +namespace Catch { + + struct StreamingReporterBase : SharedImpl { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + + virtual ~StreamingReporterBase(); + + virtual void noMatchingTestCases( std::string const& ) {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + currentTestRunInfo = _testRunInfo; + } + virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + currentGroupInfo = _groupInfo; + } + + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + currentTestCaseInfo = _testInfo; + } + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_sectionStack.push_back( _sectionInfo ); + } + + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + currentTestCaseInfo.reset(); + assert( m_sectionStack.empty() ); + } + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + currentGroupInfo.reset(); + } + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + Ptr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + }; + + struct CumulativeReporterBase : SharedImpl { + template + struct Node : SharedImpl<> { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + typedef std::vector > ChildNodes; + T value; + ChildNodes children; + }; + struct SectionNode : SharedImpl<> { + explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} + virtual ~SectionNode(); + + bool operator == ( SectionNode const& other ) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == ( Ptr const& other ) const { + return operator==( *other ); + } + + SectionStats stats; + typedef std::vector > ChildSections; + typedef std::vector Assertions; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() ( Ptr const& node ) const { + return node->stats.sectionInfo.lineInfo == m_other.lineInfo; + } + private: + void operator=( BySectionInfo const& ); + SectionInfo const& m_other; + }; + + typedef Node TestCaseNode; + typedef Node TestGroupNode; + typedef Node TestRunNode; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + {} + ~CumulativeReporterBase(); + + virtual void testRunStarting( TestRunInfo const& ) {} + virtual void testGroupStarting( GroupInfo const& ) {} + + virtual void testCaseStarting( TestCaseInfo const& ) {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + Ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = new SectionNode( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + SectionNode::ChildSections::const_iterator it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = new SectionNode( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = node; + } + + virtual void assertionStarting( AssertionInfo const& ) {} + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back( assertionStats ); + return true; + } + virtual void sectionEnded( SectionStats const& sectionStats ) { + assert( !m_sectionStack.empty() ); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + Ptr node = new TestCaseNode( testCaseStats ); + assert( m_sectionStack.size() == 0 ); + node->children.push_back( m_rootSection ); + m_testCases.push_back( node ); + m_rootSection.reset(); + + assert( m_deepestSection ); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + Ptr node = new TestGroupNode( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + virtual void testRunEnded( TestRunStats const& testRunStats ) { + Ptr node = new TestRunNode( testRunStats ); + node->children.swap( m_testGroups ); + m_testRuns.push_back( node ); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + Ptr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector > > m_sections; + std::vector > m_testCases; + std::vector > m_testGroups; + + std::vector > m_testRuns; + + Ptr m_rootSection; + Ptr m_deepestSection; + std::vector > m_sectionStack; + + }; + +} // end namespace Catch + +// #included from: ../internal/catch_reporter_registrars.hpp +#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED + +namespace Catch { + + template + class LegacyReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new LegacyReporterAdapter( new T( config ) ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + LegacyReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + // *** Please Note ***: + // - If you end up here looking at a compiler error because it's trying to register + // your custom reporter class be aware that the native reporter interface has changed + // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via + // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. + // However please consider updating to the new interface as the old one is now + // deprecated and will probably be removed quite soon! + // Please contact me via github if you have any questions at all about this. + // In fact, ideally, please contact me anyway to let me know you've hit this - as I have + // no idea who is actually using custom reporters at all (possibly no-one!). + // The new interface is designed to minimise exposure to interface changes in the future. + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + + virtual std::string getDescription() const { + return T::getDescription(); + } + }; + + public: + + ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); + } + }; +} + +#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ + namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + +// #included from: ../internal/catch_xmlwriter.hpp +#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED + +#include +#include +#include +#include + +namespace Catch { + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + ScopedElement( ScopedElement const& other ) + : m_writer( other.m_writer ){ + other.m_writer = NULL; + } + + ~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + ScopedElement& writeText( std::string const& text, bool indent = true ) { + m_writer->writeText( text, indent ); + return *this; + } + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer; + }; + + XmlWriter() + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &std::cout ) + {} + + XmlWriter( std::ostream& os ) + : m_tagIsOpen( false ), + m_needsNewline( false ), + m_os( &os ) + {} + + ~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + +//# ifndef CATCH_CPP11_OR_GREATER +// XmlWriter& operator = ( XmlWriter const& other ) { +// XmlWriter temp( other ); +// swap( temp ); +// return *this; +// } +//# else +// XmlWriter( XmlWriter const& ) = default; +// XmlWriter( XmlWriter && ) = default; +// XmlWriter& operator = ( XmlWriter const& ) = default; +// XmlWriter& operator = ( XmlWriter && ) = default; +//# endif +// +// void swap( XmlWriter& other ) { +// std::swap( m_tagIsOpen, other.m_tagIsOpen ); +// std::swap( m_needsNewline, other.m_needsNewline ); +// std::swap( m_tags, other.m_tags ); +// std::swap( m_indent, other.m_indent ); +// std::swap( m_os, other.m_os ); +// } + + XmlWriter& startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + stream() << m_indent << "<" << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + ScopedElement scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + stream() << "/>\n"; + m_tagIsOpen = false; + } + else { + stream() << m_indent << "\n"; + } + m_tags.pop_back(); + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) { + stream() << " " << name << "=\""; + writeEncodedText( attribute ); + stream() << "\""; + } + return *this; + } + + XmlWriter& writeAttribute( std::string const& name, bool attribute ) { + stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\""; + return *this; + } + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + if( !name.empty() ) + stream() << " " << name << "=\"" << attribute << "\""; + return *this; + } + + XmlWriter& writeText( std::string const& text, bool indent = true ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + stream() << m_indent; + writeEncodedText( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& writeComment( std::string const& text ) { + ensureTagClosed(); + stream() << m_indent << ""; + m_needsNewline = true; + return *this; + } + + XmlWriter& writeBlankLine() { + ensureTagClosed(); + stream() << "\n"; + return *this; + } + + void setStream( std::ostream& os ) { + m_os = &os; + } + + private: + XmlWriter( XmlWriter const& ); + void operator=( XmlWriter const& ); + + std::ostream& stream() { + return *m_os; + } + + void ensureTagClosed() { + if( m_tagIsOpen ) { + stream() << ">\n"; + m_tagIsOpen = false; + } + } + + void newlineIfNecessary() { + if( m_needsNewline ) { + stream() << "\n"; + m_needsNewline = false; + } + } + + void writeEncodedText( std::string const& text ) { + static const char* charsToEncode = "<&\""; + std::string mtext = text; + std::string::size_type pos = mtext.find_first_of( charsToEncode ); + while( pos != std::string::npos ) { + stream() << mtext.substr( 0, pos ); + + switch( mtext[pos] ) { + case '<': + stream() << "<"; + break; + case '&': + stream() << "&"; + break; + case '\"': + stream() << """; + break; + } + mtext = mtext.substr( pos+1 ); + pos = mtext.find_first_of( charsToEncode ); + } + stream() << mtext; + } + + bool m_tagIsOpen; + bool m_needsNewline; + std::vector m_tags; + std::string m_indent; + std::ostream* m_os; + }; + +} +namespace Catch { + class XmlReporter : public SharedImpl { + public: + XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} + + static std::string getDescription() { + return "Reports test results as an XML document"; + } + virtual ~XmlReporter(); + + private: // IReporter + + virtual bool shouldRedirectStdout() const { + return true; + } + + virtual void StartTesting() { + m_xml.setStream( m_config.stream() ); + m_xml.startElement( "Catch" ); + if( !m_config.fullConfig()->name().empty() ) + m_xml.writeAttribute( "name", m_config.fullConfig()->name() ); + } + + virtual void EndTesting( const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartGroup( const std::string& groupName ) { + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupName ); + } + + virtual void EndGroup( const std::string&, const Totals& totals ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", totals.assertions.passed ) + .writeAttribute( "failures", totals.assertions.failed ) + .writeAttribute( "expectedFailures", totals.assertions.failedButOk ); + m_xml.endElement(); + } + + virtual void StartSection( const std::string& sectionName, const std::string& description ) { + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionName ) ) + .writeAttribute( "description", description ); + } + } + virtual void NoAssertionsInSection( const std::string& ) {} + virtual void NoAssertionsInTestCase( const std::string& ) {} + + virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { + if( --m_sectionDepth > 0 ) { + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", assertions.passed ) + .writeAttribute( "failures", assertions.failed ) + .writeAttribute( "expectedFailures", assertions.failedButOk ); + m_xml.endElement(); + } + } + + virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { + m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); + m_currentTestSuccess = true; + } + + virtual void Result( const Catch::AssertionResult& assertionResult ) { + if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) + return; + + if( assertionResult.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", assertionResult.succeeded() ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ); + + m_xml.scopedElement( "Original" ) + .writeText( assertionResult.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( assertionResult.getExpandedExpression() ); + m_currentTestSuccess &= assertionResult.succeeded(); + } + + switch( assertionResult.getResultType() ) { + case ResultWas::ThrewException: + m_xml.scopedElement( "Exception" ) + .writeAttribute( "filename", assertionResult.getSourceInfo().file ) + .writeAttribute( "line", assertionResult.getSourceInfo().line ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::Warning: + m_xml.scopedElement( "Warning" ) + .writeText( assertionResult.getMessage() ); + break; + case ResultWas::ExplicitFailure: + m_xml.scopedElement( "Failure" ) + .writeText( assertionResult.getMessage() ); + m_currentTestSuccess = false; + break; + case ResultWas::Unknown: + case ResultWas::Ok: + case ResultWas::FailureBit: + case ResultWas::ExpressionFailed: + case ResultWas::Exception: + case ResultWas::DidntThrowException: + break; + } + if( assertionResult.hasExpression() ) + m_xml.endElement(); + } + + virtual void Aborted() { + // !TBD + } + + virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { + m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); + m_xml.endElement(); + } + + private: + ReporterConfig m_config; + bool m_currentTestSuccess; + XmlWriter m_xml; + int m_sectionDepth; + }; + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_junit.hpp +#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED + +#include + +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + {} + + ~JunitReporter(); + + static std::string getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = true; + return prefs; + } + + virtual void testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.str(""); + stdErrForSuite.str(""); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + virtual bool assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite << testCaseStats.stdOut; + stdErrForSuite << testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + virtual void testRunEndedCumulative() { + xml.endElement(); + } + + void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", "tbd" ); // !TBD + + // Write test cases + for( TestGroupNode::ChildNodes::const_iterator + it = groupNode.children.begin(), itEnd = groupNode.children.end(); + it != itEnd; + ++it ) + writeTestCase( **it ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); + } + + void writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + if( rootSection.childSections.empty() ) + className = "global"; + } + writeSection( className, "", rootSection ); + } + + void writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + "/" + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( SectionNode::ChildSections::const_iterator + it = sectionNode.childSections.begin(), + itEnd = sectionNode.childSections.end(); + it != itEnd; + ++it ) + if( className.empty() ) + writeSection( name, "", **it ); + else + writeSection( className, name, **it ); + } + + void writeAssertions( SectionNode const& sectionNode ) { + for( SectionNode::Assertions::const_iterator + it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); + it != itEnd; + ++it ) + writeAssertion( *it ); + } + void writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + std::ostringstream oss; + if( !result.getMessage().empty() ) + oss << result.getMessage() << "\n"; + for( std::vector::const_iterator + it = stats.infoMessages.begin(), + itEnd = stats.infoMessages.end(); + it != itEnd; + ++it ) + if( it->type == ResultWas::Info ) + oss << it->message << "\n"; + + oss << "at " << result.getSourceInfo(); + xml.writeText( oss.str(), false ); + } + } + + XmlWriter xml; + Timer suiteTimer; + std::ostringstream stdOutForSuite; + std::ostringstream stdErrForSuite; + unsigned int unexpectedExceptions; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_console.hpp +#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED + +#include + +namespace Catch { + + struct ConsoleReporter : StreamingReporterBase { + ConsoleReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_headerPrinted( false ) + {} + + virtual ~ConsoleReporter(); + static std::string getDescription() { + return "Reports test results as plain lines of text"; + } + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + lazyPrint(); + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + stream << std::endl; + return true; + } + + virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting( _sectionInfo ); + } + virtual void sectionEnded( SectionStats const& _sectionStats ) { + if( _sectionStats.missingAssertions ) { + lazyPrint(); + Colour colour( Colour::ResultError ); + if( m_sectionStack.size() > 1 ) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if( m_headerPrinted ) { + if( m_config->showDurations() == ShowDurations::Always ) + stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + m_headerPrinted = false; + } + else { + if( m_config->showDurations() == ShowDurations::Always ) + stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl; + } + StreamingReporterBase::sectionEnded( _sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + StreamingReporterBase::testCaseEnded( _testCaseStats ); + m_headerPrinted = false; + } + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + if( currentGroupInfo.used ) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals( _testGroupStats.totals ); + stream << "\n" << std::endl; + } + StreamingReporterBase::testGroupEnded( _testGroupStats ); + } + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotalsDivider( _testRunStats.totals ); + printTotals( _testRunStats.totals ); + stream << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ), + stats( _stats ), + result( _stats.assertionResult ), + colour( Colour::None ), + message( result.getMessage() ), + messages( _stats.infoMessages ), + printInfoMessages( _printInfoMessages ) + { + switch( result.getResultType() ) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } + else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if( _stats.infoMessages.size() == 1 ) + messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with message"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if( stats.totals.assertions.total() > 0 ) { + if( result.isOk() ) + stream << "\n"; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } + else { + stream << "\n"; + } + printMessage(); + } + + private: + void printResultType() const { + if( !passOrFail.empty() ) { + Colour colourGuard( colour ); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if( result.hasExpression() ) { + Colour colourGuard( Colour::OriginalExpression ); + stream << " "; + stream << result.getExpressionInMacro(); + stream << "\n"; + } + } + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + stream << "with expansion:\n"; + Colour colourGuard( Colour::ReconstructedExpression ); + stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n"; + } + } + void printMessage() const { + if( !messageLabel.empty() ) + stream << messageLabel << ":" << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || it->type != ResultWas::Info ) + stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n"; + } + } + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; + }; + + void lazyPrint() { + + if( !currentTestRunInfo.used ) + lazyPrintRunInfo(); + if( !currentGroupInfo.used ) + lazyPrintGroupInfo(); + + if( !m_headerPrinted ) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } + } + void lazyPrintRunInfo() { + stream << "\n" << getLineOfChars<'~'>() << "\n"; + Colour colour( Colour::SecondaryText ); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion.majorVersion << "." + << libraryVersion.minorVersion << " b" + << libraryVersion.buildNumber; + if( libraryVersion.branchName != std::string( "master" ) ) + stream << " (" << libraryVersion.branchName << ")"; + stream << " host application.\n" + << "Run with -? for options\n\n"; + + currentTestRunInfo.used = true; + } + void lazyPrintGroupInfo() { + if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { + printClosedHeader( "Group: " + currentGroupInfo->name ); + currentGroupInfo.used = true; + } + } + void printTestCaseAndSectionHeader() { + assert( !m_sectionStack.empty() ); + printOpenHeader( currentTestCaseInfo->name ); + + if( m_sectionStack.size() > 1 ) { + Colour colourGuard( Colour::Headers ); + + std::vector::const_iterator + it = m_sectionStack.begin()+1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for( ; it != itEnd; ++it ) + printHeaderString( it->name, 2 ); + } + + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; + + if( !lineInfo.empty() ){ + stream << getLineOfChars<'-'>() << "\n"; + Colour colourGuard( Colour::FileName ); + stream << lineInfo << "\n"; + } + stream << getLineOfChars<'.'>() << "\n" << std::endl; + } + + void printClosedHeader( std::string const& _name ) { + printOpenHeader( _name ); + stream << getLineOfChars<'.'>() << "\n"; + } + void printOpenHeader( std::string const& _name ) { + stream << getLineOfChars<'-'>() << "\n"; + { + Colour colourGuard( Colour::Headers ); + printHeaderString( _name ); + } + } + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { + std::size_t i = _string.find( ": " ); + if( i != std::string::npos ) + i+=2; + else + i = 0; + stream << Text( _string, TextAttributes() + .setIndent( indent+i) + .setInitialIndent( indent ) ) << "\n"; + } + + struct SummaryColumn { + + SummaryColumn( std::string const& _label, Colour::Code _colour ) + : label( _label ), + colour( _colour ) + {} + SummaryColumn addRow( std::size_t count ) { + std::ostringstream oss; + oss << count; + std::string row = oss.str(); + for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { + while( it->size() < row.size() ) + *it = " " + *it; + while( it->size() > row.size() ) + row = " " + row; + } + rows.push_back( row ); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + + }; + + void printTotals( Totals const& totals ) { + if( totals.testCases.total() == 0 ) { + stream << Colour( Colour::Warning ) << "No tests ran\n"; + } + else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + stream << Colour( Colour::ResultSuccess ) << "All tests passed"; + stream << " (" + << pluralise( totals.assertions.passed, "assertion" ) << " in " + << pluralise( totals.testCases.passed, "test case" ) << ")" + << "\n"; + } + else { + + std::vector columns; + columns.push_back( SummaryColumn( "", Colour::None ) + .addRow( totals.testCases.total() ) + .addRow( totals.assertions.total() ) ); + columns.push_back( SummaryColumn( "passed", Colour::Success ) + .addRow( totals.testCases.passed ) + .addRow( totals.assertions.passed ) ); + columns.push_back( SummaryColumn( "failed", Colour::ResultError ) + .addRow( totals.testCases.failed ) + .addRow( totals.assertions.failed ) ); + columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) + .addRow( totals.testCases.failedButOk ) + .addRow( totals.assertions.failedButOk ) ); + + printSummaryRow( "test cases", columns, 0 ); + printSummaryRow( "assertions", columns, 1 ); + } + } + void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { + for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { + std::string value = it->rows[row]; + if( it->label.empty() ) { + stream << label << ": "; + if( value != "0" ) + stream << value; + else + stream << Colour( Colour::Warning ) << "- none -"; + } + else if( value != "0" ) { + stream << Colour( Colour::LightGrey ) << " | "; + stream << Colour( it->colour ) + << value << " " << it->label; + } + } + stream << "\n"; + } + + static std::size_t makeRatio( std::size_t number, std::size_t total ) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; + return ( ratio == 0 && number > 0 ) ? 1 : ratio; + } + static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { + if( i > j && i > k ) + return i; + else if( j > k ) + return j; + else + return k; + } + + void printTotalsDivider( Totals const& totals ) { + if( totals.testCases.total() > 0 ) { + std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); + std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); + std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); + while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )++; + while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) + findMax( failedRatio, failedButOkRatio, passedRatio )--; + + stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); + stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); + if( totals.testCases.allPassed() ) + stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); + else + stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); + } + else { + stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); + } + stream << "\n"; + } + void printSummaryDivider() { + stream << getLineOfChars<'-'>() << "\n"; + } + template + static char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + private: + bool m_headerPrinted; + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) + +} // end namespace Catch + +// #included from: ../reporters/catch_reporter_compact.hpp +#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + CompactReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual ~CompactReporter(); + + static std::string getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + virtual ReporterPreferences getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + virtual void noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << "'" << std::endl; + } + + virtual void assertionStarting( AssertionInfo const& ) { + } + + virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + virtual void testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( _testRunStats.totals ); + stream << "\n" << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + private: + class AssertionPrinter { + void operator= ( AssertionPrinter const& ); + public: + AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) + : stream( _stream ) + , stats( _stats ) + , result( _stats.assertionResult ) + , messages( _stats.infoMessages ) + , itMessage( _stats.infoMessages.begin() ) + , printInfoMessages( _printInfoMessages ) + {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch( result.getResultType() ) { + case ResultWas::Ok: + printResultType( Colour::ResultSuccess, passedString() ); + printOriginalExpression(); + printReconstructedExpression(); + if ( ! result.hasExpression() ) + printRemainingMessages( Colour::None ); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if( result.isOk() ) + printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); + else + printResultType( Colour::Error, failedString() ); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType( Colour::Error, failedString() ); + printIssue( "unexpected exception with message:" ); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType( Colour::Error, failedString() ); + printIssue( "expected exception, got none" ); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType( Colour::None, "info" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType( Colour::None, "warning" ); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType( Colour::Error, failedString() ); + printIssue( "explicitly" ); + printRemainingMessages( Colour::None ); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType( Colour::Error, "** internal error **" ); + break; + } + } + + private: + // Colour::LightGrey + + static Colour::Code dimColour() { return Colour::FileName; } + +#ifdef CATCH_PLATFORM_MAC + static const char* failedString() { return "FAILED"; } + static const char* passedString() { return "PASSED"; } +#else + static const char* failedString() { return "failed"; } + static const char* passedString() { return "passed"; } +#endif + + void printSourceInfo() const { + Colour colourGuard( Colour::FileName ); + stream << result.getSourceInfo() << ":"; + } + + void printResultType( Colour::Code colour, std::string passOrFail ) const { + if( !passOrFail.empty() ) { + { + Colour colourGuard( colour ); + stream << " " << passOrFail; + } + stream << ":"; + } + } + + void printIssue( std::string issue ) const { + stream << " " << issue; + } + + void printExpressionWas() { + if( result.hasExpression() ) { + stream << ";"; + { + Colour colour( dimColour() ); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if( result.hasExpression() ) { + stream << " " << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if( result.hasExpandedExpression() ) { + { + Colour colour( dimColour() ); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if ( itMessage != messages.end() ) { + stream << " '" << itMessage->message << "'"; + ++itMessage; + } + } + + void printRemainingMessages( Colour::Code colour = dimColour() ) { + if ( itMessage == messages.end() ) + return; + + // using messages.end() directly yields compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); + + { + Colour colourGuard( colour ); + stream << " with " << pluralise( N, "message" ) << ":"; + } + + for(; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if( printInfoMessages || itMessage->type != ResultWas::Info ) { + stream << " '" << itMessage->message << "'"; + if ( ++itMessage != itEnd ) { + Colour colourGuard( dimColour() ); + stream << " and"; + } + } + } + } + + private: + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; + }; + + // Colour, message variants: + // - white: No tests ran. + // - red: Failed [both/all] N test cases, failed [both/all] M assertions. + // - white: Passed [both/all] N test cases (no assertions). + // - red: Failed N tests cases, failed M assertions. + // - green: Passed [both/all] N tests cases with M assertions. + + std::string bothOrAll( std::size_t count ) const { + return count == 1 ? "" : count == 2 ? "both " : "all " ; + } + + void printTotals( const Totals& totals ) const { + if( totals.testCases.total() == 0 ) { + stream << "No tests ran."; + } + else if( totals.testCases.failed == totals.testCases.total() ) { + Colour colour( Colour::ResultError ); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll( totals.assertions.failed ) : ""; + stream << + "Failed " << bothOrAll( totals.testCases.failed ) + << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << qualify_assertions_failed << + pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else if( totals.assertions.total() == 0 ) { + stream << + "Passed " << bothOrAll( totals.testCases.total() ) + << pluralise( totals.testCases.total(), "test case" ) + << " (no assertions)."; + } + else if( totals.assertions.failed ) { + Colour colour( Colour::ResultError ); + stream << + "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " + "failed " << pluralise( totals.assertions.failed, "assertion" ) << "."; + } + else { + Colour colour( Colour::ResultSuccess ); + stream << + "Passed " << bothOrAll( totals.testCases.passed ) + << pluralise( totals.testCases.passed, "test case" ) << + " with " << pluralise( totals.assertions.passed, "assertion" ) << "."; + } + } + }; + + INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch + +namespace Catch { + NonCopyable::~NonCopyable() {} + IShared::~IShared() {} + StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} + IContext::~IContext() {} + IResultCapture::~IResultCapture() {} + ITestCase::~ITestCase() {} + ITestCaseRegistry::~ITestCaseRegistry() {} + IRegistryHub::~IRegistryHub() {} + IMutableRegistryHub::~IMutableRegistryHub() {} + IExceptionTranslator::~IExceptionTranslator() {} + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} + IReporter::~IReporter() {} + IReporterFactory::~IReporterFactory() {} + IReporterRegistry::~IReporterRegistry() {} + IStreamingReporter::~IStreamingReporter() {} + AssertionStats::~AssertionStats() {} + SectionStats::~SectionStats() {} + TestCaseStats::~TestCaseStats() {} + TestGroupStats::~TestGroupStats() {} + TestRunStats::~TestRunStats() {} + CumulativeReporterBase::SectionNode::~SectionNode() {} + CumulativeReporterBase::~CumulativeReporterBase() {} + + StreamingReporterBase::~StreamingReporterBase() {} + ConsoleReporter::~ConsoleReporter() {} + CompactReporter::~CompactReporter() {} + IRunner::~IRunner() {} + IMutableContext::~IMutableContext() {} + IConfig::~IConfig() {} + XmlReporter::~XmlReporter() {} + JunitReporter::~JunitReporter() {} + TestRegistry::~TestRegistry() {} + FreeFunctionTestCase::~FreeFunctionTestCase() {} + IGeneratorInfo::~IGeneratorInfo() {} + IGeneratorsForTest::~IGeneratorsForTest() {} + TestSpec::Pattern::~Pattern() {} + TestSpec::NamePattern::~NamePattern() {} + TestSpec::TagPattern::~TagPattern() {} + TestSpec::ExcludedPattern::~ExcludedPattern() {} + + Matchers::Impl::StdString::Equals::~Equals() {} + Matchers::Impl::StdString::Contains::~Contains() {} + Matchers::Impl::StdString::StartsWith::~StartsWith() {} + Matchers::Impl::StdString::EndsWith::~EndsWith() {} + + void Config::dummy() {} + + INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter ) +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif + +#ifdef CATCH_CONFIG_MAIN +// #included from: internal/catch_default_main.hpp +#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED + +#ifndef __OBJC__ + +// Standard C/C++ main entry point +int main (int argc, char * const argv[]) { + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char* const*)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +#endif + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +////// + +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) +#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) + +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) + +#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) +#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" ) +#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" ) +#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" ) +#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" ) + +#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) +#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) +#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) + #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) +#else + #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) + #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) +#endif +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) +#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) +#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) + +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) + +#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) +#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) +#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) + +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) + +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) + +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) +#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) +#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) + +#ifdef CATCH_CONFIG_VARIADIC_MACROS + #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) + #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) + #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) + #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) + #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) +#else + #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) + #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) + #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) + #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) + #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) +#endif +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) + +#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) +#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) + +#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#ifdef CATCH_CONFIG_VARIADIC_MACROS +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#else +#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) +#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) +#endif +#define GIVEN( desc ) SECTION( " Given: " desc, "" ) +#define WHEN( desc ) SECTION( " When: " desc, "" ) +#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) +#define THEN( desc ) SECTION( " Then: " desc, "" ) +#define AND_THEN( desc ) SECTION( " And: " desc, "" ) + +using Catch::Detail::Approx; + +// #included from: internal/catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop +#endif + +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED + diff --git a/tests/cxx/test_main.cpp b/tests/cxx/test_main.cpp new file mode 100644 index 000000000..063e87874 --- /dev/null +++ b/tests/cxx/test_main.cpp @@ -0,0 +1,2 @@ +#define CATCH_CONFIG_MAIN +#include "catch.hpp" \ No newline at end of file diff --git a/tests/cxx/tiff_io.cpp b/tests/cxx/tiff_io.cpp new file mode 100644 index 000000000..37cfdddd4 --- /dev/null +++ b/tests/cxx/tiff_io.cpp @@ -0,0 +1,282 @@ + +#if defined(HAVE_TIFF) + +#include "catch.hpp" + +#include +#include +#include + +#include +#include "../../src/tiff_reader.cpp" + +#define TIFF_ASSERT(filename) \ + mapnik::tiff_reader tiff_reader(filename); \ + REQUIRE( tiff_reader.width() == 256 ); \ + REQUIRE( tiff_reader.height() == 256 ); \ + REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); \ + std::unique_ptr reader(mapnik::get_image_reader(filename,"tiff")); \ + REQUIRE( reader->width() == 256 ); \ + REQUIRE( reader->height() == 256 ); \ + mapnik::util::file file(filename); \ + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); \ + REQUIRE( tiff_reader2.width() == 256 ); \ + REQUIRE( tiff_reader2.height() == 256 ); \ + std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); \ + REQUIRE( reader2->width() == 256 ); \ + REQUIRE( reader2->height() == 256 ); \ + +#define TIFF_ASSERT_ALPHA \ + REQUIRE( tiff_reader.has_alpha() == true ); \ + REQUIRE( tiff_reader.premultiplied_alpha() == false ); \ + REQUIRE( reader->has_alpha() == true ); \ + REQUIRE( reader->premultiplied_alpha() == false ); \ + REQUIRE( tiff_reader2.has_alpha() == true ); \ + REQUIRE( tiff_reader2.premultiplied_alpha() == false ); \ + REQUIRE( reader2->has_alpha() == true ); \ + REQUIRE( reader2->premultiplied_alpha() == false ); \ + +#define TIFF_ASSERT_NO_ALPHA \ + REQUIRE( tiff_reader.has_alpha() == false ); \ + REQUIRE( tiff_reader.premultiplied_alpha() == false ); \ + REQUIRE( reader->has_alpha() == false ); \ + REQUIRE( reader->premultiplied_alpha() == false ); \ + REQUIRE( tiff_reader2.has_alpha() == false ); \ + REQUIRE( tiff_reader2.premultiplied_alpha() == false ); \ + REQUIRE( reader2->has_alpha() == false ); \ + REQUIRE( reader2->premultiplied_alpha() == false ); \ + +#define TIFF_ASSERT_SIZE( data,reader ) \ + REQUIRE( data.width() == reader->width() ); \ + REQUIRE( data.height() == reader->height() ); \ + +#define TIFF_READ_ONE_PIXEL \ + mapnik::image_data_any subimage = reader->read(1, 1, 1, 1); \ + REQUIRE( subimage.width() == 1 ); \ + REQUIRE( subimage.height() == 1 ); \ + +TEST_CASE("tiff io") { + +SECTION("scan rgb8 striped") { + std::string filename("./tests/data/tiff/scan_512x512_rgb8_striped.tif"); + mapnik::tiff_reader tiff_reader(filename); + REQUIRE( tiff_reader.width() == 512 ); + REQUIRE( tiff_reader.height() == 512 ); + REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); + REQUIRE( tiff_reader.rows_per_strip() == 16 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE ); + REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); + std::unique_ptr reader(mapnik::get_image_reader(filename,"tiff")); + REQUIRE( reader->width() == 512 ); + REQUIRE( reader->height() == 512 ); + mapnik::util::file file(filename); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + REQUIRE( tiff_reader2.width() == 512 ); + REQUIRE( tiff_reader2.height() == 512 ); + std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); + REQUIRE( reader2->width() == 512 ); + REQUIRE( reader2->height() == 512 ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("scan rgb8 tiled") { + std::string filename("./tests/data/tiff/scan_512x512_rgb8_tiled.tif"); + mapnik::tiff_reader tiff_reader(filename); + REQUIRE( tiff_reader.width() == 512 ); + REQUIRE( tiff_reader.height() == 512 ); + REQUIRE( tiff_reader.planar_config() == PLANARCONFIG_CONTIG ); + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_PALETTE ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + std::unique_ptr reader(mapnik::get_image_reader(filename,"tiff")); + REQUIRE( reader->width() == 512 ); + REQUIRE( reader->height() == 512 ); + mapnik::util::file file(filename); + mapnik::tiff_reader tiff_reader2(file.data().get(),file.size()); + REQUIRE( tiff_reader2.width() == 512 ); + REQUIRE( tiff_reader2.height() == 512 ); + std::unique_ptr reader2(mapnik::get_image_reader(file.data().get(),file.size())); + REQUIRE( reader2->width() == 512 ); + REQUIRE( reader2->height() == 512 ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("rgba8 striped") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgba8_striped.tif") + REQUIRE( tiff_reader.rows_per_strip() == 1 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); + REQUIRE( tiff_reader.compression() == COMPRESSION_ADOBE_DEFLATE ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("rgba8 tiled") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgba8_tiled.tif") + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("rgb8 striped") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgb8_striped.tif") + REQUIRE( tiff_reader.rows_per_strip() == 10 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); + REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("rgb8 tiled") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_rgb8_tiled.tif") + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_RGB ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray8 striped") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray8_striped.tif") + REQUIRE( tiff_reader.rows_per_strip() == 32 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray8 tiled") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray8_tiled.tif") + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 8 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray16 striped") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray16_striped.tif") + REQUIRE( tiff_reader.rows_per_strip() == 16 ); + REQUIRE( tiff_reader.bits_per_sample() == 16 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray16 tiled") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray16_tiled.tif") + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 16 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray32f striped") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray32f_striped.tif") + REQUIRE( tiff_reader.rows_per_strip() == 8 ); + REQUIRE( tiff_reader.bits_per_sample() == 32 ); + REQUIRE( tiff_reader.is_tiled() == false ); + REQUIRE( tiff_reader.tile_width() == 0 ); + REQUIRE( tiff_reader.tile_height() == 0 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_NONE ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +SECTION("gray32f tiled") { + TIFF_ASSERT("./tests/data/tiff/ndvi_256x256_gray32f_tiled.tif") + REQUIRE( tiff_reader.rows_per_strip() == 0 ); + REQUIRE( tiff_reader.bits_per_sample() == 32 ); + REQUIRE( tiff_reader.is_tiled() == true ); + REQUIRE( tiff_reader.tile_width() == 256 ); + REQUIRE( tiff_reader.tile_height() == 256 ); + REQUIRE( tiff_reader.photometric() == PHOTOMETRIC_MINISBLACK ); + REQUIRE( tiff_reader.compression() == COMPRESSION_LZW ); + mapnik::image_data_any data = reader->read(0, 0, reader->width(), reader->height()); + REQUIRE( data.is() == true ); + TIFF_ASSERT_SIZE( data,reader ); + TIFF_ASSERT_NO_ALPHA + TIFF_READ_ONE_PIXEL +} + +} + +#endif diff --git a/tests/cxx/valgrind.supp b/tests/cxx/valgrind.supp new file mode 100644 index 000000000..2f6d70bd7 --- /dev/null +++ b/tests/cxx/valgrind.supp @@ -0,0 +1,31 @@ +{ + dl_error1 + Memcheck:Cond + fun:index + fun:expand_dynamic_string_token + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + dl_error2 + Memcheck:Cond + fun:index + fun:expand_dynamic_string_token + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + tmpfile + Memcheck:Leak + fun:malloc + fun:fdopen@@GLIBC_* + fun:tmpfile@@GLIBC_* +} diff --git a/tests/data/deprecated_maps/marker-type.xml b/tests/data/deprecated_maps/marker-type.xml new file mode 100644 index 000000000..208998ff0 --- /dev/null +++ b/tests/data/deprecated_maps/marker-type.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/tests/data/good_maps/extra_arbitary_map_parameters.xml b/tests/data/good_maps/extra_arbitary_map_parameters.xml index e6bd5d444..d10979ff1 100644 --- a/tests/data/good_maps/extra_arbitary_map_parameters.xml +++ b/tests/data/good_maps/extra_arbitary_map_parameters.xml @@ -1,24 +1,22 @@ - + - - - - - - - + + + + + \ No newline at end of file diff --git a/tests/data/raster/missing_raster.vrt b/tests/data/raster/missing_raster.vrt new file mode 100644 index 000000000..98d0bea30 --- /dev/null +++ b/tests/data/raster/missing_raster.vrt @@ -0,0 +1,45 @@ + + PROJCS["WGS 84 / UTM zone 30N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-3],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","32630"]] + -1.4637000000000000e+04, 5.0000000000000000e+02, 0.0000000000000000e+00, 4.8596780000000000e+06, 0.0000000000000000e+00, -5.0000000000000000e+02 + + -9.99000000000000E+02 + 0 + Palette + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this_file_should_not_exist.tif + 1 + + + + -999 + + + diff --git a/tests/data/rasterlite/globe.sqlite b/tests/data/rasterlite/globe.sqlite new file mode 100644 index 000000000..1804ecfd7 Binary files /dev/null and b/tests/data/rasterlite/globe.sqlite differ diff --git a/tests/data/svg/airfield-12-nobox.svg b/tests/data/svg/airfield-12-nobox.svg new file mode 100644 index 000000000..bdb567083 --- /dev/null +++ b/tests/data/svg/airfield-12-nobox.svg @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/tests/data/svg/airfield-12.svg b/tests/data/svg/airfield-12.svg new file mode 100644 index 000000000..74c726a0e --- /dev/null +++ b/tests/data/svg/airfield-12.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/tests/data/svg/rect-no-fill.svg b/tests/data/svg/rect-no-fill.svg new file mode 100644 index 000000000..d4b32c644 --- /dev/null +++ b/tests/data/svg/rect-no-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tests/data/svg/rect-no-stroke.svg b/tests/data/svg/rect-no-stroke.svg new file mode 100644 index 000000000..06d034275 --- /dev/null +++ b/tests/data/svg/rect-no-stroke.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tests/data/tiff/README.md b/tests/data/tiff/README.md new file mode 100644 index 000000000..3be591138 --- /dev/null +++ b/tests/data/tiff/README.md @@ -0,0 +1,4 @@ +striped images created with rio +tiled images created with: + + tiffcp -t -w256 -l256 -c lzw input.tiff output.tif \ No newline at end of file diff --git a/tests/data/tiff/ndvi_256x256_gray16_striped.tif b/tests/data/tiff/ndvi_256x256_gray16_striped.tif new file mode 100644 index 000000000..3036698be Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray16_striped.tif differ diff --git a/tests/data/tiff/ndvi_256x256_gray16_tiled.tif b/tests/data/tiff/ndvi_256x256_gray16_tiled.tif new file mode 100644 index 000000000..65705f531 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray16_tiled.tif differ diff --git a/tests/data/tiff/ndvi_256x256_gray32f_striped.tif b/tests/data/tiff/ndvi_256x256_gray32f_striped.tif new file mode 100644 index 000000000..daf2f70b7 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray32f_striped.tif differ diff --git a/tests/data/tiff/ndvi_256x256_gray32f_tiled.tif b/tests/data/tiff/ndvi_256x256_gray32f_tiled.tif new file mode 100644 index 000000000..5ad67417d Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray32f_tiled.tif differ diff --git a/tests/data/tiff/ndvi_256x256_gray8_striped.tif b/tests/data/tiff/ndvi_256x256_gray8_striped.tif new file mode 100644 index 000000000..c6a90d6ba Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray8_striped.tif differ diff --git a/tests/data/tiff/ndvi_256x256_gray8_tiled.tif b/tests/data/tiff/ndvi_256x256_gray8_tiled.tif new file mode 100644 index 000000000..e01a743fb Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_gray8_tiled.tif differ diff --git a/tests/data/tiff/ndvi_256x256_rgb.tiff b/tests/data/tiff/ndvi_256x256_rgb.tiff new file mode 100644 index 000000000..d755b181e Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_rgb.tiff differ diff --git a/tests/data/tiff/ndvi_256x256_rgb8_striped.tif b/tests/data/tiff/ndvi_256x256_rgb8_striped.tif new file mode 100644 index 000000000..5ed7f06d3 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_rgb8_striped.tif differ diff --git a/tests/data/tiff/ndvi_256x256_rgb8_tiled.tif b/tests/data/tiff/ndvi_256x256_rgb8_tiled.tif new file mode 100644 index 000000000..5e0cb6348 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_rgb8_tiled.tif differ diff --git a/tests/data/tiff/ndvi_256x256_rgba8_striped.tif b/tests/data/tiff/ndvi_256x256_rgba8_striped.tif new file mode 100644 index 000000000..bed2b30e9 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_rgba8_striped.tif differ diff --git a/tests/data/tiff/ndvi_256x256_rgba8_tiled.tif b/tests/data/tiff/ndvi_256x256_rgba8_tiled.tif new file mode 100644 index 000000000..c3c5e2e61 Binary files /dev/null and b/tests/data/tiff/ndvi_256x256_rgba8_tiled.tif differ diff --git a/tests/data/tiff/scan_512x512_rgb8_striped.tif b/tests/data/tiff/scan_512x512_rgb8_striped.tif new file mode 100644 index 000000000..ac94c81f3 Binary files /dev/null and b/tests/data/tiff/scan_512x512_rgb8_striped.tif differ diff --git a/tests/data/tiff/scan_512x512_rgb8_tiled.tif b/tests/data/tiff/scan_512x512_rgb8_tiled.tif new file mode 100644 index 000000000..f5cbf1004 Binary files /dev/null and b/tests/data/tiff/scan_512x512_rgb8_tiled.tif differ diff --git a/tests/python_tests/compositing_test.py b/tests/python_tests/compositing_test.py index 14b697bb7..bf10ff7be 100644 --- a/tests/python_tests/compositing_test.py +++ b/tests/python_tests/compositing_test.py @@ -93,7 +93,7 @@ def test_compare_images(): if not validate_pixels_are_not_premultiplied(a): fails.append('%s not validly demultiplied' % (name)) a.save(actual,'png32') - if not os.path.exists(expected): + if not os.path.exists(expected) or os.environ.get('UPDATE'): print 'generating expected test image: %s' % expected a.save(expected,'png32') expected_im = mapnik.Image.open(expected) @@ -167,7 +167,7 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): actual = '/tmp/mapnik-style-comp-op-' + name + '.png' expected = 'images/style-comp-op/' + name + '.png' im.save(actual,'png32') - if not os.path.exists(expected): + if not os.path.exists(expected) or os.environ.get('UPDATE'): print 'generating expected test image: %s' % expected im.save(expected,'png32') expected_im = mapnik.Image.open(expected) @@ -197,13 +197,12 @@ def test_rounding_and_color_expectations(): m.background = mapnik.Color('rgba(255,255,255,.4999999)') im = mapnik.Image(m.width,m.height) mapnik.render(m,im) - # ugh 252, see: https://github.com/mapnik/mapnik/issues/1519 - eq_(get_unique_colors(im),['rgba(252,252,252,127)']) + eq_(get_unique_colors(im),['rgba(255,255,255,127)']) m = mapnik.Map(1,1) m.background = mapnik.Color('rgba(255,255,255,.5)') im = mapnik.Image(m.width,m.height) mapnik.render(m,im) - eq_(get_unique_colors(im),['rgba(253,253,253,128)']) + eq_(get_unique_colors(im),['rgba(255,255,255,128)']) im_file = mapnik.Image.open('../data/images/stripes_pattern.png') eq_(get_unique_colors(im_file),['rgba(0,0,0,0)', 'rgba(74,74,74,255)']) # should have no effect @@ -224,10 +223,7 @@ def test_background_image_and_background_color(): m.background_image = '../data/images/stripes_pattern.png' im = mapnik.Image(m.width,m.height) mapnik.render(m,im) - # note: data loss due to rounding as per https://github.com/mapnik/mapnik/issues/1519 - # means that background will roundtrip to 253 not 255 - #eq_(get_unique_colors(im),['rgba(255,255,255,128)', 'rgba(74,74,74,255)']) - eq_(get_unique_colors(im),['rgba(253,253,253,128)', 'rgba(74,74,74,255)']) + eq_(get_unique_colors(im),['rgba(255,255,255,128)', 'rgba(74,74,74,255)']) def test_background_image_with_alpha_and_background_color(): m = mapnik.Map(10,10) diff --git a/tests/python_tests/datasource_test.py b/tests/python_tests/datasource_test.py index c86b829bc..e6a05e5a5 100644 --- a/tests/python_tests/datasource_test.py +++ b/tests/python_tests/datasource_test.py @@ -13,6 +13,33 @@ def test_that_datasources_exist(): if len(mapnik.DatasourceCache.plugin_names()) == 0: print '***NOTICE*** - no datasource plugins have been loaded' +# adapted from raster_symboliser_test#test_dataraster_query_point +def test_vrt_referring_to_missing_files(): + srs = '+init=epsg:32630' + if 'gdal' in mapnik.DatasourceCache.plugin_names(): + lyr = mapnik.Layer('dataraster') + lyr.datasource = mapnik.Gdal( + file = '../data/raster/missing_raster.vrt', + band = 1, + ) + lyr.srs = srs + _map = mapnik.Map(256, 256, srs) + _map.layers.append(lyr) + + # center of extent of raster + x, y = 556113.0,4381428.0 # center of extent of raster + + _map.zoom_all() + + # Should RuntimeError here + try: + _map.query_point(0, x, y).features + except RuntimeError, e: + eq_("this_file_should_not_exist.tif' does not exist in the file system" in str(e), True) + else: + assert False + + def test_field_listing(): if 'shape' in mapnik.DatasourceCache.plugin_names(): ds = mapnik.Shapefile(file='../data/shp/poly.shp') diff --git a/tests/python_tests/extra_map_props_test.py b/tests/python_tests/extra_map_props_test.py index 06d659682..e7ffba5d4 100644 --- a/tests/python_tests/extra_map_props_test.py +++ b/tests/python_tests/extra_map_props_test.py @@ -13,13 +13,30 @@ def setup(): def test_arbitrary_parameters_attached_to_map(): m = mapnik.Map(256,256) mapnik.load_map(m,'../data/good_maps/extra_arbitary_map_parameters.xml') - eq_(len(m.parameters),6) + eq_(len(m.parameters),5) eq_(m.parameters['key'],'value2') eq_(m.parameters['key3'],'value3') eq_(m.parameters['unicode'],u'iván') eq_(m.parameters['integer'],10) eq_(m.parameters['decimal'],.999) - eq_(m.parameters['number-as-string'],u'.9998') + m2 = mapnik.Map(256,256) + for k,v in m.parameters: + m2.parameters.append(mapnik.Parameter(k,v)) + eq_(len(m2.parameters),5) + eq_(m2.parameters['key'],'value2') + eq_(m2.parameters['key3'],'value3') + eq_(m2.parameters['unicode'],u'iván') + eq_(m2.parameters['integer'],10) + eq_(m2.parameters['decimal'],.999) + map_string = mapnik.save_map_to_string(m) + m3 = mapnik.Map(256,256) + mapnik.load_map_from_string(m3,map_string) + eq_(len(m3.parameters),5) + eq_(m3.parameters['key'],'value2') + eq_(m3.parameters['key3'],'value3') + eq_(m3.parameters['unicode'],u'iván') + eq_(m3.parameters['integer'],10) + eq_(m3.parameters['decimal'],.999) def test_serializing_arbitrary_parameters(): diff --git a/tests/python_tests/filter_test.py b/tests/python_tests/filter_test.py index bf80fd9fa..fefca8496 100644 --- a/tests/python_tests/filter_test.py +++ b/tests/python_tests/filter_test.py @@ -441,5 +441,10 @@ def test_division_by_zero(): f['b'] = 0 eq_(expr.evaluate(f),None) +@raises(RuntimeError) +def test_invalid_syntax1(): + expr = mapnik.Expression('abs()') + + if __name__ == "__main__": exit(run_all(eval(x) for x in dir() if x.startswith("test_"))) diff --git a/tests/python_tests/image_filters_test.py b/tests/python_tests/image_filters_test.py index c122294c9..88277d1f2 100644 --- a/tests/python_tests/image_filters_test.py +++ b/tests/python_tests/image_filters_test.py @@ -50,7 +50,7 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): actual = '/tmp/mapnik-style-image-filter-' + filename + '.png' expected = 'images/style-image-filter/' + filename + '.png' im.save(actual,"png32") - if not os.path.exists(expected): + if not os.path.exists(expected) or os.environ.get('UPDATE'): print 'generating expected test image: %s' % expected im.save(expected,'png32') expected_im = mapnik.Image.open(expected) diff --git a/tests/python_tests/image_test.py b/tests/python_tests/image_test.py index 4947ce945..6e0fa66b7 100644 --- a/tests/python_tests/image_test.py +++ b/tests/python_tests/image_test.py @@ -7,7 +7,6 @@ from timeit import Timer, time from nose.tools import * from utilities import execution_path, run_all - def setup(): # All of the paths used are relative, if we run the tests # from another directory we need to chdir() @@ -21,22 +20,10 @@ def test_image_premultiply(): im.demultiply() eq_(im.premultiplied(),False) -# Disabled for now since this breaks hard if run against -# a mapnik version that does not have the fix -#@raises(RuntimeError) -#def test_negative_image_dimensions(): - #im = mapnik.Image(-40,40) - -def test_tiff_round_trip(): - filepath = '/tmp/mapnik-tiff-io.tiff' - im = mapnik.Image(255,267) - im.background = mapnik.Color('rgba(1,2,3,.5)') - im.save(filepath,'tiff') - im2 = mapnik.Image.open(filepath) - eq_(im.width(),im2.width()) - eq_(im.height(),im2.height()) - eq_(len(im.tostring()),len(im2.tostring())) - eq_(len(im.tostring('tiff')),len(im2.tostring('tiff'))) +@raises(RuntimeError) +def test_negative_image_dimensions(): + # TODO - this may have regressed in https://github.com/mapnik/mapnik/commit/4f3521ac24b61fc8ae8fd344a16dc3a5fdf15af7 + im = mapnik.Image(-40,40) def test_jpeg_round_trip(): filepath = '/tmp/mapnik-jpeg-io.jpeg' @@ -44,10 +31,15 @@ def test_jpeg_round_trip(): im.background = mapnik.Color('rgba(1,2,3,.5)') im.save(filepath,'jpeg') im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) eq_(im.width(),im2.width()) eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) eq_(len(im.tostring()),len(im2.tostring())) eq_(len(im.tostring('jpeg')),len(im2.tostring('jpeg'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('jpeg')),len(im3.tostring('jpeg'))) def test_png_round_trip(): filepath = '/tmp/mapnik-png-io.png' @@ -55,11 +47,17 @@ def test_png_round_trip(): im.background = mapnik.Color('rgba(1,2,3,.5)') im.save(filepath,'png') im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) eq_(im.width(),im2.width()) eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) eq_(len(im.tostring()),len(im2.tostring())) eq_(len(im.tostring('png')),len(im2.tostring('png'))) eq_(len(im.tostring('png8')),len(im2.tostring('png8'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('png')),len(im3.tostring('png'))) + eq_(len(im.tostring('png8')),len(im3.tostring('png8'))) def test_image_open_from_string(): filepath = '../data/images/dummy.png' diff --git a/tests/python_tests/image_tiff_test.py b/tests/python_tests/image_tiff_test.py new file mode 100644 index 000000000..ad37103be --- /dev/null +++ b/tests/python_tests/image_tiff_test.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys +import os, mapnik +from timeit import Timer, time +from nose.tools import * +from utilities import execution_path, run_all + +def setup(): + # All of the paths used are relative, if we run the tests + # from another directory we need to chdir() + os.chdir(execution_path('.')) + +def test_tiff_round_trip_scanline(): + filepath = '/tmp/mapnik-tiff-io-scanline.tiff' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + org_str = len(im.tostring()) + im.save(filepath,'tiff:method=scanline') + im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) + eq_(len(im.tostring()), org_str) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im2.tostring('tiff:method=scanline'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im3.tostring('tiff:method=scanline'))) + +def test_tiff_round_trip_stripped(): + filepath = '/tmp/mapnik-tiff-io-stripped.tiff' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + org_str = len(im.tostring()) + im.save(filepath,'tiff:method=stripped') + im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) + eq_(len(im.tostring()), org_str) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im2.tostring('tiff:method=stripped'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im3.tostring('tiff:method=stripped'))) + +def test_tiff_round_trip_rows_stripped(): + filepath = '/tmp/mapnik-tiff-io-stripped.tiff' + im = mapnik.Image(255,267) + im.background = mapnik.Color('rgba(1,2,3,.5)') + org_str = len(im.tostring()) + im.save(filepath,'tiff:method=stripped:rows_per_strip=8') + im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) + eq_(len(im.tostring()), org_str) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped:rows_per_strip=8')),len(im2.tostring('tiff:method=stripped:rows_per_strip=8'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('tiff:method=stripped:rows_per_strip=8')),len(im3.tostring('tiff:method=stripped:rows_per_strip=8'))) + +def test_tiff_round_trip_buffered_tiled(): + filepath = '/tmp/mapnik-tiff-io-buffered-tiled.tiff' + filepath2 = '/tmp/mapnik-tiff-io-buffered-tiled2.tiff' + im = mapnik.Image(255,267) + #im = mapnik.Image(256,256) + im.background = mapnik.Color('rgba(1,2,3,.5)') + im.save(filepath,'tiff:method=tiled:tile_width=32:tile_height=32') + im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) + im2.save(filepath2, 'tiff:method=tiled:tile_width=32:tile_height=32') + im4 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) + eq_(len(im2.tostring()),len(im4.tostring())) + eq_(len(im2.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),len(im4.tostring('tiff:method=tiled:tile_width=32:tile_height=32'))) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),len(im2.tostring('tiff:method=tiled:tile_width=32:tile_height=32'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('tiff:method=tiled:tile_width=32:tile_height=32')),len(im3.tostring('tiff:method=tiled:tile_width=32:tile_height=32'))) + +def test_tiff_round_trip_tiled(): + filepath = '/tmp/mapnik-tiff-io-tiled.tiff' + im = mapnik.Image(256,256) + im.background = mapnik.Color('rgba(1,2,3,.5)') + im.save(filepath,'tiff:method=tiled') + im2 = mapnik.Image.open(filepath) + im3 = mapnik.Image.fromstring(open(filepath,'r').read()) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(im.width(),im3.width()) + eq_(im.height(),im3.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im2.tostring('tiff:method=tiled'))) + eq_(len(im.tostring()),len(im3.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im3.tostring('tiff:method=tiled'))) + + +def test_tiff_rgb8_compare(): + filepath1 = '../data/tiff/ndvi_256x256_rgb8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-rgb8.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff')),len(im2.tostring('tiff'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_rgba8_compare_scanline(): + filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-rgba8-scanline.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=scanline') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im2.tostring('tiff:method=scanline'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_rgba8_compare_stripped(): + filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-rgba8-stripped.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=stripped') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im2.tostring('tiff:method=stripped'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_rgba8_compare_tiled(): + filepath1 = '../data/tiff/ndvi_256x256_rgba8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-rgba8-stripped.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=tiled') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im2.tostring('tiff:method=tiled'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray8_compare_scanline(): + filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray8-scanline.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=scanline') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im2.tostring('tiff:method=scanline'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray8_compare_stripped(): + filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray8-stripped.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=stripped') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im2.tostring('tiff:method=stripped'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray8_compare_tiled(): + filepath1 = '../data/tiff/ndvi_256x256_gray8_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray8-tiled.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=tiled') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im2.tostring('tiff:method=tiled'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray16_compare_scanline(): + filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray16-scanline.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=scanline') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im2.tostring('tiff:method=scanline'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray16_compare_stripped(): + filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray16-stripped.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=stripped') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im2.tostring('tiff:method=stripped'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray16_compare_tiled(): + filepath1 = '../data/tiff/ndvi_256x256_gray16_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray16-tiled.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=tiled') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im2.tostring('tiff:method=tiled'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray32f_compare_scanline(): + filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray32f-scanline.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=scanline') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=scanline')),len(im2.tostring('tiff:method=scanline'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray32f_compare_stripped(): + filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray32f-stripped.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=stripped') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=stripped')),len(im2.tostring('tiff:method=stripped'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +def test_tiff_gray32f_compare_tiled(): + filepath1 = '../data/tiff/ndvi_256x256_gray32f_striped.tif' + filepath2 = '/tmp/mapnik-tiff-gray32f-tiled.tiff' + im = mapnik.Image.open(filepath1) + im.save(filepath2,'tiff:method=tiled') + im2 = mapnik.Image.open(filepath2) + eq_(im.width(),im2.width()) + eq_(im.height(),im2.height()) + eq_(len(im.tostring()),len(im2.tostring())) + eq_(len(im.tostring('tiff:method=tiled')),len(im2.tostring('tiff:method=tiled'))) + # should not be a blank image + eq_(len(im.tostring("png")) != len(mapnik.Image(im.width(),im.height()).tostring("png")),True) + +if __name__ == "__main__": + setup() + exit(run_all(eval(x) for x in dir() if x.startswith("test_"))) diff --git a/tests/python_tests/images/style-comp-op/color.png b/tests/python_tests/images/style-comp-op/color.png index c0947a09d..899eb1f15 100644 Binary files a/tests/python_tests/images/style-comp-op/color.png and b/tests/python_tests/images/style-comp-op/color.png differ diff --git a/tests/python_tests/images/style-comp-op/color_burn.png b/tests/python_tests/images/style-comp-op/color_burn.png index cf1f72306..498fb23e0 100644 Binary files a/tests/python_tests/images/style-comp-op/color_burn.png and b/tests/python_tests/images/style-comp-op/color_burn.png differ diff --git a/tests/python_tests/images/style-comp-op/color_dodge.png b/tests/python_tests/images/style-comp-op/color_dodge.png index d4638c249..dea8ec3d1 100644 Binary files a/tests/python_tests/images/style-comp-op/color_dodge.png and b/tests/python_tests/images/style-comp-op/color_dodge.png differ diff --git a/tests/python_tests/images/style-comp-op/contrast.png b/tests/python_tests/images/style-comp-op/contrast.png index 9d3c43095..2298154c1 100644 Binary files a/tests/python_tests/images/style-comp-op/contrast.png and b/tests/python_tests/images/style-comp-op/contrast.png differ diff --git a/tests/python_tests/images/style-comp-op/darken.png b/tests/python_tests/images/style-comp-op/darken.png index 9792549f9..e0f265b3d 100644 Binary files a/tests/python_tests/images/style-comp-op/darken.png and b/tests/python_tests/images/style-comp-op/darken.png differ diff --git a/tests/python_tests/images/style-comp-op/difference.png b/tests/python_tests/images/style-comp-op/difference.png index a33f772e2..faef22d4c 100644 Binary files a/tests/python_tests/images/style-comp-op/difference.png and b/tests/python_tests/images/style-comp-op/difference.png differ diff --git a/tests/python_tests/images/style-comp-op/divide.png b/tests/python_tests/images/style-comp-op/divide.png index 551ee1043..caa5111f5 100644 Binary files a/tests/python_tests/images/style-comp-op/divide.png and b/tests/python_tests/images/style-comp-op/divide.png differ diff --git a/tests/python_tests/images/style-comp-op/exclusion.png b/tests/python_tests/images/style-comp-op/exclusion.png index bfef058a3..5a46d4541 100644 Binary files a/tests/python_tests/images/style-comp-op/exclusion.png and b/tests/python_tests/images/style-comp-op/exclusion.png differ diff --git a/tests/python_tests/images/style-comp-op/grain_extract.png b/tests/python_tests/images/style-comp-op/grain_extract.png index 7c7059891..a9a432fe7 100644 Binary files a/tests/python_tests/images/style-comp-op/grain_extract.png and b/tests/python_tests/images/style-comp-op/grain_extract.png differ diff --git a/tests/python_tests/images/style-comp-op/grain_merge.png b/tests/python_tests/images/style-comp-op/grain_merge.png index db5159e34..3be208644 100644 Binary files a/tests/python_tests/images/style-comp-op/grain_merge.png and b/tests/python_tests/images/style-comp-op/grain_merge.png differ diff --git a/tests/python_tests/images/style-comp-op/hard_light.png b/tests/python_tests/images/style-comp-op/hard_light.png index 01c0c2a6a..db2552437 100644 Binary files a/tests/python_tests/images/style-comp-op/hard_light.png and b/tests/python_tests/images/style-comp-op/hard_light.png differ diff --git a/tests/python_tests/images/style-comp-op/hue.png b/tests/python_tests/images/style-comp-op/hue.png index 2d2a3c1a2..d58e35fbd 100644 Binary files a/tests/python_tests/images/style-comp-op/hue.png and b/tests/python_tests/images/style-comp-op/hue.png differ diff --git a/tests/python_tests/images/style-comp-op/lighten.png b/tests/python_tests/images/style-comp-op/lighten.png index 3132288eb..a06819161 100644 Binary files a/tests/python_tests/images/style-comp-op/lighten.png and b/tests/python_tests/images/style-comp-op/lighten.png differ diff --git a/tests/python_tests/images/style-comp-op/linear_burn.png b/tests/python_tests/images/style-comp-op/linear_burn.png index 95a984bd8..389f86060 100644 Binary files a/tests/python_tests/images/style-comp-op/linear_burn.png and b/tests/python_tests/images/style-comp-op/linear_burn.png differ diff --git a/tests/python_tests/images/style-comp-op/linear_dodge.png b/tests/python_tests/images/style-comp-op/linear_dodge.png index 23effa569..05bdce8e8 100644 Binary files a/tests/python_tests/images/style-comp-op/linear_dodge.png and b/tests/python_tests/images/style-comp-op/linear_dodge.png differ diff --git a/tests/python_tests/images/style-comp-op/minus.png b/tests/python_tests/images/style-comp-op/minus.png index 30575e239..1c6712a25 100644 Binary files a/tests/python_tests/images/style-comp-op/minus.png and b/tests/python_tests/images/style-comp-op/minus.png differ diff --git a/tests/python_tests/images/style-comp-op/multiply.png b/tests/python_tests/images/style-comp-op/multiply.png index 28a1f54f2..dccb2713c 100644 Binary files a/tests/python_tests/images/style-comp-op/multiply.png and b/tests/python_tests/images/style-comp-op/multiply.png differ diff --git a/tests/python_tests/images/style-comp-op/overlay.png b/tests/python_tests/images/style-comp-op/overlay.png index f227d1c9c..b0be6c6a9 100644 Binary files a/tests/python_tests/images/style-comp-op/overlay.png and b/tests/python_tests/images/style-comp-op/overlay.png differ diff --git a/tests/python_tests/images/style-comp-op/plus.png b/tests/python_tests/images/style-comp-op/plus.png index 23effa569..05bdce8e8 100644 Binary files a/tests/python_tests/images/style-comp-op/plus.png and b/tests/python_tests/images/style-comp-op/plus.png differ diff --git a/tests/python_tests/images/style-comp-op/saturation.png b/tests/python_tests/images/style-comp-op/saturation.png index 4fa0aec81..42c9e7682 100644 Binary files a/tests/python_tests/images/style-comp-op/saturation.png and b/tests/python_tests/images/style-comp-op/saturation.png differ diff --git a/tests/python_tests/images/style-comp-op/screen.png b/tests/python_tests/images/style-comp-op/screen.png index b58bc8b21..b940f732a 100644 Binary files a/tests/python_tests/images/style-comp-op/screen.png and b/tests/python_tests/images/style-comp-op/screen.png differ diff --git a/tests/python_tests/images/style-comp-op/soft_light.png b/tests/python_tests/images/style-comp-op/soft_light.png index 8eeffe292..717d77106 100644 Binary files a/tests/python_tests/images/style-comp-op/soft_light.png and b/tests/python_tests/images/style-comp-op/soft_light.png differ diff --git a/tests/python_tests/images/style-comp-op/src.png b/tests/python_tests/images/style-comp-op/src.png index 6e22f7366..a7a96f57a 100644 Binary files a/tests/python_tests/images/style-comp-op/src.png and b/tests/python_tests/images/style-comp-op/src.png differ diff --git a/tests/python_tests/images/style-comp-op/src_atop.png b/tests/python_tests/images/style-comp-op/src_atop.png index 7bc1b5b37..869552455 100644 Binary files a/tests/python_tests/images/style-comp-op/src_atop.png and b/tests/python_tests/images/style-comp-op/src_atop.png differ diff --git a/tests/python_tests/images/style-comp-op/src_in.png b/tests/python_tests/images/style-comp-op/src_in.png index 6e22f7366..a7a96f57a 100644 Binary files a/tests/python_tests/images/style-comp-op/src_in.png and b/tests/python_tests/images/style-comp-op/src_in.png differ diff --git a/tests/python_tests/images/style-comp-op/src_over.png b/tests/python_tests/images/style-comp-op/src_over.png index 81ff2d4fa..f8261e01e 100644 Binary files a/tests/python_tests/images/style-comp-op/src_over.png and b/tests/python_tests/images/style-comp-op/src_over.png differ diff --git a/tests/python_tests/images/style-comp-op/value.png b/tests/python_tests/images/style-comp-op/value.png index a8ca2404a..c984d3e5b 100644 Binary files a/tests/python_tests/images/style-comp-op/value.png and b/tests/python_tests/images/style-comp-op/value.png differ diff --git a/tests/python_tests/images/style-image-filter/agg-stack-blur22.png b/tests/python_tests/images/style-image-filter/agg-stack-blur22.png index b6050539f..bda766fec 100644 Binary files a/tests/python_tests/images/style-image-filter/agg-stack-blur22.png and b/tests/python_tests/images/style-image-filter/agg-stack-blur22.png differ diff --git a/tests/python_tests/images/style-image-filter/blur.png b/tests/python_tests/images/style-image-filter/blur.png index 64e82968d..f687e511f 100644 Binary files a/tests/python_tests/images/style-image-filter/blur.png and b/tests/python_tests/images/style-image-filter/blur.png differ diff --git a/tests/python_tests/images/style-image-filter/edge-detect.png b/tests/python_tests/images/style-image-filter/edge-detect.png index 89b06685f..cda6f755a 100644 Binary files a/tests/python_tests/images/style-image-filter/edge-detect.png and b/tests/python_tests/images/style-image-filter/edge-detect.png differ diff --git a/tests/python_tests/images/style-image-filter/emboss.png b/tests/python_tests/images/style-image-filter/emboss.png index f6344727f..5e9fea5be 100644 Binary files a/tests/python_tests/images/style-image-filter/emboss.png and b/tests/python_tests/images/style-image-filter/emboss.png differ diff --git a/tests/python_tests/images/style-image-filter/gray.png b/tests/python_tests/images/style-image-filter/gray.png index 36e6df7f8..166ceb5e3 100644 Binary files a/tests/python_tests/images/style-image-filter/gray.png and b/tests/python_tests/images/style-image-filter/gray.png differ diff --git a/tests/python_tests/images/style-image-filter/invert.png b/tests/python_tests/images/style-image-filter/invert.png index ffc1e03a3..072a95be4 100644 Binary files a/tests/python_tests/images/style-image-filter/invert.png and b/tests/python_tests/images/style-image-filter/invert.png differ diff --git a/tests/python_tests/images/style-image-filter/none.png b/tests/python_tests/images/style-image-filter/none.png index b745b75d0..bf8764987 100644 Binary files a/tests/python_tests/images/style-image-filter/none.png and b/tests/python_tests/images/style-image-filter/none.png differ diff --git a/tests/python_tests/images/style-image-filter/sharpen.png b/tests/python_tests/images/style-image-filter/sharpen.png index 3c1130634..21f3f94f6 100644 Binary files a/tests/python_tests/images/style-image-filter/sharpen.png and b/tests/python_tests/images/style-image-filter/sharpen.png differ diff --git a/tests/python_tests/images/style-image-filter/sobel.png b/tests/python_tests/images/style-image-filter/sobel.png index 281d99aa7..a647a6e0f 100644 Binary files a/tests/python_tests/images/style-image-filter/sobel.png and b/tests/python_tests/images/style-image-filter/sobel.png differ diff --git a/tests/python_tests/images/style-image-filter/x-gradient.png b/tests/python_tests/images/style-image-filter/x-gradient.png index fc19f8b1a..1721fc392 100644 Binary files a/tests/python_tests/images/style-image-filter/x-gradient.png and b/tests/python_tests/images/style-image-filter/x-gradient.png differ diff --git a/tests/python_tests/images/style-image-filter/y-gradient.png b/tests/python_tests/images/style-image-filter/y-gradient.png index 1d0bbf20a..37abc0e69 100644 Binary files a/tests/python_tests/images/style-image-filter/y-gradient.png and b/tests/python_tests/images/style-image-filter/y-gradient.png differ diff --git a/tests/python_tests/images/support/dataraster_coloring.png b/tests/python_tests/images/support/dataraster_coloring.png new file mode 100644 index 000000000..da3cac4b1 Binary files /dev/null and b/tests/python_tests/images/support/dataraster_coloring.png differ diff --git a/tests/python_tests/images/support/mapnik-marker-ellipse-render1.png b/tests/python_tests/images/support/mapnik-marker-ellipse-render1.png index 254f81172..7854c5621 100644 Binary files a/tests/python_tests/images/support/mapnik-marker-ellipse-render1.png and b/tests/python_tests/images/support/mapnik-marker-ellipse-render1.png differ diff --git a/tests/python_tests/images/support/mapnik-marker-ellipse-render2.png b/tests/python_tests/images/support/mapnik-marker-ellipse-render2.png index c2cd87699..c2a4963c3 100644 Binary files a/tests/python_tests/images/support/mapnik-marker-ellipse-render2.png and b/tests/python_tests/images/support/mapnik-marker-ellipse-render2.png differ diff --git a/tests/python_tests/images/support/mapnik-palette-test.png b/tests/python_tests/images/support/mapnik-palette-test.png index e657620ad..b7fd90482 100644 Binary files a/tests/python_tests/images/support/mapnik-palette-test.png and b/tests/python_tests/images/support/mapnik-palette-test.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-0.005.png b/tests/python_tests/images/support/marker-text-line-scale-factor-0.005.png index ea9749012..5ba0afcba 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-0.005.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-0.005.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-0.1.png b/tests/python_tests/images/support/marker-text-line-scale-factor-0.1.png index 0af26d729..306424dfc 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-0.1.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-0.1.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-0.899.png b/tests/python_tests/images/support/marker-text-line-scale-factor-0.899.png index a31b8867a..cb2c651f8 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-0.899.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-0.899.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-1.5.png b/tests/python_tests/images/support/marker-text-line-scale-factor-1.5.png index 33b2751b3..a1b34a357 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-1.5.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-1.5.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-1.png b/tests/python_tests/images/support/marker-text-line-scale-factor-1.png index 07c1065f9..c86c5fa4e 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-1.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-1.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-10.png b/tests/python_tests/images/support/marker-text-line-scale-factor-10.png index ffdfad124..8a7842f9e 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-10.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-10.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-100.png b/tests/python_tests/images/support/marker-text-line-scale-factor-100.png index c5828b57a..f1c0b52b8 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-100.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-100.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-2.png b/tests/python_tests/images/support/marker-text-line-scale-factor-2.png index 25217e4f6..e3ad67f99 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-2.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-2.png differ diff --git a/tests/python_tests/images/support/marker-text-line-scale-factor-5.png b/tests/python_tests/images/support/marker-text-line-scale-factor-5.png index a6c4c1ec8..2be5f2df3 100644 Binary files a/tests/python_tests/images/support/marker-text-line-scale-factor-5.png and b/tests/python_tests/images/support/marker-text-line-scale-factor-5.png differ diff --git a/tests/python_tests/images/support/raster_warping.png b/tests/python_tests/images/support/raster_warping.png new file mode 100644 index 000000000..500a51e47 Binary files /dev/null and b/tests/python_tests/images/support/raster_warping.png differ diff --git a/tests/python_tests/images/support/raster_warping_does_not_overclip_source.png b/tests/python_tests/images/support/raster_warping_does_not_overclip_source.png new file mode 100644 index 000000000..0d6ccc5ab Binary files /dev/null and b/tests/python_tests/images/support/raster_warping_does_not_overclip_source.png differ diff --git a/tests/python_tests/json_feature_properties_test.py b/tests/python_tests/json_feature_properties_test.py index 25c6a8c41..82e909e5b 100644 --- a/tests/python_tests/json_feature_properties_test.py +++ b/tests/python_tests/json_feature_properties_test.py @@ -94,7 +94,7 @@ def test_char_escaping(): # confirm our behavior is the same as python json module # for the original string geojson_feat_string = feat.to_geojson() - eq_(geojson_feat_string,char['json'],"Mapnik's json escaping is not to spec: actual(%s) and expected(%s)" % (geojson_feat_string,char['json'])) + eq_(geojson_feat_string,char['json'],"Mapnik's json escaping is not to spec: actual(%s) and expected(%s) for %s" % (geojson_feat_string,char['json'],char['name'])) # and the round tripped string pyjson = json.loads(geojson_feat_string) eq_(pyjson['properties']['name'],expected) diff --git a/tests/python_tests/load_map_test.py b/tests/python_tests/load_map_test.py index 106981df2..283aa8aa3 100644 --- a/tests/python_tests/load_map_test.py +++ b/tests/python_tests/load_map_test.py @@ -37,6 +37,27 @@ def test_broken_files(): eq_(len(failures),0,'\n'+'\n'.join(failures)) mapnik.logger.set_severity(default_logging_severity) +def test_can_parse_xml_with_deprecated_properties(): + default_logging_severity = mapnik.logger.get_severity() + mapnik.logger.set_severity(mapnik.severity_type.None) + files_with_deprecated_props = glob.glob("../data/deprecated_maps/*.xml") + + failures = []; + for filename in files_with_deprecated_props: + try: + m = mapnik.Map(512, 512) + strict = True + mapnik.load_map(m, filename, strict) + base_path = os.path.dirname(filename) + mapnik.load_map_from_string(m,open(filename,'rb').read(),strict,base_path) + except RuntimeError, e: + # only test datasources that we have installed + if not 'Could not create datasource' in str(e) \ + and not 'Bad connection' in str(e): + failures.append('Failed to load valid map %s (%s)' % (filename,e)) + eq_(len(failures),0,'\n'+'\n'.join(failures)) + mapnik.logger.set_severity(default_logging_severity) + def test_good_files(): good_files = glob.glob("../data/good_maps/*.xml") good_files.extend(glob.glob("../visual_tests/styles/*.xml")) diff --git a/tests/python_tests/markers_complex_rendering_test.py b/tests/python_tests/markers_complex_rendering_test.py index f66277f70..41f0a0eff 100644 --- a/tests/python_tests/markers_complex_rendering_test.py +++ b/tests/python_tests/markers_complex_rendering_test.py @@ -19,11 +19,12 @@ if 'csv' in mapnik.DatasourceCache.plugin_names(): actual = '/tmp/mapnik-marker-ellipse-render1.png' expected = 'images/support/mapnik-marker-ellipse-render1.png' im.save(actual,'png32') + if os.environ.get('UPDATE'): + im.save(expected,'png32') expected_im = mapnik.Image.open(expected) eq_(im.tostring('png32'),expected_im.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected)) def test_marker_ellipse_render2(): - # currently crashes https://github.com/mapnik/mapnik/issues/1365 m = mapnik.Map(256,256) mapnik.load_map(m,'../data/good_maps/marker_ellipse_transform2.xml') m.zoom_all() @@ -32,6 +33,8 @@ if 'csv' in mapnik.DatasourceCache.plugin_names(): actual = '/tmp/mapnik-marker-ellipse-render2.png' expected = 'images/support/mapnik-marker-ellipse-render2.png' im.save(actual,'png32') + if os.environ.get('UPDATE'): + im.save(expected,'png32') expected_im = mapnik.Image.open(expected) eq_(im.tostring('png32'),expected_im.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual,'tests/python_tests/'+ expected)) diff --git a/tests/python_tests/palette_test.py b/tests/python_tests/palette_test.py index 9c8576f8e..3a009ed0f 100644 --- a/tests/python_tests/palette_test.py +++ b/tests/python_tests/palette_test.py @@ -38,12 +38,16 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): palette = mapnik.Palette(act.read(),'act') # test saving directly to filesystem im.save('/tmp/mapnik-palette-test.png','png',palette) + expected = './images/support/mapnik-palette-test.png' + if os.environ.get('UPDATE'): + im.save(expected,"png",palette); + # test saving to a string open('/tmp/mapnik-palette-test2.png','wb').write(im.tostring('png',palette)); # compare the two methods - eq_(mapnik.Image.open('/tmp/mapnik-palette-test.png').tostring(),mapnik.Image.open('/tmp/mapnik-palette-test2.png').tostring(),'%s not eq to %s' % ('/tmp/mapnik-palette-test.png','/tmp/mapnik-palette-test2.png')) + eq_(mapnik.Image.open('/tmp/mapnik-palette-test.png').tostring('png32'),mapnik.Image.open('/tmp/mapnik-palette-test2.png').tostring('png32'),'%s not eq to %s' % ('/tmp/mapnik-palette-test.png','/tmp/mapnik-palette-test2.png')) # compare to expected - eq_(mapnik.Image.open('/tmp/mapnik-palette-test.png').tostring(),mapnik.Image.open('./images/support/mapnik-palette-test.png').tostring(),'%s not eq to %s' % ('/tmp/mapnik-palette-test.png','./images/support/mapnik-palette-test.png')) + eq_(mapnik.Image.open('/tmp/mapnik-palette-test.png').tostring('png32'),mapnik.Image.open(expected).tostring('png32'),'%s not eq to %s' % ('/tmp/mapnik-palette-test.png',expected)) if __name__ == "__main__": setup() diff --git a/tests/python_tests/raster_symbolizer_test.py b/tests/python_tests/raster_symbolizer_test.py index 2c7ba1d19..b81e7c145 100644 --- a/tests/python_tests/raster_symbolizer_test.py +++ b/tests/python_tests/raster_symbolizer_test.py @@ -52,9 +52,14 @@ def test_dataraster_coloring(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - imdata = im.tostring() - # we have some values in the [20,30) interval so check that they're colored - assert contains_word('\xff\xff\x00\xff', imdata) + expected_file = './images/support/dataraster_coloring.png' + actual_file = '/tmp/' + os.path.basename(expected_file) + im.save(actual_file,'png32') + if not os.path.exists(expected_file) or os.environ.get('UPDATE'): + im.save(expected_file,'png32') + actual = mapnik.Image.open(actual_file) + expected = mapnik.Image.open(expected_file) + eq_(actual.tostring('png32'),expected.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual_file,expected_file)) def test_dataraster_query_point(): srs = '+init=epsg:32630' @@ -165,8 +170,14 @@ def test_raster_warping(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - imdata = im.tostring() - assert contains_word('\xff\xff\x00\xff', imdata) + expected_file = './images/support/raster_warping.png' + actual_file = '/tmp/' + os.path.basename(expected_file) + im.save(actual_file,'png32') + if not os.path.exists(expected_file) or os.environ.get('UPDATE'): + im.save(expected_file,'png32') + actual = mapnik.Image.open(actual_file) + expected = mapnik.Image.open(expected_file) + eq_(actual.tostring('png32'),expected.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual_file,expected_file)) def test_raster_warping_does_not_overclip_source(): lyrSrs = "+init=epsg:32630" @@ -192,7 +203,14 @@ def test_raster_warping_does_not_overclip_source(): im = mapnik.Image(_map.width,_map.height) mapnik.render(_map, im) - assert im.view(0,200,1,1).tostring()=='\xff\xff\x00\xff' + expected_file = './images/support/raster_warping_does_not_overclip_source.png' + actual_file = '/tmp/' + os.path.basename(expected_file) + im.save(actual_file,'png32') + if not os.path.exists(expected_file) or os.environ.get('UPDATE'): + im.save(expected_file,'png32') + actual = mapnik.Image.open(actual_file) + expected = mapnik.Image.open(expected_file) + eq_(actual.tostring('png32'),expected.tostring('png32'), 'failed comparing actual (%s) and expected (%s)' % (actual_file,expected_file)) if __name__ == "__main__": setup() diff --git a/tests/python_tests/rasterlite_test.py b/tests/python_tests/rasterlite_test.py new file mode 100644 index 000000000..d401b4624 --- /dev/null +++ b/tests/python_tests/rasterlite_test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +from nose.tools import * +from utilities import execution_path, run_all, contains_word, get_unique_colors + +import os, mapnik + +def setup(): + # All of the paths used are relative, if we run the tests + # from another directory we need to chdir() + os.chdir(execution_path('.')) + + +if 'rasterlite' in mapnik.DatasourceCache.plugin_names(): + + def test_rasterlite(): + ds = mapnik.Rasterlite( + file = '../data/rasterlite/globe.sqlite', + table = 'globe' + ) + e = ds.envelope() + + assert_almost_equal(e.minx,-180, places=5) + assert_almost_equal(e.miny, -90, places=5) + assert_almost_equal(e.maxx, 180, places=5) + assert_almost_equal(e.maxy, 90, places=5) + eq_(len(ds.fields()),0) + query = mapnik.Query(ds.envelope()) + for fld in ds.fields(): + query.add_property_name(fld) + fs = ds.features(query) + feat = fs.next() + eq_(feat.id(),1) + eq_(feat.attributes,{}) + +if __name__ == "__main__": + setup() + exit(run_all(eval(x) for x in dir() if x.startswith("test_"))) diff --git a/tests/python_tests/render_test.py b/tests/python_tests/render_test.py index 901021333..aa5054a46 100644 --- a/tests/python_tests/render_test.py +++ b/tests/python_tests/render_test.py @@ -230,7 +230,8 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): expected_file = './images/support/marker-text-line-scale-factor-%s.png' % size actual_file = '/tmp/' + os.path.basename(expected_file) im.save(actual_file,'png32') - #im.save(expected_file,'png32') + if os.environ.get('UPDATE'): + im.save(expected_file,'png32') # we save and re-open here so both png8 images are ready as full color png actual = mapnik.Image.open(actual_file) expected = mapnik.Image.open(expected_file) diff --git a/tests/python_tests/save_map_test.py b/tests/python_tests/save_map_test.py index 4df244d98..37cb9eb6f 100644 --- a/tests/python_tests/save_map_test.py +++ b/tests/python_tests/save_map_test.py @@ -64,6 +64,13 @@ def test_compare_map(): for m in glob.glob("../visual_tests/styles/*.xml"): compare_map(m) +# TODO - enforce that original xml does not equal first saved xml +def test_compare_map_deprecations(): + dep = glob.glob("../data/deprecated_maps/*.xml") + dep = [os.path.normpath(p) for p in dep] + for m in dep: + compare_map(m) + if __name__ == "__main__": setup() exit(run_all(eval(x) for x in dir() if x.startswith("test_"))) diff --git a/tests/python_tests/sqlite_test.py b/tests/python_tests/sqlite_test.py index f384fccae..270f350cd 100644 --- a/tests/python_tests/sqlite_test.py +++ b/tests/python_tests/sqlite_test.py @@ -368,6 +368,44 @@ if 'sqlite' in mapnik.DatasourceCache.plugin_names(): eq_(len(feat.geometries()),1) eq_(feat.geometries()[0].to_wkt(),'Point(0 0)') + def test_db_with_one_untyped_column(): + # form up an in-memory test db + wkb = '010100000000000000000000000000000000000000' + ds = mapnik.SQLite(file=':memory:', + table='test1', + initdb=''' + create table test1 (geometry BLOB, untyped); + insert into test1 values (x'%s', 'untyped'); + ''' % wkb, + extent='-180,-60,180,60', + use_spatial_index=False, + key_field='rowid' + ) + + # ensure the untyped column is found + eq_(len(ds.fields()),2) + eq_(ds.fields(),['rowid', 'untyped']) + eq_(ds.field_types(),['int', 'str']) + + def test_db_with_one_untyped_column_using_subquery(): + # form up an in-memory test db + wkb = '010100000000000000000000000000000000000000' + ds = mapnik.SQLite(file=':memory:', + table='(SELECT rowid, geometry, untyped FROM test1)', + initdb=''' + create table test1 (geometry BLOB, untyped); + insert into test1 values (x'%s', 'untyped'); + ''' % wkb, + extent='-180,-60,180,60', + use_spatial_index=False, + key_field='rowid' + ) + + # ensure the untyped column is found + eq_(len(ds.fields()),3) + eq_(ds.fields(),['rowid', 'untyped', 'rowid']) + eq_(ds.field_types(),['int', 'str', 'int']) + def test_that_64bit_int_fields_work(): ds = mapnik.SQLite(file='../data/sqlite/64bit_int.sqlite', diff --git a/tests/visual_tests/data/points.csv b/tests/visual_tests/data/points.csv index 16b469d2f..3cd780b40 100644 --- a/tests/visual_tests/data/points.csv +++ b/tests/visual_tests/data/points.csv @@ -1,11 +1,11 @@ -lat,long,name,nr,color -0,0,Test one,1,#ff0000 -0,0.1,Test two,2,red -0,0.2,Test three,3,#00ff00 -0,0.3,Test four,4,green -0,0.4,Test five,5,#0000ff -0,0.5,Test six,6,blue -0,0.6,Test seven,7,#000000 -0,0.7,Test eight,8,black -0,0.8,Test nine,9,#ffffff -0,0.9,Test ten,10,white \ No newline at end of file +lat,long,name,nr,color,placements +0,0,Test one,1,#ff0000,"N,S,E,W,SW,10,5" +0,0.1,Test two,2,red,"N,S,E,W,SW,10,5" +0,0.2,Test three,3,#00ff00,"N,S,E,W,SW,10,5" +0,0.3,Test four,4,green,"N,S,E,W,SW,10,5" +0,0.4,Test five,5,#0000ff,"N,S,E,W,SW,10,5" +0,0.5,Test six,6,blue,"N,S,E,W,SW,10,5" +0,0.6,Test seven,7,#000000,"N,S,E,W,SW,10,5" +0,0.7,Test eight,8,black,"N,S,E,W,SW,10,5" +0,0.8,Test nine,9,#ffffff,"N,S,E,W,SW,10,5" +0,0.9,Test ten,10,white,"N,S,E,W,SW,10,5" \ No newline at end of file diff --git a/tests/visual_tests/fonts/Awesome/FontAwesome.otf b/tests/visual_tests/fonts/Awesome/FontAwesome.otf new file mode 100644 index 000000000..81c9ad949 Binary files /dev/null and b/tests/visual_tests/fonts/Awesome/FontAwesome.otf differ diff --git a/tests/visual_tests/fonts/Awesome/readme.md b/tests/visual_tests/fonts/Awesome/readme.md new file mode 100644 index 000000000..6e6139b7a --- /dev/null +++ b/tests/visual_tests/fonts/Awesome/readme.md @@ -0,0 +1 @@ +Font Awesome by Dave Gandy - http://fontawesome.io diff --git a/tests/visual_tests/fonts/glukfonts/Foglihten-068.otf b/tests/visual_tests/fonts/glukfonts/Foglihten-068.otf new file mode 100644 index 000000000..84b640803 Binary files /dev/null and b/tests/visual_tests/fonts/glukfonts/Foglihten-068.otf differ diff --git a/tests/visual_tests/fonts/glukfonts/OFL_License.txt b/tests/visual_tests/fonts/glukfonts/OFL_License.txt new file mode 100644 index 000000000..dd8001ea1 --- /dev/null +++ b/tests/visual_tests/fonts/glukfonts/OFL_License.txt @@ -0,0 +1,94 @@ +Copyright (c) 2010-2011, gluk (http://www.glukfonts.pl|gluksza@wp.pl), +with Reserved Font Name Foglihten. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/tests/visual_tests/grids/dots-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/dots-500-100-1.0-grid-reference.json new file mode 100644 index 000000000..dcf3d346b --- /dev/null +++ b/tests/visual_tests/grids/dots-500-100-1.0-grid-reference.json @@ -0,0 +1,33 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/dots-500-100-2.0-grid-reference.json b/tests/visual_tests/grids/dots-500-100-2.0-grid-reference.json new file mode 100644 index 000000000..dcf3d346b --- /dev/null +++ b/tests/visual_tests/grids/dots-500-100-2.0-grid-reference.json @@ -0,0 +1,33 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/group-symbolizer-4-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-4-500-100-1.0-grid-reference.json new file mode 100644 index 000000000..e59b4aaa5 --- /dev/null +++ b/tests/visual_tests/grids/group-symbolizer-4-500-100-1.0-grid-reference.json @@ -0,0 +1,34 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!! !!! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!! !!!!! ! !!!! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! !!!!! ", + " !!! !!!!! !!! !!!! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! !!!!! ", + " !!! !!!!! !! !!!! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! !!!!! ", + " !!! !!!!! !!!! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! !!!!! ", + " !!! !! !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/group-symbolizer-4-500-100-2.0-grid-reference.json b/tests/visual_tests/grids/group-symbolizer-4-500-100-2.0-grid-reference.json new file mode 100644 index 000000000..46470ab37 --- /dev/null +++ b/tests/visual_tests/grids/group-symbolizer-4-500-100-2.0-grid-reference.json @@ -0,0 +1,34 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! ", + " !!!!! !!!!!! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! ", + " !!!!! !!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!!! !!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!! !!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!! !!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!! !!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!!!! !!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!! !! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!! !!!!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!! !!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! ", + " !!! !!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-1.0-grid-reference.json new file mode 100644 index 000000000..84bafe267 --- /dev/null +++ b/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-1.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " !! ", + " !! !!! ", + " !!! !!!! ", + " !!! ! !!! ", + " !!! ", + " !!! ", + " ! !! ", + " ! !!! ", + " ! ! ", + " ", + " !!! ", + " !!! ", + " ! ", + " ! !! ", + " !!! ", + " ! !! ", + " ", + " !!! ", + " !!! ", + " ", + " ! ", + " !! ", + " !!! ", + " !!! ! ", + " !!! ", + " ! ", + " ", + " ", + " !! !! ", + " !! !!! ", + " !! !! ", + " ! ", + " ", + " ", + " !! ", + " !! ", + " !! !! ", + " ! !!! ", + " ! ! ", + " !!! ", + " !!! ", + " ! ", + " ! ", + " !! ", + " !! !!! ", + " !!! !! ", + " !! ", + " ! ", + " ! ", + " ", + " !!! ", + " !!! !! ", + " !!! ", + " ! ", + " ", + " !!! ", + " !!! ", + " !! ", + " ! !! ", + " ! !!! ", + " ! !! ", + " !!! ", + " !!! ", + " ! ", + " ! ", + " ! ", + " !!! !! ", + " !!! !!! ", + " ! ", + " ! ", + " ! ", + " !! ", + " !!! ", + " !!! !! ", + " !!! ", + " !! ", + " ! ", + " !!! ", + " !!! ", + " ! ", + " ", + " !! !! ", + " !!! !!! ", + " !! ! ", + " ", + " ", + " ", + " !!! ", + " !!! !! ", + " !!! ", + " !! ", + " ! ! ", + " !!! ", + " !!! ", + " ! ", + " ", + " !! ", + " !!! !!! ", + " !!! ! ", + " ! ! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-2.0-grid-reference.json b/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-2.0-grid-reference.json new file mode 100644 index 000000000..84b7fe727 --- /dev/null +++ b/tests/visual_tests/grids/marker-line-placement-many-vertices-600-400-2.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ! !! !!! ", + " !!!!! ! ! !!!!! ", + " !!!!! !!!!!! ", + " !!!!!! !!!!! ", + " !!!!! !!!!!! ", + " !!! ! ", + " ! ", + " ! ", + " ! !!! ", + " !!!! ", + " !!!!!! ", + " ! !!!!!! ", + " !!!! !!!! ", + " !!!!! !! ", + " !!!!!! ", + " !!!!!! ", + " !!!! ", + " ! ", + " ! ", + " ", + " ! ", + " ", + " ", + " ! !!! ", + " !!!! !!!! ", + " !!!!! !!!!!! ", + " !!!!! !!!!!! ", + " !!!!! !!!! ", + " !!!!! !! ", + " ! ! ", + " ! ", + " ! ", + " ", + " ", + " ", + " !!!!! ", + " !!!!! ", + " !!!!!! ", + " !!!!! !!! ", + " !!!!! !!!! ", + " !!!!!! ", + " ! !!!!!! ", + " ! !!!! ", + " !! ", + " ! ", + " ", + " !!!! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!!! ", + " ", + " ", + " !!! ", + " !!!! ", + " ! !!!!!! ", + " ! ! !!!!!! ", + " !!!! !!!! ", + " !!!!! !! ", + " !!!!!! ", + " !!!!! ", + " !!!! ", + " ! ", + " ! ", + " ! ", + " ! ", + " ", + " !!!! ", + " !!!!! !!! ", + " !!!!!! !!!! ", + " !!!!! !!!!!! ", + " !!!! !!!!!! ", + " ! !!!! ", + " ! !! ", + " ! ", + " ", + " ", + " ! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!! ", + " !!! ", + " !!!! ", + " !!!!!! ", + " !!!!!! ", + " !!!! ", + " !!! !! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " ", + " ! ", + " ", + " ", + " !! ", + " !!!!! ", + " !!!!! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-hex-grid-257-256-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-257-256-1.0-grid-reference.json index 3754d9a40..303abc8b4 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-257-256-1.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-257-256-1.0-grid-reference.json @@ -6,68 +6,68 @@ "data": {}, "grid": [ " !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ", - " ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ", - " ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ", - " ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ", - " ! ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ", - " ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ", - " ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ", - " ! ! ! ! ! ! ", - " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! !! !! ! !! ", + " ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! !! !! ", + " ! ! ! ! !! !! ! ", + " ! ! ! ! ! ! ! ! !! !! ", + " ! ! ! ! ! ! ! !! ! !! !! ", + " ! ! ! ! !! !! !! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! !! ! !! ", + " ! ! ! ! ! !! !! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! !! ! !! ! !! ", + " ! ! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! !! ! !! ! ", + " ! ! ! ! ! ! ! ! ! !! ! !! ", + " ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! !! ! !! ", + " !!! ! !!!!! !!!!! !!!!! !!!!! !!!!! ! ", + " ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! !! ! ", + " ! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ", + " ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! !! ! !! ", + " !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ! ", + " ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! !! ! ", + " ! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! !! ", + " !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! !! ! ", + " ! !!! ! !!!!! !!!!! !!!!! !!!! !!!! ", + " ! ! ! ! ! ! ! !! !! !! ", + " ! ! ! ! !! !! !! ", + " ! ! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! ! ! !! ! !! !! ", + " ! ! ! ! !! !! ", + " ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! !! ! !! ", + " ! ! ! ! ! !! !! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! !! ! !! ! ", + " ! ! ! ! ! ! ! ! !! !! ", + " ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! !! ! !! ", + " ! ! ! ! ! ! ! ! ! ! !! ! ! ", + " ! ! ! ! ! ", + " ! ! ! ! ! !! ! !! ! !! ! ", + " ! !!! ! !!!!! !!!!! !!!!! !!!!! !!!!! ", + " ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! !! ! ! ", + " !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ! ", + " ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! !! ! ", + " ! !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ", + " ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! !! ", + " !!!!! !!!!! !!!!! !!!!! !!!!! !!!!! ! ", " ! ! ! ! ! ", - " ! ! ! ! " + " ! ! ! ! ! " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-hex-grid-257-256-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-257-256-2.0-grid-reference.json index a3c42b2a0..9948b2723 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-257-256-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-257-256-2.0-grid-reference.json @@ -5,69 +5,69 @@ ], "data": {}, "grid": [ - " !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ", - " ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ", - " ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ", - " ! ! ! ! ! ! ! ! ", + " !!!!! !!!! !!!! !!!! !!!! !!!! ", + " !! ! !! ! !! ! !!! ! !!! ! !!! !! ! ", + " !!! !! !!! !! !!! !! !!! ! !!! ! !!! ! ", + " !!! ! !!! ! !! ! !! ! !! ! !! ! ! ", + " ! !! ! !! ! !!!! ! !!!! ! !!!! ! !!! ", + " ! !!! !! !!! !! !!! !! !!! ! !!! ! !!! ! ", + " ! !!! ! !!! ! !! ! !! ! !! ! !! ", + " !! ! !!! ! !!! ! !!! ! !!! ! !!! ! ! ", + " !!! ! !!! !! !!! !! !!! !! !! ! !! ! ", + " ! ! ! !!! ! !!! ! !!! ! !! ! !! ! ! ", + " ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ", + " ! !!! ! !! ! !! !! !! !! !! !! !! ", + " ! ! ! ! !!! ! !!! ! !!! ! !! ! ! ", + " !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ! ", + " !! ! !! ! !! ! !! !! !! !! !! !! ! ", + " ! ! ! ! ! ! ! ! !!! ! ! !!! ! ! !! ! ! ! ", + " ! !!! ! !!! ! !!! ! !!! ! !!! ! !! ! ", + " ! !! ! !! ! !! ! !! !! !! !! !! ", + "!! ! ! ! ! ! ! ! ! ! !! ! ! !! ! ! !! ! ! ! ! ", + " !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " !! ! !! ! !! ! !! ! !! !! !! !! ! ", + " ! ! ! ! ! ! ! ! ! ! !! ! ! !! ! ! !! !! ! ", + " !! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " ! !!!! !!!! !!!! !!!! !!!!! !!!! ", + "!! ! ! ! ! ! ! ! ! ! ! !! ! ! !! !! ! !! ! ", + " !!! !! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " !!!! !!!! !!!! !!!! !!!! !!!!! ! ", + " ! ! !! ! ! ! ! ! ! ! ! ! ! !! ! !! !! ! ", + " !! !!! !! !!! ! !!! ! !!! ! !!! ! !!! ! ", " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", + " !! ! ! !! ! ! !! ! !! ! ! !! ! ! !! ! !! ! ", + " !!! !! !!! !! !!! ! !!! ! !!! ! !!! ! ", + " !!!!! !!!!! !!!! !!!! !!!! !!!! ! ", + " ! !! ! ! !! ! !!!! ! !!!! ! !!!! ! !! ! ", + " ! !!! !! !!! !! !!! !! !!! ! !!! ! !!! ! ", + " ! !!! ! !!! ! !! ! !! ! !! ! !! ", + " !! ! !! ! !!! ! !!!! ! !!!! ! !!!! ! ! ", + " !!! ! !!! !! !!! !! !!! !! !!! ! !!! ! ", + " !!! ! !!! ! !!! ! !! ! !! ! !! ! ! ", + " ! !! ! !!! ! !!! ! !!! ! !!! ! !!! ", + " ! !!! ! !!! !! !!! !! !!! !! !! ! !! ", + " ! !!! ! !!! ! !!! ! !! ! !! ! !! ", + " !! ! !!! ! !!! ! !!! ! !!! ! !!! ! ! ", + " !!! ! !! ! !! !! !! !! !! !! !! ! ! ", + " ! ! ! !!! ! !!! ! !!! ! !! ! !! ! ! ", + " ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " ! !! ! !! ! !! !! !! !! !! !! !! ", + "!! ! ! ! ! ! !!! ! ! !!! ! ! !!! ! ! ! ! ", + " !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " !! ! !! ! !! ! !! !! !! !! !! !! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! !! ! ! !! ! ! !! ! ! ", + " ! !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " ! !! ! !! ! !! ! !! ! !! !! !! ", + "!! ! ! ! ! ! ! ! ! ! ! ! !! ! ! !! !! ! !! ! ", + " !!! ! !!! ! !!! ! !!! ! !!! ! !!! ! ", + " !!!! !!!! !!!! !!!! !!!! !!!!! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! !! !! ! !! !! ! ", + " !! !!! !! !!! ! !!! ! !!! ! !!! ! !!! ! ", " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ", + " ! ! ! ! ! ! ! !! !! !! !! ! ", + " ! !! ! !! ! ! ! ! ! ", " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ", - " ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ", - " ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ", - " ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ", - " ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! !!!! !!!! !!!! !!!! !!!! !!!! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " !!!! !!!! !!!! !!!! !!!! !!!! ! ", - " ! ! ! ! ! ! ", + " ! ! ! ! ! !! !! !! ", " ! ! ! ! " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-hex-grid-400-600-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-400-600-1.0-grid-reference.json index bb8f37083..20b10a31d 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-400-600-1.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-400-600-1.0-grid-reference.json @@ -30,109 +30,109 @@ " ", " ", " ! ! ! ! ", - " !! ! !! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! ", + " ! ! ! ! ! ! ! ! ! ! !", + " ! ! ! !! ! !! ! ! ! ! !", " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", " ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ", - "! !!!! !!!! ! !!! ! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ! ! ", - " ! !! ! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! !! !! ! !", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ", - " !!!! !!!! ! !!!! ! !!! !!!! !!!! ", + " ! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ! ! ", + "! ! ! ! ! !! ! ! !! ! ! ! ! ", + "! !!!! !!!! ! !!!! ! !!! !!! !!!! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! !! ! ! ! ! ! !! ! !! ! ! ", + " ! ! ! !! ! !! ! ! ! ! !", + " ! ! ! ! ! ! ! ! ! ! ! ! ! !", + " ! ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! !", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! ! ! ! ! ! ! ", + "! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! !!!!!!! ", + " ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! ! ! ! ! ! ! !", + " ! ! ! !! ! ! !! ! ! !! ! ! !", + " !!!! !!!! ! !!!! ! !!! !!! !!!! ", " ! ! ! ! ! ! !! ! !", - " !! ! ! ! ! !! ! !! ", - " ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! !! ! !! ! ", - " ! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! ! ! !", - " !!!! !!!! ! !!!! ! !!! !!!! !!!! ", - " ! ! ! ! ! ! ! ", - " !! ! ! ! ! !! ! !! ! !", - " ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ", - "! !!!! ! !!!! ! !!!! !!!! !!!! !!!! ", + " !! ! ! ! ! ! ! !! ! !! ! ", + " ! ! ! !! ! !! ! ! ! ! ! ! ", + "! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", + "! ! ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! ", + " ! ! ! ! !! ! !! ! !", + " ! ! ! ! !! ! ! ! ! ! ! !", + " !!!! !!!! ! !!!! ! !!!! !!! !!!! ", + " ! ! ! ! ! ! ! ", + " !! ! ! ! ! ! ! !! ! !! ! !", + " ! ! ! ! ! ! ! ! ! ! ", + "! ! ! ! ! !! ! ! !! ! ! ! ", + "! !!!! ! !!!! ! !!!! !!! !!! !!!! ", " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! !! !! ! !", - " !! ! ! ! ! !! ! ", - " ! ! ! ! ! ! ! ! ! ", - "! !!!! ! !!!! ! !!! ! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ! ", - " ! !! ! ! ! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! ! ! !! ! ! ", + " ! ! ! !! ! !! ! ! ! ! !", + " ! ! !! ! ! ! ! ! ! ! ! ! ! !", + " ! ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! !", + " !! ! ! ! ! ! !! ! ! ", + " ! ! !! ! ! ! ! ! ! ! ! ", + "! !!!! ! !!!! ! !!!! ! !!! !!! !!!! ", + " ! ! ! ! ! ! ! ", + " ! !! ! ! ! ! ! ! !! ! !! ! ", + " ! ! ! ! ! ! ! ! ! !", + " ! ! ! !! ! ! !! ! !! ! ! !", + " !!!!!!! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!!! ", " ! ! ! ! ! ! ! ! !", - " !! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ! ! ", + " !! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ! ! ! ", + "! ! ! ! ! ! !! ! ! ! ! ! ! ! ! ", + "! ! ! ! ! ! ! ! ! ! ! ! ", " !! ! !! ! ! ! !! ! !! ! ", - " !! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! ! !", - " !!!! !!!! ! !!!! ! !!! !!!! !!!! ", - " ! ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! !! ! !! ! !", - " ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", + " !! ! ! ! !! ! !! ! ! ", + " ! ! ! ! !! ! ! ! ! ! ! !", + " !!!! !!!! ! !!!! ! !!! ! !!! !!!! ", + " ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! !", + " ! ! ! ! ! ! ! ! ! ", + "! ! ! ! ! ! !! ! ! !! ! ! ! ", + "! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! !!!!!!! ", " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! ! !! !! ! !", - " !! ! ! ! ! !! !! ", - " ! ! ! ! ! ! ! ! ! ! ", - "! !!!! !!!! ! !!! ! !!!! !!!! !!!! ", - " ! ! ! ! ! ! ! ", - " ! !! ! !! ! ! !! ! !! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! !! ! !! ! ! ! !", + " ! ! !! ! ! !! ! ! ! ! ! ! !", + " ! ! ! ! ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! !! ! !! ! !", + " !! ! ! ! ! ! !! ! !! ", + " ! ! ! !! ! !! ! ! ! ! ! ! ", + "! ! !!!! !!!! ! !!! ! !!! ! !!! !!!! ", + " ! ! ! ! ! ! ! ", + " ! !! ! !! ! ! ! ! !! ! !! ! ", + " ! ! ! ! ! ! ! ! ! !", + " ! ! ! !! ! !! ! !! ! ! ! !", + " !!!!!!! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!!! ", " ! ! ! ! ! ! ! ", - " !! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ! ! ! ! ", - " !! ! ! ! ! ! !! ! ! ", - " !! ! ! !! ! !! !! ", - " ! ! ! ! ! ! ! ! ! !", - " ! ! !! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " !! ! !! ! ! ! !! ! !! ! !", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!! !!!!!! !!!!!! ", + " !! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ! ! ! ", + " ! ! ! ! !! ! ! !! ! ! ! ! ! ", + "! ! ! ! ! ! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ! ", + " !! ! ! ! !! ! !! ! !! ", + " ! ! ! ! !! ! ! ! ! ! ! ! !", + " ! ! ! ! !! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ", + " !! ! !! ! ! ! ! ! !! ! !! ! !", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! ! ! ", + "! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! !!!!!!! ", " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! !! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ! !", + " ! ! ! !! ! ! !! ! ! !! ! ! ! !", + " ! ! ! ! !! ! ! ! ! ! ! ", " ! ! ! ! ! !", " ! ! ! ! ", " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ", " ", " ", " ", diff --git a/tests/visual_tests/grids/marker-on-hex-grid-400-600-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-400-600-2.0-grid-reference.json index 67f9164f2..327f40fe6 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-400-600-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-400-600-2.0-grid-reference.json @@ -34,106 +34,106 @@ " ! ! ! ! ! ! ", " ! ! ! ! ! ! ", " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ", - "! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ", - "! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ", - " ! ! ! ! ! !", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! !", - " ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ", - "! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ", - " ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - "! ! ! ! ! ! ", - "! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - "! !!!!!! !!!!!! !!!!!! !!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! !", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ", - " ", - " ", + " ! !!! ! !! !! !! ! !! ! !!! ", + " !! !! ! !! ! !! !! !!! !", + " ! ! ! ! ! ! ! ! ! !!! ! ! ! ! ", + " ! !! ! ! ! ! ! ! ", + "! ! ! ! ! ! !! ! ! ! ! ", + "!!! !!! !!! ! ! !!! ! !!! ! !!! !! !!! !!! ! ", + "!! !!! !! ! !! ! !! ! !! ", + " ! ! ! ! ! ! !! ! ! ! !", + " ! ! !! ! ! ! ! ! !! ", + " !! !! ! ! ! ! !! ! !! !! ! !! ", + " ! !!! ! !!! ! ! !!! ! !!! ! !!! !! !!! !", + " ! !!! !!! !! !! ! !! ! !!! ", + " ! ! ! !! ! ! ! ! ! ", + "! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", + "!! !! !! !! !! ! !! !! !! !! !! !! ", + "!! !!! ! !! ! !! ! !! !!! ", + "!!! ! ! ! ! ! ! !!! ! ! ! ! !", + " ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ", + " !! !!! !!! !! ! !!! ! !!! ! !!! !! !!! !", + " !! !! !! ! !! ! !! !! ", + " ! ! ! ! ! !! ! ! ! ! ", + "! !! ! ! ! ! ! ! ! !! ", + "!! ! ! ! ! !! ! !! ! !! !! ! ", + "!!! !! !!! ! ! !!! ! ! !!! ! !!! ! !!! ! ! ! ", + "!! ! !!! !! !! ! !! ! !!! ", + " ! ! ! ! ! !! ! ! !", + " !!!!!!! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! ", + " !! !! ! !! !! !! ! !! !! !! !! !! ", + " !!! !! ! !! ! !! ! !!! !!! !", + " ! ! ! ! ! ! ! !! ! !!! ! ! ! ! ", + " ! !! ! ! ! ! ! ! ! ", + "! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! ", + "!!! !! !!! !!! !! ! !!! ! !!! !! !!! !!! ! ", + "!! !! !! ! !! ! !! !! ", + " ! ! ! ! ! ! ! !! ! ! ! !", + " ! !! ! ! ! ! ! ! ", + " ! !! ! ! ! ! !! ! !! ! ! ! ", + " ! !!! ! ! !!! ! ! !!! ! !!! ! !!! !! !!! !", + " ! !!! !!! !! ! !! ! !! ! !!! ", + " ! ! ! ! !! ! ! ! ! ! ", + "! !! ! ! ! ! ! !! ! ! ", + "!! !! ! ! !! !! !! !! !! !! !! ! ", + "!!! !!! ! !! ! !! ! !!! ! !!! ! ", + "!!! ! ! ! ! !! !! ! !!! ! !", + " ! ! !! ! ! ! ! ! ", + " !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", + " !! !!! !!! !! ! !! ! !!! !! !!! !! !!! !", + " !! !! ! !! ! !! ! !! !! ", + " ! ! ! ! ! ! ! ! !! ! ! ! ! ! ", + "! ! !! ! ! ! ! ! !! ", + "! ! ! ! ! ! ! !! ! ! !! ! ", + "!!! !!! !!! ! ! !!! ! !!! ! !!! ! !!! !!! ! ", + "!! !!! !! !! ! !! ! !! ", + " ! ! ! ! ! !! ! ! ! !", + " !! ! ! ! ! ! ! ! !! ! ", + " !! !! ! ! !! !! !! !! !! !! !! !! ", + " ! !!! ! !! ! !! ! ! !!! ! !!! !!! !", + " ! !!! ! ! ! !! !! ! !!! ! ! ! ", + " ! ! ! !! ! ! ! ! ", + "! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", + "!!! !! !!! !! !! ! !! ! !!! !! !!! !!! ! ", + "!! !! !! ! !! ! !! !! ", + "! ! ! ! ! ! ! ! !! ! ! ! ! !", + " ! !! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! !! ! ! ! ", + " !! !!! !!! !!! ! ! !!! ! !!! ! !!! !! !!! !", + " ! !! !! !! ! !! ! !! !!! ", + " ! ! ! ! ! !! ! ! ! ", + "! !! ! ! ! ! ! !! ! !! ", + "!! ! ! ! ! !! !! !! !! !! !! ! ", + "!!! !!! ! !! ! ! !!! ! !!! ! !!! ! ! ", + "!!! ! ! ! ! !! ! !! ! !!! ! ", + " ! ! ! !! ! ! ! ! ! ", + " !!!!!!! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!! ", + " !! !!! !!! !! !! !! ! !! !! !!! !! !!! ", + " !! ! ! !! ! !! !! !! ", + " ! ! ! ! ! ! ! !! !!! ! ! ! ! ", + "! ! !! ! ! ! ! ! !! ", + "! ! ! ! ! ! !! ! ! ! ! ", + "!!! !!! !!! ! ! !!! ! !!! ! !!! !! !!! !!! ! ", + "!! !!! !! ! !! ! !! ! !! ", + " ! ! ! ! ! ! !! ! ! ! !", + " !! ! !! ! ! ! ! ! !! ! ", + " !! !! ! ! !! ! !! !! !! !! ! !! ", + " ! !!! ! !! ! ! !!! ! !!! ! !!! !!! !", + " ! !!! ! ! ! !! !! ! !!! ! !!! ", + " ! ! ! !! ! ! ! ! ! ", + "! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!! ", + "!!! !! !!! !! !! ! !! !! !! !! !!! !! ", + "!! !! ! !! ! !! ! !! !! ", + "!!! ! ! ! ! ! ! !!! ! ! ! ! !", + " ! !! !! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ! ! ", + " ! !!! !!! !!! ! ! !!! ! !!! ! !!! !! !!! !", + " !! !! !! ! !! ! !! !!! ", + " ! ! ! ! ! !! ! ! ! ! ", + " !! ! ! ! ! ! ! !! ", + " ! ! !! ! ! ! ", + " ! ! ! ", " ", " ", " ", diff --git a/tests/visual_tests/grids/marker-on-hex-grid-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-600-400-1.0-grid-reference.json index 70e91644a..f08630850 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-600-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-600-400-1.0-grid-reference.json @@ -7,103 +7,103 @@ "grid": [ " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", " ! !! !! ! !! ! ! !! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ", " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! ! ! ! ", + " !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!! !!!!!! ", " ! ! !! !! ! ! ! ! !! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! ! ! ", + " ! ! ! ! ! ! !! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " !!!!!! !!!!!! !!!!!! !!!!!!! !!!!!! !!!!!! ", " ! ! !! !! ! ! ! ! !! ", - " ! ! ! !! !! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! !! ! ! ! ", - " ! ! ! ! !! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! !! ! ! ! ! ! ! ", - " ! ! ! !! !! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !!!! !!!! ! !!! ! !!!! !!!! !!!! ", - " ! ! !! ! ! ! ! ! ! ", - " ! ! ! ! !! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! !!!! !!!! !!!! ! !!!! ! !!!! !!!! ", - " ! ! ! !! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! !! !! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! !! ! !! ! ! ! ", + " ! ! ! ! ! !! ! !! ! ! ! ", + " ! ! ! ! ! !! ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! ", + " ! ! ! !! ! ! ! ! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ", + " ! ! !! ! ! !! ! ! !! ! ! !! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " !!! ! !!! ! !!!! ! !!!! !!! ! !!! ", + " ! ! ! !! ! ! ! ! ! ! ", + " ! ! ! ! !! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ", + " ! !! ! ! !! ! ! !! ! !! ", + " ! !!!! !!! !!!! ! !!!! ! !!!! !!! ", + " ! ! ! ! !! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! !! ! ! !! ! ! !! ! !! ", + " !!!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", " ! ! ! !! !! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! !! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! !! ! !! ! ! ! ", + " !!!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", " ! ! ! !! !! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ! !! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ", + " !!!!!!! !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! ", " ! ! !! !! ! ! ! ! ", - " ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! !! ! !! ! ! ! ! ! ! ", - " ! ! ! !! !! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! !! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! !! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ", + " !!!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!!! !!!!!! ! ", + " ! ! !! ! ! !! ! ! ! ! ! ", + " ! ! ! ! !! ! !! ! ! ! ! ", + " ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! !! ! ! !! ! ! ! ! ", + " ! ! ! ! !! ! ! ! ! ! ", " ! ! ! ! !! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! !!!! !!!! !!!! ! !!! ! !!!! !!!! ", - " ! ! ! ! ! !! ! ! ! ! ! ! ", - " ! ! ! ! ! !! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!! !!!! ! !!! ! !!!! !!!! !!!! ", - " ! ! !! !! !! ! ! !! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ", - " !! ! ! ! ! ! ! !! ! ! ", - " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " ! !!!! !!! ! !!!! ! !!!! ! !!!! !!! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ! ! ", + " ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! !! ! ! !! ! ! ! ", + " !!! !!! ! !!!! ! !!!! !!! !!! ", + " ! ! ! !! !! !! ! ! ! !! ", + " ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ! ", " ! ! ! ! ! ! ", " ! ! ! ! ! ", - " ! ! ! ! ! ! " + " ! ! ! ! ! ! " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-hex-grid-600-400-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-hex-grid-600-400-2.0-grid-reference.json index 0f4089f51..733a97de2 100644 --- a/tests/visual_tests/grids/marker-on-hex-grid-600-400-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-hex-grid-600-400-2.0-grid-reference.json @@ -10,100 +10,100 @@ " ! ! ! ! ! ", " ! ! ! ! ! ! ! ", " ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! !!!!!! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ", - " ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! ! ", - " ! ! ! ! ! " + " !!! !! ! !! ! !! !!! !! ! ", + " ! !! ! !! !! !! ! !! ! !! ", + " ! ! ! !!! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! !! ! ! ! ", + " ! !!!!!! !!!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!!! ", + " !!! !! !!! !! !!! ! !!! ! !!! !! !!! !! ", + " !!! !! !! ! !! ! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " ! !! ! ! ! ! ! !! ! ! ", + " ! !! ! !! !! !! !! !! ! !! ! !! ! ", + " ! !!! !! !! ! !! !! ! !!! !! !! ", + " ! ! !! ! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! !! ! ! ! ", + " !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! !!!!!!! ", + " !!! ! !!! !! !!! !! !!! !! !!! ! !!! !! ", + " !!! !! !! ! !! ! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " ! !! ! !! !! !! !! ! ! !! ! !! ! ", + " ! !!! !! !! ! !! ! !! ! !!! !! !! ", + " !!! !! ! ! ! ! ! !!! !! ! ", + " ! ! ! ! ! !! ! ! ! ", + " !!!!!! !!!!!!! !!!!!! !!!!!! !!!!!! !!!!!!! ", + " !!! ! !!! !! !!! !! !!! !! !!! ! !!! !! ", + " !!! ! !! !! ! !! ! !! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " ! !! ! !! ! !! ! ! ! !! ! !! ! ", + " ! !!! !! !!! ! !! ! !! ! !!! !! !!! ", + " !!! !! ! !! ! ! ! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " ! ! !! ! ! ! ! ! !! ! ", + " !!! ! !!! !! !!! !! !! !! !!! ! !!! !! ! ", + " !! ! !! !! !! ! !! ! !! ! ", + " ! ! ! ! ! !! ! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " ! !! ! !! !! ! ! ! ! !! ! !! ", + " ! ! !!! !! !!! ! !!! ! !! ! ! !!! !! !!! ", + " !!! !! ! !! ! ! ! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! !! ! ! ! ", + " !!! ! !!! !! !! !! !! !! !!! ! !!! !! ! ", + " !! ! !! !! !! ! !! ! !! ! ", + " ! ! !!! ! ! ! ! ! ! !! ! ", + " !! ! ! ! ! ! !! ! ! ", + " !!!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!!! !!!!!! ", + " !! !!! !! !!! !! !!! ! !!! !! !!! !! !!! ! ", + " !!! !! ! !! ! !!! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " !!! ! !!! !! !! !! !! !! !!! ! !! !! ! ", + " !! ! !! ! !! !! ! !! ! !! ! ", + " ! ! !!! ! ! ! ! ! ! !!! ! ", + " !! ! ! ! ! ! ! ! ! ! ", + " !!!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! ", + " !! !!! !! !!! !! !!! ! !!! !! !!! !! !!! ! ", + " ! !! !! !! ! !! ! !! !! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " !! ! !! ! !! !! !! ! !!! ! !! ! ! ", + " !!! ! !! ! !! ! !! ! !!! ! !! ! ", + " ! ! !!! ! !! ! ! ! ! !!! ! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !!!!!! !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! ", + " !! !!! !! !!! !! !!! ! !!! !! !!! !! !!! ! ", + " ! !! !! !! ! !! ! !! !! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !! ! ! ! ! ! !! ! ! ", + " ! ! !! ! !! !! !! ! !! ! !! ! ! ", + " !!! ! !!! !! !! ! !! ! !!! !! !!! ! ", + " ! ! !!! ! !! ! ! ! ! !!! ! ! ", + " ! ! ! ! !! ! ! ! ! ! ", + " !!!!!! !!!!!!! !!!!!!! !!!!!! !!!!!! !!!!!!! ", + " !! !!! !! !!! !! !!! ! !! !! !!! !! !!! ! ", + " ! !! !! !! ! !! ! !! !! ", + " ! ! !! ! ! ! ! ! !! ! ", + " !! ! ! ! ! ! !! ! ! ", + " ! ! !! ! !! !! ! ! !! ! !! ! ! ", + " !!! !! !!! !! !!! ! !! ! !!! !! !!! !! ", + " ! ! !!! ! !! ! ! ! ! !!! ! ! ", + " ! ! ! ! !! ! ! ! ! ", + " ! ! !! ! ! ! ! ! ! !! ! ", + " !! !!! ! !!! !! !! !! !! ! !!! !! !!! ! ", + " ! !! !! !! ! !! ! !! !! ", + " ! ! ! !! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! !! ! ! ! ! ", + " ! ! !! ! ! !! ! ! ! ! !! ! ! ", + " !!! !! !!! !! !!! ! !!! ! !!! !! !!! !! ", + " !!! !! !! ! !! ! !!! !! ! ", + " ! ! ! ! !! ! ! ! ! ", + " ! ! !! ! ! ! ! ! ! !! ! ! ", + " ! !!! ! !!! !! !! !! !! ! !!! ! !!! ! ", + " !! !! !! ! !! ! !! !! ", + " ! ! ! !! ! ! ! ! ! ! ! !! ! ", + " ! ! ! ! !! ! ! ! " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-1.0-grid-reference.json index 6edc4b728..a619cee45 100644 --- a/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-1.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-1.0-grid-reference.json @@ -12,122 +12,122 @@ " ", " ", " ", - " ", - " ", - " ", - " ", - " !!!!!!!! ", - " !!!!!!!!!!!! ", - " !!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!! !!!!!!!! ", - " !!!!!!!!!!!!!!!!! !!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! !", - " ! !!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! ", - "! !!!!!!!!! ! !!!!!!!!!!!! ", - " !!!!!!!!!!! ", - " !!!!!!!!!! ", - " !!!!!!!! ", - " !!!!! ", - " ", - " ", - " ", + " !! ", + " !!!!!!!!!! ", + " !!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!! !!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !", + " !!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ", + " !!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!! ! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + "! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!! !!! ", + " !!!!!!!!! !!!!!!!!!!!! ", + " !! !!!!!!!!!! ", + " !!!!!!!!! ", + " !!!!!!! ", + " !!!! ", " ", " ", " ", diff --git a/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-2.0-grid-reference.json index 4bf221877..be8f56680 100644 --- a/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-line-and-avoid-edges-512-512-2.0-grid-reference.json @@ -10,122 +10,122 @@ " ", " ", " ", + " ! ", + " !!!!!!!!!!!!! ", + " !!!!!!!!!!!! !!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!!!!! ! ! ", + " ! !!!!!!!!!!!!!!!!!!!!!! ! ! ", + " ! !!!!!!!!!!!!!!!!!! ! ! ", + " ! !!!!!!!!!!!!!! ! ! ", + " ! !!! ! ! ", + "! !! ", + "! ! ", " ", " ", " ", " ", " ", - " !!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!! ", - " !!!! ! !!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!! ", - " !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - " ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - "! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ", - "! !!!!!!!!!!!!!!!!!!!!!!!!!!! ! ", - " !!!!!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!!!!!! ", - " !!!!!!!!!!! ", - " ", " ", " ", " ", diff --git a/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-1.0-grid-reference.json index 6d60c0905..2452c80b1 100644 --- a/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-1.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-1.0-grid-reference.json @@ -5,11 +5,11 @@ ], "data": {}, "grid": [ - " !!!!!! ", - " ! !! !!!! !! ", - " ! ! !!! ! ! ", - " ! ! !! ! !!! ", - " ! ! !!! ! !! ", + " !!!!!!!! ", + " !!!!!!! ! !! ", + " ! ! !! ! ! ", + " ! ! !!! ! !!! ", + " ! ! !!!!! ! !! ", " ! ! ! ! ! ", " ! ! ! ! !! ", " ! ! ! ! ! ! ", @@ -20,9 +20,9 @@ " ! ! ! !! ", " ! ! ! ! ! !!! ", " ! ! ! ! !!! ", - " ! ! ! ! ! ! !! ! ", + " ! ! ! ! ! ! !!! ", " ! ! ! ! !!! ", - " !! ! ! ! ! ! !!! ", + " !! ! ! ! ! ! !! ", " !! ! ! ! !! ! ", " ! !! ! ! !!! ! ", " ! !!!!! ! !! ! ", @@ -69,9 +69,9 @@ " ! ! !!!! ", " ! !! ! !!! ", " !! !! ! !!!! ", - " !! !!! ! !!!! ", + " !! !!! ! !!! ", " !! !!! !! !!! ", - " ! !!! !!! !! ", + " ! !!! !!! !!! ", " !!! !!! !!!! ", " ! ! ! !!! ", " ! ! ! ! ! ", @@ -81,7 +81,7 @@ " ! ! !! ", " ! !! ", " ! ! ! ! !! !! ", - " ! ! ! !!! !!! ", + " ! ! ! !!! !! ", " ! ! ! !!! !!! ", " ! ! ! ! !!! ", " ! ! ! !! ! ! ! ", @@ -93,8 +93,8 @@ " ! ! ! !!! ! !! ! ! !!! ", " ! ! !!!! !!! ! ! !!! ", " !!! ! !!!! !!! ! ! ", - " !!!!! !! ! ! ", - " !!!!! !! !! !! ! ! ! ", + " !!!!! !!! ! ! ", + " !!!!! !!!!! !! ! ! ! ", " !!!!! !!! !!! ! ! ! ", " !!!! !!!! !!! ! ! ! ", " ! !! ! ! ! ! ", diff --git a/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-2.0-grid-reference.json index 8615c7820..8f7a961f9 100644 --- a/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-line-and-line-placement-600-400-2.0-grid-reference.json @@ -6,22 +6,22 @@ "data": {}, "grid": [ " !!!!!!! ", - " !!!! !! ! !! ", - " ! ! ! ! ! ! ", - " !! ! ! ! ! !! ", - " ! ! ! ! ! ! ", - " ! ! ! !!!!!!! !! ", - " ! ! ! !! ! ! !! ", - " ! ! !! ! ! ! ", - " ! ! !! ! ! !! ", - " ! ! !! ! ! ! ! ", - " !! ! !! !!!! ! !!! ", + " !!!! !! ! !!!!!! ", + " ! ! ! ! ! !!!! ", + " !! ! ! ! !!!!!!! ", + " ! ! ! ! !!!!! ", + " ! ! ! !!!!!!!!!! ", + " ! ! ! !! ! !!!!!!!!! ", + " ! ! !! ! !!!!! !!!! ", + " ! ! !! ! !!!!!!!!!!! ", + " ! ! !! ! !!!! !!!! ", + " !! ! !! !!!!!! !!!!! ", " ! ! ! ! !!!!! ! ! ! ", - " ! ! ! ! !!!!! !!! ! ! ", - " ! ! ! ! !!!! !!!!! ! ", - " ! ! ! ! !! !!!!! ! ! ", - " ! ! !! ! ! !!!!! ! ! ", - " ! ! ! ! ! !!!! ! ! ", + " ! ! ! ! !!!!! ! ! ! ", + " ! ! ! ! !!!! ! ! ", + " ! ! ! ! !! ! ! ! ", + " ! ! !! ! ! ! ! ! ", + " ! ! ! ! ! ! ! ! ", " ! ! ! ! ! ! ! ! ", " ! ! ! ! ! ! ! ", " ! ! ! ! ! ! ! ! ", @@ -32,18 +32,18 @@ " ! ! ! ! ! ! ! ! ", " ! !! ! ! ! ! ! ", " ! !! ! ! ! ! ! ", - " ! !! ! ! ! ! ! ", - " !!! !!! ! ! ! ! ! ", - " !!!!! !!!!! ! !!!!! ! ! ! ", - " !!!!! !!!!! ! !!!!! ! ! ", - " !!!!! !!!!!!!!! !!!!!! ! ! ! ", - " !!!! !!!!!!!!!!! !!!!!! ! ! ! ", - " !! !!! !!!!!!! !!! ! ! ! ! ", - " ! !!!!! !!!!!!! ! ! ! ", - " ! !!!!! !!!!!! ! ! ! ", - " ! !!!!! ! !!! ! ! ! ! ", - " ! !!!! ! ! ! ! ", - " ! !! ! ! ! ! ! ", + " !!!! !! ! ! ! ! ! ", + " !!!!! !!! ! ! ! ! ! ", + " !!!!!!!!!! ! !!!!! ! ! ! ", + " !!!! !!!!! ! !!!!! ! ! ", + " !! !!!!!!!!! !!!!!! ! ! ! ", + " ! !!!!!!!!!!! !!!!!! ! ! ! ", + " ! !!!!!!!!!!!! !!! ! ! ! ! ", + " ! !!!!!!!!!!!! ! ! ! ", + " ! !!!! !!!!!! ! ! ! ", + " ! ! !! ! !!! ! ! ! ! ", + " ! !! ! ! ! ! ", + " ! ! ! ! ! ! ! ", " ! !! ! ! ! ! ", " ! ! ! ! !! ! ", " ! !! ! ! ! ! ", @@ -52,17 +52,17 @@ " ! !! ! ! ! ! ", " ! ! ! ! ! !! ! ", " !! ! ! !! ", - " ! ! ! ! ! ! ! ", - " ! ! ! !!!!! ! ", + " ! ! ! ! !!!!! ! ", + " ! ! ! !!!!!!! ", " ! !! ! !!!!!! ", " ! ! ! ! !!!!! ! ", - " ! ! ! !!!!! ! ", - " ! ! ! ! !!! ! ", - " ! ! ! ! !! !!!! ", - " ! ! ! !!!!!!!! ", + " ! ! ! !!! ! ", + " ! ! ! ! !!!!!!!! ", + " ! ! ! ! !!!!!!!!! ", + " ! ! ! !!!!!!!!! ", " ! ! ! ! !!!!!!!! ", - " ! ! ! ! !!!!!!!! ", - " ! ! ! ! !!!!!!! ", + " ! ! ! ! !!!!!!! ", + " ! ! ! ! !!!!! ! ", " ! ! ! ! !!!! ! ", " ! ! ! ! ! ! ", " ! ! ! ! !! ", @@ -98,12 +98,12 @@ " !!! ! !!! ! ! ! ! ", " !!! ! !!!! !!! ! ! ! ", " !!! ! !!! !!!!! ! ! ", - " !!! !!! !!!!!!! ! ", - " !! ! !!! ! !!!!! ! ! ", - " !! ! !!! ! !!!! ! ! ", - " !! ! !! !!!! ! ! ! ", - " !! ! !!!!!!! ! ! ! ", - " ! ! !!!!!! !! ! ! ", - " ! ! !!!!!!! ! ! " + " !!! !!!! !!!!!!! ! ", + " !! ! !!!!! ! !!!!! ! ! ", + " !! ! !!!!! ! !!!! ! ! ", + " !! ! !!!!! ! ! ! ! ", + " !! ! !!!!!!!!! ! ! ! ", + " ! ! !!!!!!! !! ! ! ", + " ! ! !!!!!!! ! ! ! " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-1.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-1.0-grid-reference.json new file mode 100644 index 000000000..a5bac90d0 --- /dev/null +++ b/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-1.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!! ", + " !!!! !!!!! !", + " !!! !!!!!!!!!!!! ", + " ! !!!! !!!!!!!!!!! ", + " !!!! !!!!!!!!!! !!! ", + " !!!!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!!! !!! !! ", + " !!! !!!!!!!!!!!!!!!!! !!! ", + " !! !!!! !!!!!!!!!! !!! ", + " ! !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!!! !!! ! ", + " !!!! !!!!!!!!!!!!! !! !! ", + " !!! !!!! !!!!!!!!!!! !!! ", + " ! !!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!!! !!! !! ", + " !!! !!!!! !!!!!!!!!!! !!! ", + " !! !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!! !!! ! ", + " !!!! !!!!!!!!!!!!!!!! !!! ", + " !! !!! !!!!!!!!!!! !!! ", + " ! !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!! !!! ", + " !!!! !!!!!!!!!!!!! !!! !! ", + " !!!!!!!!!!!!!!!! !!! ", + " !!!!!!!!!! !!! ", + "!!!!! !!! ", + " !!! ", + " ! ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-2.0-grid-reference.json new file mode 100644 index 000000000..7cf739aa1 --- /dev/null +++ b/tests/visual_tests/grids/marker-on-line-svg-no-box-600-400-2.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !! ", + " !!!!!!!! ", + " !!!!!!! ", + " !!!!! !!!!!! ", + " !!!!!!! !!!!!!!!! !", + " !! !!!!!!!! !!!!!!!!!!!! ", + " !!!!!!! !!!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!! ", + " !!!!!! !!!!!!!! !!!!!!!!!!!!!!!!!!!!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!! !!!!!!! !!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!!! !!!!!!!!!! !!!!!!!!!!!! ! !!!!!! !! ", + " !!!!!!! !!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!! !!!!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!! ", + " !!!! !!!!!!! !!!!!!!!!!!!!!!!!!!! !!!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!!!! ! !!!!! !! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!! !!!!!!!!!! !!!!!!!!!!!! !!! !!!!! !!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!! !!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!! !!!!!!!!! !!!!!!!!!!!! !!!!!! ! ", + " ! !!!!!!! !!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!! !!!!! ", + " !!!!! !!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!! ", + " !! !!!!!!!! !!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!!! !!!!!!!!!! !!!!!!!!!!!! !! !!!!! !!! ", + " !!!!!!!! !!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!! !!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!!!!!!!!!!!!!!!! !!!!!! ", + " !!!!!!!!!!!!!!!!!!!! !!!!!! ", + "!!!!!!!!!!!!!!! !!!!! !!! ", + "!!!!!!!!!! !!!!! ", + " !!!!!!!!! !!!!! ", + " !!!!!! ", + " !!!!!! ", + " !! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-font-features-500-500-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-1.0-grid-reference.json similarity index 64% rename from tests/visual_tests/grids/text-font-features-500-500-2.0-grid-reference.json rename to tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-1.0-grid-reference.json index 01d87bd03..40618aff4 100644 --- a/tests/visual_tests/grids/text-font-features-500-500-2.0-grid-reference.json +++ b/tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-1.0-grid-reference.json @@ -1,140 +1,109 @@ { "keys": [ "", - "1", - "2", - "3", - "4", - "5", - "6", - "7" + "1" ], "data": {}, "grid": [ - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ! ! ! !! ", - " ! ! ! ! ! ! ! ! ! ! ", - " ! !!!! !!! !!! !! !!! !! !!! !!! ! !!! !!! !!! ", - " ! ! ! ! ! ! ! ! !! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! !!! ! ! ! ! ! ! ! ! ", - " ! ! ! ! ! ! ! ! ! ! !! ! ! ! ! ! ! ! ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ##### # # # # # # # ## ", - " # # # # # # # ", - " # ## # # # # # ### # # # # # # # # ### ", - " # # # #### # # # ## # # # # # # # # ", - " # # # # # # # # # # # # # # # # # # ", - " ## #### ### ### ## ## ### ## ### ## ### ### ## ", - " ", - " ", - " ", - " ", - " ", - " ", - " $ $$ $$$ ", - " $ $ $ $ $ $ $ ", - " $ $$$ $$ $$$$ $$$ $$ $$$ $$ $ $$$ $$ $$$ ", - " $ $ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ ", - " $ $ $ $ $ $ $$ $ $ $ $ $$ $ $ ", - " $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $$ $ $ ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " %%%%%%% %%%% % %%%% ", - " % % % % % % % ", - " % % % % % % % %%%% % % % % % % % % % ", - " % % % %%%% % % % %% % % % % %% % % ", - " % % % % % % % % % % % % % % % % % % ", - " %%% %%%%% %% %%%% %% %%% %% %%%%% %%% %% %% ", - " ", - " ", - " ", - " ", - " ", - " ", - " & & & & & ", - " && && & && & && &&& & & ", - " & & & & & && & & && ", - " & & & & & && & & & ", - " & & & & & & & & &&&& ", - " & & &&& & & & && && & ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ''' '' ''' ''' '' ''' ''' '''' ''' ''' ", - " ' ' ' ' ' ' ' '' ' ' ' ' ' ' ", - " ' ' ' ' '' ' ' ''' '''' ' ''' ' ' ", - " ' ' ' ' ''' ' ' ' ' ' ' ' ''' ", - " ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ", - " ''' ''' '''' ''' '' '''' '' ' ''' '' ", - " ", - " ", - " ", - " ", - " ", - " ", - " ( ", - " ( ( ( ( ( ( ( ( ( ", - " ( ( ( ( ( ( (( ", - " ((((( ( ((( ( ( ( ( ", - " ( ( ( ( ( ( (((( ", - " ( ( (((( ( ( ( ( ( ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ", + " !!! !!!! !", + " ! !!!! !!!!! ", + " !!! !!!!! !! ", + " !!! !!!!!!!!!! ", + " !!! !!!!!!!!!! ! ", + " !!! !!! !!!! !!! ", + " !! !!!! !!!! !!! ", + " !!! !!!! !! ", + " !!! !!!!!! !!! ", + " !!! !!!!!!!!! ! ", + " !!! !!!! !!!! !! ", + " !! !!!! !!!!! !! ", + " ! !!!! !!!!! !! ", + " !!! !!!!! !! ", + " !!! !!!!!!!!!! ", + " !!! !!!! !!!! !! ", + " !!! !!!! !!!! !! ", + " !! !!!! !!!!! !! ", + " !!! !!!!! !! ", + " !!! !!!!!! !!! ", + " !!! !!!!!!!!! ! ", + " !!! !!!! !!!! !! ", + " !! !!!!! !!!!! !! ", + " ! !!!! !!!!! !!! ", + " !!! !!!!! !!! ", + " !!! !!!!!!!!!! ", + " !!! !!!! !!!! !! ", + " !!! !!!! !!!!! !! ", + " !!!! !!!!! !! ", + " !!!!! !! ", + "!!!!! ", + " ! ", + " ", + " ", + " " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-2.0-grid-reference.json b/tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-2.0-grid-reference.json new file mode 100644 index 000000000..f71a076f3 --- /dev/null +++ b/tests/visual_tests/grids/marker-on-line-svg-with-box-600-400-2.0-grid-reference.json @@ -0,0 +1,109 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ", + " !!!!!! ", + " !!!!! ", + " !!!!!! !!!!!!! !", + " !!!!!! !!!!!!!!! ", + " !!! !!!!!!!! !!!!!!!! ", + " !!!!!! !!!!!!!!!!! !!!!!!! ", + " ! !!!!!!! !!!!!!!!! !!!! ", + " !!!!! !!!!!!!! !!!!!!!! !! ", + " !!!!!! !!!!!!!!! !!!! ", + " !!!! !!!!!!! !!!!!!! !!!! ", + " !!!!!! !!!!!!!!!! !! !!!! ", + " ! !!!!!!!! !!!!!!!!! !!!!! ", + " !!!!!! !!!!!!!! !!!!!!!! ! ", + " !!!!! !!!!!!!!! !!!!! ", + " !!!! !!!!!!! !!!!!!! !!!! ", + " !!!!! !!!!!!!!!! ! !!!! ", + " !! !!!!!!! !!!!!!!!! !!!! ", + " !!!!!! !!!!!!!! !!!!!!!!! ", + " !!!!!! !!!!!!!!!! !!!! ", + " !!!!! !!!!!!! !!!!!! !!! ", + " !!!!!! !!!!!!!!!! !!!! ", + " !! !!!!!!!! !!!!!!!!! !!!!! ", + " !!!!!! !!!!!!!! !!!!!!!!! ", + " !!!!! !!!!!!!!! !!!!! ", + " !!!!! !!!!!!! !!!!!! !!! ", + " !!!!!! !!!!!!!!! !!!! ", + " !!! !!!!!!!! !!!!!!!! !!!! ", + " !!!!!! !!!!!!!!!!! !!!!!!! ", + " !!!!!! !!!!!!!!!! !!!! ", + " !!!!!!! !!!!!!! !! ", + " !!!!!!!!!! !!!!! ", + " !!!!!!!! !!!!! ", + "! !! !!! ", + " !!!!! ", + " ! ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-svg-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/marker-svg-500-100-1.0-grid-reference.json new file mode 100644 index 000000000..dbc0b5f97 --- /dev/null +++ b/tests/visual_tests/grids/marker-svg-500-100-1.0-grid-reference.json @@ -0,0 +1,37 @@ +{ + "keys": [ + "", + "4", + "3", + "2", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " !!!!! ", + " #### ", + " #### ", + " #### ", + " #### ", + " ", + " ", + " $$$ ", + " $$$ ", + " $$$ ", + " ", + " %%%% ", + " %%%% ", + " %%%% ", + " %%%% ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/marker-svg-500-100-2.0-grid-reference.json b/tests/visual_tests/grids/marker-svg-500-100-2.0-grid-reference.json new file mode 100644 index 000000000..8f06b3cd2 --- /dev/null +++ b/tests/visual_tests/grids/marker-svg-500-100-2.0-grid-reference.json @@ -0,0 +1,35 @@ +{ + "keys": [ + "", + "3", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " !!!!!!! ", + " ", + " ", + " ", + " ####### ", + " ####### ", + " ####### ", + " ####### ", + " ####### ", + " ####### ", + " ####### ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/orientation-800-200-1.0-grid-reference.json b/tests/visual_tests/grids/orientation-800-200-1.0-grid-reference.json index a614346b0..1ab4cbdad 100644 --- a/tests/visual_tests/grids/orientation-800-200-1.0-grid-reference.json +++ b/tests/visual_tests/grids/orientation-800-200-1.0-grid-reference.json @@ -2,8 +2,8 @@ "keys": [ "", "9", - "2", "1", + "2", "8", "3", "4", @@ -35,23 +35,23 @@ " !! ", " ! ! ", " ! ", - " # !! ", - " $ ### %% %%% ! ", - " $ # % % % !! ", - " $ $$ # & & && %% % % !!! ", - " $$$ $ ## & & & ' ( )) * % ! ++ + + ", - " $ $ &&& &&& ( )) + + ++ ", - " $$$ ### '' ( ) + + ++ ", - " $ ### ' ' ( ( ) * * ** ", - " '' ' ' ( ( )) * * * ", - " '' ' ''' ( *** *** ", - " ' '' ''' (( )) ", - " ' ' '' ( ) ) ", - " ' ' ", - " '' ", + " !! ", + " # $$ %% %%% ! ", + " # $ & % % % !! ", + " # ## $ &&& & %% % % !!! ", + " ### # $$$ & && & ' ( )) * % ! ++ + + ", + " # # & & ''' ( )) + + ++ ", + " ### $ '' ( ) + + ++ ", + " # $ ' ' ( ( ) * * ** ", + " '' ( ( )) * * * ", + " ' ' ( *** *** ", + " '' '' ' (( )) ", + " ' ' '' ( ) ) ", + " '''' '' ", + " ' ' ", + " ''' ", " '' ", - " '' ", - " '' ", + " ", " ", " ", " ", diff --git a/tests/visual_tests/grids/orientation-800-200-2.0-grid-reference.json b/tests/visual_tests/grids/orientation-800-200-2.0-grid-reference.json index 7479bb64b..61fe64b06 100644 --- a/tests/visual_tests/grids/orientation-800-200-2.0-grid-reference.json +++ b/tests/visual_tests/grids/orientation-800-200-2.0-grid-reference.json @@ -1,6 +1,7 @@ { "keys": [ "", + "9", "1", "2", "8", @@ -9,7 +10,6 @@ "5", "6", "7", - "9", "10" ], "data": {}, @@ -24,45 +24,45 @@ " ", " ", " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ! ## # ", - " !! # # # $ $$$ $$$$$$ ", - " ! ! # # # $$ $ $$ $ $$ ", - " ! ! # ## $$ $$$ $ ", - " ! ! !! # # %%%%% % % % $$ $ $ ", - " ! !!! ## % % % %% $$$ $ $ ", - " ! ! !! ## %% % % % $ $ $ $ ", - " !!! ! #### %% % % & ' ( ) $ * +++++ + + ++ ", - " ! ! ## % % % % % ' (( ( + + + ++ ", - " ! ! # % %% % % % '' ( ( ( ++ + +++ ", - " !!!! # # ' ' ( ((( ++ + + ", - " !!!!! ## ## ' ' ' ( (( + + + + + ", - " ! ## ' ' ' ( ))))) ) ) ) +++++++ ++ + ++ ", - " ! ## # ' '' (( ) ) ) ) ", - " ! # # '' ' ' (( )) ) ))) ", - " ' '' (((( )) ) ) ", - " ' ' ( ) ) ) ) ) ", - " ' ( )))))) )))) )) ", - " ''''' ( ( ", - " ' '' (( ( ", - " ' (( ", - " ' ( (( ", - " ( ( ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", + " !! ", + " ! ! ", + " ! !! ", + " ! !! ", + " ! ! ", + " !! ", + " !! ", + " !!! ", + " # !! ", + " ## $$ % %%% %%%%!% ", + " # # $$$ %% % %% % !% ", + " # # $ $$ & %% %%% %!! !! ", + " # # ## &&&& & & & %% % % !! ", + " # ### $$ & && & & %%% % % !! ! ", + " # # ## $$ & & & && % % % % ! ! ", + " ### # $$$$$ & & && & ' ( ) * % ! +++++ + + ++ ", + " # # $$ $ &&&& & & &&& ( )) ) + + + ++ ", + " # # & & ' ''' (( ) ) ) ++ + +++ ", + " #### $ $ ''' ' ( ( ) ))) ++ + + ", + " ##### $$ ''' ' ( ( ( ) )) + + + + + ", + " # $$$$ ' '' ' ( ( ( ) ***** * * * +++++++ ++ + ++ ", + " # $ $ ' '' ( (( )) * * * * ", + " # ' (( ( ( )) ** * *** ", + " '''' ' ( (( )))) ** * * ", + " ' ' ( ( ) * * * * * ", + " '' ' ( ) ****** **** ** ", + " '' '' ' '' ((((( ) ) ", + " '' ' ' '' ' ( (( )) ) ", + " ' ' ' '' ' ( )) ", + " ' ' ' '' ( ) )) ", + " ' '' '' ' ) ) ", + " '' ' ' ' ", + " '''' ' ' ", + " ' ' ", + " '''' ' ", + " ' ' ", + " '' ' ", + " '' ' ", + " ' ", " " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/text-font-features-500-500-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha4b-512-512-1.0-grid-reference.json similarity index 77% rename from tests/visual_tests/grids/text-font-features-500-500-1.0-grid-reference.json rename to tests/visual_tests/grids/raster-color-to-alpha4b-512-512-1.0-grid-reference.json index 46c069cb5..53162f357 100644 --- a/tests/visual_tests/grids/text-font-features-500-500-1.0-grid-reference.json +++ b/tests/visual_tests/grids/raster-color-to-alpha4b-512-512-1.0-grid-reference.json @@ -1,140 +1,136 @@ { "keys": [ - "", - "1", - "2", - "3", - "4", - "5", - "6", - "7" + "" ], "data": {}, "grid": [ - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " !!! ! ! ! ", - " ! ! ! ! ! ! ! !! ! ", - " ! ! ! !! ! !! ! ! ! !! !! !! ! ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ### # # # # ", - " # # ## # # ## # # # ## ## ## ", - " # # # # # # # ## # ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " $ $$ $ ", - " $ $ $ $ $$$$ ", - " $$$$$$$ $$$$$$ $ $$$$$$$$ ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " %%% % % ", - " % %% %% %%%%% %% %%%%%% ", - " % % % %%%% ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " & & & & & & ", - " & & & & &&& ", - " && && &&&& && & ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ' ' ' ' '' ' '' ' ' ", - " ' ' ' ' ' '''' ''' ' ", - " ' ' ' ' ''' '' ' ' ' ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ( (( (( ( ( ", - " ((( ( ((( ( ", - " ( ((( (( (( (( ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " ] } \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha4b-512-512-2.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha4b-512-512-2.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha4b-512-512-2.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-1.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-2.0-grid-reference.json b/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-2.0-grid-reference.json new file mode 100644 index 000000000..53162f357 --- /dev/null +++ b/tests/visual_tests/grids/raster-color-to-alpha5b-512-512-2.0-grid-reference.json @@ -0,0 +1,136 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/rasterlite-globe-256-256-1.0-grid-reference.json b/tests/visual_tests/grids/rasterlite-globe-256-256-1.0-grid-reference.json new file mode 100644 index 000000000..e023c5e7e --- /dev/null +++ b/tests/visual_tests/grids/rasterlite-globe-256-256-1.0-grid-reference.json @@ -0,0 +1,72 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/rasterlite-globe-256-256-2.0-grid-reference.json b/tests/visual_tests/grids/rasterlite-globe-256-256-2.0-grid-reference.json new file mode 100644 index 000000000..e023c5e7e --- /dev/null +++ b/tests/visual_tests/grids/rasterlite-globe-256-256-2.0-grid-reference.json @@ -0,0 +1,72 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-1.0-grid-reference.json b/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-1.0-grid-reference.json new file mode 100644 index 000000000..302de2a7e --- /dev/null +++ b/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-1.0-grid-reference.json @@ -0,0 +1,400 @@ +{ + "keys": [ + "", + "24", + "71", + "245", + "238", + "207", + "154", + "82", + "189", + "60", + "205", + "101", + "72", + "45", + "163", + "103", + "51", + "153", + "206", + "98", + "65", + "129", + "58", + "171", + "191", + "182", + "236", + "170", + "110", + "186", + "86", + "80", + "22", + "210", + "89", + "4", + "112", + "74", + "200", + "68", + "3", + "202", + "93", + "30", + "94", + "165", + "5", + "84", + "31", + "194", + "96", + "114", + "2", + "199", + "190", + "162", + "107", + "175", + "88", + "83", + "120", + "50", + "155", + "235", + "116", + "41", + "113", + "126", + "36", + "226", + "118", + "14", + "214", + "188", + "193", + "78", + "48", + "220", + "18", + "172", + "75", + "79", + "158", + "181", + "208", + "54", + "38", + "212", + "197", + "152", + "56", + "185", + "39", + "164", + "183", + "87", + "40", + "26", + "77", + "104", + "69", + "121", + "157", + "59", + "28", + "204", + "92", + "223", + "49", + "21", + "67", + "161", + "203", + "166", + "6", + "221", + "20", + "9", + "123", + "108", + "222", + "122", + "33", + "160", + "124", + "17", + "216", + "180", + "179", + "209", + "178", + "159", + "8", + "243", + "102", + "105", + "81", + "91", + "99", + "25", + "76", + "35", + "27" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!! !!### ## ######## $ $$$$$ $$ ", + " !! !!!!!!!!!!!## # %%%% $$$ ", + " !!!!!!!!!!!!!!! ### # $$$ $$$$$ $$ $$$$$ ", + " !!!!!!!!!!!!!!!!!! #### $$ $ $ $$$$ $$$$ $$$$$ ", + " && &&&! !!!!!!!!!!!!!!!! !!! !! ## #### ''''' $$ $ $ $ $ $ $", + " && !!! ! !!! !! ! ## ## ( ')) * $$$$ $$$ $$$ $ ", + " & & !!!!!!!!!!! ## # ((( ') )) $ $ $$", + " && &&&& ! ! ! ! # '' )**$ $ $$$$$ ", + " &&&& & ! !! !! + '' ,$ $ $ $ ", + " & & !!!! !! ++ -.))/$00$ $$$$ $ $ $ ", + " ! !! !! 11+++2- / 3333 4 $ $ $$ $ $ ", + " !!!! &&&&&& ! !! ! !!! +55 56 77/3 8 $ $ $$$$$$ $$$$$ $ $$ ", + " &&&& & && !&&!! !! 5 99::;< 8333 $44 44 = == $$ $ ", + " && & ! >>>555???@;; > ??DEFGGG GH$IJB B 4BBK = L LMM C ", + " & & & NN > ?? F G GOPJJP BBQR LLLMS C ", + " & && TTU VV FF WW P J XXX L L SSCCCC ", + " &&&& T T VVY YY WZ[ [ X ] L L ", + " ^^ & &&&&& T T Y Y _Z Z[P XX X `` L] L L ", + " ^^ && & aab Y _Z ZPPPX ``] ] L L ", + " ^^ c aa bd ef Y _ ggh ]X ]i]L j L ", + " ^ ^ ccc aa b d e eYYk Z Z h ]] ] lj jL ", + " ^ ^^ mnn e kZ ohh ] ] pl lj q ", + " ^^rst uubb ve e k k wo o ] lj q ", + " t xy uuud vzv{ k k |o}} ]] lljj qq ", + " ~\u007f\u007fxy y \u0080 \u0081v z {f\u0082\u0082k k } } ]\u0083 j q ", + " x y \u0084\u0084 \u0085 \u0086 z { \u0082 k| }} \u0083\u0083 l \u0087 qq ", + " x yy \u0088\u0088\u0089 \u0085 \u0082\u0082 \u008a\u008a\u008b\u008b \u008c}} \u008d\u008d\u0087 \u0087\u008d ", + " \u008e xxy \u008f \u008f \u0090\u0090 \u008a \u008b\u008b \u008c \u008d\u008d\u0087 \u008d\u008d \u008d\u008d\u008d\u008d ", + " \u0091\u0091\u0091 \u008f\u008f\u008f \u0090\u0090\u008a \u008b\u0092\u008c } \u008d \u008d\u008d\u008d \u008d\u008d\u008d\u008d\u008d ", + " \u0091 x \u008f \u008a \u0092 \u0092 \u008d \u008d\u008d \u008d \u0093 \u0093\u0093 ", + " \u0091 \u008f \u0094\u0094\u008a\u008a \u0095 \u0092 \u008d\u008d\u008d \u008d \u008d\u0093\u0093\u0093 \u0096 ", + " \u0091 \u0091\u008f\u008f \u0094 \u008a\u0095 \u0092\u0092\u0092 \u0097 \u0097 \u0093 ", + " \u0091 \u008f \u008f \u0094 \u0094\u0094\u008a\u0095\u0098 \u0099 \u0097 \u0097 ", + " \u0091\u0091 \u008f \u0095 \u009a\u009a\u009b\u0098\u009b \u0099 \u0099 \u0097 \u0097\u0097 \u0097 ", + " \u009c \u009d\u009d \u009a \u009b \u0099 \u0097 \u0097 \u009e ", + " \u009c\u009c\u009f\u009d\u008f\u009d \u008f \u00a0 \u009a \u0099\u0099 \u0097 \u0097 \u009e ", + " \u009c \u009d\u008f \u008f \u00a0 \u00a1 \u0099 \u0097 \u0097 ", + " \u009d\u009d \u00a0\u00a0 \u0097 ", + " \u009c \u008f \u008f \u00a2 \u0097 ", + " \u009c\u009c \u00a3 \u00a3 \u00a4\u00a4\u00a4\u00a4 \u0097\u0097\u0097 \u0097\u0097 \u0097 ", + " \u009c\u009c \u0097 \u00a5", + " \u009c\u009c \u00a6\u00a6 \u0097 \u00a5\u00a5", + " \u009c\u00a6 \u00a6 \u0097\u0097 \u00a5\u00a5 ", + " \u009c \u00a6 \u00a5 \u00a5 ", + " \u009c \u00a6 ", + " \u009c\u009c ", + " \u009c\u009c\u00a6 \u00a7 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!! ######### ", + " ! !!!!!!! !!#### #### %%%%%%% $$$ ", + " !!!!! !!!!! !! ### # %% $ $$$ $ ", + " ! ! ! !! # ### $$$$$ $$ ", + " &&& !!!!!! ! !! !! # ### $$ $ $ $$ $$$$$$$$$$$$$ ", + " & !!!!!!!! !! !! !! # ## ')) *$$$$$$$$$$$$$$ $$ $", + " &&& !!! ! # (((( ')' )) $$ $ $", + " & & !!!! !!!!! ## # ' ) * $ $$ $", + " & &&&&&&&& ! !!! ! # '' ) * $ $$$$ $$$ ", + " & !&& ! !! !! ++ )) 00$ $$ $$ ", + " ! !! !! !! 1 + -////\u00a8\u00a8$$ $$$ $$ $ $ $ $ ", + " !! !!!! ! ! ++55- / 33 $$ $$$ $$ $$ $$$$ $ $ $$ $ ", + " &&&&&&&&&&!&&& !!!! !! 5 5--7\u00a933 3$ $4 4=L === $$ $ ", + " && & !&&! ! ? ?@\u00aa<<<<3$ $ 4B4 4 == == LL$ C ", + " & && & > >>5 ? ? A GG$$$ JBJ BB K44 === LL CC ", + " & > > ? ?FFG PPIJ BBB L LL C ", + " & & >> UUU F GGGGGG JJP QQQXX L CCC ", + " & & TTU WW P P XQXL] L C ", + " ^^^&^ & TTT Y Y___\u00ab [[ X Q L L ", + " ^^^ & && & aaU Y Y Z Z PPP P ] `LLLLL L ", + " ^ ^^ & abbU YY Y _ gg XXXX ] p p L ", + " ^ ^^ ^ccc ab b d eefY Y_k__Z Z h ] i] Ljj L ", + " ^ ^^^ c Ue ef k k ZZh ] ] p p j ", + " ^^ ^ bb de e f wwZZooo ] p l\u00acl q ", + " rtt uu dvve{ee f k|woo ] pll\u00adj q ", + " t xyy \u00ae \u0081 v { {f \u0082 }}}} ]] l jj ", + " \u007f\u007f y \u0084 \u0081 { { \u0082\u0082 kk k } \u0087 ", + " x y y\u0084\u0088 \u0081\u0081 { \u00af\u008a\u008a\u0082\u0082 kk |}} \u0083 \u008d l ", + " x \u008fyy \u0084\u0088 \u0090\u0082\u0082\u008a \u008a\u008c \u008c} \u008d\u0087 \u008d\u008d\u008d ", + " \u008e\u0091\u0091\u008fx \u0090\u0090\u008a\u008a \u0092\u008c } \u008d\u008d \u008d\u008d \u008d\u008d ", + " \u0091 \u0091 \u008f\u008f\u008f \u008a\u008a \u0092 \u0092\u008c \u008d \u008d\u008d\u008d\u008d\u008d \u008d \u0093 \u0093 ", + " \u0091 \u0091 \u008f \u008a\u0094\u0094 \u0092 \u0092 \u008d\u008d \u008d \u0093 ", + " \u0091\u008f\u008f \u008a\u008a \u0092\u0092\u0092 \u008d \u008d\u0093\u0093\u0093 ", + " \u0091 \u009f\u009f \u008f \u0094\u008a\u008a\u0095\u0098\u009b\u009b \u0097\u0097 \u0097 ", + " \u0091\u0091\u0091\u009f \u008f \u008f \u0095 \u009b \u0099 \u0097 \u0097 \u0097 ", + " \u009c\u009f \u009f \u00a0\u00a0\u00a0\u00a0\u009a\u009a\u009a\u009a\u0098 \u0099\u0099 \u0097 \u0097 ", + " \u009c\u009c \u009f\u009d\u008f \u00a0 \u00a0\u00a1\u009a \u009b \u0099 \u0097 \u0097 \u009e ", + " \u009c\u009c\u00a6\u009d \u009d \u008f \u00a0 \u00a0 \u00a1\u00a4 \u0099 \u0097 \u0097 ", + " \u009c \u009d\u009d \u00a1 \u00a4 \u0097 ", + " \u00a6 \u008f \u00a4\u00a0 \u00a4 \u0097 \u0097 ", + " \u009c \u008f\u008f \u00a4 \u0097 \u0097\u0097\u0097 \u0097 ", + " \u009c\u009c \u00a6 \u00a4 \u0097 \u00a5 ", + " \u009c\u009c \u00a6 \u0097\u0097\u0097\u0097 \u00a5\u00a5", + " \u00a6 \u00a6 \u0097 \u00a5\u00a5 ", + " \u00a5 ", + " \u009c\u009c \u00a6 \u00a5 ", + " \u009c \u00a6 ", + " \u009c\u009c\u009c ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!! #### # ## ", + " ! !!### # # ", + " !! ## # $$ $$$$$ ", + " !! # # $$ $$$ $$ $$$$$ ", + " & &&&! !!!!!!!!!!!!!!! # # '' $$$$ $$ $$ ", + " & & !!!!! ! ! !! ## # ( '''$$$ $$$ $$ $", + " & & !! !! !!!! ! # # ''') *$* $$ ", + " & && ! ! ! !!! ## ' ' ) **$ $$$$ $", + " && &&!& ! ! ! $ $ $ ", + " & && !! ! ! ) $ $$$$$$$$ $ $ $ ", + " ! !!! ! +++ - / / $ $$$ 44 LL $$ ", + " !! && !! 55 - / 33 $ $ 4 === L $ ", + " &&&& !!!!!& && 5 5 ?- << 33 3$ $ L === == L $LL ", + " & && &&!&!! >>> 5? ? $$4 BBB L4 = =LL L LL$$ ", + " & > ? FF GG $ J B BBK LL M C ", + " & & >> ? G GP PJP JBB L M C ", + " & UU W [ QX L C ", + " && & TTTT Y W[ P Q X ] L ", + " ^^ &&& & TTT U YYY Y__ ZZZZPP X ] ] L p ", + " ^^^ &&& & b Y Y _Z Z PPX X ] L] L ", + " ^^ c abbd YY Y _ Z ]X ]L jLLL ", + " ^^ ^^ ccc a b dU U eYYY kk ZZZZZZ ] ] L j ", + " ^^^ bbd de f k oh ] ] l j ", + " ^ e e f k oo ] ] l j ", + " xy u dd { {{f k ||o } ] j ", + " x y \u00ae\u00ae {{{f k |k } ]] j ", + " x y y\u0084 { \u00af \u0082 \u0082\u0082kk k } \u0087 ", + " xy y\u0084\u008f \u00af \u00af\u00b0 \u008a \u008b } \u0087 ", + " xxy\u008f \u0084 \u008f \u00af\u008a\u008a \u008b } \u0087\u008d \u008d ", + " \u0091\u008f \u008f\u008f \u008a \u008a\u0092\u0092 \u008d \u008d ", + " \u0091\u0091 \u0091 \u008f \u008a \u008a\u0092 \u0092 \u008d ", + " \u0091 \u008f\u0091 \u008f \u0094\u008a\u0094 \u0092 \u0092 ", + " \u0091 \u0091\u008f \u0094 \u008a\u0095\u0095\u0095\u0095\u0092\u009b \u0097 ", + " \u0091\u0091\u009f\u008f \u008f \u0095 \u0095\u009b \u009b \u0097\u0097 ", + " \u0091\u009f \u009f\u008f \u008f \u0095\u0095\u009a\u009a \u0099 \u0097 \u0097 ", + " \u0091 \u009d\u009f \u00a0 \u00a0\u00a1 \u009b \u009b \u0097\u0097 \u0097 ", + " \u009c \u009f \u009d \u008f \u00a0 \u00a1\u00a4 \u0099 \u0097 ", + " \u009c \u00a6\u008f \u008f \u00a0 \u00a1\u00a4 \u009b \u0097 \u0097 ", + " \u009c \u008f \u008f \u00a4\u00a0 \u00a4 \u0097 ", + " \u009c\u009c \u00a6 \u008f \u00a4\u00a4 \u00a4 \u0097 \u0097 ", + " \u009c\u00a6 \u00a6\u008f \u00a4 \u0097 ", + " \u009c\u00a6 \u00a6 \u0097\u0097\u0097\u0097\u0097\u0097 ", + " \u00a6 ", + " \u00a5 ", + " \u009c\u009c \u00a6 \u00a5 ", + " \u009c\u00a6 ", + " \u009c\u009c ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! ######### ", + " #### # # ", + " !!! # # $$$$ ", + " ! # # $$$$$$ $$$$$ ", + " & !!!!!! !!! # # $$$$$$ $$$ $$$$$ ", + " & & !!!!!!!!! !!!! # # )''$ $$$ $", + " & ! !! !!!!! ! !!!!! # # ') $$ $ ", + " & & !! !! # # '' ) $ ", + " & & !!! ! ! $ $ ", + " &! !!!!!! $ $ ", + " ! !!! !!!! $ 44$4$$$ L $ ", + " ! !!!!!!!!!!! 33 $ 44 $ 4 $$$ LL L L $ ", + " &&&&&&&&&& &&& !!! 3 $ 444 $ $$$ L $ ", + " & &&& $ $ 444 4 ===L $$$ $ ", + " & & $ $ 44 LL $$ ", + " & & P LL L L C ", + " & & U PP XL L C ", + " & & U U PP QX ] ] L L C ", + " ^^ & & U U YYY P Q X ] ]] L ", + " ^^^ & & U YYY PX ] L] L L ", + " ^^ d UUU U X ] L L ", + " ^ dd ] LLL ", + " ^ d eeee ] ] ", + " ee ] ", + " dd ] ] ", + " ]] ", + " ] ", + " \u008f \u008a ", + " \u008f \u008f\u008f \u008a ", + " \u008f \u008f\u008f \u008a \u008a ", + " \u008f \u008f\u008f \u008a \u008a ", + " \u0091 \u008f \u008f\u008f \u008a \u008a ", + " \u0091\u008f \u008f \u008a\u008a ", + " \u0091\u008f \u008f \u008a\u008a \u0097\u0097 ", + " \u0091\u008f \u0097 \u0097 ", + " \u008f \u0097 ", + " \u008f \u008f \u0097 \u0097 ", + " \u00a6\u00a6\u008f \u008f \u00a4 \u0097 \u0097 ", + " \u00a6 \u008f\u00a6 \u008f \u00a4 ", + " \u00a6 \u00a6 \u008f \u0097 ", + " \u00a6 \u00a6\u008f \u0097 \u0097 ", + " \u00a6 \u00a6 \u0097\u0097\u0097\u0097\u0097 \u0097 ", + " \u00a6 \u0097\u0097 ", + " \u00a6 \u00a6 ", + " ", + " \u00a6 ", + " \u00a6 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-2.0-grid-reference.json b/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-2.0-grid-reference.json new file mode 100644 index 000000000..7be0c9a70 --- /dev/null +++ b/tests/visual_tests/grids/simplify-douglas-peucker-500-1000-2.0-grid-reference.json @@ -0,0 +1,369 @@ +{ + "keys": [ + "", + "24", + "71", + "238", + "245", + "207", + "154", + "82", + "189", + "60", + "205", + "51", + "103", + "153", + "72", + "163", + "102", + "98", + "65", + "206", + "110", + "86", + "182", + "186", + "80", + "22", + "170", + "210", + "30", + "89", + "74", + "200", + "202", + "94", + "84", + "194", + "114", + "2", + "88", + "31", + "162", + "120", + "107", + "190", + "83", + "50", + "175", + "235", + "116", + "155", + "113", + "226", + "118", + "41", + "126", + "188", + "14", + "18", + "214", + "36", + "193", + "172", + "79", + "208", + "54", + "220", + "158", + "38", + "181", + "152", + "56", + "25", + "212", + "76", + "87", + "69", + "40", + "185", + "164", + "104", + "121", + "21", + "157", + "35", + "28", + "204", + "92", + "223", + "49", + "67", + "161", + "203", + "166", + "6", + "221", + "17", + "108", + "122", + "9", + "123", + "160", + "216", + "222", + "124", + "33", + "180", + "8", + "178", + "209", + "159", + "101", + "93" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!!!!!! ###### ######## ", + " !!!!!!!!!!!! ###### ### $$$$$$$ %%%% ", + " !!!!! !!!!!!!!! ### ## $ %%%% %%%%%%%% %%%%% ", + " !! !! !!!! !!!!!! ## ##### %% %%%%%%% %%%% %% ", + " &&&&&&&! !!!!!!! !!!!!!!! ## ### '''''' % % %% %%%%%%%%%%%%%%% ", + " && !!! ! !!! # ### ( '))) *%%%%%%%%%%%%%%%%%% %", + " &&&& !!!!!!! ! # # ((( ')'))* %%%% %%%", + " & && ! !! !!!!! ### '' )) **% %%%%%%%%%", + " &&&&&&&&&&& ! !! !! + ))) * % %%%% %%% ", + " && !&& !! ! !! ,++ ) --%% % % %% ", + " & !& !! !! !! , +++.//0000111% %%%2 %%2 %% %%% % ", + " ! && ! ! !! !! , +++3// /000444 %% %%22 %%%%% 5%%%%%% %% %% % ", + " && &&&&&& !&&&& &&!!!! 3 36777444444% %22 255 555 %% %% ", + " & & & !&&&!!! 8 3 696999:;; %% % 2<<< =2 555 555 = % >>> ", + " & &&& & 8 8 666 ? @@@@@%% A ", + " & && & 888 66 ??@ @CCA <<
> ", + " & & 8E FFF @@@@@G CCHHIIII = >>>> ", + " &&J && EEFE KKKKKK LL GC CIIHIMM = ", + " &&&JJ &&&&&& EEEE K K NO OO C IHHMI =M===== = ", + " J &&&& & PPQ K K O OCCCCI I RRRMMM = ", + " J J PPQQS KK K O OTU IIII MMM = == ", + " J J JVVVV P Q SS WWWWKKXXXXNO OOU M MYZ =[[=== ", + " J JJJJ Q SW W ]X XXO OOUU M MM Z^^^[ _ ", + " JJJJ` QQQQ aW W X] Xbccccc M M Z Z ^[ _ ", + " dd e ffSSSaagggg X Xhbcc M M Z^i[[ _ ", + " d jjjj kSlam g g]]nX X oooo MM ^ [[ _ ", + " p ejj j qklmmg g nn X X oo M r^ r ", + " e jjsjtts l gu nvnnXXwXxooo y ^ rry ", + " z sjj ss {{n v ww oo yyryyyyyyy ", + " z||se {{{vv }wx o yr y yyy yyyy ", + " | s| sssss vv } }} yy y yy y y~ ~ ", + " || | s vv\u007f\u007f \u0080 } yyy y yy ~ ~ ", + " | ||s\u0081 vv \u0080} } \u0082 y y~~~~ ", + " | s\u0081 s \u0080\u0080\u0080\u0080 \u0083 \u0082 \u0084\u0084\u0084 \u0084 ", + " ||\u0081 ss s \u0080\u0080\u0083\u0083\u0085\u0083 \u0082\u0082 \u0084\u0084 \u0084\u0084 \u0084 ", + " |\u0081 \u0081\u0086 \u0087 \u0087\u0087\u0088\u0088\u0088\u0088\u0085 \u0082\u0082 \u0084 \u0084 \u0084 \u0089 ", + " \u008a\u008a\u0081\u0086\u0086\u0086 s \u0087 \u008b\u0087 \u008b\u0088 \u0083 \u0082 \u0084\u0084 \u0084 \u0089 ", + " \u008a\u008a \u0086\u008c\u0086 s \u0087 \u0087\u008b\u008b\u008d\u0083 \u0082 \u0084 \u0084 \u0089 ", + " \u008a\u008a \u0086s\u008c s \u0087\u008b \u008d\u008d \u0082 \u0084 ", + " \u008a\u008c \u008e\u008c s \u008d\u0087 \u008d \u0084 ", + " \u008a \u008e\u008e\u008e \u008d \u008d\u008d \u0084 \u0084\u0084\u0084\u0084\u0084 \u0084 ", + " \u008a \u008c \u0084 \u0084 \u0084 \u008f\u008f", + " \u008a\u008a \u008c\u008c \u0084\u0084\u0084\u0084 \u008f\u008f", + " \u008a\u008c \u008c \u0084 \u008f ", + " \u008a \u008c \u0084 ", + " \u008a \u008c ", + " \u008a\u008a\u008c ", + " \u008a\u008a\u008a ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!! ###### ####### ", + " !!!!!! !###### ## # $$$$$$$ ", + " !!!!!!!! # ## %%%% %%%%%%%% ", + " !!! ! ## # % %%% %%% %%%%%%% ", + " &&&&&&&&! !!!!! !!!!!! ## ## *%' %%%%%% %%% %%%%%%% ", + " & & !!!!!!! ! !!!!! # # ( ))''%% %%%%% %%%% %", + " & & !! !!!!! ! !!!! ## ## ((( ')) * % %%%% % ", + " & && & !! !!! !!!! #### ''')) **** %%%% %% ", + " && &&& & !! ! !! !! ' )) % %%%% %% ", + " && &&& !! !! ! !! \u0090\u0090\u0090\u0090% 2%%%% % %% ", + " & !! !!!!! !! ++++ % %%%% 222 %%%%%%%%% % %% ", + " ! & !! !!! +++3 4444% %%22 222 == %% % % ", + " &&&&&&&&&!!&&!!!!!!&& 33 3 4444 % %222 =2 555555555555 % ", + " & & &&& !!! 8 33 ;; %% % <<<22 =2 555 == =% ", + " & && & 8 8883 ? @@ %% AA< <<<\u00912 == = B% > ", + " & & 888 @@@@ @@CCCAA A<
", + " & & 8 FF LLG@ C HI=M = > ", + " J&J & EEEEEF N LG GC CHHIIM MM = > ", + " JJ&&&& & EEEE F KKKKN GO CC C I I ===MM = ", + " JJ J &&&& & EFQ K K NNO O CCII IM MM= = ", + " J J & PPQS KK K NOO OOU IIII MZ ===== ", + " J JJ VVVVV P QSS FF ]KKKNXXNOO OO M M Z^ [ ", + " JJJJJJJ QQQ SWWW W ]KX XXOO O M M Z ^^[ ", + " Q WS W ]]X X Occc M M Z ^ [ ", + " ff SSS ggggg]X hhcc M M Z^^[ ", + " ejjj kS g g] XX hX oo o MM ^ [ ", + " e jj j g u nnnn XXXhhhoh M r ", + " e je js uu u nnnn X o r ", + " e jj ss uu v v o rry y ", + " ees ss vv v}} oo y y ", + " ||||| s vv v}} y ", + " | s| s vv v}}} yyyyy ", + " | |s s \u007f vv\u0080\u0080\u0080\u0080}} \u0084 ", + " ||\u0081s s \u007f \u0080v\u0080\u0083\u0083\u0083 \u0082 \u0084\u0084\u0084 ", + " |\u0081\u0081ss s \u0080\u0080\u0083\u0088 \u0083 \u0082 \u0084\u0084 \u0084 ", + " \u008a\u0081 \u0081s s \u0087\u0087\u0087\u0087\u0088\u0088\u0088 \u0083 \u0082 \u0084\u0084\u0084 \u0084 ", + " \u008a \u0081\u0086\u0081s s \u0087 \u0087\u008b\u008b\u008d \u0083 \u0082 \u0084\u0084 \u0084 ", + " \u008a\u008c \u008c\u0086\u0086 s \u0087\u008b\u0087\u008b\u008b\u0083\u0083 \u0084 \u0084 ", + " \u008a\u008a\u008c s s \u0087\u008d \u008d \u0084 ", + " \u008a\u008a \u008c s \u0087 \u008d \u0084 \u0084 ", + " \u008a\u008a \u008cs \u008d\u008d \u0084 \u0084 ", + " \u008a\u008c \u008c \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084 \u0084 ", + " \u008a\u008c \u008c ", + " \u008a\u008c \u008c \u008f ", + " \u008a\u008a \u008c \u008f ", + " \u008a\u008a \u008c ", + " \u008a\u008a ", + " \u008a ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-radial-distance-500-1000-1.0-grid-reference.json b/tests/visual_tests/grids/simplify-radial-distance-500-1000-1.0-grid-reference.json new file mode 100644 index 000000000..78aa6c267 --- /dev/null +++ b/tests/visual_tests/grids/simplify-radial-distance-500-1000-1.0-grid-reference.json @@ -0,0 +1,396 @@ +{ + "keys": [ + "", + "24", + "71", + "245", + "238", + "207", + "154", + "82", + "189", + "60", + "205", + "45", + "53", + "51", + "163", + "103", + "102", + "153", + "98", + "30", + "65", + "129", + "72", + "191", + "182", + "170", + "206", + "110", + "186", + "86", + "80", + "236", + "22", + "210", + "112", + "74", + "200", + "68", + "3", + "202", + "93", + "94", + "89", + "84", + "31", + "194", + "96", + "114", + "2", + "199", + "190", + "88", + "162", + "120", + "107", + "175", + "83", + "50", + "155", + "235", + "116", + "226", + "14", + "18", + "41", + "113", + "126", + "214", + "36", + "188", + "193", + "244", + "48", + "54", + "220", + "118", + "172", + "75", + "79", + "158", + "181", + "208", + "56", + "99", + "212", + "197", + "152", + "185", + "25", + "39", + "164", + "38", + "183", + "87", + "35", + "40", + "77", + "157", + "104", + "26", + "121", + "59", + "28", + "204", + "92", + "223", + "49", + "21", + "67", + "161", + "203", + "27", + "166", + "6", + "221", + "9", + "123", + "108", + "222", + "122", + "33", + "160", + "180", + "124", + "17", + "216", + "8", + "178", + "209", + "159", + "101", + "57", + "105", + "81", + "165", + "91", + "76", + "69", + "19" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! !!######## ###### $ $$ $$ $$ ", + " !! !!! !!!!!!!!## # %%%%% $ $$$ ", + " !!!!!! !!!!!!!! #### ## $$$ $$$$ $$ $$$$$$ ", + " ! !!!!!! ! !!!! # ### $ $$ $$ $$ $ $$$$ $$$$ ", + " & &&&! !!!!!!!! !!!! !!!!! ! ## ## '''''$$ $$$ $ $$$$$$$", + " && !!! ! !! ## ## (( ) ) $$$$$$ $$$ ", + " & && ! !! !!!!! ! # (( ') )** $ $$ $", + " & &&& ! ! !! ## ' )* $ $$$ $ ", + " & & && ! ! !!! + ', ) -$ $$ $ $ $ ", + " && & !!! ! .++ ))/$01$ $$$ $ $ ", + " ! !! ! ..+ 2 / 11 $$ $ 3 $ $ $4$ $ $ ", + " !!!!!!! & !!! ! ++5556 7/// $$ $ $$$$$ $$$$$$4 $ $$ ", + " & & &!! !! 5 8899:: : ;$ $3 33 < <4 $$$ $ ", + " !&&& === 55>>?@@:A ; $$ $3 B BB < < $$ ", + " & = >> CDEE EEEFG HB B BBBII < JJ K ", + " & & = = >> D E EGLHHL BBMN 4JO K ", + " & PPQ RR DD S ST H UUU 4 O KKK ", + " &&V& P P RWW WW SX T U Y Y K ", + " VV && &&& && PP Q W ZX XXL UU U [[ Y 4 ", + " VV && & ]]^ Q W ZX XL_LU Y [`Y a 4 ", + " VV b ]] ^c QdW W Z _ U YYY 4 e 4 ", + " V VV bb ]] ^ c d dfWg gX he e4 i ", + " V VV jj ^ d d kXXllmm Y Y ah he n ", + " Vopq rr^c sd d gtl l Y ue nn ", + " qq vv rrrc swsx xx g g t y Y hhze n ", + " {||}vv v ~ \u007fs w x\u0080\u0081\u0081 t y YY h e n n ", + " v \u0082\u0082\u0083 \u0084 \u007f wx x g yy \u0085 \u0086 \u0086 n ", + " vvv\u0082 \u0087 \u0081\u0088\u0081 \u0088g\u0089\u008a\u008ay y \u008b\u008b \u0086\u008b \u008b ", + " \u008c\u008c }\u008dv \u0082 \u008d \u008e\u008e \u0089 y \u008b\u008b \u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b ", + " \u008f\u008f\u008f \u008d \u008d \u008e\u008e\u0088 \u0090\u0090\u0090 y \u008b \u008b \u008b\u008b\u008b \u008b\u008b\u008b\u008b\u008b ", + " \u008f \u008f} \u008d \u0091 \u0090 \u0090 \u008b \u008b \u008b \u0092 \u0092\u0092 ", + " \u008f \u008f \u008d \u0093\u0088\u0088\u0088 \u0094 \u0090 \u008b\u008b\u008b \u008b \u008b\u0092\u0092\u0092 ", + " \u008f \u008f\u008d \u008d \u0093 \u0088\u0094 \u0094 \u0090 \u0095 \u0092\u0092 ", + " \u008f \u008d \u008d \u0093 \u0094 \u0094\u0094\u0096 \u0097 \u0095\u0095 \u0095 ", + " \u008f\u008f \u008d \u008d \u0093 \u0094 \u0098\u0098\u0098 \u0099 \u0097 \u0097 \u0095 \u0095\u0095 \u0095 ", + " \u009a \u009b\u009b \u009c \u0098\u0099 \u0097 \u0095 \u0095 \u009d ", + " \u009a\u009a\u009e\u009b\u009b \u008d \u009f \u009c\u0098 \u0097 \u0095 \u0095 \u009d ", + " \u009a\u00a0 \u009b \u00a0 \u008d \u009c \u0099 \u0097\u0097 \u0095 \u0095 ", + " \u009a \u009b\u009b \u009f\u009f \u00a1 \u0095 ", + " \u009a \u00a2 \u008d \u00a1 ", + " \u009a \u008d \u00a1\u00a1\u00a1\u00a1 \u0095\u0095 \u0095\u0095 \u0095 ", + " \u009a\u009a \u0095 \u0095 \u00a3 ", + " \u009a \u00a0 \u00a3 ", + " \u009a \u00a0 \u0095\u0095 \u00a3 ", + " \u009a \u00a0 \u00a3 ", + " \u009a ", + " \u009a ", + " \u009a\u009a\u00a0 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! ######### ", + " !!! !!!!! # ### %%%% $$$$ ", + " !! !! !!!!!!! # %% $$ $$$$$ ", + " !!!! !!!! # ## $$ $ $$$$ ", + " &&& ! !! ! ! !! # ## ' $ $$$ $$$$ $$$$$ ", + " && & !! !!!! !!!!!!!! ! !! # ## ')) $ $$ $$$$$$ $ $$ $$ $", + " && !!! ! ! # # (((( ) $$ $ $", + " &! ! ! !! # # ' ' ) $ $$", + " & &&&&&&& ! !!! '' ) * $$$$$ $ $ ", + " && & !! ! + )) \u00a4\u00a4$ $$ $ ", + " ! ! ! !! ++ 7 /// $ $$$$$$ $ $$$ $$ ", + " ! !! +557 / ;$; $$$$33 3$$ $$$$$< $$ $ $$ ", + " &&&&&&&&& !!! !!! 77\u00a5 \u00a6\u00a7; ;$ 3 44 < $ $ $ ", + " & !&&!!! 5 > > \u00a7: :; 3 B3 33 <4 < 4 $ ", + " & & & = = >>> AA EE FFF 3HB BBB33I <<<< J$ ", + " & = = > E E H BBBII4 4 J K ", + " & \u00a8= QQRR EEEEST H HMMN KK ", + " && & P P R ST UY Y KKK ", + " V V&& & P P W W ZZZ \u00a9 XTT MMU U 4 ", + " V V & & P]Q W W Z XLL U U [[44Y4 4 ", + " VV V ] ]^Q W W X X__ UU YY ", + " V V bb ]] ^ c Qdd WWWZgggX m Y a ee44 ", + " V VVV cd dffg X mm Y Y a he ", + " VVV ^^ ^ cc gk XX l Y Y e ", + " q rr cs xxxd g gtkll Y ahze n ", + " } v \u00aa \u00abss \u0080 yy h e ", + " }} \u00aa\u007f\u007f\u00ab\u00ac x \u0081\u0081 g g y h n ", + " v v\u0082 \u007f \u0080 \u0081 \u0081\u0081g g\u008atty \u008b h \u0086\u0086 ", + " } vv \u008d \u008e\u0081 \u0089\u0089 y \u008b\u0086 \u0086\u008b\u008b \u008b ", + " \u008c\u008f \u008d} \u008d\u008d \u008e\u008e\u0091 \u0088\u0089\u008a\u008ay \u008b \u008b \u008b\u008b \u008b\u008b ", + " \u008c \u008f \u008d\u008d \u0091\u0088 \u0090 \u008b\u008b \u008b \u008b \u008b \u0092 ", + " \u008f \u008f \u008d \u0088\u0088\u0088 \u0090 \u0090 \u008b\u008b\u008b \u008b\u0092\u0092 ", + " \u008f \u008d \u008d \u0093 \u0088 \u0094\u0090 \u008b \u0092 ", + " \u008f\u009e\u008d \u0093 \u0094\u0094 \u0094\u0090\u0099 \u0095\u0095\u0095 \u0095 ", + " \u008f\u008f\u008f \u009e \u008d \u0093 \u0093 \u0098\u0099\u0096\u0099 \u0097 \u0095 \u0095 \u0095 ", + " \u009a \u008d \u009f\u009f\u009f\u009f\u0094 \u0098 \u0099 ", + " \u009a\u009e \u009b\u009b \u008d \u009f \u009f \u0098 \u0099 \u0097 \u0095 \u0095 ", + " \u009a\u009a \u009b \u009b \u008d \u009c \u009c\u00a1\u0099 \u0097\u0097 \u0095 \u0095 ", + " \u009a\u00a0 \u009b\u009b \u00a1\u009c\u00a1 \u00a1 \u0095 ", + " \u009a \u008d \u008d \u00a1 \u00a1 \u0095 ", + " \u009a \u00a0\u00a2\u00a2 \u00a1 \u00a1 \u0095 \u0095\u0095\u0095\u0095 \u0095 ", + " \u009a \u00a1 \u0095\u0095 \u0095 \u00a3 ", + " \u009a\u009a \u00a0 \u0095\u0095\u0095\u0095 \u00a3", + " \u00a0 \u00a3 ", + " \u009a \u00a3 ", + " \u009a \u00a0 ", + " \u00a0\u00a0 ", + " \u009a ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ! ##### ###### ", + " !!! # # ", + " !! !!! ## $$$ $$ ", + " !!! # # $$$$ $ $$$ $$ ", + " & && ! !!!! !!! !! ! # '** $$$ $$$$$$", + " ! !!! # # ' ) *$$$$$$$ $", + " & &! ## ## '' ) ** $ ", + " & &! ! ' ' ) $ $$$ ", + " & & & ! !!! ) $ $$ $$ ", + " !! !! ! $ 33 $ ", + " ! ! $ $3 3$ $ 44 ", + " !!!!!! & ! ; $ $$3 3 $$$< $$$$$$$$$ $ ", + " && !&& ! > 3 3 4< <4 $ ", + " && == > > $ 3BBB3333 4 <44 <4 4$$ ", + " & & = = > EEEEE 3 BB II 4 K ", + " & & = EE EELLL HHHH 4 4 K ", + " & & Q Q L L MUY 4 K ", + " &&& Q Z X L L U U Y 4 ", + " & &&&& & Q WWW Z Z XX L L U Y Y4 4 ", + " V V& ^]^Q W WZ Z X L UUU Y a 4 ", + " V V ] ^cQ Q WW ZZ X X Y 44 e 44 ", + " VVVV ] ^ c d ff g X ah e ", + " VV V ^ c c d d g g XXl Y Y huee ", + " d d g g ll Y Y h e ", + " }v c xx fff gtl Y h ", + " } v v x \u0081 g g t ", + " } v x \u0080\u0081\u0081\u0081g gt y ", + " } }v\u008d \u008d\u008d \u0080\u0081\u0081 \u008a y \u008b\u008b ", + " }} \u008d \u008d \u0088 \u0088 \u008a \u008b \u008b ", + " \u008d \u008d\u008d \u0091\u0088 \u0088\u0090\u0090 \u008b \u008b \u0092 ", + " \u008f \u008d \u008d \u0088 \u0090 \u0090\u008a \u008b\u008b \u0092 ", + " \u008f\u008f\u008f \u0093\u0093\u0093\u0088 \u008b \u0092 ", + " \u008f\u008d \u008d \u0093 \u0093\u0088\u0094 \u0099 \u0095 ", + " \u009e \u008d \u008d \u0093 \u0093 \u0094 \u0099\u0099 \u0097 \u0095\u0095 \u0095 ", + " \u009e \u008d \u008d \u0093\u0093 \u0094\u0094 \u0099 \u0097\u0097 \u0095 \u0095\u0095 \u0095 ", + " \u009a \u008d \u009f \u0097\u0097 \u0095 \u0095 ", + " \u009a \u009e \u008d \u009f \u00a1\u00a1 \u0097 \u0095 ", + " \u009a\u00a0 \u00a0\u00a0 \u008d \u009f \u00a1 \u00a1 \u0097 \u0095 \u0095 ", + " \u009a \u00a0\u008d \u009f \u00a1 \u0095 ", + " \u00a0 \u00a0 \u00a1 \u0095 ", + " \u009a \u00a0 \u00a1\u00a1 \u0095\u0095\u0095\u0095\u0095 \u0095 \u0095 ", + " \u009a ", + " \u009a \u00a0 ", + " ", + " \u00a0 ", + " \u00a0 ", + " \u00a0 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !! ######## ", + " ! # # ", + " !! ## ## $$$ ", + " # # $$ $$ ", + " & # $$$$ $$$ ", + " && !!!!!!!!!!!!! # # ' $$$ $ ", + " & ! ! # # '' $ ", + " & ! ## ' ' $ $ ", + " & &&! ! !! ' $ ", + " &&& ! ! !! ! $ $$$ $ ", + " ! $ 3 $$$ 4 $ $$ ", + " ! ! $ $$$ 33$$ 4 $ ", + " !!!!!&&&! ! $ $ 3 3 <<<< $$4 $ ", + " & &&!! $ $ 3 344 << 444 $ ", + " & 333 3 444 $ ", + " & L 4 4 ", + " & & LL 4 4 ", + " & & LL YY Y 4 ", + " && & L 4YY 4 ", + " V&& Y 4 Ya 4 ", + " V &&&& Y Y44 4 ", + " V g Y Y 4 ", + " V g Y Y ", + " g Y ", + " g ", + " ", + " gg ", + " \u008d \u0088 g ", + " \u008d \u0088 g ", + " \u008d \u008d \u0088 \u0088 ", + " \u008d \u0088 \u0088 ", + " \u008d \u0088\u0088 \u0088 ", + " \u0088\u0088 ", + " \u008d \u0088\u0088 \u0095 ", + " \u008d \u008d \u0095 ", + " \u009a \u008d \u008d \u0095\u0095\u0095\u0095\u0095\u0095\u0095 ", + " \u009a \u008d \u0095 ", + " \u009a \u008d \u0095 \u0095 ", + " \u009a \u00a0 \u008d \u008d \u0095 \u0095 ", + " \u009a \u00a0 \u008d\u008d \u0095 \u0095\u0095 ", + " \u009a \u00a0 \u0095 ", + " \u009a \u0095\u0095\u0095\u0095\u0095\u0095\u0095 ", + " \u009a ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-radial-distance-500-1000-2.0-grid-reference.json b/tests/visual_tests/grids/simplify-radial-distance-500-1000-2.0-grid-reference.json new file mode 100644 index 000000000..352b52d93 --- /dev/null +++ b/tests/visual_tests/grids/simplify-radial-distance-500-1000-2.0-grid-reference.json @@ -0,0 +1,367 @@ +{ + "keys": [ + "", + "24", + "71", + "238", + "245", + "207", + "154", + "82", + "189", + "60", + "205", + "101", + "98", + "72", + "163", + "102", + "206", + "30", + "65", + "86", + "57", + "105", + "170", + "110", + "186", + "210", + "165", + "22", + "74", + "200", + "68", + "202", + "93", + "94", + "84", + "194", + "89", + "2", + "199", + "190", + "88", + "31", + "162", + "83", + "114", + "107", + "120", + "50", + "175", + "235", + "116", + "226", + "155", + "113", + "118", + "99", + "41", + "126", + "188", + "18", + "214", + "36", + "54", + "220", + "193", + "172", + "181", + "208", + "158", + "38", + "152", + "56", + "25", + "212", + "76", + "87", + "19", + "40", + "185", + "77", + "69", + "121", + "21", + "35", + "28", + "204", + "92", + "223", + "49", + "67", + "161", + "203", + "166", + "27", + "6", + "221", + "17", + "9", + "122", + "108", + "222", + "123", + "33", + "160", + "216", + "180", + "8", + "178", + "209", + "159" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! !!!!!!!!!################### ", + " !!! !!! !!!#### ## $$$$$ %%%% ", + " !!!!! !!!!!!!! ##### $ %%%% %%%%%%%% %%% ", + " !!!!!! !!!! # ## %%% % %% %%%%%%%% %%% ", + " &&&&&&&! !!! !! !! !!!!! ! ## ### ''' % % %%%%%% %%%%%% % ", + " &&& & !!!!!!!!!! ! ! !!! ## #### ( ))) %%%%%%%%%% %%%%% %", + " &&& &! !!!!! !! ! # ## ((((( ') )* %%%% %%%", + " & &! ! !!! ### '' ' ) *% %% %%%", + " &&&&&& &&&& ! !!! + '' ) **% %%%%% %%% ", + " && & !!! !! ++ ) ,,% - %% %% ", + " !! !! !! + + .../ / 0%1 %%-%%%%% %2 %% % ", + " !! !!!!! +33. ./// 11%%1 %%%%-- -%%%%%%%%%%%%%% %% %% ", + " &&&&&&&& &&& !!! !! 3 345 6711 1% % -228 8 % % % ", + " & & !&&&!! 993 34 4 777 %%% - ::: -- 888 88 % % ", + " & & & ;9 9 444 <=<>>>>??? @@: :::-AA 888 2B% ", + " & & 9 9 4=>> >>C @@ :::DD2 2 B E ", + " && & ;9FFFGG >>>>HI @@@JKKL EEE ", + " &&& & MMFM GN NN HI I KKL L 2 EE ", + " OO O&& &&&&& MMM NGN N PQ QQI KKKK K L L 2 ", + " OO O&& RRS N N PQ QQCTCK K UULLL2 2 ", + " OO O RRRSV NNN N PQ TTW KK LLL X 2 ", + " O O YYY R S VVFZZZZ NN[[[[Q QWW LL L ] ^^22 ", + " OO OO S S VZ Z _[ [`QaaaWW L LL ]] b^ c ", + " OOO SSdS eVZ Z_ [ [` aQaa L L ]]]b^^ c ", + " f g d VVVeehhh [ [iiaa LLL ]bj^ c ", + " gg kkk l meen h_ o[ [ pp p b ^ c ", + " gkkk kq mmrnh h o [ [ ip bb s c ", + " g k kq t m u ooov[[w[xipp yyb sy ", + " z tkk t {{ov ww p yysssyy yy ", + " z|||g ttt {{v }wxxp y yyy yy yy~ ", + " | | ttt \u007fv } } yy y y yyy~~ ", + " | | t \u0080vv \u0081 } yyy y~~ ", + " | t|\u0082 t \u0080 v \u0081\u0081}} \u0083 ~ ", + " | |\u0082tt t \u0080 \u0081\u0081\u0081 \u0081}\u0084 \u0085 \u0083\u0083\u0083\u0083 \u0083 ", + " ||| \u0082t t \u0080 \u0080\u0080\u0081\u0081\u0086\u0084\u0087\u0084 \u0085\u0085\u0085 \u0083\u0083 \u0083\u0083 \u0083 ", + " \u0088 \u0089 t \u008a\u008a\u008a\u008a\u0081\u0086 \u0086\u0084 \u0083 \u0083 ", + " \u0088\u0088\u0082\u0089\u0089 t \u008a \u008b\u008a \u0086\u0086\u0084 \u0085 \u0083\u0083 \u0083 ", + " \u0088\u0088 \u0089\u008c\u0089\u0089 tt \u008d\u008b\u008b\u008b\u008d\u0084 \u0085\u0085 \u0083 \u0083 ", + " \u0088\u008c \u0089t t \u008a\u008a\u008b \u008d \u0083 ", + " \u0088 \u008et t \u008d \u008d \u0083 ", + " \u0088 \u008e\u008e\u008e \u008d \u008d\u008d \u0083 \u0083\u0083\u0083\u0083\u0083 \u0083 ", + " \u0088\u0088 \u008e \u0083 \u0083\u0083 \u0083 \u008f ", + " \u0088\u0088 \u008c\u008c \u0083\u0083\u0083 \u008f\u008f", + " \u0088 \u008c \u008f ", + " \u0088 \u008c \u008f ", + " \u0088 \u008c ", + " \u0088\u0088 ", + " \u0088 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! ################# ", + " !!! ## # ", + " !!! !!!!!! ## # %%%%%%% ", + " !! ## # %% %% %%%% ", + " &&&&&&&!! !!!! !!!!!! # # ''* %% %%%% %%%%% ", + " & & !!!!!!!!!! ! !! # # ')) *%%%%%%%%% %", + " & &! ! ! ### ## ((( '' ) *% % ", + " & &! ! # ''' ) % %%% ", + " & &&&&&&& ! !!! '' ) % %%%%%%%% ", + " && && !!!!!! !! %% - % ", + " !! !! %% %%- %%%% 22 % % ", + " ! !! 11 % %%%% -%%%%%8 %%%%%%%%%% % % ", + " && !&&&& !! 4 1 % %-- - 88 882 %2 % ", + " &&& !& 9 44 %% --:::-- --22 82 882 2%% ", + " &&& & 9 99 44 >>> -::: AA 88888 2 E ", + " & & 999 4 >>> >>CCC @@@: 2 2 E ", + " & & 9FFF >> C CC KL 2 E ", + " &&& & F F P CC C KKKLL 2 E ", + " OO&& &&& & F F NN PPPPQQQQCC C KKLK 2L 2 ", + " O &&& & R F N NP PP Q CC KKKK LLLL ] 2 ", + " O O R SVF F NN NPP Q Q KK L L222 ^ 2 ", + " O OOOOO R S VVFZZZ__NN [ Q Q L L ]X ^22 ", + " OOO OO S S VVZ Z _[ [ Q Qa L L ]bX^^ ", + " OO SSSS V Z Z _[ [ Qaa L L bbX^ ", + " VV hh _ [ [iaaa L b ^ ", + " ggkkkk V hh _[ [ p b ^ ", + " gkg k h uoo[ [iip ", + " g kgkttt huoooo[[[ p yy ", + " gggkk tt uv v x yy y ", + " tt t \u007fv v}}xx y y y ~ ", + " | t t v } }x yy ~ ", + " || t vvvv }}}} yy ~~ ", + " || t \u0080 \u0080\u0080v\u0081v \u0084 yy ~~ ", + " \u0082\u0082t t \u0080 \u0080 \u0081v \u0084\u0084 \u0085 \u0083 \u0083\u0083 ", + " \u0088\u0082\u0082t\u0082 t \u0080\u0080 \u0081\u0081 \u0084 \u0085\u0085 \u0083\u0083 \u0083\u0083\u0083 \u0083 ", + " \u0088\u0082 \u0082t \u008a\u008a\u008a\u008a\u0081\u0081 \u0084 \u0085\u0085 \u0083\u0083 \u0083 ", + " \u0088\u008c\u0082 t t \u008a \u008a \u008d\u0084 \u0085\u0085 \u0083 \u0083 ", + " \u0088\u008c \u008ct tt \u008a\u008d\u008a\u008d \u008d \u0085 \u0083 \u0083 ", + " \u0088\u0088 t\u008ctt \u008a \u008d \u0085 \u0083 \u0083 ", + " \u0088 tt \u008d \u008d \u0083 ", + " \u0088 \u008c \u008d \u008d\u008d \u0083 \u0083\u0083\u0083\u0083\u0083\u0083 \u0083 ", + " \u0088 \u008c \u008d \u0083 \u0083 ", + " \u0088 \u008c\u008c \u0083\u0083\u0083\u0083 ", + " \u0088 \u008c ", + " \u0088\u008c ", + " \u008c\u008c ", + " \u008c ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-1.0-grid-reference.json b/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-1.0-grid-reference.json new file mode 100644 index 000000000..b757b4cc3 --- /dev/null +++ b/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-1.0-grid-reference.json @@ -0,0 +1,359 @@ +{ + "keys": [ + "", + "24", + "71", + "238", + "245", + "207", + "154", + "60", + "189", + "82", + "205", + "101", + "102", + "98", + "72", + "206", + "65", + "163", + "86", + "81", + "170", + "110", + "186", + "210", + "30", + "89", + "74", + "200", + "202", + "93", + "94", + "84", + "194", + "114", + "199", + "190", + "88", + "162", + "83", + "107", + "175", + "120", + "50", + "31", + "155", + "235", + "116", + "41", + "113", + "126", + "36", + "118", + "214", + "188", + "193", + "220", + "18", + "99", + "158", + "181", + "38", + "212", + "208", + "152", + "56", + "185", + "25", + "76", + "87", + "19", + "35", + "40", + "77", + "121", + "21", + "157", + "28", + "204", + "92", + "223", + "49", + "67", + "161", + "203", + "27", + "166", + "6", + "221", + "9", + "17", + "108", + "222", + "122", + "160", + "33", + "216", + "180", + "178", + "209", + "8", + "159", + "2" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!! !!### ## ", + " !!!! !### $ $$ ", + " !!!!! !!!!! ## # %%%%% %% ", + " !!!!!!!! !! # # % %%% %%%% %%%% ", + " && &&&! !!!! ! !!!!!!! !! # ### '' (%% %%% % %%%%%%", + " && !!! ! !!! # # ') ( %%%%%%% % ", + " && ! !! # * '') ) % %% %", + " & && ! !! ! ## ' ( % % %%%% ", + " &&& ! !! ! ! ! + '' ) ,% %% %% ", + " ! !!! ! ++ ) -% .%%% % % ", + " ! ! + + / / -00% % % %%% % % ", + " !&&&&&&&&&&& !! 11 1/ /222 %% % %%%% % %%%% % %% ", + " & && ! 1 33 45 5000 % .. 6 6 % % ", + " && &&! 771 13 3 555 %% % .8888 . 6 6 9 ::: ", + " & & 7 3 ;;<<< < =. 8 .> > 6 ?? : ", + " & 7 7 ; < <@@==@ 88AA 9 ? : ", + " & & BBB CC DD E = FGG 9 ::: ", + " &&&& & B B CCH HH DI E F G 9 ", + " J & &&& && BBB H H KI II@ FL F GM G9 9 ", + " J & NOO H H KI @@ F MM G 9 ", + " J J P NN OQ HRS H K I T F GGG9 U 9 ", + " J J J PP NN O Q R S HV I I T G WUUU ", + " J JJ R V VI XXTT G G YWYWZ ", + " JJ [ ]]OO QQR R V X G G WWW ", + " [ ^_ ]]Q Q``a a V V b c G d ", + " ^ _ ee f g h iiV V c c G ", + " __ j f g a i Vb c k ", + " ^ _l_mm h in nooppc c qq kq ", + " r^ l_ j l ss oo c qq qqq qqq ", + " rttt ll ssn ouppc qq qq q ", + " tt l l vn u q q q w ", + " t t l xxnn u u qww ", + " tll x n yuu z ", + " t {l l x x y | z z z ", + " tt l y }}~ ~ | | z z ", + " t \u007f } ~ | z z ", + " \u0080\u0080{\u007fl\u007f l \u0081 } | z z ", + " \u0080 \u007f l \u0082\u0083\u0083~ || z z ", + " \u0080 \u007f \u0081\u0081 z ", + " \u0080 l l \u0083 ", + " \u0080 \u0084\u0084l \u0083\u0083\u0083 z zz z z ", + " \u0080\u0080 \u0085 z \u0086 ", + " \u0080 \u0085\u0085 z \u0086\u0086", + " \u0080 \u0085 \u0086\u0086 ", + " \u0080 \u0085 \u0086\u0086 ", + " \u0080 ", + " \u0085 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!! ############# ", + " !! !# ## ", + " !!!! !! ### %%% ", + " !!!!! # ## %%% %%% ", + " &&& ! ! ! ! !! # # %%% %%% %%%% ", + " && !! !!!!!!!!!! ! !!! ! # ## '') (%%%% %%% %%%%", + " & ! ! ! # ## ') )) %% % %", + " & ! ! !! # ' ' )( (% % %%", + " & & &!! ! ! # '' ) ( % %%%%%%%%% ", + " && !! ! ! + ) % %% % % ", + " ! ! ++ /2222--%% %% .% 9 %% % ", + " ! !!! 11 /2 0-- %% %%%%% %%% %% % 9% % % ", + " && 1 // 00 % . .6 66 9 % % ", + " & && & 133 555 % %. 88. . 6 6 9%% ", + " & & 77 3 <<< %% .=8 8 >>> 66666 99 ", + " 7 3 @@ = 88 >> 9 : ", + " & & 777\u0087\u0087\u0087 <<<<<<< = = LF9 9 :: ", + " & & BB\u0087 DD @ F G 9 :: ", + " & & & B B H HHHHKKK IEE FF F G ", + " J &J& & B \u0087 H H I @ F F GG99GG 9 ", + " J O O\u0087 H H I I T@FFFF G Y ", + " J O O Q \u0087RRHH VVVVVI I T GGY 9999999 ", + " J JJJJ R R V XIT G W ", + " JJ J OOO R R II T G G Y W W ", + " QQ Raaa V VbbXX G WW ", + " ^__ e f a a i cccc G ", + " ^ ff hii V V c G ", + " ^ _ l f h hiiiVVVV bcc q ", + " ^ l_l lll hsh no c q q q ", + " rtt^ ll ssn oo c qq q q ", + " t t ll n u up qqq q w ", + " t l xnx u u q w ", + " t tll x nn ynu qwww ", + " t{ l x xyny u zz z ", + " t t l l y~ ~ || z z ", + " t l \u0081\u0081\u0081\u0081}}}}~ | z z z ", + " \u0080{ {\u007fl l \u0081 } ~ | zz z ", + " \u0080\u0080\u0085\u007f \u007f ll \u0081 \u0082\u0083 | z z ", + " \u0080 \u007f l \u0082 z ", + " \u0080 l l \u0083 \u0083 z z ", + " \u0080 l \u0083 z zz z ", + " \u0080\u0080 \u0085 \u0083 zz z \u0086 ", + " \u0080 \u0085 zzzz \u0086\u0086", + " \u0080 \u0085 \u0086\u0086", + " ", + " \u0080 ", + " \u0085 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!! #### ## ", + " !! !## # ", + " ! ## ## %%%%%% %% ", + " ! !!!! # # %%% %%%% %%% ", + " && &&&! ! !! !!!! !! # ## ' ( %%% %%% %", + " !!!! ! ! # ## ') ( %%% ", + " ! ! # # ') ) ((%% %", + " & ! !!! ## ' ' ) % %%%%%% ", + " && &&& ! !! ! ! ' )) %% ", + " ! !!! ! ) % .% % ", + " ! ! %% % ..% %. 6 %% % ", + " !&&&&&&&&&&& ! 11 00 0 % .% .%%%%%%%%%% 9 9% % ", + " && && 1 1 3 000 .. 9 6 6 9% % ", + " && 771113 3 %% 8888...... 966 6 9% ", + " & & 77 3 << = 88 9 6 99 : ", + " & & 77 < <@ @@= = :: ", + " & & \u0087 @ =LLFF9 : :: ", + " &&&& BBBB HHHHHH @ L F FGG ", + " JJJ& && BBB H H II @ F G GG99999 9 ", + " && O H H I I @@ FF G9 9 ", + " J J O OQ \u0087HHS H K I F GY 9 9 ", + " J J JJ O Q\u0087R RS HV V I I G 9 ", + " J J Q R VI II G G YY ", + " JJ O QRRR V V X G G Y ", + " _ QQ a a V Vbb c ", + " ^^ __ a h S V b b G ", + " ^ ^ _ aaa h V b bc ", + " __ l h hn n bcc q ", + " ^^ l_ l n c q ", + " ^^ ll nu c q qqq ", + " t l l nu u q w ", + " tll l x x uu q ", + " t t l x nnyy u~ z ", + " t t{{l l y ~ | z z ", + " { l yy ~~ || zz z z ", + " \u0080 { l \u0082 ~ || z z ", + " \u0080 { l l \u0081 \u0081\u0082 \u0083 | z ", + " \u0080\u0085 \u0085l l \u0082 \u0083 | z z ", + " \u0080\u0085 l \u0081\u0081 ", + " \u0080 \u0085l \u0083 z z ", + " \u0080 \u0085l \u0083\u0083 z zz z z ", + " \u0080\u0080 z ", + " \u0080 \u0085\u0085 ", + " \u0080 ", + " \u0085 ", + " \u0080\u0085 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! ############# ", + " !! ! # ", + " !!! # ## %%% ", + " # # %%% %%%% ", + " &&& # # %%% %%%%%%%% ", + " & !!!!!!!!!!!!! # ## ) %%% ", + " & ! # )) % %", + " & ! ! # # % %%%", + " && ! ! ! # ) % %%%% ", + " && !! ! ! ) % % ", + " ! ! % %%% .% 9 % ", + " ! ! % %.. %%%% 6 6 %% 9% % ", + " & & !! % ..% .996 66 % % ", + " & !& &&& % .... . 66 96 9 % ", + " &&! & % 9 666 99 ", + " & & < < @@ 9 9 ", + " & \u0087 <<<<<<< @ F9 9 ", + " & \u0087 \u0087 @ FFFG 9 ", + " && && \u0087 HHH @ F F G ", + " J && &&& \u0087 \u0087HH H K II I @ F G GGGGGG ", + " J J OO\u0087 H H KI @ F G 9 ", + " J O O Q \u0087 HH HKVKKI I G 9999999 ", + " J O Q Q S HV V II G ", + " JJJ O Q S V II G G ", + " Q V Vb G ", + " ^__ S V b GG ", + " V V b G ", + " ^ ^_ l nnnV bb ", + " ^ ^_l l n n ", + " r ^^^l ll n ", + " ^ ll n ", + " l l x ", + " l xxnn ", + " l l x x n zz z ", + " { l l x z z ", + " \u0080{ l \u0081\u0081\u0081\u0081 zz ", + " \u0080 { l \u0081 \u0081 z z ", + " \u0080 \u0085\u0085 l \u0081 \u0081 \u0083\u0083 z z ", + " \u0080\u0085 \u0085 \u0081\u0083 ", + " \u0080\u0085 \u0083 \u0083 z z ", + " \u0080\u0085 \u0085l \u0083\u0083 z zzz z ", + " \u0080\u0080 z zz ", + " \u0080 \u0085 z ", + " \u0080\u0085 \u0085 ", + " \u0085 \u0085 ", + " \u0080\u0085\u0085 ", + " \u0085 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-2.0-grid-reference.json b/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-2.0-grid-reference.json new file mode 100644 index 000000000..36900a513 --- /dev/null +++ b/tests/visual_tests/grids/simplify-visvalingam-whyatt-500-1000-2.0-grid-reference.json @@ -0,0 +1,336 @@ +{ + "keys": [ + "", + "24", + "71", + "245", + "207", + "60", + "154", + "189", + "205", + "98", + "72", + "163", + "102", + "206", + "65", + "30", + "110", + "186", + "86", + "170", + "210", + "200", + "202", + "93", + "89", + "84", + "114", + "2", + "190", + "88", + "162", + "107", + "83", + "120", + "50", + "175", + "31", + "116", + "113", + "36", + "118", + "126", + "188", + "18", + "193", + "220", + "152", + "56", + "38", + "212", + "76", + "87", + "40", + "185", + "35", + "223", + "21", + "28", + "204", + "92", + "49", + "67", + "161", + "203", + "166", + "6", + "221", + "17", + "108", + "9", + "122", + "216", + "222", + "33", + "160", + "180", + "178", + "8", + "159" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!!!!######### ####### ", + " !! ### # ", + " !!!!!!! #### # $$$$$$$$ ", + " !!!!! ! !!!! # ## $$$$ $$$$$ $$ ", + " %%%%%%%%! !!! !! ! !!!!! !!! ## ## &$ $$$$ $$ $$$$$ ", + " %%% !!!!!!!!! ! !! ! # #### '((&&$$$$$$$$$ ", + " % % !! ! ! ## ## '(( (& $$$$ $", + " % % % !! !!!! ## ''''((&&&$ $$ $$$$", + " % %% !! !!! ! !! # ''(( $ $$$$$$$$ ", + " % ! !!!!! !! )) ( $$ *$ $$ $ $ ", + " ! !! ))) ++,,,,--.$ $ $$ $$$ $$ $ ", + " ! %%%% !!! ///+++ ,,.-- $$ $$ $$ $$$$$$$ $$$ $$$ 0$ $ $ ", + " % !%% % / + .... .$ $ *11 111 $ $ ", + " %%%% % 2 ///333 44 $$$ $**5555****0* 1 11 0$$ ", + " % % %% ! 2 2 33 666666$$ 77555 8888 11111 00 9 ", + " % % 2 2 3 6 6:::7 5 8 00 9 ", + " % %% ;2 <<< 6 ===> 777 ?0 0 999 ", + " %%%% % ; ;; @@ @ == :> : ? AA 0 99 ", + " B %B %%%%%% ;;;; @ @@@@ CD DD>: ??E ? A0 00 0 ", + " B %%% % ;<< @ @ D D :: ? ? AAAAAA 0 ", + " B B F FG @@H @ D D I ???? A 0 0 ", + " B B B F F GG??@AA:: 2 %% %< B BB < 6 6 %% C % ", + " &&& = = ? ??DEFGG GGGH IJBBB BBBK 6 LMM C ", + " & && NNN N= == O?? FFG PQPJJJ BBRR LLLMS C ", + " & && TTT OO FFUUV V J WXW L SSCCCC ", + " &&&& Y T TT OOZ ZZ V[ W X L CC C ", + " ] && &&&&&& ==TT Z Z ^[ [_P WW W ``` LX LL ", + " ]] & &a bbc Z Z ^[ [Pd W ``X X ee C C ", + " & ]] &faa bb cg ZhZ Z ^[ idd WW XXXLj k LLeC ", + " & ] ] ]] ff&a bb c g h h Zl l[ m X XX j n kkL L ", + " ] ] ]]] oopqrst h h l[ uu m X X jn nk v w ", + " ]xyz { | }cc ~h h l\u007fu u X X jj nk vv w \u0080 ", + " z \u0081 \u0081\u0082 \u0083\u0084 }}}g ~\u0085~\u0086 l \u0087 \u0087\u0088 uu X Xjnn\u0089k vvv \u0080\u0080 ", + " \u008a\u008b\u008b\u0081\u0083 \u0083 \u008c ~ \u0085 \u0086\u008d\u008e\u008e l \u008f \u008f XX n kk v vv \u0080\u0080 ", + " \u0083\u0083 \u0083\u0090\u0091 \u0092 \u0093\u0085\u0086 \u0086 l l \u008f \u0094 \u0095\u0095 X n\u0096 \u0096vvv \u0097 \u0098 \u0098 \u0098\u0098 \u0080\u0080 ", + " \u0099 \u0081 \u0083\u0083\u0083 \u009a \u0092 \u0086 \u008e\u008e\u009b \u009c\u009c\u009d\u009d\u008f \u008f \u0094 \u009e\u009e\u0096 \u009e \u0096\u009e \u009e\u009e ", + " \u009f \u00a0 \u00a0\u00a1 \u0081\u0081\u0083 \u00a2 \u00a2 \u00a3\u00a3 \u009c \u008f \u0094 \u009e\u009e\u009e\u009e \u009e\u0096\u009e\u009e\u009e\u009e\u009e \u0099 ", + " \u00a1\u00a1\u00a1 \u00a2\u00a2 \u00a2 \u00a3\u00a3\u009b \u009c\u00a4\u00a4 \u008f \u009e \u009e\u009e \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u00a5 \u00a5 \u0099 ", + " \u0099 \u00a1 \u00a1\u00a1 \u00a2 \u009b \u00a4 \u009e\u009e \u009e\u009e \u009e\u009e\u009e \u00a5\u00a5\u00a5\u00a5 \u00a5 ", + " \u00a1 \u00a1 \u00a2 \u00a6 \u009b\u009b \u00a4 \u00a4 \u00a7 \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009e\u009e\u00a5\u00a5\u00a5 \u00a8\u00a8\u00a8 ", + " \u00a9 \u00a1 \u00a1\u00a2\u00aa \u00a2 \u00a6 \u009b\u00ab \u00ab\u00a4\u00a4 \u00ac \u00ad \u00ae \u009e\u009e \u00af \u00af \u00af \u00a5 \u00a8\u00a8\u00a8 ", + " \u00b0\u00b1\u00b1 \u00a1 \u00a2 \u00a2 \u00a6 \u00ab \u00ab \u00b2\u00b3 \u00af\u00af \u00af \u00af \u00b4 ", + "\u00b5 \u00a9 \u00a1\u00a1 \u00a2 \u00a2 \u00ab \u00b6\u00b6\u00b7\u00b8\u00b7 \u00b3 \u00b3 \u00af\u00af\u00af \u00af\u00af \u00af \u00b4 \u00b5", + "\u00b5 \u00b9 \u00ba \u00a9 \u00bb \u00bc\u00aa \u00bd \u00be \u00b6\u00b7 \u00b3\u00b3 \u00af \u00af \u00bf\u00bf \u00b4 ", + " \u00a9 \u00a9 \u00bb\u00bb\u00aa\u00bc\u00bc\u00bc \u00a2 \u00bd \u00b6 \u00b7 \u00b3 \u00af \u00af \u00bf\u00bf ", + " \u00c0 \u00c0 \u00bb\u00bb \u00bc \u00a2 \u00be\u00c1 \u00b7 \u00b3\u00b3 \u00af \u00af ", + " \u00c2 \u00bc\u00bc \u00a2 \u00bd\u00bd \u00c1\u00b7 \u00af ", + " \u00bb \u00c3 \u00a2 \u00c4\u00c1 ", + " \u00bb \u00bb \u00c3 \u00c3 \u00c1\u00c1\u00c1\u00c1 \u00af\u00af\u00af \u00af\u00af \u00af \u00c5 ", + " \u00bb\u00bb \u00c6 \u00af\u00af \u00c5 ", + " \u00bb \u00c2 \u00af \u00c5\u00c5", + " \u00bb \u00c2 \u00af\u00af \u00c5\u00c5 ", + " \u00bb\u00bb\u00bb\u00c2 \u00c5 \u00c5 ", + " \u00bb\u00bb \u00c2 \u00c7 \u00c5 ", + " \u00bb\u00bb\u00c2 \u00c8\u00c8 \u00c5 ", + " \u00bb\u00bb\u00c2 \u00c9 \u00ca ", + " \u00bb \u00c9 ", + " \u00c9 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! !!!!!!!! ############ ", + " !!!!!!!!!!!!!## #### $$$$$$$$$$ %%%%%% % %%%%% ", + " !!!!!!!!!!!!!!!! #### ### $$$$$ %% % %%%%%%% % ", + " !!!!! !!!!!!!!!!! ## #### $ %%% % %%%%% %%%%%%%% %%%% ", + " %% &&&& ! !!! !!!!!!!!! !!!!! ### #### $$ ''' %%% % %%%% %%%%% %%%%%%% ", + " && !!! !!!!!!!!!!!!!!!!!!!!! ## ### '')) %%%%%%%%%% %% %% %%%%% ", + " &&&& !!!!!!! !!! ## ## ((((( '') )) %%%%% %%", + " && & !! !!!!!!! ##### + ''') )* % %% %%", + " & &&&&&&&&&&& ! !!! ! ! ### ,, ''' ))\u00cb*\u00cc% %%% %%%% ", + " && &&&& &&& !! !! ! ! ,,, \u00cd\u00cd)))//% %% % % ", + " &&& !&! ! !!! 0,,, 11..5%%/ %% <%% %%% % %%% %% % ", + "&& !!! ! !!! 0 ,,,1. \u00ce5 2\u00cf\u00cf%% %%%%% %% %%66 % % %% % ", + " && &&! !!!!!!! 4 8..\u00ce\u00d0222 % % <6 6 %% %% % ", + " & &&&!! 4 ? 9@\u00d1A 222% %< @AA:\u00d3 2 %% %< B : ? @ABBC6C6$$ $00DD00 00 === == $$ E$$ ", + " ' ''' >> >>>FFFFGBHIIIIIJ$$KKDDKDDDD00L 88= MM$ EE ", + " '' ''' NNN N> >>>FOFFFHII IP KK DDDQQ 88MMR E ", + " '' ''' NS>TTTOOUU HIIIIIIII PK KKKDVWWW 88RREEEE ", + " ''' '' X SS S OYY YZ []] ^ WWW__ 88 RREE E ", + " `` '' ''''''' >SSS O Y Y ZabbbbcP WWW W d88 8_ 88 EE E ", + " ' ``` '' '' >>eee Y Y fb bbPg W W ddd___8 888 E EE ", + " ' ``` ` '''h ee ii YYj Y bb ggg WWWW ___8k 88lEE E E ", + " ''' ``` ` `mmm'nn eee i oT ppppYYqqqqqb bgr ___ _kk 8sss8t8 u ", + " ``` `````` vw'xyz{{ i op p q qbb | r _ __ k}}}s8 uu ~ \u007f ", + " ``\u0080`\u0080\u0080 { \u0081 \u0082\u0082ii pp p q q\u0083||||r _ __ kk} }s uu ~ \u0084\u0084 ", + " \u0085\u0086\u0086\u0087 \u0087\u0088 \u0089\u008a \u0082\u0082\u0082o \u008b\u008c\u008b\u008d\u008d\u008d\u008d q q\u008e|| || ___ _k}}ss uuuu \u008f \u0084 ", + " \u0090\u0090\u0090\u0087\u0091\u0091\u0088\u0091\u0091\u0091 \u0092\u0092oo\u008b\u008b\u008c\u008d \u008d\u0093j\u0094q q \u0095\u0095 \u0095 ____ _ k}ssss uuu \u0084\u0084 ", + " \u0096\u0090\u0090\u0090 \u0091\u0087 \u0091\u0097 \u0092\u0098 \u0099\u008c\u008d \u008d \u0094 q q\u008e \u0095\u0095 \u009a_\u009b\u009b _ } \u009cuuuu \u009d \u009e\u009e\u009e\u009e \u009e\u009e \u0084\u0084\u0084 ", + " \u009f \u0087 \u0091\u0091\u0091\u00a0\u00a0\u00a1 \u0098\u0098\u00a2\u0099\u008c\u008d\u008d\u0093 \u0094\u0094\u0094\u0094qq\u00a3q\u00a4\u0095 \u0095 \u009a _\u00a5}} \u00a5\u009c\u00a6\u00a5\u00a5 \u00a5\u00a5 \u009e \u009f ", + " \u009f \u00a7 \u00a7 \u0087\u0091\u0091 \u0097\u0097 \u00a8 \u00a9\u00aa\u00aa\u0094 \u00a3\u00a3 \u0095\u0095 \u009a\u009a \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u009f ", + " \u009f \u00a7 \u00a7\u00ab\u00ab\u0087 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00ac\u00aa\u00aa\u00aa\u00ad \u00a3\u00a3\u00a4 \u0095 \u009a \u00a5\u00a5\u00a5\u00a5\u00a5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00ae \u00ae \u009f ", + " \u009f \u00ab\u00ab \u00a8\u00ab \u00a8\u00a8 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00aa\u00aa\u00ad \u00af \u00af\u00af \u00b0 \u00a5\u00a5\u00a5\u00a5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a5\u00ae\u00ae \u00ae\u00ae \u00b1 ", + " \u00b2 \u00ab \u00ab \u00a8 \u00b3\u00ad\u00ad\u00ad\u00ad \u00b4 \u00af \u00b0 \u00b5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00ae\u00ae\u00ae \u00ae\u00b1\u00b1 \u00b6", + " \u009f \u00b2\u00b2\u00b2 \u00ab \u00ab\u00ab\u00a8\u00b7 \u00a8 \u00b3 \u00ad\u00ad \u00b4\u00b4 \u00af \u00b0 \u00b8 \u00b9 \u00ba \u00a5\u00a5\u00a5\u00a5\u00bb\u00bc\u00bc \u00bc\u00a5\u00ae\u00ae\u00ae\u00ae\u00ae\u00b1\u00b1\u00b1\u00b1 ", + " \u00bd \u00be \u00ab \u00ab \u00a8\u00a8 \u00a8 \u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4 \u00bf \u00c0\u00c1 \u00b9 \u00bc\u00bc\u00bc\u00bc\u00bc \u00bc \u00b1\u00b1\u00c2 \u00c3", + "\u00c3 \u00be \u00b2\u00b2 \u00ab\u00ab \u00a8\u00a8 \u00a8 \u00b3\u00b3\u00b3 \u00b4 \u00c4\u00c4\u00bf \u00bf \u00c1\u00c1\u00c1 \u00bc\u00bc\u00bc \u00bc\u00bc\u00bc \u00bc \u00c2\u00c2 \u00c3", + "\u00c3 \u00c5 \u00c6\u00c6 \u00b2\u00b2 \u00ab \u00c7\u00a8 \u00a8 \u00c8 \u00c8\u00c8\u00c4\u00c4 \u00c4\u00c9 \u00c1\u00c1 \u00bc \u00bc\u00bc \u00ca \u00c2 \u00c3\u00c3", + "\u00c3\u00c5\u00c5 \u00c6 \u00b2 \u00b2 \u00cb\u00cb\u00b7\u00c7\u00c7\u00c7 \u00a8 \u00a8 \u00c8 \u00cc \u00cc\u00c4\u00bf\u00bf \u00c1\u00c1 \u00bc\u00bc \u00bc \u00ca\u00ca ", + " \u00b2 \u00cd\u00cd\u00cd \u00cb\u00cb \u00c7\u00c7\u00c7\u00ce \u00a8\u00a8 \u00c8 \u00c8 \u00cc\u00cc\u00cf\u00bf \u00c1\u00c1 \u00bc \u00bc\u00bc \u00ca ", + " \u00cb\u00cb \u00cb\u00cb \u00c7\u00c7 \u00a8 \u00c8\u00c8\u00cc \u00d0\u00d0 \u00bc \u00bc ", + " \u00ce \u00d1\u00ce \u00a8 \u00c8 \u00d2\u00cf \u00bc \u00bc ", + " \u00cb \u00cb\u00cb \u00d1\u00d1\u00d1 \u00cf \u00cf \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bc ", + " \u00cb\u00cb \u00ce \u00bc\u00bc\u00bc \u00bc \u00d3 ", + " \u00cb\u00cb \u00ce\u00ce\u00ce \u00bc\u00bc\u00bc \u00d3\u00d3", + " \u00cb\u00cb\u00ce \u00ce\u00ce \u00bc\u00bc\u00bc \u00d3\u00d3 ", + " \u00d3 \u00cb\u00cb\u00cb \u00ce \u00bc \u00d3\u00d3 ", + " \u00cb\u00cb \u00ce\u00ce \u00d4 ", + " \u00cb\u00cb\u00ce\u00ce \u00d5 \u00d4\u00d4 \u00d3\u00d3\u00d3 ", + " \u00cb\u00cb\u00cb\u00cb \u00d5\u00d5 \u00d6 \u00d7 \u00bc ", + " \u00cb\u00cb\u00cb\u00cb \u00d6\u00d6 \u00d6 \u00bc ", + " \u00d6\u00d6\u00d6 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!!!!!!#################### $$$$$$ $ $ ", + " !!!!!!!!!!!!!!!#### ##### %%%%%%%%%%% $$$$$ $ $$$$$$$$ ", + " !!!!!!!!!!!!!!!!!!###### #### %%%%%% $$$$$$ $$$$$$$$$$$$$$ $$$$$ ", + " !!!!!!!!!!!!!!!!!!!! ### ##### % & $$$$ $$$$$$$$ $$$$$$$$$$$$$$$ ", + " $$ ''''''''!!!!!!!!!!! !!!!!!!!!!!!!!! ### #### %% &&&&&$$ $$$$$$$$$$$$ $$$$$$$$$$$$ $$ ", + " '''' !! !!!!!!!!!!!!!!!!!!!!!#### #### ( &&&)) $$$$$$$$$$$ $$$$$ $$ ", + " ''''' ' !!!!!!!!!!!! ####### (((((( &&)))))*$$$$$ $$$", + " ''' ''' ' !! !!!!!!!! ###### + &&&&) ** $$ $$$$ $$$", + " ' ''''''' '''' ! !! !!!! ### ,,, &&)))))*$$ $$$$$$$$ ", + " '' ''''' '''! !!!!! !!!! ,,,, -.))/$/$$ 0$ $$ $ $$ ", + " '''''' ''!! !!! !!!! 1,,,,22-33$33/$$ $$ $$$$ $88 $$$ $$ $ ''", + " !!!! '''' ! !!!!!! 1,,4,2- -333666 $6 $$$$$$ $$$$$$$$$$$$$$ $$8 $$ $ ", + " '' ''! ''!!!9! ::: ;;<<666666$$ $ 80==8 == $$$ $$ $$ ", + " '' !''''!!!! > : ? @ABBC6C6$$ $000DDD 00 === == 8$$ E$$ ", + " ' ''' >> >>>FF FG\u00d8HIIIIIJ$$KKDDK00DD00L 88= MM$ EE ", + " '' ''' NNN N>>>>>FOFFFHII IP KK DDDQQ 88MMR E ", + " '' ''' N>> TTTOUU HIIIIIIII PKPKKKDVWWW 88RREEEE ", + " ''' '' X SSSS OYY YZ []f^ ^ PVWWW__ 8 RREE E ", + " `` '' ''''''' >SSS O Y Z ZbbbbbcP WWW _W d8 _ 8 EE E ", + " ' ``` ''' '' >>Sei Y Y Zb bbbPgPW W ddd___ 888 E EE ", + " ' ``` ` '''h eei i Yp Y bb ggg WWW_ ___ 8 88lEE E E ", + " ''' ``` ` `mmm'nn ee ioT TppjYYqqqqqb bgr ___ _kk \u00d9sss8t8 u ", + " ``` `````` vw'xyz{{ op p jq qbb bb _ __ k}}}ss uu ~ \u007f ", + " ``\u0085`\u0080\u0080 { \u0081 \u0082iiii po p q q\u0083||||| _ __ kk} ss uu ~ \u0084\u0084 ", + " \u0085\u0086\u0086\u0087 \u0087\u0088 \u0089\u008a \u0082\u0082\u0082\u0082 \u008b\u008b\u008b\u008d\u008d\u008d\u008d jq q\u008e| || ___ _k}}ss uuuu \u008f \u0084 ", + " \u0090\u0090\u0090\u0087\u0091\u0091\u0088\u0091\u0091\u0091 \u00da\u0092\u0092\u008b\u008b\u008b\u008c\u008d \u008djj\u0094\u0094 q \u0095\u0095 \u0095 ____ _ k}sss uuu \u0084\u0084 ", + " \u0096\u0090\u0090\u0090\u0087\u0091 \u0091\u0097 \u0092\u0098 \u00a2\u0099\u008c\u008d \u008d \u0094 qqq\u008eq \u008e\u008e\u0095 \u009a_\u009b\u009b _ } \u009cuuuu \u009d \u009e\u009e\u009e\u009e \u009e\u009e \u0084\u0084\u0084 ", + " \u009f \u0087 \u0087\u0091\u0091\u0091\u00a0\u00a0\u00a1\u00a8 \u0098\u0098\u00a2\u0099\u008c\u008d\u008d\u0093\u0093\u0094 \u0094\u0094\u0094 \u00a3q\u00a4\u00a4\u0095 \u009a _\u00a5}} \u00a5\u009c\u00a6\u00a5\u00a5 \u00a5\u00a5 \u009e \u009f ", + " \u009f \u00a7 \u00a7 \u0087\u0091\u0091 \u0097 \u00a8 \u00a9\u00aa\u00aa\u0094\u00ad \u00ad\u00a3\u00a3\u00a4 \u0095\u0095 \u009a\u009a \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u009f ", + " \u009f \u00a7 \u00ab\u00a7\u00ab\u00ab\u0087 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00ac\u00aa\u00aa\u00aa\u00ad \u00a3\u00af\u00a4 \u0095 \u009a \u00a5\u00a5\u00a5\u00a5\u00a5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00ae \u00ae \u009f ", + " \u009f \u00ab \u00ab \u00a8\u00a8 \u00a8\u00a8 \u00a8 \u00db\u00ad\u00ad \u00af\u00af\u00af\u00af \u00b0 \u00a5\u00a5\u00a5\u00a5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a5\u00ae\u00ae \u00ae\u00ae \u00b1 ", + " \u00b2 \u00ab \u00ab \u00a8\u00a8 \u00b3\u00ad\u00ad\u00ad\u00b3 \u00b4\u00af\u00af\u00af \u00b0 \u00b5 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00ae\u00ae\u00ae \u00ae\u00b1\u00b1 \u00b6", + " \u009f \u00b2\u00b2\u00b2 \u00ab \u00ab\u00a8\u00b7\u00b7 \u00a8 \u00b3 \u00ad\u00ad \u00b4\u00b4\u00af\u00af\u00bf\u00b0 \u00b8 \u00b9 \u00ba \u00a5\u00a5\u00a5\u00a5\u00bb\u00bc\u00bc \u00bc\u00a5\u00ae\u00ae\u00ae\u00ae\u00ae\u00b1\u00b1\u00b1\u00b1 ", + " \u00bd \u00be \u00ab \u00b7\u00a8\u00a8 \u00a8 \u00b3 \u00b4\u00b4\u00b4\u00b4\u00c9 \u00bf \u00c0\u00c1 \u00b9 \u00bc\u00bc\u00bc\u00bc\u00bc \u00bc \u00b1\u00b1\u00c2 \u00c3", + "\u00c3 \u00be \u00b2\u00b2 \u00ab\u00ab\u00b7 \u00a8\u00b7 \u00a8 \u00b3\u00b3 \u00b3\u00b4\u00c4\u00c4\u00bf\u00bf \u00c1\u00c1\u00c1 \u00bc\u00bc\u00bc \u00bc\u00bc\u00bc \u00bc \u00c2\u00c2 \u00c3", + "\u00c3 \u00c5 \u00c6\u00c6 \u00b2\u00b2 \u00cb\u00b7 \u00c7\u00a8 \u00a8 \u00c8 \u00c8\u00c8\u00c4 \u00c4\u00c4\u00c9 \u00c1\u00c1 \u00bc\u00bc \u00bc\u00bc \u00ca \u00c2 \u00c3\u00c3", + "\u00c3\u00c5\u00c5 \u00c6 \u00b2 \u00b2 \u00cb \u00b7\u00c7\u00c7\u00a8 \u00a8 \u00a8 \u00c8 \u00c8\u00c8 \u00c4\u00c4 \u00bf \u00c1 \u00bc\u00bc \u00bc \u00ca\u00ca ", + " \u00b2 \u00cd\u00cd\u00cd \u00cb\u00ce \u00ce\u00c7\u00c7\u00c7 \u00a8\u00a8 \u00c8\u00c8\u00cc\u00cc\u00cc\u00cf\u00bf \u00c1 \u00bc \u00bc\u00bc \u00ca ", + " \u00cb\u00cb \u00cb\u00ce \u00c7\u00a8 \u00a8 \u00c8\u00c8\u00cc \u00d0\u00d0 \u00bc \u00bc\u00bc ", + " \u00cb\u00ce \u00d1\u00a8 \u00a8 \u00d2\u00cf \u00bc \u00bc ", + " \u00cb \u00cb\u00cb \u00d1\u00d1\u00a8 \u00cf\u00cf\u00cf \u00bc \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bc ", + " \u00cb\u00cb \u00d1 \u00bc\u00bc\u00bc \u00bc \u00d3 ", + " \u00cb\u00cb \u00ce\u00ce\u00ce \u00bc\u00bc \u00d3\u00d3", + " \u00cb\u00cb\u00ce \u00ce\u00ce \u00bc\u00bc\u00bc \u00d3\u00d3 ", + " \u00d3 \u00cb\u00cb\u00ce \u00ce \u00bc \u00d3\u00d3 ", + " \u00cb\u00cb \u00ce \u00d4 ", + " \u00cb\u00cb\u00ce \u00d5 \u00d4\u00d4 \u00d3\u00d3\u00d3 ", + " \u00cb\u00cb\u00cb\u00cb \u00d5\u00d5 \u00d6 \u00d7 \u00bc ", + " \u00cb\u00cb\u00cb\u00cb \u00d6\u00d6 \u00d6 \u00bc ", + " \u00d6\u00d6\u00d6 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-font-features-1100-1100-1.0-grid-reference.json b/tests/visual_tests/grids/text-font-features-1100-1100-1.0-grid-reference.json new file mode 100644 index 000000000..a746fab20 --- /dev/null +++ b/tests/visual_tests/grids/text-font-features-1100-1100-1.0-grid-reference.json @@ -0,0 +1,289 @@ +{ + "keys": [ + "", + "1", + "2", + "3", + "4", + "5", + "6" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ! ", + " ! ! ! # ## ##### ######## ###### $ % % % % % % && &&& ' ' ' ' ' ' ", + " !! ! ! ! ! ! !!! !! !!!!! # # # # # # # ## # # $$ $$ %%% %%% % %% && & & & && && &&&& && & ' ' ' ' ' ", + " !! !!!!!!!!!! !!!!!!!!!! ! ! ! ! ! # ### ## ## # # # ## # $$ $ %% % %% % %% %% & && & & && && & & & & && & ' ' ''' ' ", + " ! !!!!!!!! !!! ! !!!!!!!!!! ! ! ! ! !! # # # # # ## # # $ $$ % %% & && & & & & & & & && & ' '' ' ' ' ", + " ! !!! !! ! ## # ##### ## #### #### ## $$ $ $ & &&&&& &&&& && & & & '''' ' ''' '' ", + " & & ' ' ", + " ", + " ", + " ", + " ", + " ", + " !!!! !!! #### # #### # $$ $$ % %% && && &&& &&& && &&& &&& &&&& &&& &&& '' '' ''' '''' ''' '' ", + " !! ! ! ! !!! !! ! !! ! !! ! !!! !!!! ! !!!!!!! ## ### ## ##### ######### $ $$$ $$$ %% % %%% %% %%%%% %%% % %% &&&& & & && & &&& & && & && & & && '' '' ' ' ' ' '' ''' ", + " ! !!!!!! !!! ! !!!!!! !!! !!!! !! ! !! ! ! ## # # #### # ## #### # $ $$ $$ % % % % % %%% %% % %%% & & & && &&& &&&& &&& &&&& && &&& &&&& ''''' '' '''' ' '''''' ", + " !! !!!!! ! ! !! !!!!!! !! ! !!! !! ! ! !! ! ## # # #### # ## # ### # $ $$ $$ % % % % % %% %% % % % & & & && & &&&& &&&& & & && & &&& '' '' '' ' ' '''''' ", + " !! ! ! !!! !! ## # # #### # ## # ### ## $$$ $$$ $$$ %%% % %%% %%% % % %% %%%%% %%%% &&&& &&& &&&& &&& && &&& &&& && &&&& &&& '' '' ''' '''' '''' '' ", + " %%% % %%% %%%% %% %%%%% % ", + " ", + " ", + " ", + " !! ! !!! ####### #### # $$$ $ % % &&& &&& &&& &&& && &&&& &&& &&&& &&& && ' ' ''' ''' ''' '' ", + " !!! !! ! !!! ! !! ! !! ! !! ! !!! !! ! !! !!!! ! !!!!! !!!!!!!!! ## ### ## ######## ###### $$ $$$$$$$ %%% % %%% %% % %%% %%% % %%% && & && & & && &&& & & && & & & && '' '' ' '' '' '' ''' ", + " ! !!!!!! !!!! !!!!!!!!! !!! !!! ! ! !!!! !!!!!! !! !!!! !! !!! ## # #### # ## # ## ## ## $ $$ $$ % % % % %% %%% %% % %%% & & & && &&& &&&& &&& &&&& && && &&&& ''''' '' '''' ' '''''' ", + " !! !!!!! ! !! !!!! !!!! !! !!! !! !!!! !! ! !! ! !! ! !! !!!! ## # # #### # # # ## ## $ $$ $ % % %% % % %% %% % % % & && & & & &&&& & && & & & & &&& '' '' '' '' ' '''''' ", + " ! ! ! !!! !! # ## # #### # # # ### ## $$$$ $$$ $$ %%% % %%%% %%%%%% % %% %%% % %%%%% &&& &&& &&&&&&&& & &&&& &&&& && &&&& &&& ' ' '''' '''' '''' ' ", + " %%%%% %%%% %%%%% %% %%% % %% ", + " ", + " ", + " ", + " !! !! ##### # # $$ $ % %% && && &&& && && &&& && &&& && && ' ' ''' ''' ''' ' ", + " !! ! ! !!! ! ! ! ! !! ! ! !!! !!!!! !! # ### ## ############# $ $$ $$ %% % % % % % %% % %% & & & && & & & & && & ' ' ' ' ' ' '' ", + " ! !! !!!!!! ! ! !! !!! ! ! ! ! ! ! # # # # # ## # $ $ $ % % % % %%% % % % & & & && & & &&& &&& & && & & '''' ' ''' ' ' '' ", + " !! ! !! !! !! ! !! !! ! ! ! ! ! !!! # # # # ## ## $ $$$ % % % % % % % % & & & &&&&& & & & & & & ' ' ' '' ''''' ", + " ! ! !!!!! # # ### # ## ### ## $$$ $$ $$ % % % % % % % % &&& &&&&&&& &&& & &&& &&& & &&& && ' ' ''' ''' ''' ' ", + " %%%% %%% %%% % %% %%%% % ", + " ", + " ", + " ", + " !!! !! ### # ### # $$ $ % % && && && &&& && && && &&& &&& && ' '''' ''' '' ' ", + " ! !!! !! ! ! ! ! !! ! ! ! ! ! ! ! !!! !!!! !! # ## ## #### #### ## $ $$$$$ % %% % %% % % %% % & & & & && & & & & && & ' ' ' ' ' '' ", + " !!!!!!!!! !!! !! ! ! !!!!! ! ! ! ! ! # # ## # # # # $ $ $ % % % % % %% % % % & & & & && & & && &&& && & & '''' ' ''' ' ' '' ", + " !! !!!! !! !!!! !! ! ! ! ! !!!!!! ! ! ! !!! # # ## # # # # $ $$ % % % % % % % % & & & & & &&& && & & & & & ' ' ' ' ' ''''' ", + " ! ! ! !!!!! # # # ## # # ## ## $$$$$$ $ % % %% % % % % &&& &&&&&& &&& & && && & &&& && ' '''' ''' ''' ' ", + " %%%% %%% %%%% %% %%%% ", + " ", + " ", + " ", + " !!!! !!! ##### ### # $$ $$ % % && &&& &&& &&& & &&& &&&&&&& &&& &&& '' ' ''' ''' ''' ' ", + " !! ! ! !!!! !! ! !!!! !! ! ! !! !! ! ! ! !! !! ! !!!!!!! !!!!! # ### ## #### ## ## ## $ $$ $$$ %% % %%% %% %%%% %%% % %% & && && & && && && & & && & & & & '' ' ' ' '' '' '' ", + " !!!! !!!!!! ! !!!!!! ! ! !!!!!!!!!!!! !!!!!! !!!!!! ! ! # ##### ## ## # # ## # $ $ $$ % % % % % %% %% % %% & && && & && &&& &&&&&&& & &&& &&& '''' ' ''' ' ''' ' ", + " !! ! !!! !! !! !!!!!! ! ! !!!!!!!!! ! ! !!!!! ! !!!!!! !! ! # # ###### ## # # ## # $ $$$$ % % % % % %% %% % % % & && && & &&&&&& &&& & & & & && '' ' '' '''' '''''' ", + " !!!!!! !!! !! # # ###### ## # # ### ## $$$ $$ $$ %%% % %%% %%% % % % %%%%% %%%% &&& &&&&&&&&&&& & &&&& &&& && &&& &&& '' ' ''' ''' ''' ' ", + " %%%% %%% %%% % %% %%%%% % ", + " ", + " ", + " ", + " !!! !! #### # #### # $$ $ % %% && && && &&& && &&& && &&& &&& &&& ' ''''' ''' ''' '' ", + " !! ! !! !!!! !! ! !!!! !! ! ! !! !! ! ! ! !! !! ! !! ! !!!!!! ! !!!! !!!!!!!! ## ### ## #### # ####### $ $$$$$$ %% %%%% %%% %%%%% %% % %% &&&& & & && && &&& & & & & & & & '' ' ' ''' ''' '' '' ", + " !!!! !!!!!! ! !!!!!! ! !!! !!!!!!!!!!! !!!!!!! !! !!!!! !! ! !! ! ! # ######## # # #### ### $ $$ $$ % % % % %% %% % %%% & && && & && &&& &&&&&&& & &&& &&& '''' ' ''' ' ''''' ", + " !! !! ! ! !! !! ! !! !!!!!! ! !!!!!!!!!! !! !!!!! ! !!! !!!!!! ! ! ! !! ! # # ###### ## # # ##### $ $$$$ % % % % % %% %% % % % & & & & &&&&&& &&&& & && && & & ' ' '' ' ' '''''' ", + " ! !!!! !!! !! # # # ### # # # ### ## $$$$$$$ $$ %%%% %%% %%% % %%% %%% % %%%% &&& &&& &&& &&& & &&& &&& & &&&& && ' ' ''' ''' '''' ' ", + " %%%%% %%%% %%%% %% %%%% % ", + " ", + " ", + " ", + " !!! !! ##### ## $$ $ % && && && && & &&& &&&&&&&&&& && ' '' ''' ''' '' ", + " !! !! !!!!! ! !!! !!! ! !!! ! ! ! ! !! ! ! ! !!! !! !!!! # ### ## ### ## #### $ $$$$$ %% % % %% % % % %% & & & & & && & & & & & & ' ' '' ' ' ' ", + " !!!!!!!!!! !!!!!! ! ! !!! !!!!! ! ! ! ! !! ! ! ! ! ! # # ## # # # # # $ $ % % % % % %% % % % % & & & & && & & &&&&&& & && &&& '''' ' '' ' ' '' ", + " ! !!!!!! !! ! !! !! ! ! ! ! ! !!! ! ! ! ! ! ! ! ! !!! # ## # # # # $$ % % % % % % % % & & & & & &&& && & & & ' ' ' ' ' ''''' ", + " ! ! !!!!! # # ### # ## ## ## $$$ $$ $$ % % % % % % % &&& && &&& &&& & &&& &&& & &&&&&& ' ''' ''' ''' ' ", + " %%% %%% %% % %% %%%% % ", + " ", + " ", + " ", + " ##### # $$ $ % % && & &&& && & &&& && &&& && && ' ' ''' '' ''' ' ", + " ! ! ! ! ! ! ! ! !!!!! !!! ! !!! !!!!! !! # ### ## ### ####### $ $$ $$ % % % % % % %% & & & & & & & & ' ' ' ' ' ' ", + " ! ! ! !!! ! ! ! ! ! !! ! ! # # # # $ $ $ % % % % % % % & & && & & & & & & && & '''' ' '' ' ' ", + " !! ! ! ! !! !!!! ! ! !!! ! !! !! !! ! ! ! # # # ## $ $ % % % % % % % % & & &&&&& & & & & & ' ' ' ' ''''' ", + " ! ! # # # # # $$$ $$ $ % % % % % % & & & & & & & & & ' ' ' ' ' ' ", + " %%%% %%% %% % %% %%% % ", + " ", + " ", + " ", + " !!! ! # ## # $$ $ % % && && &&& &&& && &&& &&&&&&& && && ' ' ''' ''' ''' '' ", + " !! ! !! ! !! !! ! ! !!! !!! !!! !!! ##### # # $ $$ $$$$ %% % % %% %%% % %%% %% % %% & & & & & && & & & &&&&& & ' ' ' ' ' ' '' ", + " !!!! !!!!!!! ! !!!!! !!!!!!! !!!!! !! ! ! !! ! ! # ### ### ### ## ### ## #### $ $ $ % % % %% % %% % % %%% &&& & && && &&& &&& &&& & && &&&& ''' '' ''' ' ' ''' ", + " !!!! !!! !!! ! !!!!!! !!!!!! ! !!!!!!!! ! ! !! !! ! # # # ### # # # ## # $ $$ $ % % %% %% % % % % %%% & & & && & &&& & & & && & & &&& ' ' '' ' ' ' ''' ", + " ! ! ! !! !!! !! # # # # # # # # ## ## $$$ $$$ $$$ %%% % %%%% %%%% % % % %%% % %%% &&& &&& &&& &&& && &&& &&& & &&&&&& ' ' ''' ''' ''' '' ", + " # # # ## # ### # ## ## %%% % %%%% %%%%% %% %%% % %% ", + " ", + " ", + " ", + " !!! ! # ## ## $$ $ % % && && &&& &&& & &&& && &&& &&& && '' '''' '' '' ' ", + " !! ! ! !! !! !! ! ! !! ! ! !!!! !!! !! !!! ###### # # $ $$$ $$$ %% % %%% %% % %%% %%% % %% &&& && & & && & & && & &&&&& ' '' ' ' ' ' '' ", + " !!!! !!!!!! ! !!!!! !!!!!!! ! !!! !! !!! ! ! !!!!! !!! ! !! ! # ### ### ### ## ### ####### $ $ $ % % %% % % %% % % % % &&& & && & &&& &&& &&& & && &&&& ''' '' ''' ' ' ''' ", + " ! !! !!!!!! !! ! !!!! !!!!!!!! !! !!!!!! !!!! !!! ! ! !! ! ! !! !! ! # # # ### # # # ## # $ $$ $ % % %% %% % % % % %%%% & & & && &&&&& &&& & && & & && ' ' '' ' ' ''''' ", + " ! ! ! ! ! !!! !!! # # # # # ## # # # # # $$$$$$$ $$ %%%% % %%% %%% % %% %%% % %%%% &&& &&&&&&&&&&& & &&& && & &&& &&& ' ' ''''''' ''' ' ", + " # # # # ## #### # ## # %%% % %%% %%% % %% %%% % % ", + " ", + " ", + " ", + " !!! ! ##### ## # # $$ $ % % && && &&& &&& && && && &&&& && && ' ' ''' ''' ''' ' ", + " ! ! !! ! ! !! !!! ! !! ! !! !!! !! !! !!! # ### ## ### ## ### ## ### $ $$ $$$ %% % % % % % % %% % % & & & & & && & & & & && ' ' ' ' ' ' ' ", + " !!! !! !! ! !! !!! ! ! ! ! ! ! !! ! ! ! ! ! # # # # # # # # # # $ $ $ % % % % % %% % % % &&& & & & & & &&& &&& & && & && ''' ' ''' ' ' ' ", + " ! !! !! ! ! ! !! !!! ! !! ! ! ! ! !! ! ! ! !! ! # # # # # # # # # $ $$ $ % % % % % % % % % & & & & & &&& & & & & & & ' ' ' ' ' ' ''' ", + " ! ! ! !!! !! # # # ### # ### # ## ## $$$ $$ $$ % % % % % % % % &&& &&& &&& &&& & &&& &&& & &&& && ' ' ''' ''' ''' ", + " %%% %%%% %% % %% %%% % ", + " ", + " ", + " ", + " !!! ! #### # ## # # $$ $ % % && && &&& &&& & &&& && &&& &&& && ' '''' '' '' ' ", + " !! ! ! !! !! ! ! !! ! ! ! !!! ! ! ! !!!! !!! !! !!! # ### ## ### ## ### ### ### $ $$$ $$$ %% % % %% % % % %% & & & & && & & & & && & ' ' ' ' ' ' '' ", + " !!! !! !! ! !!!!!! !!! ! ! ! !! !!!!!! ! ! ! ! # # # # # # # # # # $ $ $ % % %% % % %% % % % % &&& & & & & & &&& &&& & && & && ''' ' ''' ' ' ' ' ", + " ! !! !! !! !! ! ! !!!!! ! ! ! !!!!!!!!!! ! ! !! # # # # # # # # # $ $ $ % % %% % % % % % & & & & &&&&& && & & & && ' ' ' ' ' ''''' ", + " ! ! ! !!! !! # # # ### #### # ### ## $$ $$$ $$ % % %% % % % % % % &&& &&& &&&&&&& & &&& && & &&& &&& ' ' ''' ''' '' ' ", + " %% % %%% %%% % %% %%% % % ", + " ", + " ", + " ", + " !!! !! #### # ### # $$ $ % % && && &&& &&& & &&& &&&&&&& &&& && ' '''' ''' ''' '' ", + " ! ! !! !!! ! !! ! ! !! !! !! ! !!!! !! !!!!! # ### ## #### ## ## ## $ $$$$$$ %% %% % % % %% % % & & & & & && & & & & && & ' ' ' '' ' '' ", + " ! !! !!!!!! ! !!!!!! ! ! !!! !!!!! ! ! ! ! # # ## # # # # # # $ $ $ % % % % %%% % %% & & & & && & & &&& &&& & && & && '''' ' ''' ' ' '' ", + " !! ! ! ! !! !! ! !! !! ! !!!! ! ! ! !!! # # # # # ## ## $ $ $ % % % % % % % % % & & & & &&&&& & & & & & & & ' ' ' '' ''''' ", + " ! ! ! !! !! # # # ### # # # ### # $$$ $$$ $$ % % % % % % % % &&& &&& &&& &&& & &&&& &&& & &&& &&& ' ' ''' ''' '''' ' ", + " %%% % %%%% %%% %% %%% % ", + " ", + " ", + " ", + " !!! !!! ####### ### # $$ $ % % % %% %% % && && &&& &&& & &&& &&& &&&& &&& &&& ''''''''' '''' '''' ' ", + " !!! ! ! !! !! !! ! ! !! ! !! ! ## #### # ## # ## # $ $$$$$$ %% % % % %% %% %%% % %% && & & & && & && & && & && & & && ' ' ' '' ' ''' ' '' ", + " ! !!!! ! !!!! !!!! ! !! !!! !!!! !! ! !!!! ! ## #### # # ## # #### # $ $$ $ % % % % % %% %% % % % & & & && && & & & & &&&& & &&& & && '''' '' ''' '' ''' ' ", + " !! !!!!!! !!! !! ! !!!! !!! ! !!!! !! ! ! !!! ! ## ######## ## # # ### # $ $$ $ % % % % % %% %% % % % & & & & & &&&&&& &&&& & & && & &&& ' ' ' ' '''' '''''' ", + " ! !!!! !! ! ! !! ### #### # # #### ## # # # # $$$ $$$ $$ % % %%%% % % % %% %% % % &&&& &&& &&&& & & &&& & & &&& & &&&& & & '''''''''' ' '' '''' ''' ", + " %%% % %%%% %%%% %% %%%%% %%% ", + " ", + " ", + " ", + " $$$ $$ % % %% % % %% &&& && &&& &&& && &&&& &&& &&&& &&& && '''''' ''' ''' ''' '' ", + " ! ! ! ! ! !!! !! ! ! ! !! !! !! ## ## $$ $$ $$ %%% % % % %% % % % % %% && & && & && && &&& & & & & & & & && ' ' ' ' ' ' ' '' ''' ", + " ! !!!!! !!! !!! ! ! !!! !!!! ! !!! !! ! ! !! # # ### # ## $ $$ $ % % % % % %% %% % % % && & & && && & & & & &&&& & &&& & && '''' '' ''' '' ''' ' ", + " !! !!!!! ! !! !!!! !!!! !!! ! !!! !!!!!! !!! !!!! !!!!!!!!! # #### ### #### ###### ### $ $$ $ % % % %% % %% %% % % % & && & & & & &&&& & &&&& & && & && '' '' ' ' '''' ' '''' ", + " !! ! ! !!! ! ## # ###### ## # # ### # $$$ $$$ $$ % % %%%% %% % % %% % % %% & & &&& &&&&& && &&&& && &&&& && &&&& &&& '' '' '''''' ' ' '' ''' ", + " !!!! ! ! ! !! ## # #### # # ## # # # # %%%% %%%% %%% % %%% %%% % %%% ", + " ! !! ! !! !! ### # ## ## # ## # ## ## ", + " !! ## ", + " ", + " !! !!! ###### ### $$ $ % % % % % && & &&& && & &&& && &&& && && '' '' ''' ''' ''' ' ", + " ! ! ! ! ! ! ! !! ! # ## # # ## # $ $$ $$ %% % % %% % % %% % %% & & & & & & & & & & & ' ' ' ' ' ' ", + " ! !! !!!!!! !!!!! ! ! ! !! ! ! ! ! ! ! # # # # # # # # ## # $ $ $ % % % % % % % % % % & & & & && & & & & & && & & '''' ' ''' ' ' '' ", + " !! ! !! ! ! !!! !! !! ! !!!! ! ! ! !! ! # # ## # # # ## $ $ $ % % % % % % % % % & & & &&&&& & & & & & & & ' ' '' ''''' ", + " ! ! ! ! ! !! # # # # # # # # # # # $$$ $$ $$ % % % % % % % % % % & & &&&& & & & & & & & & & & & & ' ''' ' ' ' ' ' ", + " %%%% %%% %% % %% %%%% %% ", + " ", + " ", + " ", + " !! !! ##### ### # $$ $ % % % % % && & &&& &&& & && && &&& &&& && '' ''''' ''' '' ' ", + " !! ! ! ! ! ! !!!! ! # ### # # #### # $ $$$$$ %% %% % %% % %% % & & & & & & & && & ' ' ' ' ' ' ' ' '' ", + " ! !!!!!!!!! !!!! !!!!!!!!!!! ! ! ! ! ! ! ! # # # # # # # # # # $ $ $ % % % % % % % % %% & & & & && & &&&&&& & && & '''' ' ''' ' ' '' ", + " !! !!!! !! !! !! !! !! !!!!!!!!!! ! !! ! ! ! !! ! # # # # # # ## # $ $$$ % % % % % % % & & & & & &&& && & & & & & ' ' ' ' ' ''''' ", + " ! ! ! ! !! # # # # # # # # # ## $$ $$$ $ % % % % % % % % & & & && & & &&& && & & & & ' ' ''' ' ' ' '' ' ", + " %% % %%% %%%% %% %%%% %% ", + " ", + " ", + " ", + " !!! !!! ###### ### # $$ $ % % % % %% % && && &&& &&& & &&& &&& &&& &&& &&& '' '' ''' ''' ''' '' ", + " !! ! ! ! ! ! ! ! ! ! !! ! !! ! ## ## # # #### # $ $$ $$ %% % % %% %% % %%% % %% & && && & && && && & & & & & & '' '' ' ' ' ' ' '' ", + " ! ! ! !!!! ! ! !! ! ! !!!!!!!!!!!!! !!!!!! !!!! ! ! ! ! ## # # # # # # # ## # $ $$ $ % % % % % %% %% % %% & && && & && & &&&&&& & &&& & & ''''' '' ''' ' ''' ' ", + " !! ! !! !! !! ! !!!! !! !!!!!!!!!!!!!!!! !!!!!!!!! !!!! ! !! ! ## # ##### # # # #### $ $$ $ % % % % % % %% % % % & && && & & &&&&&& &&&& & & && & & '' '' ''' ' ' ' '''' ", + " ! !!!!!! ! ! !! ## #### # # ####### #### $$$$$$ $$ % % %%% % % % %% %% % % &&& && &&&&& && &&&& && &&& & & &&& '' '' ''' ' ' '''' '' ", + " %%%% %%% %%% % %% %% % %%% ", + " ", + " ", + " ", + " $$ $$ % % % % % %% && && && &&& && &&& &&& &&& &&& &&& ''''''''' ''' ''' ' ", + " !! ! ! ! ! ! ! !! ! !! !! !! ! # ## $ $$$$$ %% %% % %%% %% %% %% % %% &&&& && & && && && & & & & & & ' '' ' ' '' '' '' ", + " ! ! !!!! ! !! ! ! !!!!!!!!!!!!!! !!!!!! !! !!!! ! ! ! ! # # # # ## $ $ $ % % % % % %% %% % %% & && && & && & &&&& & & &&& & & ''''' '' ''' ' ''' ' ", + " !! ! ! ! !! !! ! !! !!!! !!!!!!!!!!!!! !!!!!!!! !!! ! !!!! !!!!!!!!!!!!! ## ### # # #### #### ### $ $$ $ % % % % % % %% % % % & & & & &&&&&& &&&&&& & && & & '' ' ' ' ' ' ' ''' ", + " ! !!!! ! !!! ! ## ## # ### # # # ## # $$ $$$ $$ %% % %%%% % % % % % % & & &&& &&& & & && & & &&&& & &&&&& & ''''''''''''' ' '' '' ", + " ! ! !! ! !!!! # ###### # #### # # # # %% % %%%% %%%% %% %%% %% ", + " ! !!! !! ! ### # ## ## #### # ## ## ", + " !! # ", + " ", + " $$ $ % % % && & && && & &&& &&& &&& && &&& '' '' '' '' ''' ' ", + " !! ! ! ! ! ! !! ! !! # ## $ $$$$ %% %% % %% % % % % % & & & & & && & & & & & & ' ' ' ' ' ' ' ' ", + " ! !!!!!!!!! !!!! !!!!!!!!!!! !! !!!!! ! ! ! # ## # # $ $ $ % % % % % % % % %% & & & & && & & &&&& & && & ''' ' ''' ' ' '' ", + " ! !!!!! !! !!!!! !!!!!!!!!!!!! ! ! ! !!!!!! !!! !!!!! !! # ### # # ### ##### ## $ $$$ % % % % % % % & & & & & &&& && & & & ' ' ' ' ' ''''' ", + " ! ! ! !! ! # # # ### # # # ## # $$ $$ $$ % % % % % % % % % % & & &&& & & & & & & & && & & ' ' ''' ' ' ' ' ' ", + " ! ! ! ! ! ! # # # # # # # # # %% %%% %% % % %% % %% ", + " ! ! ! ! ! ## # # ## # # # # # ", + " ! # ", + " ", + " $$ $ % % % % % && && &&& &&& & &&& &&& &&& &&& &&& ''''''''' ''' ''' ' ", + " ! ! ! ! ! ! !! # ## $ $$$$$ %% %% % %% % % %% % %% & & & & & && & & && & ' ' ' ' ' ' ' ' '' ", + " ! !!! !!!!! !!!!! ! ! !!!!! ! ! ! # # # # # $ $ $ % % % % % %% % % & & & & && & & & & & && & & '''' ' ''' ' ' '' ", + " !! ! !! !! !! ! ! ! ! !!!!!!! !!!!!!!!!! !! ### # # ### #### #### $ $ $ % % % % % % % % % & & & & &&&&& & & & & & & ' ' ' ' ''''' ", + " ! ! ! !! ! # # # ### # # # ## # $$ $$$ $$ % % % % % % % % % & & & &&& & & & & && & & & & & & & ' ' '''' ' ' ' ' ' ", + " ! ! ! ! ! # # # # # # ## %% % %%%% %%%% % %% % %% ", + " ! !!! ! ! ### # ## ## # # # ## ## ", + " ! # ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-font-features-1100-1100-2.0-grid-reference.json b/tests/visual_tests/grids/text-font-features-1100-1100-2.0-grid-reference.json new file mode 100644 index 000000000..1414ab279 --- /dev/null +++ b/tests/visual_tests/grids/text-font-features-1100-1100-2.0-grid-reference.json @@ -0,0 +1,286 @@ +{ + "keys": [ + "", + "1", + "2", + "3" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !! ! # # ", + " ! ! # # # # $$ ", + " ! ! ! ! ! ! # # # ## # ## # # # # # # # ## # # # $$ ", + " ! ! ! ! ! ! ! ! ! !! !! ! # ## # ## # # # # # # # # $$ $$ $ ", + " ! ! !!!! ! !!! !!! ! ! ! ! ! !! !!!! ! ! !! ! ! ! ! !! ! ! ! ! # ## # ## # # # # # # ## # $$ $ $ $ ", + " !! ! ! ! ! ! ! ! ! ! ! !!! !! ! ! ! ! ! ! ! ! ! !! ! # ###### #### # # # # # ## # $$ $$ $ ", + " ! ! ! !! ! ! ! ! ! ! ! ! !!! ! ! ! ! ! ! ! ! !! ! # ## # ## # # # # #### ### # $$ $$$ $ ", + " ! ! ! !! ! ! ! !! !! ! ! ! ! ! ! !!!! !!! ! !!!!! ! ! ! ! ! # ## # ## # # # # ## # # # $$ $$ $ ", + " ! ! ! ! ! !! ! ! # ## # ## # # # ## ## # $$ $ $ $ $ ", + " !! !! !!! !!!!!!! !!!! !!! # ## # ## # # # # # # # # $$$ $$$$ $$$ ", + " # ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!! !!!! ######### ### ###### $$$$ ", + " !! !! !! !!!!!!! !!!!!! ######### ### ####### ## $$$$ ", + " !!!! !! !! ! !!!! !!!!! !! !! !! ! !!!! !! ### ### # # ### # # ## $$ $$$$$ $", + " ! !! !!! !! !!! !! !! ! !! !! !!!! !!!! !!! !! !! !!! !! !!!! !!!!!!!!! !!!!! !!!!!!!!!!!! ### ####### ###### ######## ###### ###### ###### $$ $$$$$$ $", + " ! !!!!!!!!! !!! ! ! ! !! !!!! !!! ! !! !! !!!!!!! !!!! ! !! !!!!!!!!! !!!!! !! !!!!!!! ### ####### ### ## ######## ######### ## ###### $$ $$ ", + " ! !!!! !!!! !! !!! ! !! ! ! !! ! !! !! !! !!!! !!!! ! !! !! !!! !!! !!!! !! ### ### ## ######## ### ## ### ##### ## $$ $$$$$$ ", + " !!!! !!! !! !!!! !! !!!! !!!! !!!! ! !! !!! !!!! !!! !! !!!! !! !!! !! !!!!!! !! ### ### ## ######## ### ## ### ###### ## $$ $$$$$ ", + " !!! !! !!! !! !!! !! ### ### ## ### ### ## ### ### ## $$ $ $$$ ", + " !! !! !!! !! !!!!!! !!!! ### ### ## ####### ### ## ### ####### #### $$$$$$$ $$$$$$ ", + " !! !!! !! !!!!!! !!!! ### ### ## ###### ### ## ### ###### #### $$$$$$$ $$$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!! !!! !!! ######### ### #### ## $$$$$ ", + " ! ! ! ! ! !! !!!! !! !!!!!! ######### ### ######## ### $$$$$ ", + " !!!! ! !! !! !!!! !!!!! ! ! !!!! !! !! ! !!! ! !!! !! ### ## # # ## # ## ### $$$ $$$$$$ ", + " !! !! !!! ! !!! ! !! ! !! !! !!!! !!!! !!! !! !! !!! !! !!!! !! ! !!!! !! ! !!!! !! ! !!!! !!!!!!!!! !!!!!!!!!!!!!!!!!! ## ####### ###### ########## ###### ###### ###### $$$ $$$$$$$ ", + " ! !!!!!!!!! !!!! ! ! !! ! !!!! !!!! ! !!!!! !!!! !! !!!!!! !! ! ! !! ! !! ! ! !! ! !! !!!! !!!!!!!!! !!!!! !! !!!!!!! ### #### ### ## ### ######### ######### # ##### $$ $$$ ", + " ! !! !! !!!! ! !!! !! ! ! !!!! !!!! ! !!! ! ! !! ! !!!! !! !! !! ! ! ! !!!! !! ! !!!! !! !!! !! !!!! !!! ### ### ### ######## ### ## ### ##### ### $$ $$$$$$ ", + " !!!!! !!!! ! !!!! !! !!!! !!!! !!!! !! ! !!!! !!!! !!!! ! !!! !!!! !!!! ! !! !!!! !!!! !!! !!! !! !!! !!!!!! !!! ### ### ## ######## ## ### ## ##### ### $$$ $$$$$ ", + " !! ! !!! !! !!! !!! !! ### ## ## ## ## ### ## ### ### $$$ $$ ", + " ! !!! !! !!! !!!!!!! !!!! ## ## ## ####### ## ### ### ###### ##### $$$$$$$ $$$$$$$ ", + " !! !!! !! !!!!!! !!!! ### ### ### ###### ### ## ### ###### #### $$$$$$$ $$$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ! !! ######## ## ###### $$$ $$", + " ! ! ! ! !!!! ######## ## # ## # $ $ $$", + " !!!! ! ! ! ! ! ! ! ! ! !! ! ## ## # # # # # # $ $$$$ $$", + " ! ! !!! ! !!! ! ! ! ! !!! !!!! !!! ! ! !!! !!! ! ! !!!!!!! !!!!! !!!! !!!!! ## ###### ##### ####### #### ##### ##### $ $$ $ $$", + " ! ! ! !! !!! ! ! ! !!! !! ! ! ! !!! ! ! ! ! !! ! ! !! !! ! ## ## # ## ## # ## ## # # $ $$ $$", + " ! ! ! ! ! ! !!! ! ! ! ! ! ! !! ! !! ! ! ! !! ! ! !! !! ! ## ## # ## ## # ## # ## # $ $$$$ $$", + " !!!! !!!!! !!!! ! !!! !!! !!! ! ! !!! !!! !!! !!! ! ! ! ! !! !!!! ! ## ## # ####### # ## # #### # $ $$$ $$", + " ! ! ! !! !! ! ## ## # ## # ## # # # $ $$ $$", + " ! ! !! ! !! !! ## ## # # # # ## # # ## $$$$$ $$ $$$ $", + " ! ! !! !!!!! !!! ## ## # ###### # ## # ##### #### $$$$$ $$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! !! ########## ### # $$$$ $ ", + " ! !! !! !!!! ########## # # # $$$$ $ ", + " !!! ! ! ! ! ! !! ! !! ! !! ! ## ## # # # # ## # $$ $$$$ $$$$", + " ! ! !! ! !!! ! ! ! ! ! !!! !!! !! ! !! !!! !!! !!! !!! !!! !! !!! !!!!!!! !!!!!!!! !!!! ## ###### ##### ###### #### #### #### $$ $$ $ $ ", + " ! !! !! !! ! ! ! ! !!! !!! ! ! ! ! ! !! ! ! ! ! ! ! ! !! ! !! !! ! ! ! ## ## ## # # # # ## ## # $$ $$ $ ", + " ! !! ! ! ! !! ! ! ! ! ! ! ! ! ! ! !! ! ! ! ! ! !! ! ! !! !! ! !! ! ## ## # ## # # # # ## # $$ $$$ $ ", + " !!! !!!! !!! ! !!! !!! !!! ! !!!! !!!! !! ! !!! !!! ! ! !!! !! !!! !! !! ! !!!! ! ## ## # ####### # # # #### # $$ $$$ $ ", + " ! !! !! ! ! ! ## ## # ## # # # ## # $$ $ $ ", + " !! !! ! ! ! ! ## ## # ## # # # # # # $$$$$ $$ $$ $$$", + " !! !! ! !!!! !!! ## ## # #### # # # ##### ### $$$$$ $$$ $$", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! !!! ######## ## ###### $$$$$ $$", + " !! ! ! ! ! !!!!!!! !!!!! ######## ## ###### ## $$$$$ $$", + " !!!! !! !! !! !!! !!!! ! ! !!! ! ! !!! ! !!!! !! ## ## # # ## # # ## $$$ $$$$ $$$", + " ! ! !!! !!!!!! ! !!!! ! ! !!!! !!! !!! !! !!! !!!! !!! !!! !!!! !!! !!! !!! ! ! !!!! ! !!! !!!!!!!! !!!!!!!!!!!!!!!! ## ###### ##### ####### ##### ##### ##### $$$ $$$$$ $$$", + " ! ! !!!!!! !!! ! ! !! ! !!! !!! ! ! !! ! !! ! ! !!!! ! !!!!!! ! !! !!!! ! ! !!! !! ! ! ! ! !!!!!!!! !!!!!!! !!!!!! ## ### ### ### ### ####### ######## # ##### $$$ $$ $$", + " ! !! ! !!!!!! !!! !!!! !!!!!! ! ! !! !! !! ! ! !!!! ! ! !! ! !!!! ! ! ! !!!! ! ! ! ! !!! !! !! !!!! !! ## ### ### ####### ## ## ### #### ## $$$ $$$$$ $$", + " !!! !!! !!!!!! !! !!!! !!! !!!! ! ! !!! !!! !!! ! !! !!! !!!!!! ! !!! !!! !!! !!! !!!! ! !!! !!! !! !! !!!!! !! ## ## ### ####### ## ## ## ##### ## $$$ $$$$$ $$", + " !! !!! !! !! !! !! ## ## ### ## ## ## ## ### ## $$$ $$ $$", + " !! !!! !! !! !!!!!! !!!! ## ## ### ####### ## ## ## ##### #### $$$$$$$ $$$$$$ $", + " !!! !! !! !!!!!! !!! ## ## ### ###### ## ## ## ##### ### $$$$$$$ $$$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!!! !!!! ######## ## #### ## $$$$ $", + " ! !! !! ! !! !! ! ! !!!! !! !!!!!! ######## ## ####### ### $$$$ $", + " !!!! ! ! ! !!! !!!! ! !! !!! ! !! !!!! ! !! ! !! ! !!! !!! ### ## # ### # # ### $$ $$$$$ $$", + " ! ! !!! !! !!! ! !!!!!! ! !!!! !!! !!! ! !!! !!!! !!! !!! !!!! !!! !!! !!! !! ! !!!! ! !!! !! ! !!! !!!! !!! ! !! !!! !!!!!!!! !!!!!!!!!!!!!!!! ### ###### ###### ######## ##### ##### ##### $$ $$$$$$ $$", + " ! ! !!!!!! !!! ! ! ! !! !!! !!!!! ! !! ! !! ! ! !!!! ! !!!!!!!!!!! !!!!!! ! !!!! ! !!!!!! ! ! !! ! !!!!!!!! ! ! !!!!!! !!!!!!!! !!!!!!! !!!!!! ### ####### ## ## ######## ####### # ##### $$$ $$ $", + " !! !! ! ! ! !! !!! ! !! ! ! ! !!!! ! !! ! !!! ! ! ! ! !!!! ! !! !!!! !! ! !! ! ! !!!!!! ! !! !!!! ! ! !!! ! ! ! ! !! !!! !!! !!!! !! ## ### ## ####### ## ## ## #### ## $$$ $$$$$ $$", + " !!!! !!! ! !!!! !! !!! !!!! !!! ! !!!!!! !!! !!!!!! ! !!!! !!! ! ! !!! !!!!!!!! !!!! !!! ! !!!! !!!! !!!! ! ! !!!! !!! !!!! !!! !!! !!! !!!!! !! ## ## ### ####### ## ## ## ##### ### $$ $$$$$ $$", + " !! !! !! !! !! !!!!!! ## ## ### ## ### ### ### ### ### $$ $$$ $$", + " ! !! !! !! !!!!!! !!!! ### ## ## ###### ### ### ### ###### #### $$$$$$ $$$$$$ $$", + " !! !! !! !!!!!! !!! ### ## ## ##### ## ## ## ##### ### $$$$$$ $$$$ $", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! !!! ####### ## ### # $$$$ $ ", + " ! ! ! ! ! ! !! !! !!!! ####### # # # # $ $ $ ", + " ! !! ! ! ! !! ! ! ! ! ! !!!! ! ! ! !! ! !! ! ## # # # # ## # $ $$$$ $$$", + " ! ! !!! ! !! ! !! ! ! !! !!! !!! ! !!! !!! !!! !!! !!! !! !!! !!! ! ! !!! ! !!! ! !!! !!!!!! !!!! !!!! !!!! ## ##### #### ####### ######### #### $ $ $ $$ ", + " ! !! ! !! ! ! ! !! !! ! ! ! ! ! ! !! !! ! !!! ! !! ! ! ! ! ! ! ! ! ! ! ! ! ! !! !! !! ## # # # ## ## ## ## # # $$ $ $ ", + " !!! ! ! ! ! ! ! ! ! ! ! ! !! ! ! !! !! !! ! !! ! ! ! !! !! ! ! ! ! ! ! ! ! ! !!! ! # ## # ## ## # # ## ## ## $$ $$$ $ ", + " !!!! !!! ! !!! ! !!! !!! !!! ! ! !! !!!! !! ! !!! !! ! ! !!! !!!!!! !!! !!! ! ! !!! !!! !!! !! !! ! !!!! ! # ## # ###### # # # ### # $$ $$ $ ", + " ! ! !! !! !! ! ! # # ## ## # # # ## # $ $ $ ", + " ! ! !! !! ! ## # ## ## # # # # # # # $$$$$ $$ $$ $$$", + " ! ! ! !!!! !!! ## # # ##### ## ## # ##### ### $$$$$ $$$$ $$", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ! ######## ## $$ $", + " ! ! # # # $ $", + " ! ! ! ! ! ! ! ! !! ! ! # # # # # # # $ $$$$ $$", + " ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !!! ! ! ! ! ! !! ! ! # # # ## # # ## # # # $ $", + " ! ! ! !!! ! !! !!! ! ! ! !! !! ! ! ! ! ! ! ! ! ! # # # # # # # # # $ $ $", + " ! ! ! ! ! !! ! ! ! ! ! ! !! ! ! ! ! ! ! ! ! ! ! # # # # # # # # $ $$ $", + " !!! ! ! !! !! !!! ! ! !!! ! ! ! ! ! ! ! ! !!! ! ! ! ! ! !!! ! # # ####### # # ## # $ $ $", + " ! ! ! ! ! ! # # # # # # # $ $", + " ! ! ! ! ! # # # # # # # $ $ $ $", + " ! ! ! !!!! !! # # #### # # ##### ## $$$$$ $$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! ### $$$$ ", + " !!!!!! !! ####### ## #### ### ## $$$$ ", + " !! !! !! ! !!! !!!! !!! !! ! !!! ! !! !! ####### ## ### ## $$ $$$$ $$", + " ! ! !! !!! !! !! ! ! ! ! !! !! !!! !!!! !! !!! !! ! ! !! ! !!! !!!!!!! !!!!!! !!!!! !!!!!!! ## ## ## ## ###### #### ## ## #### ####### $$ $$$$$ $$", + " ! ! ! ! !! ! !! !!! ! ! !!! ! ! ! ! ! !!!!!!!! ! ! ! ! !!! !! ! ! ! ! !!! !! !!! ! !! !! ## ###### ###### ###### #### ###### ##### ####### $$ $$ ", + " ! ! !!!! !! !!!! !! ! ! !!!!!! ! ! !!! !! !!! ! ! ! ! ! ! !!! ! ! ! ! !!! !! !! !!!! !! ## ## ## ## ## ## ### ### # ## ## $$ $$$$$ ", + " !!! !!! !! !!!! !! !!! !!!!!!!! ! ! ! ! ! !!!!! ! ! !!! !!!!!!!! !! !!! !!! !! !! !!!! !! ## ## ## ####### ## ### ## ##### ## $$ $$$$ ", + " !! !! ! ! ! ! ! ! ! ! ! !!! !! !! !! !! ## ## ## ####### ## ### ## ##### ## $$ $$ ", + " !! !!! !! !! !! !!! !!!!! ## ## ## ## ## ### ## ## ## $$$$$$$ $$$$$$ ", + " !!! !! !! !!!!! !!!! ## ## ## ###### ## ####### ## ###### ##### $$$$$$$ $$$$ ", + " ## ## ## ##### ## ####### ## ##### #### ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! ## $$$$ ", + " !!!!!! !! ####### ## #### ### ## $$$$ ", + " !!! ! ! !! !!! !! ! !!! !! ! !!! ! !! ! !! ! ! !! ####### ## ## ## $$ $$$$ $", + " ! ! !! !! !! ! ! ! ! !! ! !! !!! !! !!!! !! !!! !! !! ! !! ! !!! !! ! !!! ! !! !!! ! ! !! !!!!!!! !!!!!! !!!!! !!!!!! ## ##### ### ###### #### ###### ### ###### $$ $$$$$ $", + " ! ! ! !! ! ! ! ! ! ! !!! ! ! ! ! !!!!!! ! ! ! ! ! !!!! ! ! ! ! !! !! ! ! ! ! !! !!!! ! ! ! ! !! !! !!! ! !! ! !!! ### ##### ###### ###### #### ###### ##### ###### $$$ $$ ", + " !! ! !!! !! !!!! !! ! ! ! !!!! ! ! !!! !! !!! ! ! ! ! ! ! !!! ! !! ! ! ! !! ! ! ! ! ! !!!!!!!!!! !!! !! !! !!! !! ## ### ## ## ## ## ## ### # ## ### $$ $$$$ ", + " !!!! ! ! ! ! !! !! !!! !!! ! !!!!!! ! ! ! !!!!!!!! ! !!! !!!!!!!! !!! !!! !!! !!!! !!! !!! !!! !!!!!! ! !! !! !! !!!! !! ## ## ## ####### ## ### ## #### ## $$ $$$$ ", + " ! ! ! ! ! ! !! ! ! !! ! ! ! !! ! ! !! !! !!! !! !! ## ## ## ####### ## ## ## #### ## $$ $$ ", + " !!! ! !! !! !! ! !! !!!! ## ## ## ## ## ## ### ## ## $$$$$$ $$$$$ ", + " !! !! !! !!!!!! !!!! ### ## ### ###### ## ###### ## ##### #### $$$$$$$ $$$$ ", + " ## ## ## ##### ## ####### ## ##### #### ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ! ######## ## ### # $$$ ", + " ! ! ! !! ######## ## # # ## $ $ ", + " !!! ! ! !!! ! !! ! !! ! ! ! !! !! ## ## # # # # # ## $ $$$$ $", + " ! ! !!! ! !! ! ! ! ! ! !! !!! !!! !!!! !!! !!! !!! ! ! !!! !!! ! ! !!!!!!! !!!!!! !!!!! !!!!!! ## ###### ##### ##### ### ###### #### ###### $ $$ $ ", + " ! ! ! ! !!! ! ! ! !! !!! ! ! ! !!!!! ! ! ! ! ! !!!!! ! ! ! !! ! ! !! !! !! ## ## ## ## ## # # ## ## ## $ $$ ", + " ! ! ! ! ! !! ! ! !! ! ! ! ! ! !! ! ! ! ! ! ! !! ! ! ! ! ! ! ! !! !!! !! ## ## ## # # # # ## ### ## $ $$$ ", + " !! !!! !!!! ! !!! !!! !!!! ! ! !!! ! ! !!! ! ! !!! !!!! !!! !!! ! !! ! ! !! !!!! !! ## ## ## ###### # # ## #### ## $ $$$ ", + " ! ! ! !! !! !! ## ## ## # # # ## ## ## $ $$ ", + " ! ! !! ! ! !! ## ## ## ## # # # ## # ## # $$$$$ $$ $$$ ", + " ! ! !! !!!!! !!! ## ## ## ##### # ###### ## ##### #### $$$$$ $$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! ! ######## ## ### # $$$$ ", + " ! ! !! ! !! ! !! ######## ## ## # ## $$$$ ", + " !!! ! ! ! ! ! !! ! ! ! ! ! ! !! ! ! ! # # # # ## # # ## $$ $$$$ $", + " ! ! !!! !! !!! ! ! ! ! ! !!! !!! !!! !!!! !!! !!! !!! ! ! !!! ! ! !!! ! ! !!! !!!!!!! !!!!! !!!!! !!!!!! # ##### ##### ###### #### ##### ##### ###### $$ $$ $ ", + " ! ! ! ! !!! !!! ! ! !! !!! ! ! !! !!!!! ! ! ! ! ! ! ! ! ! ! ! ! !! ! ! ! ! ! !! ! ! # # # ## # # # ### # # $ $ ", + " ! ! ! ! ! !! ! ! ! ! ! ! ! ! !! ! ! ! ! ! ! !! ! ! ! ! ! ! !! ! ! !! !! !! ## ## # # # # # ## ## ## $ $$$ ", + " !!! !!! ! !!! !! !!! !!! !!! ! ! !!! !!! ! ! !!! !!! !!! !! !!! !!! !!! !!! !! ! ! !!!! !! ## ## ## ####### ## # ## ### ## $$ $$ ", + " ! ! !! !! ! ! ! # # ## ## ## ## # # ## $$ $ ", + " !! !! ! !! ! # # # # ## ## # # # ## $$$$$$ $$ $$ ", + " ! !! !! !!!! !!!! # # # ##### # ###### # ##### #### $$$$$ $$$$ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! !!! ######## ## ##### $$$$ ", + " ! ! ! ! ! !!!! ######## ## ## ## ## $ $$ $", + " ! !! ! ! ! !! ! ! !! ! ! ! !! ! !!! ! # # # # # # # # $$ $$$$ $$", + " ! ! !!! ! !!! ! !! ! ! !!! !!! !!! ! ! !!! ! ! !!!! ! !!! !!!!!!! !!!!!!!!!! !!!!! # ##### ##### ####### #### ##### ##### $$ $$ $ $", + " ! ! ! ! !!! ! ! ! ! !! !!! ! ! !! ! ! ! ! ! ! ! ! ! ! ! ! !! !! ! !! ## # ## # ## ## # ## ## # $ $ $", + " ! ! ! ! ! ! !! ! ! !!! ! ! ! ! ! ! ! ! ! ! ! ! ! !! ! !! ! !! !! ## ## ## ## # ## # ## ### ## $ $$$ $", + " !!!! !!! ! !!! !! !!! !!!! !!!!! ! !!! !!!! !!!! ! ! !!! !!! !!! ! ! ! !!!! !! ## ## # ####### # ## # #### ## $$ $$$ $$", + " ! ! !! ! !! !! ! # # # # # ## # # # $$ $$ $$", + " !! ! !! ! !! ! # # # ## # # # # # ## $$$$$$ $$ $$ $$", + " !! !! ! !!!!! !!! ## # ## ##### ## # ## ##### ### $$$$$ $$$$ $", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!! !!!! ############## ###### $$$ ", + " !! ! !! !!! # ## # ### ## # ## $ $$ ", + " !!!!! !! !! ! !!!! !! ! ! !!!!! ! ! !! !! !!! # ## # ### ### ## $$ $$ ", + " !! !! !!! !! !!! ! !!!!! ! !! !!!!!!!!! ! !! !! ! !!! !!!!!!!! !!! !!! !!!!!!!!!!! ## ####### ##### ######## ### ### ##### ##### $$ $$$ $$ $", + " !! !! ! ! !! ! !!! !! ! !!!! ! !!!! !!! ! !!!! ! !! ! !! ! !! !!! !!! !!! ! !!! ## ### ## ### ### ### ## ### ### # ## $$ $$ $ ", + " !! !!!!!!!!! ! ! !!! !! ! !! !!!!!! !! ! ! ! ! !! ! !! ! !! !!! !!! !!!! !!! ## ### ## ### ### ### ## ### #### ## $$ $$$$$ ", + " !!!! ! ! !! !!! ! !!!! ! !! ! ! !! !! ! ! !! !!!! ! !!!! !! !!! !! !!!!!! !!! ## ### ## ####### ### ## ## ###### ## $$ $$$$$ ", + " !! !! !!! !! !!! !!! ## ### ## ### ### ## ## ### ## $$ $ $$ ", + " !! !! !!! !! ! !! !!! ! ## ### ## ### ## ### ## ## # ## ## # $$ $ $$ " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-iconic-font-1000-1000-1.0-grid-reference.json b/tests/visual_tests/grids/text-iconic-font-1000-1000-1.0-grid-reference.json new file mode 100644 index 000000000..afd2e140b --- /dev/null +++ b/tests/visual_tests/grids/text-iconic-font-1000-1000-1.0-grid-reference.json @@ -0,0 +1,483 @@ +{ + "keys": [ + "", + "135", + "150", + "165", + "15", + "30", + "45", + "60", + "75", + "90", + "105", + "120", + "180", + "195", + "210", + "225", + "29", + "44", + "59", + "74", + "89", + "104", + "119", + "149", + "179", + "194", + "209", + "224", + "14", + "134", + "164", + "13", + "28", + "43", + "58", + "73", + "88", + "103", + "118", + "133", + "148", + "163", + "178", + "193", + "208", + "223", + "12", + "57", + "102", + "117", + "27", + "42", + "72", + "87", + "132", + "147", + "162", + "177", + "192", + "207", + "222", + "11", + "26", + "41", + "56", + "71", + "86", + "101", + "116", + "131", + "146", + "161", + "176", + "191", + "206", + "221", + "10", + "25", + "40", + "55", + "70", + "85", + "100", + "115", + "130", + "145", + "160", + "175", + "190", + "205", + "220", + "24", + "39", + "54", + "84", + "99", + "144", + "159", + "174", + "189", + "219", + "9", + "69", + "114", + "129", + "204", + "8", + "23", + "38", + "53", + "68", + "83", + "98", + "128", + "143", + "158", + "173", + "188", + "203", + "218", + "113", + "52", + "67", + "142", + "7", + "22", + "37", + "82", + "97", + "112", + "127", + "157", + "172", + "187", + "202", + "217", + "6", + "21", + "36", + "66", + "81", + "96", + "126", + "141", + "156", + "171", + "186", + "201", + "216", + "51", + "111", + "5", + "20", + "35", + "50", + "65", + "80", + "95", + "110", + "125", + "140", + "155", + "170", + "185", + "200", + "215", + "64", + "79", + "139", + "184", + "4", + "19", + "34", + "49", + "94", + "109", + "124", + "154", + "169", + "199", + "214", + "198", + "3", + "18", + "33", + "48", + "63", + "78", + "93", + "108", + "123", + "138", + "153", + "168", + "183", + "213", + "17", + "32", + "107", + "167", + "212", + "2", + "47", + "62", + "77", + "92", + "122", + "137", + "152", + "182", + "197", + "31", + "46", + "61", + "121", + "136", + "151", + "181", + "1", + "16", + "76", + "91", + "106", + "166", + "196", + "211" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!! ## $$$$$$$$$ ", + " %%%% &&&&&&& '''''' (((((((((( ) ) ***** +++++ ,, , !!!!! !!! #### $$$$$$ $ -- ......... //// 00 ", + " %%%%%% &&& &&& ' '' ((( ( )) )) ** *** +++++++ ,,,,,,,,, ! !!!! ### $$$$$$$$$ - ------ . . . / / / 0 000 ", + " %% % %% && &&&& ' ' ((( (( ( ))) ))) ** **** + +++++ + , , ! !! ## ## $$$$$$$$$ . . . / / 000000000 ", + " % %%%%% & '' '' ( (((( ( )))))))) ** ** * + ++++ + ! !! #### ## $$$$$$$$$ -- ------ . . . / / 000000000 ", + " % % %% & ''''''''' ( (((((((( )))))))) **** * ++ ++ + ! ! ! ## ## $$$$$$$$$ -- ------ . . . / / 0 000 ", + " %% %%% && & ''''''''' (((((((((( ))) ))) ** ** +++++ ! ! ## ## # $$$$$ $ -- . . . /// 00 ", + " %%%%%% &&&&& ' ' ( ( )) )) ****** !!!!!! ## ## # $$$$$$$$$ -- ------ . . . /// ", + " %% && '''''' ((((((((( ) ) ** - ....... / ", + " % -- ", + " ", + " ", + " ", + " ", + " ", + " ", + " 111 222222 33333 4444444 55 6 7 888888888 9 : ;;;;;; <<<< ", + " == == 111111 2222222 3333333 3 4444444 555555 6 777 >>>> 8 8 ??? 99 999999 :: ; ; < < ", + " ====== 111 11 2222222 333333333 4444444 5 55 666 7 >>>> 8888888888 ?? ::: ;;;;;; <<<<<<<<< ", + " ==== 1 111 11 2222222 333333333 4444444 555 55 5 6666 7 >>>> 8888888888 ????? 99 999999 ::: ;;;; ;; <<<< <<<< ", + " ==== 1 111111 2222222 333333333 4444444 555555 5 66666 7 >>>> 8 8 ????? 99 999999 :: ;;;; ; ; <<< << ", + " ====== 1 11 1 2222222 3333333 3 4444444 55 55 55 6666 7 >>>>>> 8 8 ??? 9 : ;;;; ;;;; <<<< <<<< ", + " == == 11 11 222 222 333333 4444444 55 55 66 7 >>>>>> 88 88 8 ??? 99 999999 ;;;; ; <<<< <<<< ", + " 11111 22 22 4444444 55555 6 777 > 8888888888 ??? 9 ;;;; ; <<<<<<<<< ", + " 777 ?? ; ; ", + " 6666666 7 ;;;;; ", + " ", + " ", + " ", + " ", + " ", + " ", + " @@ AAAAA BBBBBB CCCCCCCCC DDD DDD EEEE FFF GGGG HHHHHHHH III JJJJ KKKKKKKK L M NNNNNNN ", + " @@@ AA AA B BB DDD DDD EE EE FFFFFFF GGGGGGGG HHHHHHHH II I J JJJ LL MMMMMM NNN NNN ", + " @@ @@@ A A BBBBBB B CC CCCCCC DDD DDD EE EEEEE FFFFFFFF GGGGGGGG HHHHHHHH I I JJ JJJ KKKKKKKK LLL MMMMMMMM NNNN NN ", + " @@@@@@ AAA AAA BBBBBBB CC CCCCC DDD DDD EE EEE E FF FFFFF GGG GGGGGG H H H HH IIIIII I JJ JJJ KKKKKKKK LL MMMMMMMM NN NNN NNN ", + " @@@@ AAAAAAAA BBBBBBB C CCCCCC DDD DDD EEEEEE E F FFFFF GGGGGGGGGG H H HH H IIIIII JJJ JJJJ L M MM NNNNNNNNNN ", + " @@ AAAAAAAA BBBBBB B CCCCCCCCC DDD DDD EE E EE FFFFFFF GGGGGGGGG H H HH H IIIIII JJJJJJJ KKKKKKKK M NNNNNNNNNN ", + " AAAAAAA BBBBBBB CCCCCCCCC DDD DDD EEEEEE F F GGGGGGG HHHHHHHH IIIIII JJJJ J KKKKKKKK M M NN NNNNNNN ", + " BBBBBBB DDD DDD EEEE HHHHHH JJJJ MM NNN NN ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " OOO OOOOOO PPPPPPPPP Q Q RRRR ", + " OOO OOOOOO SSSSS TTTTTTT PPPPPPPPP UU VV Q QQ RRRR W WW XXXXX YYYYY ZZZZZZZZ [ ]]] ^^ ", + " SS S SS TTTTTTTT PPPPPP UUUU VVVV QQQQQ RRRRRRRRR W WWWWW XXXXX X YYY YYY ZZZZZZZZ [[[ ]]] ^^^^ ^^ ", + " OOO OOOOOO S SSS S TTTTTTTTT P PPPPPP UUUUU V V QQQ QQQQ RRRRRRRRR W WWWWWW XX X YYYY YYY ZZZZZZZZ [[[[[ ] ^ ^^^ ", + " OOO OOOOOO S SSSSSS TTTTTTTTT P PPPPPP UUUUUUU VVV VVV QQQ QQQQ RRRRRRRRR W WWWWW X XX YY Y Y ZZZZZZZZ ]]]]]]] ^^ ^^^ ", + " OO OOOOO S S SS TTTTTT T PPPPPP UUUUUU V V QQQ QQQ RRRRRRRRR W WW XX X YYY YY ZZZZZZZZ ] ] ] ^ ", + " OOO OOOOOO SS S SS TTTT T PPPPPPPPP UUUU VVVV QQQQQQQ RRRRRRRRR WWW W XXX XXX YYY YYY ZZZZZZZZ ]] ]]]]]] ^^ ^^^ ", + " OO OOOOO SSSSS TT T PPPPPPPPP UU VV RRRRRRR XX XX YYYYY ZZZZZZZZ ]] ]]]]]] ^^ ^ ", + " U ^ ^^ ", + " ^^^^^^^ ", + " ", + " ", + " ", + " ", + " ", + " ", + " ___ __ ___ ``` aaaa bbbbbbbbb c c dddd eee ff ggg ggg hhh iii jjjjjj kkkkk ll mmmmmmm ", + " ___ __ ___ `````` aaaaa cc cc ddd dd eeeeee ffffffff g gg g hh iiiiii jjj j j kkkkk ll mm mmm ", + " __ __ __ `` ` ` aaaaaa bbbbbbbbb ccc ccc dddddddd eee eee fffffff g g h ii iii jjj j j kkk lll m ", + " ___ __ ___ ` ` `` aaaaaaa cccccccc ddd ddd eee eeee fffffff g g hhhhh ii ii jjjjj j llll mm mmm ", + " __ __ __ ` ``` `` aaaaaaa bbbbbbbbb cccccccc dddd ddd eee eeee fffffff g g hhhhh ii i iii j j llll mm mmm ", + " ___ __ ___ ` `` ` aaaaaa ccc ccc dddd ddd eeeeeeee f g g h iiii iii jjjjjjjj l mm mmm ", + " ___ __ ___ ``` `` aaaa bbbbbbbbb cc cc dd dd eee eee ffffff g g h iii iii jj jj l m ", + " ````` aa c c dddd eeee f f gg h iiii jjjjjjjj l m mm ", + " l m mm ", + " ", + " ", + " ", + " ", + " ", + " ", + " nnn nnn oo ppppppppp qqqqqqqqq ", + " nnnnnnnn oo ppppppppp qqqqqqqqq r r r ssss tt u uuuuu v w www xxxxx yyy zzzzzzzzz {{{ |||||| ", + " nnnnnnnn oo ppppppppp qqqqqqqqq r rr rr ss ss tt tttt uuuuuuuu v ww wwww xxxxxxx y y z zzz z {{ { | | | ", + " nnnnnnnn ooooo ppppppppp qqqqqqqqq r rrr rrr sssss ss ttttttt uuuuu u vvvv wwwwwww xxxx xxx yyyyyy z z { {{ | |||| ", + " nnnnnnnn ooo ppppppppp qqqqqqqqq rrrrrrrrr ssss ss ttttt u uuuu vvvv wwwwwww xx xx yyyyyy z z { {{{ | | ", + " nnnnnnnn ooooo ooo ppppppppp qqqqqqqqq rrrrrrrrr ssss sss ttttttt u uuu vvv wwwww xxxxx xx yyyyy z zzz z {{ {{ {{ | |||| | ", + " nnnnnnnn ooooooooo ppppppppp qqqqqqqqq r rrr rrr sss sss ttttttt uuuuuuu vvv wwwww xxx xxx yy y zz zz {{{{ {{{ | |||| | ", + " nnnnnnnn ooooooooo ppppppppp qqqqqqqqq r rr rr ssssss tt vvv xxxxxx yyy {{{{{ | |||| | ", + " r r r sss tt v xxx y { | | ", + " |||||||| ", + " ", + " ", + " ", + " ", + " ", + " ", + " }} }} ~~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f \u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083 \u0084\u0084\u0084 \u0085\u0085\u0085\u0085 \u0086\u0086 \u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087 }} }} ~~~ ~~ \u007f\u007f\u007f\u007f\u007f\u007f \u0088 \u0088 \u0080\u0080\u0080\u0080\u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u0089 \u0089 \u008a\u008a\u008a\u008a\u008a\u008a\u008a \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084 \u0084 \u0085 \u0085 \u008b\u008b\u008b\u008b\u008b \u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087 \u0087 \u0087 \u0087 }}}}}}} ~~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088 \u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0089\u0089\u0089 \u0089\u0089\u0089 \u008a\u008a \u008a \u0082 \u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083 \u0083\u0083\u0083 \u0084 \u0084 \u0084\u0084\u0084\u0084 \u0085 \u0085 \u008b\u008b \u008b\u008b \u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087 \u0087\u0087\u0087 }}} }}} ~~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088 \u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080 \u0080 \u0089\u0089\u0089 \u0089\u0089\u0089 \u008a\u008a \u008a \u0082 \u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083 \u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084 \u0084\u0084 \u0085\u0085 \u0085 \u008b \u008b \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087 \u0087 \u0087 \u0087 }}}}}}}} ~~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088\u0088\u0088 \u0080\u0080 \u0080 \u0080\u0080 \u0089\u0089\u0089\u0089\u0089 \u008a\u008a \u008a \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083 \u0083 \u0084 \u0084 \u0084 \u0085 \u008b \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087 \u0087 \u0087 \u0087 }}}} }}}} ~~~ ~~ \u0088 \u0088\u0088\u0088 \u0080\u0080\u0080 \u0080\u0080\u0080 \u0089\u0089\u0089 \u008a\u008a\u008a \u008a \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083 \u0083\u0083\u0083\u0083 \u0084 \u0084\u0084\u0084\u0084 \u0085\u0085\u0085\u0085 \u008b \u008b\u008b \u0086\u0086 \u0086\u0086\u0086 ", + " \u0087 \u0087 \u0087 \u0087 }}}} }}}} ~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088 \u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0089 \u008a\u008a \u008a\u008a \u0082\u0082\u0082\u0082 \u0082\u0082 \u0083\u0083\u0083 \u0083\u0083\u0083 \u0084 \u0084 \u0085\u0085 \u0085 \u008b\u008b \u008b\u008b \u0086\u0086 \u0086\u0086 ", + " \u0087 \u0087 \u0087 \u0087 \u0088 \u0088 \u0080\u0080\u0080\u0080\u0080 \u008a \u008a \u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084 \u0085\u0085 \u0085 \u008b\u008b\u008b\u008b\u008b \u0086\u0086 \u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087 \u0088 \u008a\u008a \u0084 \u0085\u0085\u0085 \u008b\u008b \u0086\u0086 \u0086\u0086 ", + " \u0084\u0084\u0084\u0084\u0084 \u0086\u0086 \u0086\u0086 ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u008c\u008c \u008d\u008d\u008d\u008d \u008e \u008f\u008f\u008f\u008f \u0090 \u0091\u0091\u0091\u0091 \u0092\u0092 \u0093\u0093 \u0094\u0094\u0094\u0094\u0094\u0094\u0094 \u0095\u0095\u0095\u0095\u0095 \u0096\u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c \u008d\u008d\u008d \u008d\u008d\u008d \u008e \u008e\u008e\u008e \u0090\u0090\u0090 \u0091\u0091\u0091\u0091\u0091\u0091 \u0092\u0092 \u009a\u009a\u009a \u0093 \u0093 \u0094 \u0094 \u0095\u0095\u0095\u0095\u0095 \u0096\u0096\u0096\u0096 \u0096\u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c \u008d\u008d \u008d \u008e\u008e\u008e\u008e \u008e\u008e \u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090 \u0091\u0091\u0091\u0091\u0091 \u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u009a\u009a\u009a\u009a\u009a \u0093\u0093 \u0093\u0093 \u0094 \u0094 \u0095 \u0095 \u0096\u0096 \u0096 \u0096 \u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098 \u0098\u0098\u0098\u0098 \u0098 \u0099\u0099\u0099\u0099\u0099\u0099 \u0099 ", + " \u008c\u008c\u008c\u008c \u008d \u008d\u008d \u008e\u008e\u008e\u008e \u008e\u008e \u008e \u0090 \u0090 \u0090 \u0091\u0091\u0091 \u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u009a\u009a\u009a \u009a\u009a\u009a \u0093\u0093\u0093 \u0093 \u0094 \u0094 \u0095\u0095 \u0095 \u0096\u0096\u0096\u0096 \u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c\u008c\u008c \u008d \u008d\u008d \u008d\u008d \u008e\u008e\u008e\u008e \u008e\u008e \u008e \u008f\u008f\u008f\u008f\u008f\u008f \u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0091\u0091\u0091 \u0091\u0091\u0091 \u0092\u0092 \u009a\u009a\u009a \u009a\u009a\u009a \u0093\u0093 \u0093 \u0094 \u0094 \u0094 \u0095\u0095 \u0095 \u0096\u0096\u0096 \u0096 \u0096 \u0097\u0097\u0097 \u0097\u0097\u0097 \u0098\u0098\u0098\u0098 \u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u008d\u008d \u008d \u008e\u008e \u008e\u008e\u008e \u0090\u0090 \u0090 \u0090\u0090 \u0091\u0091\u0091\u0091\u0091 \u0091\u0091 \u0092\u0092 \u009a \u009a \u0093\u0093 \u0093 \u0094 \u0094\u0094\u0094 \u0094 \u0095\u0095\u0095 \u0095 \u0096\u0096 \u0096 \u0096\u0096 \u0096 \u0097 \u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098 \u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u008d\u008d\u008d \u008d\u008d\u008d \u008e \u008e\u008e \u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090 \u0091\u0091\u0091\u0091\u0091\u0091 \u0092\u0092 \u0093\u0093 \u0093 \u0094\u0094\u0094 \u0094\u0094\u0094 \u0095 \u0095\u0095\u0095\u0095 \u0096\u0096\u0096\u0096 \u0096\u0096 \u0097\u0097 \u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098 \u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u008c\u008c\u008c\u008c\u008c\u008c \u008d\u008d\u008d\u008d \u0090\u0090\u0090 \u0091\u0091\u0091\u0091 \u0093\u0093\u0093\u0093\u0093\u0093\u0093 \u0094\u0094 \u0094\u0094 \u0095 \u0095 \u0096\u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 ", + " \u0090\u0090\u0090 \u0095\u0095\u0095 ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c\u009c\u009c\u009c\u009c\u009c \u009d\u009d\u009d\u009d\u009d ", + " \u009e\u009e \u009f\u009f\u009f\u009f\u009f\u009f \u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c \u009c\u009c \u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2 \u00a3\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4 \u009d \u009d \u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7 \u00a8\u00a8 \u00a9\u00a9 ", + " \u009e\u009e \u009f \u009f \u009f \u00a0\u00a0\u00a0\u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c \u009c\u009c \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2 \u00a3\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u009d \u009d \u00a5 \u00a5 \u00a6\u00a6 \u00a7\u00a7 \u00a7\u00a7 \u00a8\u00a8\u00a8\u00a8 \u00a9\u00a9 \u00a9 ", + " \u009e\u009e\u009e \u009e\u009e\u009e \u009f \u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0 \u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c\u009c\u009c\u009c \u009c\u009c \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2 \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u009d \u009d \u00a5 \u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6 \u00a7 \u00a7\u00a7\u00a7 \u00a7 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00a9 \u00a9 ", + " \u009e\u009e \u009e\u009e \u009f \u009f \u00a0\u00a0\u00a0\u00a0 \u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c \u009c\u009c\u009c\u009c \u009c \u00a1\u00a1 \u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a3\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u009d \u009d \u00a5\u00a5\u00a5 \u00a5 \u00a6 \u00a6 \u00a7 \u00a7\u00a7\u00a7 \u00a7 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00a9 ", + " \u009e\u009e \u009e\u009e \u009f \u009f \u00a0\u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c \u009c\u009c \u009c \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2 \u00a3\u00a3\u00a3\u00a3 \u00a3\u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u009d \u009d \u00a5\u00a5 \u00a5 \u00a6\u00a6 \u00a6 \u00a7 \u00a7\u00a7\u00a7 \u00a7 \u00a8\u00a8\u00a8\u00a8\u00a8 \u00a9 \u00a9 ", + " \u009e \u009e \u009f \u009f \u00a0 \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c \u009c \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2 \u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3 \u00a4\u00a4 \u00a4 \u00a4\u00a4\u00a4 \u009d \u009d \u00a5\u00a5 \u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a7\u00a7 \u00a7\u00a7 \u00a8\u00a8 \u00a8\u00a8 \u00a9 \u00a9 ", + " \u009e\u009e\u009e\u009e\u009e\u009e \u009f \u009f \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009c\u009c\u009c\u009c\u009c\u009c \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2 \u00a3\u00a3\u00a3\u00a3\u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4\u00a4 \u009d\u009d\u009d\u009d\u009d \u00a5 \u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a7\u00a7 \u00a7\u00a7\u00a7\u00a7 \u00a8\u00a8\u00a8 \u00a9 \u00a9 ", + " \u009e \u009e \u009f \u009f \u00a1\u00a1 \u00a3\u00a3\u00a3 \u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7 \u00a8\u00a8\u00a8 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 ", + " \u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f \u00a5\u00a5\u00a5\u00a5\u00a5 \u00a8 \u00a9\u00a9 ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u00aa\u00aa \u00ab \u00ab\u00ab \u00ac \u00ad\u00ad \u00ad\u00ad \u00ae\u00ae \u00af\u00af\u00af \u00b0\u00b0 \u00b1\u00b1 \u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4 \u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6 ", + " \u00aa\u00aa \u00ab\u00ab\u00ab\u00ab\u00ab \u00ac\u00ac \u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7 \u00ad \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00af\u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0 \u00b0\u00b0 \u00b1\u00b1\u00b1 \u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b6 \u00b6 ", + " \u00aa\u00aa\u00aa\u00aa \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00ac\u00ac\u00ac\u00ac \u00b7 \u00b7\u00b7 \u00b7 \u00ad \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae \u00ae\u00ae\u00ae \u00af\u00af\u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b1\u00b1 \u00b2\u00b2\u00b2\u00b2 \u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5 \u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00ac\u00ac\u00ac\u00ac \u00b7\u00b7 \u00ad\u00ad\u00ad\u00ad \u00ad\u00ad \u00ae\u00ae\u00ae\u00ae \u00ae\u00ae\u00ae \u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b1\u00b1 \u00b2 \u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4 \u00b4\u00b4\u00b4 \u00b4 \u00b5\u00b5\u00b5 \u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00ac\u00ac\u00ac\u00ac \u00b7\u00b7 \u00ad \u00ad \u00ae\u00ae \u00ae\u00ae \u00af \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0\u00b0 \u00b0\u00b0\u00b0 \u00b1\u00b1 \u00b1 \u00b2\u00b2\u00b2 \u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4 \u00b4\u00b4\u00b4 \u00b4 \u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00aa\u00aa\u00aa\u00aa \u00ab\u00ab \u00ab\u00ab\u00ab \u00ac\u00ac \u00b7\u00b7 \u00ad \u00ad \u00ad \u00ae\u00ae\u00ae\u00ae \u00ae\u00ae\u00ae \u00af\u00af\u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0\u00b0\u00b0 \u00b0\u00b0\u00b0\u00b0\u00b0 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00b2 \u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4 \u00b4 \u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00ab\u00ab \u00ab\u00ab\u00ab \u00ac \u00b7\u00b7\u00b7 \u00ad \u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00af\u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0\u00b0\u00b0\u00b0\u00b0 \u00b0\u00b0 \u00b1\u00b1\u00b1\u00b1 \u00b2 \u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4 \u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5 \u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00aa\u00aa \u00aa\u00aa \u00b7 \u00b7 \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae \u00af\u00af\u00af \u00b8\u00b8\u00b8\u00b8\u00b8 \u00b0 \u00b0 \u00b0 \u00b0\u00b0 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5\u00b5\u00b5 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00b6 ", + " \u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7 \u00b8\u00b8\u00b8 \u00b0\u00b0 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bc \u00bd \u00bd\u00bd \u00be\u00be\u00be \u00bf \u00c0 \u00c1\u00c1\u00c1 \u00c2\u00c2\u00c2\u00c2\u00c2 \u00c3\u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c7\u00c7 \u00c7\u00c7 ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb \u00bb\u00bb \u00bc \u00bc \u00bc\u00bc\u00bc \u00bd \u00bd\u00bd\u00bd \u00be\u00be\u00be \u00bf\u00bf\u00bf\u00bf\u00bf \u00c0\u00c0\u00c0 \u00c0\u00c0\u00c0\u00c0\u00c0 \u00c1\u00c1 \u00c1\u00c1 \u00c2 \u00c2 \u00c3 \u00c3 \u00c4 \u00c4 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c7 \u00c7 ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba \u00bb \u00bb \u00bc \u00bc \u00bc \u00bd \u00bd\u00bd\u00bd \u00be\u00be\u00be \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0\u00c0\u00c0 \u00c0 \u00c1\u00c1 \u00c1\u00c1 \u00c2 \u00c2 \u00c3\u00c3\u00c3 \u00c3\u00c3\u00c3\u00c3\u00c3 \u00c4 \u00c4\u00c4\u00c4 \u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7\u00c7\u00c7 ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba\u00ba\u00ba \u00ba \u00bb \u00bb \u00bb\u00bb \u00bc \u00bc \u00bd \u00bd\u00bd\u00bd \u00be\u00be\u00be \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c1\u00c1 \u00c1\u00c1 \u00c2 \u00c2 \u00c3\u00c3 \u00c3 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7\u00c7\u00c7 ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba\u00ba\u00ba \u00ba \u00bb\u00bb\u00bb \u00bb\u00bb\u00bb \u00bc \u00bc \u00bd \u00bd \u00bd\u00bd \u00be\u00be\u00be \u00bf\u00bf\u00bf \u00bf\u00bf \u00c0\u00c0\u00c0 \u00c0 \u00c1\u00c1\u00c1\u00c1\u00c1 \u00c1 \u00c2 \u00c3\u00c3 \u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4\u00c4 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c6\u00c6 \u00c6\u00c6 \u00c7\u00c7\u00c7 \u00c7 ", + " \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00ba\u00ba\u00ba \u00ba \u00bb\u00bb \u00bb\u00bb\u00bb \u00bc \u00bc \u00bd \u00bd\u00bd \u00bd \u00be\u00be\u00be \u00bf\u00bf \u00bf \u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0 \u00c1\u00c1\u00c1\u00c1 \u00c2 \u00c2 \u00c3\u00c3 \u00c3 \u00c4 \u00c4 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c6\u00c6 \u00c6\u00c6 \u00c6\u00c6 \u00c7 \u00c7 ", + " \u00b9\u00b9\u00b9\u00b9 \u00ba \u00bb \u00bb \u00bc \u00bc \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00be\u00be\u00be \u00bf \u00c0\u00c0 \u00c0\u00c0\u00c0\u00c0\u00c0 \u00c1\u00c1 \u00c2 \u00c2 \u00c3\u00c3\u00c3 \u00c3 \u00c4 \u00c4\u00c4 \u00c5 \u00c5 \u00c5\u00c5 \u00c6\u00c6 \u00c6\u00c6 \u00c6\u00c6 \u00c7 \u00c7\u00c7 ", + " \u00b9\u00b9 \u00ba\u00ba\u00ba\u00ba\u00ba \u00bc\u00bc\u00bc\u00bc \u00bc \u00be \u00c0 \u00c1\u00c1 \u00c2\u00c2\u00c2\u00c2\u00c2 \u00c3\u00c3\u00c3 \u00c4\u00c4 \u00c5 \u00c7\u00c7\u00c7 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u00c8 \u00c9 \u00ca \u00cb \u00cb ", + " \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd \u00cd\u00cd\u00cd \u00ce \u00ce\u00ce\u00ce\u00ce \u00ce \u00cf\u00cf \u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9 \u00d0\u00d0 \u00d1 \u00d1 \u00d1\u00d1 \u00d2\u00d2 \u00d2 \u00d2 \u00ca\u00ca\u00ca \u00d3\u00d3\u00d3 \u00d4\u00d4 \u00d4\u00d4\u00d4 \u00cb \u00cb \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6 ", + " \u00cc \u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00cf\u00cf \u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9 \u00d0\u00d0 \u00d1\u00d1 \u00d1\u00d1\u00d1 \u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00ca\u00ca\u00ca\u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb \u00cb \u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6 ", + " \u00cc\u00cc\u00cc \u00cc\u00cc\u00cc \u00cd\u00cd \u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00cf\u00cf \u00c8\u00c8\u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9 \u00d0\u00d0 \u00d0\u00d0 \u00d0 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2 \u00d2\u00d2\u00d2\u00d2 \u00ca\u00ca\u00ca\u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6 ", + " \u00cc \u00cc\u00cc \u00cc\u00cc \u00cc \u00cd\u00cd \u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00cf\u00cf \u00c8\u00c8\u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9 \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d1 \u00d1 \u00d1 \u00d1 \u00d1 \u00d2\u00d2\u00d2 \u00d2\u00d2 \u00d2\u00d2\u00d2 \u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6 \u00d6 ", + " \u00cc \u00cc\u00cc\u00cc\u00cc \u00cc \u00cd\u00cd \u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00cf\u00cf \u00c8 \u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9\u00c9 \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2 \u00d2\u00d2 \u00d2\u00d2\u00d2 \u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5 \u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6 ", + " \u00cc \u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce\u00ce \u00cf \u00c8\u00c8\u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9\u00c9 \u00d0\u00d0\u00d0\u00d0 \u00d1 \u00d1 \u00d1 \u00d1 \u00d1 \u00d2\u00d2\u00d2\u00d2 \u00d2\u00d2\u00d2\u00d2 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6 \u00d6 \u00d6 ", + " \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd \u00cd\u00cd\u00cd \u00ce \u00cf\u00cf \u00c8\u00c8\u00c8 \u00c9\u00c9\u00c9 \u00d0\u00d0 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2 \u00d2 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00ca\u00ca \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb\u00cb\u00cb \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6 ", + " \u00d1 \u00d1 \u00d1 \u00d1 \u00d1 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00d3 \u00d3 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00cb ", + " \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 ", + " ", + " ", + " ", + " ", + " \u00d7\u00d7 ", + " \u00d7\u00d7\u00d7\u00d7 ", + " \u00d8 \u00d9 \u00da\u00da\u00da \u00db\u00db\u00db\u00db\u00db\u00db \u00dc\u00dc\u00dc \u00dd \u00de \u00df\u00df \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2 \u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00e5\u00e5\u00e5\u00e5 ", + " \u00d8\u00d8\u00d8\u00d8\u00d8 \u00d9 \u00da \u00da\u00da \u00db\u00db \u00db\u00db \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3 \u00e3\u00e3\u00e3 \u00e4 \u00e4 \u00e4 \u00e4 \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 ", + " \u00d8\u00d8 \u00d8\u00d8 \u00d9 \u00da \u00da\u00da \u00db\u00db \u00db\u00db \u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0 \u00e1\u00e1 \u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5 ", + " \u00d8 \u00d8\u00d8 \u00d9 \u00d9 \u00da\u00da\u00da\u00da\u00da\u00da \u00db\u00db\u00db\u00db\u00db \u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0 \u00e1 \u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3 \u00e4 \u00e4 \u00e4 \u00e4 \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5 ", + " \u00d8 \u00d8\u00d8 \u00d9 \u00d9 \u00da\u00da\u00da\u00da\u00da\u00da \u00db\u00db \u00db\u00db \u00dc \u00dc\u00dc\u00dc\u00dc \u00de\u00de \u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df \u00e0\u00e0\u00e0 \u00e0\u00e0 \u00e1 \u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5\u00e5 ", + " \u00d8\u00d8 \u00d8\u00d8 \u00d9 \u00d9 \u00d9 \u00da\u00da\u00da\u00da\u00da\u00da \u00db\u00db \u00db\u00db \u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de \u00df\u00df \u00df \u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0 \u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3 \u00e4 \u00e4 \u00e4 \u00e4 \u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5\u00e5 ", + " \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00d9 \u00d9 \u00d9 \u00d9 \u00da\u00da\u00da\u00da\u00da\u00da \u00db\u00db \u00db\u00db \u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de \u00df \u00df \u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 ", + " \u00d8\u00d8\u00d8 \u00d8\u00d8 \u00d9\u00d9\u00d9 \u00d9 \u00d9 \u00d9 \u00db\u00db\u00db\u00db\u00db\u00db\u00db \u00dc\u00dc\u00dc\u00dc\u00dc \u00de\u00de \u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3 ", + " \u00d8 \u00e2\u00e2\u00e2 ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e8 \u00e9\u00e9\u00e9\u00e9 \u00ea ", + " \u00eb\u00eb \u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00ec\u00ec \u00ed\u00ed\u00ed \u00ee \u00ee\u00ee \u00ef \u00e8\u00e8 \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1 \u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00f3\u00f3\u00f3 \u00f3\u00f3 \u00ea\u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb\u00eb\u00eb \u00e6 \u00e6 \u00e6\u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00ec\u00ec \u00ed\u00ed \u00ed\u00ed \u00ee\u00ee \u00ee\u00ee \u00ef\u00ef\u00ef \u00e8\u00e8\u00e8 \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1 \u00f2\u00f2\u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00f3 \u00f3 \u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb\u00eb\u00eb \u00e6\u00e6 \u00e6 \u00e6\u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00ec\u00ec\u00ec \u00ed \u00ed \u00ee\u00ee\u00ee \u00ee\u00ee \u00ef\u00ef\u00ef \u00e8\u00e8 \u00e8\u00e8 \u00f0\u00f0\u00f0\u00f0 \u00f0\u00f0 \u00f1 \u00f1\u00f1\u00f1\u00f1\u00f1 \u00f1 \u00f2\u00f2\u00f2\u00f2\u00f2 \u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00f3 \u00f3 \u00f4\u00f4\u00f4\u00f4\u00f4\u00f4 \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb \u00eb \u00e6 \u00e6 \u00e6\u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00ec \u00ec\u00ec \u00ed\u00ed \u00ed\u00ed \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00e8\u00e8 \u00e8\u00e8 \u00f0\u00f0 \u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1 \u00f2\u00f2\u00f2\u00f2 \u00f2\u00f2 \u00f3 \u00f3 \u00f4\u00f4\u00f4\u00f4 \u00ea\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00ea ", + " \u00eb \u00e6 \u00e6\u00e6 \u00e7 \u00e7 \u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8 \u00f0\u00f0 \u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1 \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00f3 \u00f3 \u00f4\u00f4 \u00ea\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb \u00e6\u00e6 \u00e6 \u00e7 \u00e7 \u00ec \u00ec\u00ec \u00ed\u00ed\u00ed \u00ee\u00ee\u00ee \u00ee\u00ee \u00ef\u00ef\u00ef\u00ef \u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8 \u00f0\u00f0\u00f0 \u00f0\u00f0\u00f0\u00f0 \u00f1 \u00f2\u00f2 \u00f2\u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00f3\u00f3 \u00f3 \u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb \u00e6\u00e6\u00e6 \u00e6\u00e6\u00e6 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00ec \u00ec\u00ec \u00ed\u00ed\u00ed \u00ee\u00ee \u00ee\u00ee \u00ef\u00ef\u00ef\u00ef \u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8\u00e8 \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1 \u00f2\u00f2 \u00f2 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea ", + " \u00eb\u00eb\u00eb \u00e6\u00e6\u00e6\u00e6 \u00ec\u00ec\u00ec \u00ec\u00ec\u00ec\u00ec \u00ed \u00ee \u00ee\u00ee \u00ef\u00ef\u00ef \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8 \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1 \u00f2\u00f2\u00f2 \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 ", + " \u00eb\u00eb ", + " ", + " ", + " ", + " ", + " ", + " ", + " \u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6 \u00f7 \u00f8 \u00f9\u00f9\u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa \u00fb ", + " \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u00fd\u00fd\u00fd\u00fd \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7 \u00fe \u00fe\u00fe \u00fe\u00fe \u00ff\u00ff \u0100\u0100\u0100\u0100 \u00f8 \u00f8\u00f8 \u00f9\u00f9 \u00f9\u00f9 \u00fa \u00fa \u0101\u0101\u0101\u0101\u0101\u0101\u0101 \u00fb\u00fb \u00fb\u00fb \u0102\u0102 \u0103 ", + " \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u00fd\u00fd \u00fd\u00fd \u00f5\u00f5 \u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7 \u00fe\u00fe \u00fe\u00fe\u00fe \u00fe\u00fe \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100 \u0100 \u00f8 \u00f8 \u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa \u00fa \u0101\u0101\u0101\u0101\u0101 \u00fb \u00fb \u0102\u0102\u0102\u0102 \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fc\u00fc\u00fc\u00fc \u00fd\u00fd \u00fd\u00fd \u00f5\u00f5 \u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7 \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00ff\u00ff\u00ff \u0100 \u0100\u0100\u0100 \u0100\u0100\u0100 \u00f8 \u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa \u00fa \u0101\u0101\u0101 \u00fb\u00fb\u00fb \u0102\u0102\u0102\u0102\u0102 \u0103\u0103 ", + " \u00fc\u00fc \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7 \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u0100 \u0100\u0100\u0100 \u0100 \u0100 \u00f8 \u00f8 \u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u0101\u0101 \u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb \u0103 \u0103 ", + " \u00fc\u00fc \u00fd\u00fd \u00fd \u00f5\u00f5\u00f5 \u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7 \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u0100\u0100 \u0100 \u0100 \u0100 \u00f8 \u00f8 \u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9 \u00f9 \u00fa \u00fa\u00fa\u00fa \u0101\u0101 \u00fb\u00fb \u0102\u0102\u0102\u0102\u0102 \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fc\u00fc \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7 \u00fe\u00fe \u00fe\u00fe\u00fe \u00fe\u00fe \u00ff\u00ff\u00ff \u0100\u0100 \u0100\u0100 \u00f8 \u00f8 \u00f8 \u00f8\u00f8\u00f8 \u00f9 \u00f9\u00f9\u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u0101\u0101 \u00fb \u00fb \u0102\u0102\u0102 \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fc\u00fc \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7 \u00fe \u00fe\u00fe \u00fe\u00fe \u00ff\u00ff\u00ff \u0100 \u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8 \u0101 \u00fb\u00fb \u00fb\u00fb \u0102 ", + " \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u00fd\u00fd \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00fe \u00fe\u00fe \u00ff\u00ff ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-iconic-font-1000-1000-2.0-grid-reference.json b/tests/visual_tests/grids/text-iconic-font-1000-1000-2.0-grid-reference.json new file mode 100644 index 000000000..6d6bbd77f --- /dev/null +++ b/tests/visual_tests/grids/text-iconic-font-1000-1000-2.0-grid-reference.json @@ -0,0 +1,483 @@ +{ + "keys": [ + "", + "135", + "30", + "45", + "60", + "90", + "120", + "150", + "165", + "180", + "195", + "210", + "15", + "75", + "105", + "225", + "29", + "44", + "59", + "74", + "89", + "104", + "119", + "149", + "179", + "194", + "209", + "224", + "14", + "134", + "164", + "58", + "103", + "118", + "208", + "13", + "28", + "43", + "73", + "88", + "133", + "148", + "163", + "178", + "193", + "223", + "12", + "27", + "42", + "57", + "87", + "102", + "117", + "132", + "147", + "162", + "177", + "207", + "222", + "72", + "192", + "11", + "56", + "146", + "26", + "41", + "71", + "86", + "101", + "131", + "161", + "176", + "191", + "221", + "116", + "206", + "10", + "25", + "40", + "55", + "130", + "70", + "85", + "100", + "115", + "145", + "160", + "175", + "190", + "220", + "205", + "24", + "39", + "54", + "84", + "99", + "144", + "159", + "174", + "189", + "219", + "9", + "69", + "129", + "204", + "114", + "53", + "98", + "128", + "23", + "38", + "68", + "83", + "143", + "158", + "173", + "188", + "203", + "218", + "113", + "8", + "7", + "22", + "37", + "52", + "67", + "82", + "97", + "112", + "142", + "157", + "172", + "187", + "217", + "127", + "202", + "66", + "141", + "6", + "21", + "36", + "81", + "96", + "126", + "171", + "186", + "201", + "216", + "51", + "156", + "111", + "35", + "65", + "80", + "95", + "110", + "170", + "5", + "20", + "50", + "125", + "140", + "155", + "185", + "200", + "215", + "64", + "19", + "34", + "49", + "79", + "94", + "109", + "124", + "139", + "169", + "184", + "214", + "4", + "154", + "199", + "33", + "108", + "183", + "198", + "18", + "48", + "63", + "78", + "93", + "123", + "138", + "153", + "168", + "213", + "3", + "167", + "32", + "107", + "212", + "17", + "47", + "62", + "77", + "122", + "137", + "152", + "182", + "2", + "92", + "197", + "31", + "46", + "61", + "121", + "136", + "151", + "181", + "196", + "1", + "16", + "76", + "91", + "106", + "166", + "211" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!!!!! ", + " ## $$$$$$$$ %%%%%%%%%%%%%%%%% && ' ' !!!!!!!! !!!!!((((( )))))))))))))))))** +++++++++++++++ ,, ", + " ----- ######## # $$$$$$$$$$ %%%%%%%%%%%%%%%%%.%% . &&&&&&&& ////// '' '''!!!!!!!!! !!!!((((((( ))))))))))))) *** +++++++++++++++++ ,,,,,,, 00000 ", + " --------- ############# $$ $$$ %% ..% .. &&&&&&&&&&& ////////// '''''''''''''''!! !!!!!(((((((( )))))))))))))))))** +++++++++++++++++ ,, ,,, 000 ", + " ----------- ##### ###### $$ $$$$%% %%% ... ... &&&& &&&& ///// //////''''''''''''''''!' !!!!!! (((((( )))))))))))))))))** ***********++ + ++ ,, , ,, 00 0000 ", + " ---- ---- ### #### $$ $$$%% %%%% .... .... &&& &&&&& ///// ////// //'''''''''''''''!' !!!! !! ((((( **** ***********++ + ++ , , , 000 00000 ", + " --- - --- #### ##### $$ $%% %%%% %% ..... ..... &&& &&&&&&// // ////// //'' ''! !!!! (((( (((( ))))))))))))))))**** ***********++ + ++ , , 0000 00000000 ", + " --- - --- ### ###### $$ $%% %%% %%%% ...... ...... &&& &&&& &&// ///////// //' ''! !!!! (((((( (((( ))))))) ) ++ + ++ ,, ,, 0000000000000000000 ", + " -- - --- ### $$$$ $%% %%%%%% ....... ....... &&& &&&& &&// ///////// // ! !!!! (((((( ((( ))))))) **** ++ + ++ ,, ,,, 0000000000000000000 ", + " -- ------- --- ### $$$$$$$$$$$$$$%%$ %%%%%%%%................&&& &&&& &&// /////// // ! !!!! ! ((((( (((())))))))))))))))))** ***********++ + ++ ,, ,, 0000 00000000 ", + " --- - --- ### $$$$$$$$$$$$$$%%$ %% %%%%%%%%%............... &&& &&&& &&&/// ///// // ! !!! ! (((( ((( ** ***********++ + ++ ,, ,, 000 00000 ", + " --- - ---- ### $$$$$$$$$$$$$$%%$ %%%%%%%%%%%%%....... ...... && &&&& &&& /// /// ! ! ! ((( ((( ((())))))))))))))))** * ***********++ + ++ ,,,,, 00 0000 ", + " ---- - --- #### ## $$$$$$$$$$$$$$%%$%%%%%%%%%%%%%%...... ..... &&&&&& &&& ////////// ! ! ((( ((( (())))))))))))))))**** ++ + ++ ,,,,,, 000 ", + " ----- ----- #### #### $$$$ $%%$%%%%%%%%%%%%%%..... .... &&&&& &&&& ////// !! !! ((((( ((( (())))))))))) ) ++ + ++ ,,,,,, 00000 ", + " ------------ ############ $$$$ $%%$%%%%%%%%%%%%%%.... ... &&&&& &&&&& !!!!!!!!!!!!!! ((( ((( (())))))))))))))))**** ***********++ + ++ ,,,,,, ", + " ------- ---- ######### $$ $%% ... .. &&&&&&&&&& !!!!!!!!!!!! * * ***********++ + ++ ,,,,,, ", + " ---- ####### $$$$$$$$$$$$%%%%%%%%%%%%%%%%%.. . &&&&&& *** ***********+++++++++++++++++ ,,, ", + " --- 11111 2222222222222 3333333333 444444444444444 555555 6 7 8888888888888888888 99** :: ;;;;;;;;;;;;; <<<<<<<< ", + " === === -- 111111111 2222222222222333333333333 3444444444444444 555555555 666 777 >>>>>>>>>> 8888888888888888888 ??????**** 9999999999999 ::: ;;;;;;;;;;;;; <<<<<<<< ", + " ===== ===== 11111111111 22222222222223333333333333 33444444444444444 555555555555 666 77777 >>>>>>>>>> 8 8 ?????? 9999 9999999999999 :::: ;;; ;;; < << ", + " ============ 1111 111 22222222222223333333333333 333444444444444444 555 5555 66666 7777777 >>>>>>>> 8 8 ???? 999 9999999999999 ::::: ;;;;;;;;;;;;; << <<<<<<<<<<< << ", + " ========== 111 11 111 222222222222233333333333333333444444444444444 555 555 666666 777 >>>>>> 8888888888888888888 ???? :::::: ;;;;;;;;;;;;; << <<<<<<<<<<< <<< ", + " ======== 111 1111 111 222222222222233333333333333333444444444444444 55 55 555 6666666 777 >>>>>> 8888888888888888888 ????? 99 :::::: ;;;;;;;; ;; << <<<<< <<<< <<< ", + " ====== 111 11111 11 222222222222233333333333333333444444444444444555 5 555 555 66666666 777 >>>>>> 8888888888888888888 ????? ?9999 9999999999999 ::::: ;;;;;;;; ;;; << <<<<< <<<< <<< ", + " ======== 11 1111111 11 222222222222233333333333333333444444444444444555 555 5555 555 666666666 777 >>>>>> 8888888888888888888 ????????9999 9999999999999 :::: ;;;;;;;; ; ;;<< <<<<< <<<< <<< ", + " ========== 11 1111111 11 222222222222233333333333333333444444444444444555 5555555 555 666666666 777 >>>>>>>> 8 8 ?? ??????9999 9999999999999 ::: ;;;;;;;; ; ;<< << << <<< ", + " ============ 111 11111 11 222222222222233333333333333333444444444444444555 55555 555 66666666 777 >>>>>>>>>> 8 8 ???? ???? :: ;;;;;;;; ;;;;<< << << <<< ", + " ===== ===== 111 111 111 22222222222223333333333333 333444444444444444 555 555 555 6666666 777 >>>>>>>>>>>>8 8 ?????? 99 : ;;;;;;;; ;;;;<< <<<<< <<<< <<< ", + " ==== ==== 111 11 1111 222222 2222223333333333333 33444444444444444 555 5 555 66666 777 >>>>>>>>>>>>8 8 ?????? 9999 9999999999999 ;;;;;;;; << <<<<< <<<< <<< ", + " == == 1111 1111 22222 22222 33333333333 3444444444444444 5555 5555 6666 777 >>>>>>>>>> 8 888 8888 8?????? 9999 9999999999999 ;;;;;;;; << <<<<< <<<< <<< ", + " 11111111111 2222 2222 444444444444444 55555555555 666 777 >> 8 ?????? 9999 9999999999999 ;;;;;;;; << <<<<<<<<<<< <<< ", + " 111111111 222 222 444444444444444 55555555 66 7777777 >> 88888888888888888??? ?? ;;;;;;;; << <<<<<<<<<<< <<< ", + " 1111 2 @@@@@@@@@@@@@@@@@444444444444444 5555 6 ABBBBB7777777 >> 8888888888888888????? ;;;;;;;; C < <<<<<<<<<<< << ", + " DDD EEEEEEEEEEE FFFFFFFFFFF@@@@@@@@@@@@@@@@@GGGGGG GGGGGG HHHHHHH ABBBBBBB77777 IIIIII>>IIIIII JJJJJJJ ??? KKKKKKK LLLLLLLLLLLLLLLL MM ;;CC ; NNNNNNNNNNNNNN ", + " DDDDD EEEEEEEEEEE FFFFFFFFFFFF@@@@@@@@@@@@@@@@@GGGGGG GGGGGG HHHHHHHHHH 6666666666666BBBBBBBB777 IIIIIIIIIIIIIIII JJJ JJJJ KKKKKKKKKK LLLLLLLLLLLLLLLL MMM ;;;;;;;;;;;; NNNNNN NNNNNN ", + " DDDDDD EEE EEE FFFFFFFFFFFF GGGGGG GGGGGG HHHHH HHHH AAAAAAAAAAABBBBBBBBBBBBBBB IIIIIIIIIIIIIIII JJ JJ KKK KKKKKK LLLLLLLLLLLLLL MMMM CCCCCCCCCC NNNNNN NNNNNN ", + " D DDDDDD EEE EE FFF FFF@F @@@@@@@@@@@GGGGGG GGGGGG HHHH HHH AAAAAAAAAAAABBBBBBBBBBBBBBB III IIIIIIIIIII JJ JJKK KKK KKKK MMMMM CCCCCCCCCCCC NNNNNN NNNNNN ", + " DDD DDDDDD EE EEE FFFFFFFFFFFF @@ @@@@@@@@@@@GGGGGG GGGGGG HHH H H HHH AAAAAAAAA AAABBBBBBBBBBBBBBB III IIIIIIIIIIII JJ JJKK K KKKK MMMMMM CCCCCCCCCCCCCC NNNNNN NNN ", + " DDDDD DDDDDD EEE EE FFF FF @@@ @@@@@@@@@@@GGGGGG GGGGGG HH HHHHHH HHH AAAAAA AAAABBBBBBBBBBBBBBB IIIIIIIIIIIIIIIIJJJJJJJJJJ JJKKK KKKKKLLLLLLLLLLLLLLLL MMMMMM CCCCCCCCCCCCCCCCNNN NNN NNN ", + " DDDDDDDDDDDD EE EE FFFFFFFFFFFF @@@ GGGGGG GGGGGGHHH HHHHHH HHHAAAAA AAAAAAABBBB III I I IIIJJJJJJJJJJJJ JKKKK KKKKKKLLLLLLLLLLLLLLLL MMMMM CCCCCCCCCCCCCCCNNN NNNNNN NNNNNN ", + " DDDDDDDDDD EEEEEE EEEEE FFFFFFFFFFFF F@@@ @@@@@@@@@@@GGGGGG GGGGGGHHH HHHH HHHAAAA AAAAAAAAABBB BBBBBBBBBBBBIII I II IIJJJJJJJJJJJJ KKKKK KKKKKKKLLLLLLLLLLLLLLL MMMM C CCCCC CC NNNNNNNNNNN NNNNNN ", + " DDDDDDDD EEEEEE EEEEEE FFFFFFFFFFFF F@@ @@@@@@@@@@@GGGGGG GGGGGGHHH HHHHHH HHHAAA AAAAAAAAAABB BBBBBBBBBBBBBIII I III IIJJJJJJJJJJJJ KKKKKK KKKKKKKKK MMM C CC CC NNNNNNNNNNN NNNNNN ", + " DDDDDD EEEEEEEEEEEEEEE FFFFFFFFFFFF F@ @@@@@@@@@@@GGGGGG GGGGGG HH HHHHHHH HHH AAAAAAAAAAAAABB BBBBBBBBBBBBBBIII I III IIJJJJJJJJJJJJ KKKKK KKKKKKKKK MM CC NNNNNNNNNNNNNNNNNNN ", + " DDDD EEEEEEEEEEEEEEEFFFFFFFFFFFF FF GGGGGG GGGGGG HHH H HH HH AAAAAAAAAAAAA B BBBBBBBBBBBBBBBIII I III IIJJJJJJJJJJJJ KKKKKKK KKKKKKKLLLLLLLLLLLLLLLL CC NNNNNNNNNNNNNNNNNNN ", + " DD EEEEEEEEEEEEEEEFFFFFFFFFFFF FF@@@@@@@@@@@@@@@@@GGGGGG GGGGGG HHHH HHHAAAAAAAAAAAA BBBBBBBBBBBBBBB III I III IIJJJJJJJJJJJJ KKKKKKKKK KKKK LLLLLLLLLLLLLLLL CC NNNNNNNNNNNNNNNNNNN ", + " EEEEEEEEEEEEEEEFFFFFFFFFFFF F @@@@@@@@@@@@@@@@@GGGGGG GGGGGG HHHH HHHH AA AAA BBBBBBBBBBBBBBB III I III IIJJJJJJJJJJJJ KKKKKKKK KK LLLLLLLLLLLLLLLL C CC NNN NNNNNNN NNNN ", + " F FF GGGGGG GGGGGG HHHHHHHHHH IIIIIIIIIIIIIIII KKKKKKKKKK C CC NN NN NN NN ", + " FFFFFFFFFFFFF GGGGGG GGGGGG HHHHHHHH IIIIIIIIIIIIII KKKKKKK CCCC NNNN NNNN ", + " OOOOO OOOOOOOOOOOO PPP QQQQQQ QQQ RRRRRRRRRRRRRRRRRR SS TTT TTT UUUUUUU VVVVV WWW XXXX YYYYYYYYYYYY CCZZZ [[[[[[ ", + " OOOOO OOOOOOOOOOOO PPPPPPPPP QQQQQQQQ QQQ RRRRRRRRRRRRRRRRR]]] SSS TTTT TTTTT UUUUUUUU VVVVVV VV WWWWWWWWW XXXXXXXX YYYYYYYYYYYYYY ^ ZZZZZZ [[[[[[[ ", + " OOOOO OOOOOOOOOOOO PPPPPPPPPPPQQQQQQQQQQ QQQ ]]]] SSSS TT TTTT T UUUUUUUUUUUUUUUUV VVV WWWWWWWWWWW XXXXXXXXXXX YYYYYYYYYYYYYYYY ^^^ ZZZZZZ [[ [[ [ ", + " OOOOO OOOOOOOOOOOPPPP PPPQQQ QQQQQQ QQQ ]]]]]] SSSSSSSS TTTTTTTTTT UUUUUUUUUUUUUUUUV VVVV WWWWWWWWWWWWW XXXXX XXXXXX YYYYYYYYYYYYYYYY ^^^^^ ZZZZZZ [[ [ ", + " PPP P PPQQQ QQQQQQQ QQQ RR RRRRRRRRRRR]]]]]]]] SSS SSSSSS TTTTTTTT UUUUUUUUUUUUUUUUV VVVVVVVVVVV WW W W WWW XXXXXX XXXXXX YYYYYYYYYYYYYYYY ^^^^^^^ ZZZZZZ [[[[[ [[ [[[[[ ", + " OOOOO OOOOOOOOOOOPPP PPP PQQQQQQQQQQQQQ QQQ RRR RRRRRRRRRRR]]]]]]]]]] SS SS S TTTTTT TTTTTTUUUUUUUUUUUUUUUUV VVVVVVVVVVVV WWWW WWW XXXXXX XXXXXXXYYYYYYYYYYYYYYYY ^^^^^^^^^ ZZZZ [[[[[[[[[[[[[[ ", + " OOOOO OOOOOOOOOOOPPP PPPPP PQQQQQQQQQQQQQ QQRRRR ]]]]]]]]]]]] SS SS TTTTTT TTTTTTUUUUUUUUUUUUUUUUV VVVVVVVVVVVV WWW WWW XXXXXX XXXXXXXYYYYYYYYYYYYYYYY ^^^^^^^^^^^ ZZ [ [[[[[[ [[ ", + " OOOOO OOOOOOOOOOOPP PPPPPPP PQQQQQQQQQQQQQQ QRRRR RRRRRRRRRRR]]]]]]]]]]]]] SSSSSS SSSSSTTTTTT TTTTTTUUUUUUUUUUUUUUUUV VVVVVVVVVVVV WWW WWWXXXX X XX XXXYYYYYYYYYYYYYYYY ZZZZZZZZZZZZZ [ [[ ", + " OOOOO OOOOOOOOOOOPP PPP PPQQQQQQQQQQQQQQ QRRR RRRRRRRRRRR]]]]]]]]]]]]]]]SSSSSS SSSSSTTTTTT TTTTTTUUUUUUUUUUUUUUUUV VVVVVVVVVVV WWW WWWXXX X XXXYYYYYYYYYYYYYYYY ZZZZZZZZZZZZZZ [ [[ [ [[ [ [[ ", + " PPP PPP PP QQQQQQQQQQQQQ QQRR RRRRRRRRRRR]]]]]]]]]]]]] SSSS SSSSS TTTTT TTTTT UUUUUUUUUUUUUUUUV VVVVVVVVV WWW WWW XXX XXXXYYYYYYYYYYYYYYYY Z ZZ Z [ [[ [ [[ [ [[ ", + " OOOOO OOOOOOOOOOOPPP PPP PPP QQQQQQQQQQQQ QQ ]]]]]]]]]]]] SS SS TTTTT TTTTT UUUUUUUUUUUUUUUUV VVV WWWW WWWW XXXX XXXXXYYYYYYYYYYYYYYYY Z ZZ Z [ [[ ", + " OOOOO OOOOOOOOOOOPPPP PPP PPP QQQQQQQQQQ QRRRRRRRRRRRRRRRRR]]]]]]]]]] SS SSS SS TTTTT TTTTT UUUUUUUUUUUUUUUUVV VV W WWW WWWWWW XXXXX XXXXX YYYYYYYYYYYYYYYY ZZZZZ ZZZZZZ ZZZZZ[ [[ [ [[ [ [[ ", + " OOOOO OOOOOOOOOOOOPPPP PPP QQQQQQQQ QQRRRRRRRRRRRRRRRRR]]]]]]]] SSSSSSSS TTTTTTTTTTTTT UUUUUUUUUUUUUUUUVVVVVV V WW WW WWWWW XXXXX XXXXXX YYYYYYYYYYYYYYYY ZZZZZ ZZZZZZ ZZZZZ[ [[ ", + " OOOOO OOOOOOOOOOOO PPPPPPPPPPP QQQQQQ QQ RRRRRRRRRRRRRRRRR]]]]]] SSSSS TTTTTTTTTTTT UUUUUUUUUUUUUUU WW WWWW XXXXXXXXXXXX YYYYYYYYYYYYYYYY ZZZZZ ZZZZZZ ZZZZZ[ [[ [ [[ ", + " PPPPPPPPP QQQQ QQ ]]]] SSS WWW WWW XXXXXXXXX YYYYYYYYYYYYYYY ZZZZZ ZZZZZZ ZZZZZ[ [[ [[[[ [ [[ ", + " _____ ____ _____ PPPPP QQ Q ``` `````````````]]] SSS W aaaa XXXXXX YYYYYYYYYYYYY ZZZZZ ZZZZZ ZZZZZ[ [[[[ [[ ", + " _____ ______ _____ bbbbbb ccccccc ``` `````````````` d d eeeeee ffffff ggggg ggggg aaaaa hhhhhh iiiiiiiiiiii jjjjjjjjjjj [kkkk[[[[kkk[[ ", + " _____ ______ _____ bbbbbbbbb ccccccccc ``` `````````````` dd dd eeeeeeeeee ffffffffff llll ggggggg ggggggg aaaaaa hhhhhhhhhh ii iiii iiii jjjjjjjjjjj mmmmm [[[[[[[[[[[[[[ ", + " _____ ______ _____ bbbbb bbbbb ccc ccccc ddd ddd eeeee eeeee ffffffffffff llllllllllllgg gggg gg aaaa hhhhhhhhhhhh ii iiii ii ii jjjjjjjjj mmmmm [[[[[[[[[[[[[[ ", + " bbbb bbb ccc cccccc ``` `````````````` dddd dddd eeeee eeeeee fffff fffff llllllllllllgg gg gg aaa hhhhh hhhhhh ii iiii ii ii jjjjjjj mmmm k kk k kk k kk ", + " ____ ____ ____bbbb bbb bbbcccccccccccc ``` `````````````` ddddd dddddeeeeeeeeeeeeee fffff ffffff llllllllllllgl g aaa hhhhh hhhhh ii iiii ii ii jjjjj mmmm k kk ", + " _____ ______ ____bbb bbb bbbccccccccccccc ``` `````````````` dddddd ddddddeeeee eeeeeeefffffff ffffff llllllllllllgg gg aaaaaaaaa hhhh hhhhhii iiiiiiii ii jjj mmmm mmmm k kk k kk k kk ", + " _____ ______ ____bb bbb bb ccccccccccccc ddddddd ddddddeeeeee eeeeeeefffffff ffffff lllllllllllgg gg aaaaaaaaa hhh hhhhii iiiiiii ii mmmmmmmm k kk k kk k kk ", + " _____ ______ ____bb bbb bb cccccccccccccc``` `````````````dddddddddddddddeeeeeee eeeeeeefffffff fffffff llllllllllllgg gg aaaaaaaaa hhh h h hhhii ii mmmmmmmm k kk ", + " ____ ____ ____bb bbbbbbb bb ccccccccccccc``` `````````````dddddddddddddddeeeeeee eeeeeeefffffff fffffff llllllllllllggg ggg aaaaaaaaa hhhh hh hh hhhii ii mmmmmmm k kk k kk k kk ", + " bbb bbbbb bb cccccccccccc``` ``````````````ddddddd ddddddeeeeeee eeeeeeefffffffffffffff llll ggg ggg aaa hhhhhh hhhhhhhii iiiiiiiiii ii mm mmm k kk ", + " _____ ______ ____bbb bbb bbb ccccccccccc dddddd ddddddeeeeee eeeeeeefffffff ffffff ll ggg ggg aaa hhhhhh hhhhhhhii i i ii mm k kk k kk k kk ", + " _____ ______ _____bbb b bbbb ccccccccc ``` `````````````` ddddd dddddeeeee eeee ffffff ffffff llllllllllll ggg ggg aaa hhhhhh hhhhhh ii i i ii mmm k kk k kk k kk ", + " _____ ______ _____bbbb bbbb ccccccc ``` `````````````` dddd dddd eeee eee ffffff fffff ll ll ggg ggg aaa hhhhh hhhhhh ii i i ii mmm k kk ", + " _____ ____ _____ bbbbbbbbbbb ccccc ``` `````````````` ddd ddd eeeeeeeeeee fffffffffff lll lll gggggg aaa hhhhhhhhhhh ii i i ii mm k kk k kk ", + " bbbbbbbb ccc dd dd eeeeeeee ffffffff ll ll gggg aaa hhhhhhhh iiiiiiiiiiiiiiii mm k kkkk kk ", + " nnnnnnn nnnnnnn bbbo ppp ppp p ppp qqqqqqqqqqqqqqqqqq d d eee fff r aaa hhh iiiiiiiiiiiiii mm k kkkk kk ", + " nnnnnnn nnnnnnn oooo ppp ppp p ppp qqqqqqqqqqqqqqqsss s ss tttttttt uuuu v vvvvvvvvvvv r wwwwwww xxxxxxxx yyyyyy zzzzzzzzzzzzzzzzzzz mm {k{{{{kkkk{{ kk ", + " nnnnnnn nnnnnnn oooo ppp ppp p ppp qqqqqqqqqqqqqqqsss ss sss tttttttttt uuuu vvv vvvvvvvvvv rr ww wwwwwwww xxxxxxxxxx yy yyy zzzz zzzz||||m||| {kkkkkkkkkkkkkk ", + " nnnnnnn nnnnnnn oooo ppp ppp p ppp pp sss sss ssssttttt ttttt u uuuu uu vvvvv vvvvvvvvvv rr wwww wwwwwwww xxxxxx xxxxx y yyy zzz zzz zz||| ||| { { {{ ", + " nnnnnnn nnnnnnn ooooooooo ppp ppp p ppp qqqqqqqqqqqqqqqsss ssss ssssttttt tttt uuuu uuuuuuuuvvvvvvv vvv rrr wwwwwwwwwwwww xxxxxx xxxxx y yyyyyy zz zz zz || ||| { { {{ ", + " nnnnnnn nnnnnnn ooooooooooo ppp ppp p ppp qqqqqqqqqqqqqqqsss sssss ssssstttt ttt uuuuuuuuuuuuuuvvvvvvvv vvv rrrrrrr wwwwwwwwwwwwww xxxxxx xxxxx yy yyyyyyy z zz zzz ||z || | { { {{ ", + " nnnnnnn nnnnnnn ooooooooo ppp ppp p ppp qqqqqqqqqqqqqqqsss ssssss ssssssttttttttt tttt uuuuuuuuuuuuuvvvvvvv vvv rrrrrrrrr wwwwwwwwwwwwww xxxxxxx xxxx yyy y yyyyy z zzz zzz ||z | ||{ {{{{{{{ ", + " ooooooo ppp ppp p ppp pp sss sssssssssssssttttttttt tttt uuuuuuuuuuuu vvv vvv rrrrrrrr wwwwwwwwwwwww xxx xxx yyyyy yyyyyz zzz zzz ||z | ||{ {{ ", + " nnnnnnn nnnnnnn ooooo ppp ppp p ppp qqqqqqqqqqqqqqqssssssssssssssssstttttttt ttttt uuuuuuuuu vvv vvvvvvvv rrrrrrr wwwwwwwwwwww xxx xxx yyyyy yyy z zzz zzz ||z || ||{ {{{{{{{{ {{ ", + " nnnnnnn nnnnnnn ooo ppp ppp p ppp qqqqqqqqqqqqqqqsssssssssssssssssttttttt ttttttt uuuuuuuuuuuu vvv vvvvvvv rrrrrr wwwwwwwwwww xxxx xxxx yyyyy yy z z z || || ||{ {{{{{{{{ {{ ", + " nnnnnnn nnnnnnooooooo oooooppp ppp p ppp pp sss sssssss ssssssttttttttttttttt uuuuuuuuuuuuuu vvvvvvvvv vvvvv rrrrr wwwwwwwww xxxxxxx xxxxx yyyyy yyzzz zzzzz zz|| || |||| |||{ {{ ", + " nnnnnnn nnnnnnoooooooooooooooppp ppp p ppp pp sss ssssss ssssstttttt tttttt uuuuuuuuuuuuuu vvvvvvvvvv vvvv rrrrr wwwwwwww xxxxxx xxxxx yyyy yzzzz zzz|||||||| ||||{ {{{{{{{{ {{ ", + " nnnnnnn nnnnnnoooooooooooo ooppp ppp p ppp qqqqqqqqqqqqqqqsss sssss sssstttttt tttttt uuuu uuuu uuu vvvvvvvvvvv vv rrrrr wwwwwwwww xxxxx xxxxxx yyy yzzzzzzzzzzzzzzzzz|||| ||||||{ {{ ", + " nnnnnnn nnnnnnoooooooooooooooppp ppp p ppp qqqqqqqqqqqqqqqsss ssss sssstttttttttttt u uuuu uu rrrrr wwww xxxxxxxxxxxx yyy yzzzzzzzzzzzzzzzzzzz ||||||||| { {{{{{{{{ {{ ", + " ooooooooooooooooo sss sss sss tttttttttt uuuu rrr xxxxxxxxxx yyyyyy ||||||| { {{{{{{{{ {{ ", + " sss ss ss ttttttt uuuu rr xxxxxxx yyy ||{ {{ ", + " }}}} }}}} ~~~~~~~ ~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007fss s s \u0080\u0080\u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084\u0084\u0084 \u0085\u0085\u0085\u0085\u0085\u0085\u0085 {\u0086 \u0086\u0086 \u0086 \u0086\u0086\u0086\u0086{{ ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087 }}}}} }}}} ~~ ~~ ~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u0089\u0089\u0089\u0089\u0089\u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084 \u0085\u0085 \u0085\u0085 \u008a\u008a {{{{{{{{{{{{{{{{ ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0087\u0087}}}}} }}}} ~~ ~ ~~ ~ ~~ ~ \u0088\u0088\u0088 \u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u008b\u008b\u008b \u008b\u008b \u0089\u0089\u0089\u0089\u0089\u0089\u0089\u0089 \u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084 \u0084\u0084 \u0085\u0085 \u0085\u0085\u0085 \u008a\u008a\u008a\u008a\u008a\u008a\u008a\u008a\u008a\u008a {{{{{{{{{{{{{{{ ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0087\u0087}}}}}}}}}}}} ~~ ~ ~~ ~ ~~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081\u0081 \u008b\u008b\u008b\u008b\u008b \u008b\u008b\u008b\u008b\u0089\u0089\u0089\u0089\u0089 \u0089 \u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084 \u0084 \u0084\u0084 \u0085\u0085\u0085 \u0085\u0085 \u008a\u008a\u008a\u008a \u008a\u008a\u008a\u008a \u0086 \u0086\u0086 \u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0087}}}}}} }}}}} ~~ ~~ ~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b \u008b\u008b\u008b\u008b\u008b\u0089\u0089 \u0089 \u0089\u0089 \u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083 \u0084\u0084 \u0084 \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0085\u0085\u0085 \u0085\u0085 \u0085 \u008a\u008a\u008a \u008a\u008a\u008a \u0086 \u0086\u0086 \u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087 \u0087\u0087\u0087\u0087\u0087}}}}} }}}}} ~~~~~~~ ~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b \u008b\u008b\u008b\u008b\u008b\u008b\u0089\u0089\u0089\u0089 \u0089 \u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083\u0084\u0084\u0084\u0084\u0084\u0084 \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0085\u0085 \u0085 \u0085 \u008a\u008a \u008a\u008a\u0086 \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 }}}}}} }}}}}} \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b \u008b\u008b\u008b\u008b\u008b\u008b \u0089\u0089\u0089\u0089 \u0089\u0089 \u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0084\u0084\u0084\u0084\u0084\u0084 \u0084\u0084\u0084\u0084 \u0084\u0084\u0085\u0085\u0085\u0085\u0085\u0085\u0085 \u0085 \u008a\u008a \u008a\u008a\u0086\u0086\u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 }}}}}} }}}}}} ~~~~~~~ ~~~~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b \u0089\u0089\u0089\u0089 \u0089 \u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0083\u0083\u0083\u0083 \u0083\u0083\u0084 \u0084\u0084\u0084\u0084\u0084 \u0084\u0084 \u0085\u0085\u0085 \u0085\u0085\u0085\u0085\u008a\u008a \u008a\u0086\u0086\u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 }}}}}}}}}}}}}}}}~~~~~~~ ~~~~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080 \u0080\u0080 \u0080\u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b\u008b \u0089\u0089\u0089\u0089 \u0089\u0089\u0082\u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0083\u0083\u0083\u0083 \u0083\u0083\u0084 \u0084\u0084\u0084 \u0084\u0084 \u0084\u0084 \u0085\u0085\u0085 \u0085 \u008a\u008a \u008a\u0086\u0086\u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087}}}}}}}}}}}}}}}}}~~ ~~ ~~~~~~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b\u008b\u008b \u0089\u0089\u0089\u0089 \u0089\u0089\u0082\u0082\u0082\u0082\u0082 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0084 \u0084\u0084\u0084\u0084\u0084\u0084\u0084 \u0084\u0084 \u0085\u0085\u0085 \u0085 \u008a\u008a \u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 }}}}}}} }}}}}}}~~ ~ ~~ ~ ~~~~ \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u008b\u008b\u008b\u008b\u008b \u0089\u0089\u0089\u0089\u0089\u0089 \u0089\u0089\u0082\u0082\u0082\u0082\u0082 \u0082 \u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083\u0084 \u0084\u0084\u0084\u0084\u0084\u0084 \u0084\u0084\u0085\u0085\u0085 \u0085\u0085\u0085 \u008a\u008a \u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 }}}}}}} }}}}}}}~~ ~~ ~ \u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080 \u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u008b\u008b\u008b \u0089\u0089\u0089 \u0089\u0089\u0089\u0089\u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0084 \u0084\u0084 \u0084\u0085\u0085 \u0085\u0085\u0085 \u008a\u008a\u008a \u008a\u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087 \u0087\u0087}}}}}}}} }}}}}}}~~~~~~~ ~ ~~ ~\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0089\u0089 \u0089\u0089\u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083 \u0083\u0083\u0083\u0083\u0083\u0083\u0084 \u0084\u0084 \u0085\u0085\u0085 \u0085\u0085 \u008a\u008a\u008a \u008a\u008a\u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087 \u0087\u0087\u0087\u0087\u0087\u0087 ~~~~~~~ ~ ~~ ~\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f\u007f \u0088\u0088\u0088 \u0088\u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0089\u0089 \u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084 \u0085\u0085\u0085 \u0085\u0085 \u008a\u008a \u008a\u008a\u008a\u008a\u008a\u008a\u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0088\u0088\u0088 \u0088\u0088 \u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080\u0080 \u0089 \u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083\u0083 \u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084 \u0084\u0085\u0085 \u0085\u0085 \u008a\u008a\u008a\u008a\u008a\u008a\u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087\u0087 \u0087\u0087 \u0087\u0087 \u0087\u0087 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0088\u0088\u0088 \u0088 \u0080\u0080\u0080\u0080\u0080 \u008d\u008d\u008d\u008d \u0089\u0089\u008e\u0089\u0089 \u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082\u0082 \u0083\u0083\u0083\u0083\u0083 \u0084\u0084 \u0084\u0085\u0085\u0085\u0085\u0085\u0085\u0085\u0085 \u008a\u008a\u008a\u008a \u0086\u0086\u0086\u0086 \u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087 \u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090\u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0089\u0089\u0089\u0089\u0089 \u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093\u0093 \u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094 \u0095 \u0084\u0084 \u0084\u0084\u0096\u0096\u0096\u0085\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096 \u008a\u008a\u008a\u008a \u0097\u0097 \u0098\u0086\u0086\u0086\u0086\u0098\u0098\u0098\u0098\u0098\u0086\u0086\u0086\u0086 ", + " \u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087\u0087 \u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090\u0090 \u0090\u0090\u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099 \u008e\u0089\u0089\u0089\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094\u0094\u0094\u0094 \u0094\u0094\u0095\u0095\u0095\u0095\u0095\u0095\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0084\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096 \u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0086\u0086\u0086\u0086\u0098\u0098\u0098\u0098\u0098\u0086\u0086\u0086\u0086\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f\u008f \u008f\u008f\u008f\u008f\u008f \u0090\u0090\u0090 \u0090 \u0090\u0090 \u0091\u0091\u0091\u0091\u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099 \u008e \u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0095\u0095 \u0095\u0095\u0095 \u0095\u0095\u0095\u0096\u0096\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096 \u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f\u008f\u008f \u0090\u0090\u0090\u0090 \u0090\u0090\u0090 \u0090\u0090\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091\u0091\u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099 \u008e\u008e \u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0095\u0095 \u0095\u0095\u0095 \u0095\u0095 \u0096\u0096\u0096\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096 \u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 \u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f \u008f\u008f\u008f \u0090\u0090\u0090\u0090\u0090 \u0090\u0090 \u0090\u0090\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0092\u0092\u0092\u0092 \u0092\u0092\u0092 \u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 \u008e\u008e \u008e\u008e\u008e\u008e \u0093\u0093 \u0093 \u0094\u0094 \u0094\u0094\u0095\u0095 \u0095\u0095 \u0095\u0095 \u0095\u0095\u0096\u0096\u0096 \u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 \u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f \u008f\u008f\u008f\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0090\u0090 \u0090\u0090 \u0090\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0092\u0092\u0092 \u0092 \u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099\u0099 \u008e\u008e\u008e \u008e\u008e\u008e\u008e\u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094 \u0094\u0094 \u0095\u0095\u0095\u0095\u0095\u0095\u0095 \u0095\u0095 \u0095\u0095 \u0096\u0096\u0096 \u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097 \u0097\u0097\u0097\u0097 \u0097\u0097 \u0097\u0097 \u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 \u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f \u008f \u008f\u008f\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0090 \u0090\u0090 \u0090\u0090 \u0091\u0091 \u0091\u0091\u0091 \u0091\u0091\u0092\u0092\u0092\u0092\u0092 \u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099 \u0099\u0099\u0099\u0099\u0099 \u008e\u008e\u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094 \u0094 \u0095\u0095\u0095\u0095\u0095 \u0095 \u0095 \u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f \u008f \u008f\u008f\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0090\u0090 \u0090 \u0090\u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0091\u0091\u0091 \u0091\u0091\u0092\u0092\u0092\u0092\u0092\u0092 \u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099 \u0099\u0099\u0099\u0099\u0099 \u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094 \u0094\u0094 \u0095 \u0095 \u0095\u0095 \u0096\u0096\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f \u008f\u008f\u008f\u008f \u008f\u008f\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0090\u0090 \u0090\u0090 \u0090\u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0092\u0092\u0092\u0092\u0092\u0092 \u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099\u0099 \u0099\u0099\u0099\u0099\u0099\u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093 \u0093 \u0094\u0094\u0094 \u0094\u0094 \u0095\u0095\u0095\u0095\u0095 \u0095\u0095\u0095\u0095 \u0096\u0096\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f\u008f\u0090\u0090\u0090\u0090\u0090\u0090\u0090\u0090 \u0090\u0090 \u0090\u0090 \u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0091\u0092\u0092\u0092\u0092\u0092 \u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099\u0099\u0099\u0099 \u0099\u0099\u0099\u0099\u008e\u008e\u008e\u008e \u008e \u0093\u0093 \u0093\u0093 \u0093 \u0094\u0094 \u0094 \u0094\u0095\u0095\u0095\u0095\u0095\u0095\u0095\u0095\u0095 \u0095 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0097\u0097 \u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097 \u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f\u008f\u008f \u0090\u0090\u0090\u0090 \u0090\u0090 \u0090\u0090 \u0091\u0091 \u0091\u0091\u0091 \u0091\u0091 \u0092\u0092\u0092\u0092 \u0092\u0092 \u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u0099\u0099\u0099 \u0099\u0099 \u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093 \u0093\u0093\u0093\u0093 \u0093 \u0094\u0094\u0094\u0094\u0094 \u0094\u0095\u0095\u0095 \u0095\u0095 \u0095\u0095 \u0095 \u0096\u0096\u0096 \u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0097\u0097 \u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097 \u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f \u008f\u008f\u008f\u008f \u0090\u0090\u0090 \u0090\u0090 \u0090\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u0091 \u0091\u0091\u0091 \u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093 \u0093\u0093 \u0093\u0093\u0093 \u0093 \u0094\u0094\u0094\u0094\u0094 \u0094\u0094\u0094\u0095\u0095 \u0095\u0095 \u0095\u0095 \u0095\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0097\u0097\u0097 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f\u008f\u008f \u008f\u008f\u008f\u008f \u0090\u0090 \u0090\u0090\u0090\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d\u008d \u008e\u008e \u008e \u008e\u008e \u0093\u0093\u0093\u0093\u0093 \u0093\u0093\u0093 \u0093 \u0094\u0094 \u0094\u0094\u0094\u0094\u0094\u0094\u0094\u0095\u0095 \u0095\u0095 \u0095\u0095\u0095\u0096\u0096\u0096\u0096 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097 \u0097\u0097\u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090\u0090\u0090 \u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c\u008c \u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008d\u008d\u008d \u008e\u008e\u008e\u008e\u008e\u008e \u008e \u0093\u0093\u0093\u0093 \u0093\u0093\u0093\u0093 \u0094\u0094 \u0094\u0094\u0094 \u0095\u0095\u0095\u0095\u0095\u0095 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a\u009a \u008f\u008f\u008f\u008f\u008f\u008f\u008f\u008f \u0090 \u0091\u0091\u0091\u0091\u0091\u0091\u0091 \u0092\u0092\u0092\u0092\u0092\u0092\u0092\u0092 \u008e\u008e\u008e\u008e\u008e\u008e\u008e\u008e \u008e\u008e \u0093\u0093\u0093 \u0093\u0093\u0093 \u0094\u0094 \u0094\u0094 \u0095\u0095\u0095\u0095 \u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0096\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0097\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098\u0098 ", + " \u009b\u009b \u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c \u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009f\u009f\u009f\u009f\u009f\u0091\u0091\u0091\u0091\u0091\u009f\u009f \u00a0\u00a0 \u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2 \u008e\u008e\u008e\u008e\u008e\u008e\u008e \u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3 \u0094\u0094\u00a4\u00a4\u0094\u0094 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a7 ", + " \u009b\u009b \u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c \u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009f\u009f \u0091\u0091\u0091 \u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8 \u00a3\u00a3 \u00a3\u00a3\u00a3 \u0094\u0094\u0094\u0094\u0094 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9 \u00a7\u00a7 ", + " \u009b\u009b\u009b\u009b \u009c \u009c \u009c\u009c \u009d\u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009f\u009f \u0091 \u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1 \u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a3\u00a3 \u00a3\u00a3 \u00a4\u0094\u0094\u0094\u0094\u00a4 \u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7\u00a7\u00a7\u00a7\u00a7 ", + " \u009b\u009b\u009b\u009b \u009c \u009c \u009c\u009c \u009d\u009d\u009d\u009d \u009f\u009f \u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4 \u00a4\u00a4 \u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7\u00a7\u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009c\u009c \u009d\u009d\u009d\u009d\u009d\u009d\u009d\u009d \u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009f\u009f \u009f \u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4 \u00a4\u00a4 \u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7\u00a7 ", + " \u009b\u009b\u009b\u009b\u009b\u009b\u009b \u009b\u009b\u009b\u009b\u009b\u009b\u009b\u009c \u009c \u009c \u009d\u009d\u009d\u009d\u009d\u009d\u009d\u009d \u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009f\u009f \u009f\u009f\u009f \u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8 \u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4 \u00a4\u00a4\u00a4\u00a4\u00a4 \u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7 \u00a7\u00a7 ", + " \u009b\u009b\u009b\u009b \u009b\u009b\u009b\u009b\u009c \u009c\u009c\u009c\u009c\u009c\u009c \u009d\u009d\u009d\u009d\u009d\u009d\u009d\u009d \u009d \u009f\u009f \u009f\u009f\u009f\u009f \u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4 \u00a4 \u00a4\u00a4\u00a4\u00a4\u00a4 \u00a5\u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7\u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009d\u009d\u009d\u009d\u009d\u009d\u009d\u009d \u009d\u009d \u009f\u009f \u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4\u00a4\u00a4 \u00a4\u00a4 \u00a5\u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a6\u00a6\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009d\u009d\u009d\u009d\u009d\u009d\u009d\u009d \u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009f\u009f \u009f\u009f\u009f\u009f\u009f\u009f\u009f \u009f \u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3 \u00a4 \u00a4\u00a4 \u00a4\u00a4 \u00a5\u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009d\u009d\u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e \u009f\u009f \u009f\u009f\u009f\u009f\u009f \u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3\u00a4\u00a4 \u00a4 \u00a5\u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6 \u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009d\u009d\u009d \u009f\u009f \u009f\u009f\u009f \u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4 \u00a4\u00a4 \u00a5\u00a5 \u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9 \u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7\u00a7 ", + " \u009b\u009b \u009b\u009b \u009c \u009c \u009d\u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009f\u009f \u009f \u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a3\u00a3 \u00a3\u00a3 \u00a4\u00a4\u00a4 \u00a4\u00a4 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6 \u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9 \u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7 \u00a7\u00a7 ", + " \u009b\u009b \u009b\u009b \u009b\u009b \u009c \u009c \u009d \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009f\u009f \u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1\u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a3\u00a3 \u00a3\u00a3\u00a3 \u00a4\u00a4 \u00a4 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9 \u00a9\u00a9\u00a9\u00a9\u00a9 \u00a7\u00a7 \u00a7 ", + " \u009b \u009b\u009b\u009b\u009b\u009b\u009b \u009b \u009c \u009c \u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009e\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f\u009f \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1\u00a1 \u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8\u00a8 \u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3\u00a3 \u00a4\u00a4 \u00a4\u00a4 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a9\u00a7\u00a7 \u00a7\u00a7 ", + " \u009b\u009b\u009b \u009b\u009b\u009b \u009c \u009c \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1\u00a1\u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8\u00a8 \u00a4 \u00a4\u00a4 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a9\u00a7\u00a7\u00a7 \u00a7\u00a7 ", + " \u009b \u009b \u009c \u009c \u00aa \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a1 \u00a2\u00a2\u00a2\u00a2\u00a2\u00a2\u00a2 \u00a8\u00a8 \u00ab \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5\u00a5 \u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6\u00a6 \u00a9\u00a9\u00a9\u00a9\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7\u00a7 ", + " \u00ac\u00ac \u009c \u00ad\u00ad \u00ad\u00ad\u00ad\u009c \u00ae \u00aa\u00aa\u00aa\u00aa\u00aa \u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b1\u00b1 \u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab \u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u00a4\u00a4 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4 \u00a9\u00a9\u00a9\u00a9\u00a9 \u00b5\u00a7\u00a7\u00a7\u00a7\u00a7\u00b5\u00b5 ", + " \u00ac\u00ac \u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c \u00ae\u00ae \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00aa\u00aa\u00aa\u00aa\u00aa \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab \u00b7\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00a9\u00a9\u00a9 \u00b5\u00a7\u00a7\u00a7\u00a7\u00a7\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac \u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c\u009c \u00ae\u00ae\u00ae \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00aa\u00aa \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1\u00b1\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00b7\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4\u00a4 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5 \u00a7\u00a7 \u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae \u00b6\u00b6 \u00b6\u00b6\u00b6 \u00b6\u00aa\u00aa \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b1\u00b1\u00b1 \u00b1 \u00b1\u00b1\u00b1 \u00b1\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b7 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00b6 \u00b6\u00b6\u00b6 \u00b6\u00aa\u00aa \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b0\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00ab\u00ab\u00ab \u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7 \u00b7\u00b7 \u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0 \u00b0\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab \u00b7\u00b7\u00b7 \u00b7\u00b7\u00b7\u00b7\u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa\u00aa \u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b7\u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3 \u00b3\u00b3 \u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa \u00aa \u00af\u00af\u00af\u00af \u00af\u00af\u00af \u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1 \u00b1 \u00ab\u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3 \u00b3 \u00b3\u00b3\u00b3 \u00b3\u00b3 \u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa \u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af \u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab \u00ab \u00b7\u00b7\u00b7\u00b7\u00b7 \u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3 \u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3 \u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa \u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab \u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3 \u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3 \u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa \u00aa \u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00b0\u00b0 \u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1 \u00b1 \u00b1 \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00b7 \u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad\u00ad\u00ad \u00ae\u00ae \u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa \u00aa \u00af\u00af\u00af\u00af\u00af\u00af \u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00b7 \u00b7\u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b3 \u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4 \u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac\u00ac \u00ad\u00ad\u00ad\u00ad \u00ad\u00ad\u00ad\u00ad\u00ad \u00ae \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00aa\u00aa \u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab\u00ab\u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b3\u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac\u00ac \u00ac\u00ac\u00ac\u00ac \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6 \u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa\u00aa \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b1\u00b1 \u00b1\u00b1\u00b1\u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1 \u00ab\u00ab\u00ab \u00b7\u00b7 \u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2\u00b2 \u00b3\u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac\u00ac\u00ac \u00ac\u00ac\u00ac \u00b6\u00b6 \u00b6\u00b6 \u00af\u00af\u00af\u00af\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8\u00b8 \u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1 \u00b1\u00b1\u00b1 \u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7\u00b7 \u00b3\u00b3 \u00b3\u00b3\u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5\u00b5 ", + " \u00ac \u00ac \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00b6\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00ba\u00ba \u00bb\u00bb\u00af\u00af\u00af\u00af \u00b0\u00b0\u00b0\u00b0\u00b0\u00b0 \u00bc \u00b8\u00b8\u00b8\u00b8\u00b8 \u00bd\u00bd \u00b1\u00b1\u00b1\u00b1 \u00b7\u00b7\u00b7\u00b7 \u00be\u00be\u00be\u00be \u00b3\u00b3\u00b3\u00b3 \u00b4\u00b4\u00b4\u00b4 \u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5\u00b5 \u00b5\u00b5 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf \u00bf\u00bf\u00bf\u00bf\u00bf \u00c0\u00c0\u00c0\u00c0\u00c0\u00c0 \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00b6\u00b6\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1 \u00b6\u00b6\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb \u00bc\u00bc \u00b8\u00b8\u00b8 \u00bd\u00bd\u00bd \u00c2\u00c2\u00c2\u00c2\u00c2 \u00b1\u00b1\u00b1\u00b1\u00b1 \u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4 \u00be\u00be\u00be\u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7 \u00c7\u00c7\u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9\u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1\u00b6\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1 \u00b6\u00ba\u00ba \u00ba \u00ba\u00ba\u00ba\u00ba\u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc \u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00c2\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2 \u00b1 \u00b1 \u00c3\u00c3\u00c3\u00c3 \u00c3\u00c3\u00c3\u00c3\u00c3 \u00c4\u00c4 \u00c4\u00c4 \u00be\u00be\u00be \u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7 \u00c7\u00c7\u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0 \u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00c1 \u00c1\u00c1\u00c1 \u00c1\u00c1 \u00c1\u00ba\u00ba\u00c1 \u00ba\u00ba\u00ba \u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2\u00c2 \u00c3\u00c3\u00c3 \u00c3\u00c3 \u00c4\u00c4 \u00c4 \u00be\u00be \u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6 \u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9\u00c1 \u00c1\u00c1\u00c1 \u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2 \u00c3\u00c3 \u00c3\u00c3 \u00c4\u00c4 \u00c4\u00c4 \u00be\u00be \u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00b9\u00b9\u00b9 \u00b9\u00c1 \u00c1\u00c1\u00c1 \u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00c2\u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2 \u00c3\u00c3 \u00c3 \u00c4\u00c4 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4\u00c4\u00be\u00be\u00be \u00be\u00be\u00be\u00be \u00c5\u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7\u00c7 \u00c7\u00c7\u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0 \u00c0 \u00c0 \u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bd \u00bd\u00bd\u00bd \u00bd\u00bd\u00c2\u00c2 \u00c2\u00c2\u00c2 \u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4 \u00c4\u00be\u00be\u00be\u00be \u00be\u00be\u00be\u00be \u00c5\u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7\u00c7 \u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bd\u00bd\u00bd \u00c2\u00c2 \u00c2\u00c2\u00c2\u00c2 \u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4 \u00c4\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be \u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7\u00c7 \u00c7\u00c7\u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9 \u00b9\u00b9 \u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc\u00bc \u00bd\u00bd\u00bd \u00c2\u00c2 \u00c2\u00c2\u00c2\u00c2 \u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4 \u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7 \u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba \u00ba\u00ba \u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc\u00bc\u00bc \u00bc\u00bc\u00bc\u00bc \u00bd\u00bd\u00bd \u00bd \u00bd\u00bd\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2\u00c2 \u00c3 \u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4\u00c4\u00c4 \u00be\u00be\u00be\u00be \u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7 \u00c7\u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba\u00ba \u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc \u00bc\u00bc\u00bc \u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00c2\u00c2\u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2\u00c2 \u00c2\u00c2\u00c2 \u00c3 \u00c3\u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4 \u00be\u00be\u00be\u00be \u00be\u00be\u00be\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7\u00c7\u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9\u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00ba\u00ba \u00ba\u00ba\u00ba \u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc\u00bc \u00bc\u00bc \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00c2 \u00c2\u00c2\u00c2 \u00c2\u00c2\u00c2\u00c2\u00c3 \u00c3\u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4 \u00be\u00be \u00be \u00be\u00be\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c0 \u00c0\u00c0 \u00c0\u00c0 \u00b9\u00b9\u00b9 \u00b9\u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00c1\u00ba \u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00c2\u00c2\u00c2\u00c2 \u00c2\u00c2\u00c3\u00c3 \u00c3\u00c3\u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4 \u00be\u00be\u00be \u00be\u00c5\u00c5\u00c5\u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c5\u00c5 \u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7 \u00c7\u00c7 ", + " \u00bf\u00bf\u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00b9\u00b9 \u00b9\u00b9\u00b9 \u00c1\u00c1\u00c1 \u00c1\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba\u00ba \u00bb\u00bb\u00bb\u00bb\u00bb \u00bc\u00bc \u00bd\u00bd\u00bd\u00bd\u00bd \u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd\u00bd \u00c2\u00c2\u00c2 \u00c3\u00c3 \u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4 \u00c4 \u00be\u00be\u00be\u00be \u00be\u00be\u00be \u00c5\u00c5 \u00c5 \u00c5\u00c5 \u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7 \u00c7 ", + " \u00bf\u00bf\u00bf\u00bf \u00c0 \u00c0\u00c0 \u00c1\u00c1\u00c1 \u00c1\u00c1\u00c1\u00c1 \u00bb\u00bb\u00bb\u00bb \u00bc\u00bc \u00bd\u00bd\u00bd \u00c2\u00c2\u00c2 \u00c3 \u00c3\u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4\u00c4\u00c4 \u00c4\u00c4 \u00be\u00be\u00be\u00be\u00be\u00be\u00be \u00c5\u00c5\u00c5\u00c5\u00c5 \u00c5\u00c5\u00c5\u00c5\u00c5\u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7 \u00c7\u00c7\u00c7 ", + " \u00bf\u00bf \u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0\u00c0 \u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1 \u00c1\u00c1 \u00c8 \u00bb\u00bb \u00bc \u00bd\u00bd \u00c2\u00c2\u00c2 \u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3\u00c3 \u00c4\u00c4\u00c4\u00c4\u00c4\u00c4 \u00be\u00be\u00be\u00be\u00be \u00c5\u00c5\u00c5 \u00c5\u00c5\u00c5 \u00c6\u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6 \u00c6\u00c6\u00c6\u00c6 \u00c7\u00c7\u00c7\u00c7\u00c7\u00c7 ", + " \u00c9\u00c9\u00c9 \u00ca\u00ca \u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00c1\u00cb\u00cb\u00cb\u00cb \u00c1 \u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc \u00bc \u00cd\u00cd\u00cd \u00ce\u00ce\u00ce \u00ce\u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00c2\u00c2\u00cf \u00d0\u00d0 \u00d1\u00d1 \u00be \u00d1\u00d1 \u00d2 \u00d2 \u00d2\u00d2 \u00d3\u00d3 ", + " \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca \u00cb\u00cb\u00cb\u00cb\u00cb\u00cb\u00cb \u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce \u00ce\u00ce\u00ce\u00ce \u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5 \u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2 \u00d2 \u00d2 \u00d2\u00d2\u00d2\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4\u00d4 \u00d4\u00d4 \u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9 \u00ca\u00ca \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00ca\u00ca \u00cb\u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd \u00ce\u00ce \u00ce\u00ce \u00ce\u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2 \u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4\u00d4 \u00d4\u00d4\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00ce\u00ce\u00cf\u00ce \u00cf \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2 \u00d2\u00d2 \u00d2\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4\u00d4 \u00d4\u00d4\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce \u00ce\u00ce\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2 \u00d2\u00d2 \u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4\u00d4\u00d4 \u00d4\u00d4\u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd \u00cd\u00cd\u00cd\u00cd \u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1 \u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1 \u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4 \u00d4\u00d4 \u00d4\u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd \u00cd\u00cd\u00cd\u00cd \u00cd\u00cd\u00cd\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4 \u00d4\u00d4\u00d4 \u00d4\u00d4\u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9\u00c9\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd \u00cd\u00cd\u00cd\u00cd \u00cd\u00cd\u00cd\u00cd\u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf \u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d2\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6 \u00d3 \u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00d4 \u00d4\u00d4\u00d4 \u00d4\u00d4\u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9\u00c9\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6 \u00d3 \u00d3\u00d3 \u00d3\u00d3 \u00d3\u00d3 ", + " \u00d4 \u00d4\u00d4\u00d4 \u00d4\u00d4\u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9\u00c9\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8 \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d3\u00d3 \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 \u00d3\u00d3 ", + " \u00d4 \u00d4\u00d4\u00d4\u00d4 \u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9 \u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8 \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d3\u00d3 \u00d3\u00d3\u00d3\u00d3\u00d3 \u00d3\u00d3 ", + " \u00d4 \u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca\u00ca\u00ca\u00ca \u00ca\u00ca\u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf \u00cf\u00cf\u00cf\u00cf\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d3\u00d3 \u00d3\u00d3\u00d3\u00d3 \u00d3\u00d3 \u00d3\u00d3 ", + " \u00d4 \u00d4\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca \u00cb\u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd\u00cd\u00cd \u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d3 \u00d3\u00d3 \u00d3\u00d3\u00d3 \u00d3\u00d3 \u00d3\u00d3 ", + " \u00d4 \u00d4 \u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9\u00c9 \u00ca\u00ca \u00cb\u00cb\u00cb \u00c8\u00c8\u00c8\u00c8\u00c8\u00c8\u00c8 \u00cc\u00cc\u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd\u00cd\u00cd \u00ce \u00ce \u00ce \u00ce \u00cf\u00ce \u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d2\u00d2\u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d3 \u00d3\u00d3\u00d3 \u00d3\u00d3 \u00d3 ", + " \u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4\u00d4 \u00c9 \u00c9\u00c9\u00c9 \u00ca\u00ca \u00cb\u00cb\u00cb\u00cb\u00cb \u00cc\u00cc\u00cc\u00cc \u00cd\u00cd\u00cd \u00ce \u00ce \u00ce \u00ce \u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5\u00d5\u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d2\u00d2\u00d2\u00d2 \u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d6\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00c9\u00c9\u00c9 \u00ca\u00ca \u00d7\u00d7\u00d7 \u00cb\u00cb\u00cb\u00cb\u00cb\u00cb\u00cb \u00cc\u00cc \u00ce \u00ce \u00ce \u00ce \u00d8\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00cf\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0\u00d0 \u00d5\u00d5\u00d5 \u00d5\u00d5 \u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1 \u00d9\u00d2\u00d2\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da \u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3\u00d3 ", + " \u00db\u00db\u00db \u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de \u00df\u00df \u00ce \u00ce \u00ce \u00ce\u00d8\u00d8\u00ce\u00ce\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2 \u00e3\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2 \u00e3\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da\u00da \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00d7\u00d7 \u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df \u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00ce\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00d1\u00e3\u00e3\u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00d7\u00d7 \u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3\u00e3\u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00d7\u00d7 \u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db \u00d7\u00d7 \u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3 \u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3 \u00e3\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5 \u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df\u00df \u00d8 \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5 \u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00df\u00df\u00df\u00df \u00df\u00df\u00df\u00df \u00df\u00df\u00df\u00df\u00df\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3 \u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00df\u00df\u00df \u00df\u00df\u00df\u00df \u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8\u00d8\u00d8 \u00d8\u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 \u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8\u00d8 \u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3 \u00e3\u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8 \u00d8\u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3\u00e3\u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de\u00de \u00df\u00df\u00df\u00df \u00d8\u00d8\u00d8 \u00d8\u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1 \u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2 \u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5\u00e5 \u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7 \u00dc\u00dc\u00dc \u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00df\u00df\u00df\u00df \u00d8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e3\u00e3\u00e3\u00e3\u00e3 \u00e3\u00e3\u00e3\u00e3\u00e3\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9\u00d9 \u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4\u00e4 ", + " \u00e5\u00e5\u00e5\u00e5\u00e5 \u00e5\u00e5\u00e5\u00e5\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00dc\u00dc\u00dc\u00dc\u00dc \u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd\u00dd \u00df\u00df\u00df\u00df \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1\u00e1\u00e1\u00e1\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e3\u00e3\u00e3\u00e3\u00e3\u00e3\u00e6\u00e6\u00e6\u00e6\u00e3\u00e3\u00e3\u00e3\u00e3\u00e3 ", + " \u00e5\u00e5\u00e5\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00db\u00db \u00db\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc\u00dc \u00dd\u00dd\u00dd \u00e8\u00e8\u00e8 \u00e0\u00e0\u00e0\u00e0\u00e0\u00e0\u00e0 \u00e0\u00e0\u00e0 \u00e1\u00e1\u00e1\u00e1 \u00e1\u00e1\u00e1 \u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e2\u00e3\u00e3\u00e3\u00e3\u00e3\u00e3\u00e6\u00e6\u00e6\u00e6\u00e3\u00e3\u00e3\u00e3\u00e3 \u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00e5\u00e5\u00e5 \u00ea\u00ea\u00ea \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed \u00ed\u00ed \u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00e2\u00e2\u00e2\u00e2\u00e2 \u00f0\u00f0 \u00e6 \u00e6\u00e6 \u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1 \u00f1\u00f1\u00f1\u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00e2\u00e2\u00e2\u00e2 \u00f0\u00f0\u00f0\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec \u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00ea\u00e7\u00e7 \u00e7 \u00eb\u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec \u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00e7\u00e7 \u00e7 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e7 \u00eb\u00eb\u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec \u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8 \u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ef\u00ef \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00ea\u00e7\u00e7 \u00e7 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e7 \u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec \u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee \u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ef\u00ef \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00ea\u00e7\u00e7 \u00e7 \u00eb\u00eb \u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec \u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee\u00ef\u00ef \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00ef\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2 \u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea \u00ea\u00e7\u00e7 \u00e7 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e7 \u00eb\u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00f4\u00f4\u00f4\u00f4\u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2 \u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00e7\u00e7 \u00e7 \u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1\u00f1 \u00f4\u00f4\u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2 \u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00ea\u00e7\u00e7 \u00e7 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e7 \u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8 \u00ee\u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1 \u00f1 \u00f4\u00f4 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2 \u00f2\u00f2\u00ea\u00ea\u00ea \u00ea\u00ea\u00e7\u00e7 \u00e7 \u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00e7 \u00eb\u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef \u00f0\u00f0\u00f0 \u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1\u00f1 \u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2 \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00e7\u00e7 \u00e7 \u00eb\u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00ee\u00ee\u00ee\u00ee \u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00f0\u00f0\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2 \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea\u00ea \u00ea\u00ea\u00ea\u00ea\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7\u00e7 \u00eb\u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec\u00ec\u00ec \u00ed\u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00f0\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 \u00f1\u00f1\u00f1\u00f1 \u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9\u00e9 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea \u00eb\u00eb \u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec \u00ed\u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6\u00e6 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea\u00ea \u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb \u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb\u00eb \u00ec\u00ec\u00ec \u00ed\u00ed \u00ed\u00ed \u00f3\u00f3\u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee\u00ee \u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef\u00ef \u00f0\u00f0\u00f0\u00f0 \u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1\u00f1 ", + " \u00f2\u00f2\u00f2\u00f2\u00f2\u00f2\u00f2 \u00ea\u00ea\u00ea\u00ea\u00ea \u00f5\u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7 \u00ed\u00ed \u00f3\u00f3 \u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00e8\u00f8\u00e8\u00e8 \u00f9\u00f9\u00f9\u00f9\u00f9 \u00fa\u00f0\u00f0\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u00fb\u00fb\u00fb\u00fb\u00fb \u00fc\u00fc ", + " \u00fd\u00f2\u00f2\u00f2\u00f2\u00f2\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff \u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100 \u0101\u0101 \u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9 \u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb \u00fc\u00fc\u00fc\u00fc \u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7\u00ff\u00ff\u00ff \u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101\u0101\u0101\u0101\u0101 \u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb \u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7 \u00f7\u00f7\u00f7\u00f7\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101\u0101\u0101\u0101\u0101\u0101\u0101 \u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa \u00fa\u00fa \u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb \u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe\u00fe \u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7 \u00f7\u00f7\u00f7\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101\u0101\u0101 \u0101\u0101\u0101\u0101 \u0101\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa \u00fa\u00fa \u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb \u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00f7\u00f7\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101 \u0101\u0101\u0101\u0101\u0101\u0101\u0101 \u00f8\u0101 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101 \u0101 \u0101\u0101\u0101\u0101 \u0101 \u00f8\u0101\u0101 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa \u00fa\u00fa \u0102\u0102\u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb\u00fb\u00fb \u0103\u0103 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0101\u0101 \u0101\u0101\u0101\u0101\u0101\u0101 \u0101 \u00f8 \u0101 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb \u0103 \u0103 ", + " \u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0101\u0101 \u0101\u0101\u0101\u0101\u0101 \u0101\u0101 \u00f8\u0101\u0101\u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9\u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb\u00fb \u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5 \u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0101\u0101 \u0101\u0101\u0101\u0101 \u0101\u0101 \u00f8\u0101\u0101\u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9\u00f9 \u00f9\u00fa\u00fa \u00fa\u00fa \u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102 \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe \u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101 \u0101\u0101\u0101 \u0101 \u0101\u00f8\u0101 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9\u00f9 \u00f9\u00fa\u00fa \u00fa\u00fa \u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102 \u00fb\u00fb\u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe\u00fe \u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5 \u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101\u0101\u0101 \u0101\u0101\u0101\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9\u00f9 \u00f9\u00f9\u00fa\u00fa \u00fa \u0102\u0102\u0102\u0102 \u00fb \u00fb\u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f6 \u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101\u0101 \u0101\u0101\u0101\u0101 \u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f8\u00f8\u00f8 \u00f9\u00f9 \u00f9\u00f9\u00f9\u00f9\u00f9\u00f9 \u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa \u0102\u0102\u0102\u0102 \u00fb \u00fb\u00fb\u00fb \u00fc\u00fc\u00fc\u00fc\u00fc \u0103\u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f7 \u00f7\u00f7 \u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101\u0101 \u0101\u0101 \u00f8 \u0102\u0102\u0102 \u00fb\u00fb \u00fb\u00fb \u00fc\u00fc\u00fc \u0103\u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe\u00fe\u00fe\u00fe\u00fe \u00fe\u00fe\u00fe\u00fe\u00f5\u00f5 \u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7\u00f7 \u00ff\u00ff \u00ff\u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100\u0100 \u0101 \u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8 \u0102\u0102 \u00fb\u00fb\u00fb\u00fb \u00fb\u00fb\u00fb \u00fc \u0103 ", + " \u00fd\u00fd \u00fe\u00fe\u00fe\u00fe \u00f5\u00f5\u00f5\u00f5\u00f5 \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f7\u00f7\u00f7\u00f7 \u00ff \u00ff \u00ff\u00ff\u00ff \u0100\u0100\u0100\u0100\u0100 \u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8\u00f8 \u00fb\u00fb\u00fb\u00fb\u00fb ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe\u00fe \u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6\u00f6 \u0100\u0100\u0100 ", + " \u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd\u00fd \u00fe\u00fe ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/text-line-wrap-512-512-2.0-grid-reference.json b/tests/visual_tests/grids/text-line-wrap-512-512-2.0-grid-reference.json index 1a4b97273..39f99bbe3 100644 --- a/tests/visual_tests/grids/text-line-wrap-512-512-2.0-grid-reference.json +++ b/tests/visual_tests/grids/text-line-wrap-512-512-2.0-grid-reference.json @@ -1,138 +1,138 @@ { "keys": [ - "", - "4", - "3" - ], - "data": {}, + "", + "2", + "1" + ], + "data": {}, "grid": [ - " ", - " !! !! ", - " ! !! !! ", - " !!!!!!!!!!!!!! ", - " !!!!!!!!!!!!!! ", - " ! !! !!!!!!!!!!! ", - " !!!! !!!!!!!! ", - " !!!! !!!!!!!! ", - " ", - " ", - " !! !! !! ", - " !!!!!!! !!!!!!! ", - " !!!!!!!!!!!!!!!! ", - " !!!!! !!!!!!!!!!!! ", - " !!!!! !! !!!!!!!!! ", - " !!!!! !!!!!!!!!! ", - " !!!! !!!!!!!!!! ", - " ", - " ! ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ## ## ## ", - " ####### ## ### ", - " ############## ", - " ## ########### ", - " ## ## ######## ", - " ##### ########## ", - " #### ########## ", - " ## ", - " ", - " ## ## ## ", - " ####### ######## ", - " ################ ", - " ## ## ######## ", - " #### ## ######## ", - " ####### ########## ", - " ## ### ", - " ", - " # ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", + " ", + " !! !! ", + " ! !! !! ", + " !!!!!!!!!!!!!! ", + " !!!!!!!!!!!!!! ", + " ! !! !!!!!!!!!!! ", + " !!!! !!!!!!!! ", + " !!!! !!!!!!!! ", + " ", + " ", + " !! !! !! ", + " !!!!!!! !!!!!!! ", + " !!!!!!!!!!!!!!!! ", + " !!!!! !!!!!!!!!!!! ", + " !!!!! !! !!!!!!!!! ", + " !!!!! !!!!!!!!!! ", + " !!!! !!!!!!!!!! ", + " ", + " ! ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ## ## ## ", + " ####### ## ### ", + " ############## ", + " ## ########### ", + " ## ## ######## ", + " ##### ########## ", + " #### ########## ", + " ## ", + " ", + " ## ## ## ", + " ####### ######## ", + " ################ ", + " ## ## ######## ", + " #### ## ######## ", + " ####### ########## ", + " ## ### ", + " ", + " # ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", " " ] -} \ No newline at end of file +} diff --git a/tests/visual_tests/images/building-symbolizer-opacity-512-512-1.0-agg-reference.png b/tests/visual_tests/images/building-symbolizer-opacity-512-512-1.0-agg-reference.png index 99d578c40..092f8f837 100644 Binary files a/tests/visual_tests/images/building-symbolizer-opacity-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/building-symbolizer-opacity-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/building-symbolizer-opacity-512-512-2.0-agg-reference.png b/tests/visual_tests/images/building-symbolizer-opacity-512-512-2.0-agg-reference.png index c4cc3e52c..1a2d6c58f 100644 Binary files a/tests/visual_tests/images/building-symbolizer-opacity-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/building-symbolizer-opacity-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/collision-600-400-1.0-agg-reference.png b/tests/visual_tests/images/collision-600-400-1.0-agg-reference.png index 696c521d2..c7a701139 100644 Binary files a/tests/visual_tests/images/collision-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/collision-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/collision-600-400-2.0-agg-reference.png b/tests/visual_tests/images/collision-600-400-2.0-agg-reference.png index a1f012819..642fd3cb7 100644 Binary files a/tests/visual_tests/images/collision-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/collision-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha1-512-512-1.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha1-512-512-1.0-agg-reference.png index da04eee23..4f2eb273e 100644 Binary files a/tests/visual_tests/images/colorize-alpha1-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha1-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha1-512-512-2.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha1-512-512-2.0-agg-reference.png index ab7ed1f02..af5fef69d 100644 Binary files a/tests/visual_tests/images/colorize-alpha1-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha1-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha2-512-512-1.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha2-512-512-1.0-agg-reference.png index a6ff00a29..b857b9f22 100644 Binary files a/tests/visual_tests/images/colorize-alpha2-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha2-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha2-512-512-2.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha2-512-512-2.0-agg-reference.png index 3d9c7b855..36d524d1b 100644 Binary files a/tests/visual_tests/images/colorize-alpha2-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha2-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha3-512-512-1.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha3-512-512-1.0-agg-reference.png index 1327518ab..ac7b198ec 100644 Binary files a/tests/visual_tests/images/colorize-alpha3-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha3-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/colorize-alpha3-512-512-2.0-agg-reference.png b/tests/visual_tests/images/colorize-alpha3-512-512-2.0-agg-reference.png index 903640376..9c5f7eee6 100644 Binary files a/tests/visual_tests/images/colorize-alpha3-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/colorize-alpha3-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/dots-500-100-1.0-agg-reference.png b/tests/visual_tests/images/dots-500-100-1.0-agg-reference.png new file mode 100644 index 000000000..cc8bb8af2 Binary files /dev/null and b/tests/visual_tests/images/dots-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/dots-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/dots-500-100-1.0-cairo-reference.png new file mode 100644 index 000000000..e11b74acf Binary files /dev/null and b/tests/visual_tests/images/dots-500-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/dots-500-100-2.0-agg-reference.png b/tests/visual_tests/images/dots-500-100-2.0-agg-reference.png new file mode 100644 index 000000000..cc8bb8af2 Binary files /dev/null and b/tests/visual_tests/images/dots-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/dots-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/dots-500-100-2.0-cairo-reference.png new file mode 100644 index 000000000..e11b74acf Binary files /dev/null and b/tests/visual_tests/images/dots-500-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-agg-reference.png index 14c046af4..f139484e4 100644 Binary files a/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-agg-reference.png and b/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-cairo-reference.png b/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-cairo-reference.png index a76c90bc5..463cafc1b 100644 Binary files a/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-cairo-reference.png and b/tests/visual_tests/images/geometry-transform-scale-500-500-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-agg-reference.png index 914448140..7506ac38c 100644 Binary files a/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-agg-reference.png and b/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-cairo-reference.png b/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-cairo-reference.png index a88adae33..f141e8c8e 100644 Binary files a/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-cairo-reference.png and b/tests/visual_tests/images/geometry-transform-scale-500-500-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-agg-reference.png b/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-agg-reference.png new file mode 100644 index 000000000..8ce927052 Binary files /dev/null and b/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-cairo-reference.png new file mode 100644 index 000000000..78f393769 Binary files /dev/null and b/tests/visual_tests/images/group-symbolizer-4-500-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-agg-reference.png b/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-agg-reference.png new file mode 100644 index 000000000..428386721 Binary files /dev/null and b/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-cairo-reference.png new file mode 100644 index 000000000..d6f257344 Binary files /dev/null and b/tests/visual_tests/images/group-symbolizer-4-500-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-1.0-agg-reference.png b/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-1.0-agg-reference.png index c81967cc8..ca690ff11 100644 Binary files a/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-1.0-agg-reference.png and b/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-2.0-agg-reference.png b/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-2.0-agg-reference.png index c581d6477..81d122b50 100644 Binary files a/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-2.0-agg-reference.png and b/tests/visual_tests/images/halo-comp-op-on-satellite-450-450-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-galore-512-512-1.0-agg-reference.png b/tests/visual_tests/images/image-filters-galore-512-512-1.0-agg-reference.png index 54b234cc1..d72a7beaa 100644 Binary files a/tests/visual_tests/images/image-filters-galore-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/image-filters-galore-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-galore-512-512-2.0-agg-reference.png b/tests/visual_tests/images/image-filters-galore-512-512-2.0-agg-reference.png index 54b234cc1..d72a7beaa 100644 Binary files a/tests/visual_tests/images/image-filters-galore-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/image-filters-galore-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-multi-blur-512-512-1.0-agg-reference.png b/tests/visual_tests/images/image-filters-multi-blur-512-512-1.0-agg-reference.png index 55ebc5712..9e061602b 100644 Binary files a/tests/visual_tests/images/image-filters-multi-blur-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/image-filters-multi-blur-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-multi-blur-512-512-2.0-agg-reference.png b/tests/visual_tests/images/image-filters-multi-blur-512-512-2.0-agg-reference.png index b945e8220..eec2679f6 100644 Binary files a/tests/visual_tests/images/image-filters-multi-blur-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/image-filters-multi-blur-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-1.0-agg-reference.png b/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-1.0-agg-reference.png index a94e93adc..29774f193 100644 Binary files a/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-2.0-agg-reference.png b/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-2.0-agg-reference.png index 79b2afbbc..715234ea7 100644 Binary files a/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/image-filters-multi-blur-inflate-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png b/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png index ef457d59d..83429fc53 100644 Binary files a/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/line-symbolizer-expressions-256-256-2.0-agg-reference.png b/tests/visual_tests/images/line-symbolizer-expressions-256-256-2.0-agg-reference.png index aea44bb57..0871c46e8 100644 Binary files a/tests/visual_tests/images/line-symbolizer-expressions-256-256-2.0-agg-reference.png and b/tests/visual_tests/images/line-symbolizer-expressions-256-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/line-symbolizer-expressions-all-256-256-2.0-agg-reference.png b/tests/visual_tests/images/line-symbolizer-expressions-all-256-256-2.0-agg-reference.png index 9ada2e9ce..c49be440c 100644 Binary files a/tests/visual_tests/images/line-symbolizer-expressions-all-256-256-2.0-agg-reference.png and b/tests/visual_tests/images/line-symbolizer-expressions-all-256-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/map-background-image-compositing-512-512-1.0-agg-reference.png b/tests/visual_tests/images/map-background-image-compositing-512-512-1.0-agg-reference.png index 1778b2e83..15d9748bc 100644 Binary files a/tests/visual_tests/images/map-background-image-compositing-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/map-background-image-compositing-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/map-background-image-compositing-512-512-2.0-agg-reference.png b/tests/visual_tests/images/map-background-image-compositing-512-512-2.0-agg-reference.png index 02b41e6b9..c48ffb17b 100644 Binary files a/tests/visual_tests/images/map-background-image-compositing-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/map-background-image-compositing-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-collide-512-512-1.0-agg-reference.png b/tests/visual_tests/images/marker-collide-512-512-1.0-agg-reference.png index 104e87d11..1b93b4a23 100644 Binary files a/tests/visual_tests/images/marker-collide-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/marker-collide-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-collide-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/marker-collide-512-512-1.0-cairo-reference.png index 5767f7fdc..bef31b744 100644 Binary files a/tests/visual_tests/images/marker-collide-512-512-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-collide-512-512-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-collide-512-512-2.0-agg-reference.png b/tests/visual_tests/images/marker-collide-512-512-2.0-agg-reference.png index 95b84c6b5..965c59454 100644 Binary files a/tests/visual_tests/images/marker-collide-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/marker-collide-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-collide-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/marker-collide-512-512-2.0-cairo-reference.png index c5d981e62..59e8e64d8 100644 Binary files a/tests/visual_tests/images/marker-collide-512-512-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-collide-512-512-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-agg-reference.png new file mode 100644 index 000000000..4c09b645a Binary files /dev/null and b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-cairo-reference.png new file mode 100644 index 000000000..a9904e195 Binary files /dev/null and b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-agg-reference.png new file mode 100644 index 000000000..12dbf26d6 Binary files /dev/null and b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-cairo-reference.png new file mode 100644 index 000000000..47c4c7551 Binary files /dev/null and b/tests/visual_tests/images/marker-line-placement-many-vertices-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-agg-reference.png index 36268a453..c96b1cf08 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-cairo-reference.png index 37ffc2529..469264aa2 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-257-256-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-agg-reference.png index 2f5c6b627..93aa57d54 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-cairo-reference.png index 2c9aa8945..2d7fe3945 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-257-256-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-agg-reference.png index 987302d42..a9b5c9cad 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png index 3c8665889..dd276c1d0 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-400-600-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-agg-reference.png index 7047e230c..c58cccf2f 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-cairo-reference.png index 4f9a0113d..9855a52d2 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-400-600-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-agg-reference.png index 48ed8e678..19f6383b1 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png index c0d01e3f1..21e0de79d 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-agg-reference.png index d064ce2fd..6897880d7 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-cairo-reference.png index 1970f5dc3..9ccf84133 100644 Binary files a/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-hex-grid-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-agg-reference.png index dbb58e15e..e93a253c7 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-cairo-reference.png index 8ad863304..76888a567 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-agg-reference.png index a92820548..b20e8ddbd 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-cairo-reference.png index 86e73713a..1406071eb 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-and-avoid-edges-512-512-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-agg-reference.png index 63fa8a641..8302737f6 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-cairo-reference.png index baf6176a2..369d2813d 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-agg-reference.png index 754d22092..11e7edc10 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-cairo-reference.png index 81322150c..ea61d4a04 100644 Binary files a/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-and-line-placement-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-agg-reference.png index cc8483f9e..e60350382 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png index b73700424..9f7f2ca63 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-agg-reference.png index b2c926dbb..17cad8c0d 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png index 9f2e33cb3..82e032c79 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-agg-reference.png index 4d7850fe6..7002220d6 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png index 0318ea9d1..cf7f63b67 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-agg-reference.png index 11fdf0eb9..ab5797cd9 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png index bcea41ab5..c638c1d31 100644 Binary files a/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png and b/tests/visual_tests/images/marker-on-line-spacing-eq-width-overlap-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-agg-reference.png new file mode 100644 index 000000000..7440348e0 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-cairo-reference.png new file mode 100644 index 000000000..a60243b11 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-agg-reference.png new file mode 100644 index 000000000..e43ecac82 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-cairo-reference.png new file mode 100644 index 000000000..e6ee27b07 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-no-box-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-agg-reference.png new file mode 100644 index 000000000..de22a5c3a Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-cairo-reference.png new file mode 100644 index 000000000..4645618b6 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-agg-reference.png new file mode 100644 index 000000000..6e0335885 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-cairo-reference.png b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-cairo-reference.png new file mode 100644 index 000000000..1f85d5d28 Binary files /dev/null and b/tests/visual_tests/images/marker-on-line-svg-with-box-600-400-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-500-100-1.0-agg-reference.png b/tests/visual_tests/images/marker-svg-500-100-1.0-agg-reference.png new file mode 100644 index 000000000..99881f230 Binary files /dev/null and b/tests/visual_tests/images/marker-svg-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/marker-svg-500-100-1.0-cairo-reference.png new file mode 100644 index 000000000..b182681ed Binary files /dev/null and b/tests/visual_tests/images/marker-svg-500-100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker-svg-500-100-2.0-agg-reference.png new file mode 100644 index 000000000..93084a3b4 Binary files /dev/null and b/tests/visual_tests/images/marker-svg-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/marker-svg-500-100-2.0-cairo-reference.png new file mode 100644 index 000000000..1a6f86f32 Binary files /dev/null and b/tests/visual_tests/images/marker-svg-500-100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-empty-g-element-500-100-1.0-agg-reference.png b/tests/visual_tests/images/marker-svg-empty-g-element-500-100-1.0-agg-reference.png index 4d75272bb..677bf4b8c 100644 Binary files a/tests/visual_tests/images/marker-svg-empty-g-element-500-100-1.0-agg-reference.png and b/tests/visual_tests/images/marker-svg-empty-g-element-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-empty-g-element-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker-svg-empty-g-element-500-100-2.0-agg-reference.png index cec958b65..f39d6b2fa 100644 Binary files a/tests/visual_tests/images/marker-svg-empty-g-element-500-100-2.0-agg-reference.png and b/tests/visual_tests/images/marker-svg-empty-g-element-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-opacity-500-100-1.0-agg-reference.png b/tests/visual_tests/images/marker-svg-opacity-500-100-1.0-agg-reference.png index 11c31d9e0..fe9571114 100644 Binary files a/tests/visual_tests/images/marker-svg-opacity-500-100-1.0-agg-reference.png and b/tests/visual_tests/images/marker-svg-opacity-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-svg-opacity-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker-svg-opacity-500-100-2.0-agg-reference.png index 4d5ac73ae..88f7e6064 100644 Binary files a/tests/visual_tests/images/marker-svg-opacity-500-100-2.0-agg-reference.png and b/tests/visual_tests/images/marker-svg-opacity-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-vs-point-512-512-1.0-agg-reference.png b/tests/visual_tests/images/marker-vs-point-512-512-1.0-agg-reference.png index fc0e96c2b..eeaa6ddf7 100644 Binary files a/tests/visual_tests/images/marker-vs-point-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/marker-vs-point-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-vs-point-512-512-2.0-agg-reference.png b/tests/visual_tests/images/marker-vs-point-512-512-2.0-agg-reference.png index 73fb609dd..44a90a8f6 100644 Binary files a/tests/visual_tests/images/marker-vs-point-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/marker-vs-point-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-257-256-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-257-256-1.0-agg-reference.png index ac1111281..15cc73992 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-257-256-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-257-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-257-256-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-257-256-2.0-agg-reference.png index e1698d84c..d203e5cc9 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-257-256-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-257-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-400-600-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-400-600-1.0-agg-reference.png index cb0f2a1f6..99a221385 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-400-600-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-400-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-400-600-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-400-600-2.0-agg-reference.png index fb29c30b6..33ea95b53 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-400-600-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-400-600-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-600-400-1.0-agg-reference.png index 75256d5ae..1ebc0701b 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-600-400-2.0-agg-reference.png index 602da3304..23c7d6744 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png index 674820933..1880a89fb 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png index 7c0bc703a..08d99b87d 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-257-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png index ac6008a97..b616c7d75 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png index 1281cd309..b158566f8 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-400-600-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png index d4a31bb7e..6ebe7a221 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png index 9a06fdb99..cda6e556e 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-and-hsla-transform-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-agg-reference.png index 281f78d6e..637ce5338 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png index 76bd8c286..67b899865 100644 Binary files a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png and b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-agg-reference.png b/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-agg-reference.png index 084beba4c..cd8a9885d 100644 Binary files a/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-agg-reference.png and b/tests/visual_tests/images/marker_line_placement_on_points-500-100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-agg-reference.png index 9ab762723..b47817ceb 100644 Binary files a/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-agg-reference.png and b/tests/visual_tests/images/marker_line_placement_on_points-500-100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/orientation-800-200-1.0-agg-reference.png b/tests/visual_tests/images/orientation-800-200-1.0-agg-reference.png index 0bd22d32a..5eaa3c15f 100644 Binary files a/tests/visual_tests/images/orientation-800-200-1.0-agg-reference.png and b/tests/visual_tests/images/orientation-800-200-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/orientation-800-200-1.0-cairo-reference.png b/tests/visual_tests/images/orientation-800-200-1.0-cairo-reference.png index a52275693..b6723dd5b 100644 Binary files a/tests/visual_tests/images/orientation-800-200-1.0-cairo-reference.png and b/tests/visual_tests/images/orientation-800-200-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/orientation-800-200-2.0-agg-reference.png b/tests/visual_tests/images/orientation-800-200-2.0-agg-reference.png index 285d8c73d..1a9555e90 100644 Binary files a/tests/visual_tests/images/orientation-800-200-2.0-agg-reference.png and b/tests/visual_tests/images/orientation-800-200-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/orientation-800-200-2.0-cairo-reference.png b/tests/visual_tests/images/orientation-800-200-2.0-cairo-reference.png index 96b88ca2a..817f99dea 100644 Binary files a/tests/visual_tests/images/orientation-800-200-2.0-cairo-reference.png and b/tests/visual_tests/images/orientation-800-200-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-1.0-agg-reference.png b/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-1.0-agg-reference.png index 02598d615..d6fbf1c60 100644 Binary files a/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-1.0-agg-reference.png and b/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-2.0-agg-reference.png b/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-2.0-agg-reference.png index 99c858eb9..bfccc86a0 100644 Binary files a/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-2.0-agg-reference.png and b/tests/visual_tests/images/polygon-symbolizer-expressions-256-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-1.0-agg-reference.png b/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-1.0-agg-reference.png index 931d6fd3b..12f6cceda 100644 Binary files a/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-1.0-agg-reference.png and b/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-2.0-agg-reference.png b/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-2.0-agg-reference.png index f32817429..3c2ca54ed 100644 Binary files a/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-2.0-agg-reference.png and b/tests/visual_tests/images/polygon-symbolizer-expressions-all-256-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..0d27d72f1 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-cairo-reference.png new file mode 100644 index 000000000..fed820399 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..0d27d72f1 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-cairo-reference.png new file mode 100644 index 000000000..fed820399 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha4b-512-512-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-agg-reference.png new file mode 100644 index 000000000..78a99ee54 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-cairo-reference.png new file mode 100644 index 000000000..fed820399 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-agg-reference.png b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-agg-reference.png new file mode 100644 index 000000000..78a99ee54 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-cairo-reference.png new file mode 100644 index 000000000..fed820399 Binary files /dev/null and b/tests/visual_tests/images/raster-color-to-alpha5b-512-512-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/rasterlite-globe-256-256-1.0-agg-reference.png b/tests/visual_tests/images/rasterlite-globe-256-256-1.0-agg-reference.png new file mode 100644 index 000000000..d83fd2345 Binary files /dev/null and b/tests/visual_tests/images/rasterlite-globe-256-256-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/rasterlite-globe-256-256-1.0-cairo-reference.png b/tests/visual_tests/images/rasterlite-globe-256-256-1.0-cairo-reference.png new file mode 100644 index 000000000..d7dd2ff53 Binary files /dev/null and b/tests/visual_tests/images/rasterlite-globe-256-256-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/rasterlite-globe-256-256-2.0-agg-reference.png b/tests/visual_tests/images/rasterlite-globe-256-256-2.0-agg-reference.png new file mode 100644 index 000000000..d83fd2345 Binary files /dev/null and b/tests/visual_tests/images/rasterlite-globe-256-256-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/rasterlite-globe-256-256-2.0-cairo-reference.png b/tests/visual_tests/images/rasterlite-globe-256-256-2.0-cairo-reference.png new file mode 100644 index 000000000..d7dd2ff53 Binary files /dev/null and b/tests/visual_tests/images/rasterlite-globe-256-256-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png index 90783f56d..4ffb4c7a2 100644 Binary files a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png index 64427eac7..dba86d672 100644 Binary files a/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/shield-on-line-spacing-eq-width-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png index 3afdfbdb0..8bfc74a39 100644 Binary files a/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/shield-on-polygon-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-agg-reference.png b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-agg-reference.png new file mode 100644 index 000000000..6f67be6ae Binary files /dev/null and b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-cairo-reference.png b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-cairo-reference.png new file mode 100644 index 000000000..6dfb11a34 Binary files /dev/null and b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-agg-reference.png b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-agg-reference.png new file mode 100644 index 000000000..635fc0e20 Binary files /dev/null and b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-cairo-reference.png b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-cairo-reference.png new file mode 100644 index 000000000..1e1d0f222 Binary files /dev/null and b/tests/visual_tests/images/simplify-douglas-peucker-500-1000-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-agg-reference.png b/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-agg-reference.png new file mode 100644 index 000000000..2826debd0 Binary files /dev/null and b/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-cairo-reference.png b/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-cairo-reference.png new file mode 100644 index 000000000..2318a1961 Binary files /dev/null and b/tests/visual_tests/images/simplify-radial-distance-500-1000-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-agg-reference.png b/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-agg-reference.png new file mode 100644 index 000000000..9659f8e62 Binary files /dev/null and b/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-cairo-reference.png b/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-cairo-reference.png new file mode 100644 index 000000000..8d4861eae Binary files /dev/null and b/tests/visual_tests/images/simplify-radial-distance-500-1000-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-agg-reference.png b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-agg-reference.png new file mode 100644 index 000000000..f7e600a88 Binary files /dev/null and b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-cairo-reference.png b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-cairo-reference.png new file mode 100644 index 000000000..7c8dec67d Binary files /dev/null and b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-agg-reference.png b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-agg-reference.png new file mode 100644 index 000000000..5e836006f Binary files /dev/null and b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-cairo-reference.png b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-cairo-reference.png new file mode 100644 index 000000000..d07e7ed69 Binary files /dev/null and b/tests/visual_tests/images/simplify-visvalingam-whyatt-500-1000-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-agg-reference.png b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-agg-reference.png new file mode 100644 index 000000000..ea8047549 Binary files /dev/null and b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-cairo-reference.png b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-cairo-reference.png new file mode 100644 index 000000000..d2f5e40e0 Binary files /dev/null and b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-agg-reference.png b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-agg-reference.png new file mode 100644 index 000000000..e147d00d9 Binary files /dev/null and b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-cairo-reference.png b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-cairo-reference.png new file mode 100644 index 000000000..6e4bb1e9c Binary files /dev/null and b/tests/visual_tests/images/simplify-zhao-saalfeld-500-1000-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-1.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-1.0-agg-reference.png index 8ba187dd9..035316921 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-2.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-2.0-agg-reference.png index 8ba187dd9..035316921 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-0,0-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-1.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-1.0-agg-reference.png index 2ecb9eeb5..760f0d758 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-2.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-2.0-agg-reference.png index 2ecb9eeb5..760f0d758 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-0,1-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-1.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-1.0-agg-reference.png index 56a8ef59c..43bf38801 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-2.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-2.0-agg-reference.png index 56a8ef59c..43bf38801 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-1,0-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-1.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-1.0-agg-reference.png index 0e1cd5b09..b5f969206 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-2.0-agg-reference.png b/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-2.0-agg-reference.png index 0e1cd5b09..b5f969206 100644 Binary files a/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/style-level-compositing-tiled-1,1-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-charplacement-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-charplacement-512-512-1.0-agg-reference.png index f99d8cbe8..e76b172b3 100644 Binary files a/tests/visual_tests/images/text-charplacement-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-charplacement-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-charplacement-512-512-2.0-agg-reference.png b/tests/visual_tests/images/text-charplacement-512-512-2.0-agg-reference.png index 2c8c01191..1865ef546 100644 Binary files a/tests/visual_tests/images/text-charplacement-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/text-charplacement-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-displacement-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-displacement-512-512-1.0-agg-reference.png index 0167438fd..552cbfa73 100644 Binary files a/tests/visual_tests/images/text-displacement-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-displacement-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-font-features-1100-1100-1.0-agg-reference.png b/tests/visual_tests/images/text-font-features-1100-1100-1.0-agg-reference.png new file mode 100644 index 000000000..8f7383e66 Binary files /dev/null and b/tests/visual_tests/images/text-font-features-1100-1100-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-font-features-1100-1100-1.0-cairo-reference.png b/tests/visual_tests/images/text-font-features-1100-1100-1.0-cairo-reference.png new file mode 100644 index 000000000..d2126c324 Binary files /dev/null and b/tests/visual_tests/images/text-font-features-1100-1100-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-font-features-1100-1100-2.0-agg-reference.png b/tests/visual_tests/images/text-font-features-1100-1100-2.0-agg-reference.png new file mode 100644 index 000000000..dd957784b Binary files /dev/null and b/tests/visual_tests/images/text-font-features-1100-1100-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-font-features-1100-1100-2.0-cairo-reference.png b/tests/visual_tests/images/text-font-features-1100-1100-2.0-cairo-reference.png new file mode 100644 index 000000000..c061af081 Binary files /dev/null and b/tests/visual_tests/images/text-font-features-1100-1100-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-font-features-500-500-1.0-agg-reference.png b/tests/visual_tests/images/text-font-features-500-500-1.0-agg-reference.png deleted file mode 100644 index 5783e072c..000000000 Binary files a/tests/visual_tests/images/text-font-features-500-500-1.0-agg-reference.png and /dev/null differ diff --git a/tests/visual_tests/images/text-font-features-500-500-1.0-cairo-reference.png b/tests/visual_tests/images/text-font-features-500-500-1.0-cairo-reference.png deleted file mode 100644 index 9412911e0..000000000 Binary files a/tests/visual_tests/images/text-font-features-500-500-1.0-cairo-reference.png and /dev/null differ diff --git a/tests/visual_tests/images/text-font-features-500-500-2.0-agg-reference.png b/tests/visual_tests/images/text-font-features-500-500-2.0-agg-reference.png deleted file mode 100644 index d89e950c9..000000000 Binary files a/tests/visual_tests/images/text-font-features-500-500-2.0-agg-reference.png and /dev/null differ diff --git a/tests/visual_tests/images/text-font-features-500-500-2.0-cairo-reference.png b/tests/visual_tests/images/text-font-features-500-500-2.0-cairo-reference.png deleted file mode 100644 index fda86f340..000000000 Binary files a/tests/visual_tests/images/text-font-features-500-500-2.0-cairo-reference.png and /dev/null differ diff --git a/tests/visual_tests/images/text-halo-opacity-512-512-2.0-agg-reference.png b/tests/visual_tests/images/text-halo-opacity-512-512-2.0-agg-reference.png index 0b08856a8..be503a3ab 100644 Binary files a/tests/visual_tests/images/text-halo-opacity-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/text-halo-opacity-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-agg-reference.png b/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-agg-reference.png index 83d49e2aa..16369d9d3 100644 Binary files a/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/text-halo-rasterizer-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-halo-transform-600-400-1.0-agg-reference.png b/tests/visual_tests/images/text-halo-transform-600-400-1.0-agg-reference.png index 80177ff20..032100bfb 100644 Binary files a/tests/visual_tests/images/text-halo-transform-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/text-halo-transform-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-agg-reference.png b/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-agg-reference.png new file mode 100644 index 000000000..02ad3f1da Binary files /dev/null and b/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-cairo-reference.png b/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-cairo-reference.png new file mode 100644 index 000000000..d9fb7d6f2 Binary files /dev/null and b/tests/visual_tests/images/text-iconic-font-1000-1000-1.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-agg-reference.png b/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-agg-reference.png new file mode 100644 index 000000000..a846e12f9 Binary files /dev/null and b/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-cairo-reference.png b/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-cairo-reference.png new file mode 100644 index 000000000..cd00c7e2b Binary files /dev/null and b/tests/visual_tests/images/text-iconic-font-1000-1000-2.0-cairo-reference.png differ diff --git a/tests/visual_tests/images/text-multi-layout-2-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-multi-layout-2-512-512-1.0-agg-reference.png index 90efb5344..da5387a14 100644 Binary files a/tests/visual_tests/images/text-multi-layout-2-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-multi-layout-2-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-multi-layout-2-512-512-2.0-agg-reference.png b/tests/visual_tests/images/text-multi-layout-2-512-512-2.0-agg-reference.png index cf94c153a..b839f414a 100644 Binary files a/tests/visual_tests/images/text-multi-layout-2-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/text-multi-layout-2-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-overlap-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-overlap-512-512-1.0-agg-reference.png index 3fccea803..897065a4e 100644 Binary files a/tests/visual_tests/images/text-overlap-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-overlap-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-overlap-512-512-2.0-agg-reference.png b/tests/visual_tests/images/text-overlap-512-512-2.0-agg-reference.png index cdb9d974f..d13a7d559 100644 Binary files a/tests/visual_tests/images/text-overlap-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/text-overlap-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-spacing-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-spacing-512-512-1.0-agg-reference.png index 16ea18075..cf887dc93 100644 Binary files a/tests/visual_tests/images/text-spacing-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-spacing-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-ttc-font-600-400-1.0-agg-reference.png b/tests/visual_tests/images/text-ttc-font-600-400-1.0-agg-reference.png index dad75d20d..fb1e44b0a 100644 Binary files a/tests/visual_tests/images/text-ttc-font-600-400-1.0-agg-reference.png and b/tests/visual_tests/images/text-ttc-font-600-400-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-ttc-font-600-400-2.0-agg-reference.png b/tests/visual_tests/images/text-ttc-font-600-400-2.0-agg-reference.png index 96ea0de58..67b1f51cb 100644 Binary files a/tests/visual_tests/images/text-ttc-font-600-400-2.0-agg-reference.png and b/tests/visual_tests/images/text-ttc-font-600-400-2.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-typographic-512-512-1.0-agg-reference.png b/tests/visual_tests/images/text-typographic-512-512-1.0-agg-reference.png index 54415f38f..d945ed00e 100644 Binary files a/tests/visual_tests/images/text-typographic-512-512-1.0-agg-reference.png and b/tests/visual_tests/images/text-typographic-512-512-1.0-agg-reference.png differ diff --git a/tests/visual_tests/images/text-typographic-512-512-2.0-agg-reference.png b/tests/visual_tests/images/text-typographic-512-512-2.0-agg-reference.png index 1a4c1b191..3c7860b00 100644 Binary files a/tests/visual_tests/images/text-typographic-512-512-2.0-agg-reference.png and b/tests/visual_tests/images/text-typographic-512-512-2.0-agg-reference.png differ diff --git a/tests/visual_tests/styles/building-symbolizer-opacity.xml b/tests/visual_tests/styles/building-symbolizer-opacity.xml index b6db1c611..5ddd40d4c 100644 --- a/tests/visual_tests/styles/building-symbolizer-opacity.xml +++ b/tests/visual_tests/styles/building-symbolizer-opacity.xml @@ -4,6 +4,9 @@ background-image-opacity=".5" background-image-comp-op="soft-light" > + + 512, 512 + + + + dots + + csv + 0,0,5,5 + +fill, opacity,height, width, wkt +green,.5, 40, 40, "POINT(2.5 2.5)" +red, .5, 20, 20, "MULTIPOINT((2 2.5),(2.5 2.5),(3 2.5))" +blue, .5, 45, 45, "POLYGON((1 1,4 1,4 4,1 4,1 1))" +red, .5, 3, 3, "LINESTRING(3 2.5,3.0472522909029145 2.5549083791557554,3.088039946704745 2.6192015984770367,3.120968717931644 2.692088134329871,3.1447426958020195 2.7725928396160553,3.1581869214177796 2.859569153953152,3.1602684919277424 2.9517139787160285,3.150115859191815 3.0475850341520374,3.1270360384124487 3.1456204818095705,3.090529469857131 3.2441605641461093,3.0403023058681398 3.3414709848078967,2.9762759274968564 3.435767728064507,2.898593529924341 3.525242994563949,2.8076236529182754 3.6080919132297717,2.7039605714802892 3.6825396759861526,2.588421502084629 3.7468687332550683,2.4620406210083243 3.799445683953957,2.3260599327010416 3.838747494110833,2.181917067429678 3.863386683229473,2.0312301280479197 3.872135127146751,1.8757797451792864 3.8639461402385225,1.7174885378702207 3.8379745183057543,1.5583982123914466 3.7935942461113443,1.4006445648882897 3.7304136000915884,1.246430683579882 3.648287406936956,1.0979986727928661 3.547326252181924,0.9576002439358948 3.4279024692786355,0.8274665372684367 3.290652778432585,0.7097775527295491 3.136477485296219,0.606631577958298 2.966536191967265,0.5200150067991092 2.7822400161197343,0.45177294193977735 2.5852403579882455,0.4035809708310185 2.3774142988020817,0.3769184946959401 2.160846757592015,0.37304397632518604 1.9378095755409703,0.3929724535957084 1.7107377376983552,0.4374556424314622 1.4822029804218395,0.5069649254805411 1.2548850688650404,0.6016774914054002 1.0315410617374736,0.7214658547096571 0.8149729099992633,0.8658909478409702 0.6079937617301794,1.0341989363401651 0.4133933667857521,1.2253218645141815 0.23390299172467044,1.437882193988065 0.07216026761394456,1.6702012510582676 -0.06932559950169326,1.920311551565356 -0.18820782357901678,2.185972924581849 -0.2823348101737011,2.4646923091307618 -0.34978128405768727,2.753747051974397 -0.38887736562393815,3.0502114897965984 -0.3982352072417812,3.350986556389679 -0.37677282398941525,3.6528321152745926 -0.3237347810995832,3.9524016810311693 -0.2387094327324748,4.246279158964359 -0.12164244300528804,4.531017203016431 0.027153639820840958,4.803176766446595 0.2069939418962261,5.0593673990838255 0.416820095021341,5.2962878292111855 0.6552034322979141,5.510766357600486 0.9203525899932274,5.6998005860669245 1.2101255063356857,5.860596003276281 1.5220457563037595,5.990602956471176 1.8533231098340628,6.087551549283583 2.200878149857013,6.149484022799466 2.5613707367678797,6.1747841994053125 2.9312320579468265,6.162203596480088 3.306699955329308,6.110883849442411 3.683857181350839,6.02037512070598 4.058672194373903,5.890650212364317 4.427042069440575,5.722114145495159 4.78483706933339,5.515609017373219 5.127946394875156,5.272413999093365 5.4523246125098,4.994240389582243 5.754038241781528,4.683221697131584 6.029311975608545,4.34189877581244 6.2745740024088335,3.9732001007988598 6.486499901292641,3.5804173231036964 6.662054589735392,3.16717629986471 6.798531817364951,2.737403850475655 6.893590719648262,2.2952905409040607 6.945288971186986,1.8452498478612391 6.952112109805218,1.3918741005021504 6.912998639345142,0.9398876394743532 6.827360560726954,0.4940976708866134 6.695099026966764,0.05934332565157785 6.516614868014918,-0.3595565377529124 6.292813784961579,-0.7578562271360596 6.0251060697957435,-1.1309362311473898 5.715400765898583,-1.474355768902115 5.3660942451696325,-1.783904285743506 4.980053239466529,-2.055651309423385 4.560592426208784,-2.285994090762115 4.1114467298642285,-2.4717024691612375 3.636738561911254,-2.6099604260809084 3.1409402810613676,-2.698403818583074 2.6288322123574606,-2.7351538200309866 2.105456617575501,-2.718845635708872 1.5760680595181986,-2.648652107097507 1.0460806487014485,-2.524301869365668 0.5210127020395867,-2.3460917818082168 0.006429378924498685)" + + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/dst-over-compositing.xml b/tests/visual_tests/styles/dst-over-compositing.xml index c8623fe85..8ebefe298 100644 --- a/tests/visual_tests/styles/dst-over-compositing.xml +++ b/tests/visual_tests/styles/dst-over-compositing.xml @@ -1,6 +1,9 @@ + + 512,512 + - \ No newline at end of file + diff --git a/tests/visual_tests/styles/line-opacity-multi-render.xml b/tests/visual_tests/styles/line-opacity-multi-render.xml index f4ad94d48..37bda8e7d 100644 --- a/tests/visual_tests/styles/line-opacity-multi-render.xml +++ b/tests/visual_tests/styles/line-opacity-multi-render.xml @@ -1,4 +1,7 @@ + + 512,512 + @@ -49,4 +52,4 @@ i|wkt - \ No newline at end of file + diff --git a/tests/visual_tests/styles/marker-interior-position.xml b/tests/visual_tests/styles/marker-interior-position.xml index 08945ef80..6fdd44897 100644 --- a/tests/visual_tests/styles/marker-interior-position.xml +++ b/tests/visual_tests/styles/marker-interior-position.xml @@ -1,7 +1,10 @@ - + + 600,400 + + - + poly @@ -22,4 +25,4 @@ - \ No newline at end of file + diff --git a/tests/visual_tests/styles/marker-line-placement-many-vertices.xml b/tests/visual_tests/styles/marker-line-placement-many-vertices.xml new file mode 100644 index 000000000..6c9d155d2 --- /dev/null +++ b/tests/visual_tests/styles/marker-line-placement-many-vertices.xml @@ -0,0 +1,24 @@ + + + + + 600, 400 + + + My Style + + csv + + name,wkt + one,"LINESTRING(-11910145.81 4703881.8, -11910145.81 4703423.84,-11910160.59 4703432.16,-11910166.19 4703437.59,-11910173.45 4703446.41,-11910177.3 4703450.97,-11910192.16 4703462.59,-11910204.85 4703471.78,-11910212.45 4703479.48,-11910221.64 4703489.36,-11910226.1 4703494.08,-11910237.21 4703504.49,-11910243.24 4703510.09,-11910248.05 4703515.34,-11910252.77 4703519.28,-11910270.35 4703533.17,-11910287.15 4703551.01,-11910297.38 4703561.96,-11910305.77 4703571.92,-11910310.15 4703577.61,-11910316.36 4703584.26,-11910322.14 4703588.67,-11910331.31 4703595.72,-11910344.33 4703608.96,-11910351.24 4703615.98,-11910355.65 4703620.48,-11910366.33 4703631.8,-11910372.95 4703639.49,-11910377.01 4703645.05,-11910379.94 4703647.91,-11910384.5 4703651.34,-11910393.1 4703660.65,-11910398.84 4703665.75,-11910405.07 4703670.16,-11910407.65 4703673.09,-11910410.87 4703677.79,-11910414.38 4703681.34,-11910417.73 4703687.09,-11910420.81 4703692.48,-11910429.84 4703699.54,-11910432.91 4703703.67,-11910437.32 4703710.88,-11910442.36 4703715.78,-11910449.22 4703720.33,-11910451.95 4703722.55,-11910455.8 4703727.74,-11910464.26 4703732.86,-11910471.12 4703737.82,-11910478.04 4703746.84,-11910491.9 4703763.57,-11910498.05 4703770.49,-11910507.08 4703782.24,-11910519.18 4703795.54,-11910521.99 4703802.82,-11910526.6 4703809.54,-11910530.8 4703813.87,-11910535.7 4703823.8,-11910540.95 4703834.86,-11910543.54 4703839.76,-11910548.78 4703853.41,-11910550.39 4703856.97,-11910553.61 4703860.69,-11910555.77 4703869.08,-11910558.86 4703875.87,-11910561.37 4703879.51,-11910566.84 4703882.72,-11910571.38 4703883.63,-11910576.21 4703884.4,-11910580.05 4703884.4,-11910584.18 4703885.38,-11910593.08 4703887.55,-11910599.16 4703891.19,-11910605.39 4703894.13,-11910609.37 4703895.74,-11910612.17 4703896.01,-11910617.49 4703893.15,-11910623.37 4703888.19,-11910634.42 4703883.42,-11910644.28 4703881.75,-11910653.52 4703881.8)" + + + + + + diff --git a/tests/visual_tests/styles/marker-multi-policy.xml b/tests/visual_tests/styles/marker-multi-policy.xml index 937cc15ae..7c77c3ec4 100644 --- a/tests/visual_tests/styles/marker-multi-policy.xml +++ b/tests/visual_tests/styles/marker-multi-policy.xml @@ -1,4 +1,7 @@ + + 600,400 + @@ -21,6 +24,7 @@ point-placement csv + -10, 0, 15, 20 ../data/marker-on-line.csv | diff --git a/tests/visual_tests/styles/marker-on-line-and-vertex-first-placement.xml b/tests/visual_tests/styles/marker-on-line-and-vertex-first-placement.xml index e001cd4d2..9e1084f9d 100644 --- a/tests/visual_tests/styles/marker-on-line-and-vertex-first-placement.xml +++ b/tests/visual_tests/styles/marker-on-line-and-vertex-first-placement.xml @@ -1,6 +1,9 @@ + + 600,400 + @@ -17,6 +20,7 @@ markers csv + -1, -1, 11, 4 wkt, placement "LINESTRING(0 0)", "vertex-first" diff --git a/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml b/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml index b35a65d1a..fd89c57d2 100644 --- a/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml +++ b/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml @@ -1,6 +1,9 @@ + + 600,400 + @@ -17,6 +20,7 @@ markers csv + -1, -1, 11, 4 wkt, placement "LINESTRING(0 0)", "vertex-last" diff --git a/tests/visual_tests/styles/marker-on-line-spacing-eq-width-overlap.xml b/tests/visual_tests/styles/marker-on-line-spacing-eq-width-overlap.xml index 3b58e5430..21294b5cc 100644 --- a/tests/visual_tests/styles/marker-on-line-spacing-eq-width-overlap.xml +++ b/tests/visual_tests/styles/marker-on-line-spacing-eq-width-overlap.xml @@ -1,6 +1,9 @@ + + 600,400 + alpha @@ -51,4 +54,4 @@ - \ No newline at end of file + diff --git a/tests/visual_tests/styles/marker-on-line-spacing-eq-width.xml b/tests/visual_tests/styles/marker-on-line-spacing-eq-width.xml index c4ad7d961..c4962ce9b 100644 --- a/tests/visual_tests/styles/marker-on-line-spacing-eq-width.xml +++ b/tests/visual_tests/styles/marker-on-line-spacing-eq-width.xml @@ -1,6 +1,9 @@ + + 600,400 + alpha @@ -50,4 +53,4 @@ - \ No newline at end of file + diff --git a/tests/visual_tests/styles/marker-on-line-svg-no-box.xml b/tests/visual_tests/styles/marker-on-line-svg-no-box.xml new file mode 100644 index 000000000..a6ba56083 --- /dev/null +++ b/tests/visual_tests/styles/marker-on-line-svg-no-box.xml @@ -0,0 +1,51 @@ + + + + + 600,400 + + + alpha + + csv + + wkt + "LINESTRING(0 0, 10 2)" + + + + + beta + + csv + + wkt + "LINESTRING(0 2, 10 4)" + + + + + gamma + + csv + + wkt + "LINESTRING(0 4, 10 6)" + + + + + + + diff --git a/tests/visual_tests/styles/marker-on-line-svg-with-box.xml b/tests/visual_tests/styles/marker-on-line-svg-with-box.xml new file mode 100644 index 000000000..ceb1c4586 --- /dev/null +++ b/tests/visual_tests/styles/marker-on-line-svg-with-box.xml @@ -0,0 +1,51 @@ + + + + + 600,400 + + + alpha + + csv + + wkt + "LINESTRING(0 0, 10 2)" + + + + + beta + + csv + + wkt + "LINESTRING(0 2, 10 4)" + + + + + gamma + + csv + + wkt + "LINESTRING(0 4, 10 6)" + + + + + + + diff --git a/tests/visual_tests/styles/marker-on-line.xml b/tests/visual_tests/styles/marker-on-line.xml index 42f67a425..6c8732435 100644 --- a/tests/visual_tests/styles/marker-on-line.xml +++ b/tests/visual_tests/styles/marker-on-line.xml @@ -1,4 +1,7 @@ + + 600,400 + @@ -15,6 +18,7 @@ point-placement csv + -10, 0, 15, 20 ../data/marker-on-line.csv | diff --git a/tests/visual_tests/styles/marker-recenter-collide.xml b/tests/visual_tests/styles/marker-recenter-collide.xml index 3f22b242d..9ace272ee 100644 --- a/tests/visual_tests/styles/marker-recenter-collide.xml +++ b/tests/visual_tests/styles/marker-recenter-collide.xml @@ -1,7 +1,10 @@ - + + 256,128 + + + + + ellipse + + csv + +x,y,id +1,1,1 +2,2,2 +3,3,3 +4,4,4 + + + + + + + + + + frame + + csv + +x,y +0,0 +5,0 +0,5 +5,5 + + + + + \ No newline at end of file diff --git a/tests/visual_tests/styles/marker-symbolizer-expressions-all.xml b/tests/visual_tests/styles/marker-symbolizer-expressions-all.xml index f488668d2..273d553d5 100644 --- a/tests/visual_tests/styles/marker-symbolizer-expressions-all.xml +++ b/tests/visual_tests/styles/marker-symbolizer-expressions-all.xml @@ -1,6 +1,9 @@ + + 256,256 + - + frame @@ -71,4 +74,4 @@ x,y - \ No newline at end of file + diff --git a/tests/visual_tests/styles/marker-whole-multi-polygon.xml b/tests/visual_tests/styles/marker-whole-multi-polygon.xml index 110ef7f78..4b95c31f1 100644 --- a/tests/visual_tests/styles/marker-whole-multi-polygon.xml +++ b/tests/visual_tests/styles/marker-whole-multi-polygon.xml @@ -1,4 +1,7 @@ + + 512,512 + diff --git a/tests/visual_tests/styles/orientation.xml b/tests/visual_tests/styles/orientation.xml index e0e283b78..aaf34575c 100644 --- a/tests/visual_tests/styles/orientation.xml +++ b/tests/visual_tests/styles/orientation.xml @@ -1,11 +1,15 @@ + + 800, 200 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv @@ -13,52 +17,52 @@ diff --git a/tests/visual_tests/styles/point-symbolizer-expressions-all.xml b/tests/visual_tests/styles/point-symbolizer-expressions-all.xml index e9cf2a16e..d5953435e 100644 --- a/tests/visual_tests/styles/point-symbolizer-expressions-all.xml +++ b/tests/visual_tests/styles/point-symbolizer-expressions-all.xml @@ -1,6 +1,9 @@ + + 256,256 + + + + DISCRETE RAINBOW + + ../../data/raster/dataraster.tif + raster + 1 + + + + diff --git a/tests/visual_tests/styles/raster-color-to-alpha5.xml b/tests/visual_tests/styles/raster-color-to-alpha5.xml index 6a2f4add6..e6acda42b 100644 --- a/tests/visual_tests/styles/raster-color-to-alpha5.xml +++ b/tests/visual_tests/styles/raster-color-to-alpha5.xml @@ -1,4 +1,7 @@ + + 512,512 + + + + DISCRETE RAINBOW + + ../../data/raster/dataraster.tif + raster + 1 + + + + diff --git a/tests/visual_tests/styles/raster_colorizer.xml b/tests/visual_tests/styles/raster_colorizer.xml index 8c1c91831..6954118b4 100644 --- a/tests/visual_tests/styles/raster_colorizer.xml +++ b/tests/visual_tests/styles/raster_colorizer.xml @@ -1,4 +1,7 @@ + + 512,512 + @@ -68,4 +71,4 @@ - \ No newline at end of file + diff --git a/tests/visual_tests/styles/raster_symbolizer.xml b/tests/visual_tests/styles/raster_symbolizer.xml index 14632b103..48bfa0ba4 100644 --- a/tests/visual_tests/styles/raster_symbolizer.xml +++ b/tests/visual_tests/styles/raster_symbolizer.xml @@ -1,4 +1,7 @@ + + 512,512 + + + 1 + + rasterlite + globe + ../../data/rasterlite/globe.sqlite + + + + diff --git a/tests/visual_tests/styles/repeat-labels-1.xml b/tests/visual_tests/styles/repeat-labels-1.xml index 1938a6a99..a84350fcb 100644 --- a/tests/visual_tests/styles/repeat-labels-1.xml +++ b/tests/visual_tests/styles/repeat-labels-1.xml @@ -1,20 +1,23 @@ - + + 750,250 + + - + - + - + - + - + - + - + - + - \ No newline at end of file + diff --git a/tests/visual_tests/styles/shield-on-polygon.xml b/tests/visual_tests/styles/shield-on-polygon.xml index c4f2f9e55..da92ef1ec 100644 --- a/tests/visual_tests/styles/shield-on-polygon.xml +++ b/tests/visual_tests/styles/shield-on-polygon.xml @@ -1,6 +1,9 @@ + + 600,400 + -180,-85.05112877980659,180,85.05112877980659 @@ -46,4 +49,4 @@ - \ No newline at end of file + diff --git a/tests/visual_tests/styles/shieldsymbolizer-1.xml b/tests/visual_tests/styles/shieldsymbolizer-1.xml index 0af96590a..848ca0ede 100644 --- a/tests/visual_tests/styles/shieldsymbolizer-1.xml +++ b/tests/visual_tests/styles/shieldsymbolizer-1.xml @@ -2,11 +2,15 @@ + + 490, 100; 495, 100; 497, 100; 498, 100; 499, 100; 500, 100; 501, 100; 502, 100; 505, 100; 510, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/shieldsymbolizer-2.xml b/tests/visual_tests/styles/shieldsymbolizer-2.xml index 7acf4276d..9f4473bcf 100644 --- a/tests/visual_tests/styles/shieldsymbolizer-2.xml +++ b/tests/visual_tests/styles/shieldsymbolizer-2.xml @@ -2,11 +2,15 @@ + + 490, 100; 495, 100; 497, 100; 498, 100; 499, 100; 500, 100; 501, 100; 502, 100; 505, 100; 510, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/shieldsymbolizer-3.xml b/tests/visual_tests/styles/shieldsymbolizer-3.xml index 01e3dc151..67c60f54c 100644 --- a/tests/visual_tests/styles/shieldsymbolizer-3.xml +++ b/tests/visual_tests/styles/shieldsymbolizer-3.xml @@ -2,11 +2,15 @@ + + 490, 100; 495, 100; 497, 100; 498, 100; 499, 100; 500, 100; 501, 100; 502, 100; 505, 100; 510, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/shieldsymbolizer-4.xml b/tests/visual_tests/styles/shieldsymbolizer-4.xml index 14fe55ebf..6693ba00a 100644 --- a/tests/visual_tests/styles/shieldsymbolizer-4.xml +++ b/tests/visual_tests/styles/shieldsymbolizer-4.xml @@ -2,11 +2,15 @@ + + 490, 100; 495, 100; 497, 100; 498, 100; 499, 100; 500, 100; 501, 100; 502, 100; 505, 100; 510, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-E.xml b/tests/visual_tests/styles/simple-E.xml index d937efa01..799a3d65c 100644 --- a/tests/visual_tests/styles/simple-E.xml +++ b/tests/visual_tests/styles/simple-E.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-N.xml b/tests/visual_tests/styles/simple-N.xml index a5e6eebdf..5b9b79d15 100644 --- a/tests/visual_tests/styles/simple-N.xml +++ b/tests/visual_tests/styles/simple-N.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-NE.xml b/tests/visual_tests/styles/simple-NE.xml index 8589c77d9..aee999c0e 100644 --- a/tests/visual_tests/styles/simple-NE.xml +++ b/tests/visual_tests/styles/simple-NE.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-NW.xml b/tests/visual_tests/styles/simple-NW.xml index c133eb16e..bf4d35ffe 100644 --- a/tests/visual_tests/styles/simple-NW.xml +++ b/tests/visual_tests/styles/simple-NW.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-S.xml b/tests/visual_tests/styles/simple-S.xml index 2ceb0c594..a868ea30a 100644 --- a/tests/visual_tests/styles/simple-S.xml +++ b/tests/visual_tests/styles/simple-S.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-SE.xml b/tests/visual_tests/styles/simple-SE.xml index eea79a652..5c411a0e2 100644 --- a/tests/visual_tests/styles/simple-SE.xml +++ b/tests/visual_tests/styles/simple-SE.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-SW.xml b/tests/visual_tests/styles/simple-SW.xml index d7038b308..bc0712931 100644 --- a/tests/visual_tests/styles/simple-SW.xml +++ b/tests/visual_tests/styles/simple-SW.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-W.xml b/tests/visual_tests/styles/simple-W.xml index ea8258984..f687644ca 100644 --- a/tests/visual_tests/styles/simple-W.xml +++ b/tests/visual_tests/styles/simple-W.xml @@ -6,6 +6,7 @@ My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv diff --git a/tests/visual_tests/styles/simple-shield.xml b/tests/visual_tests/styles/simple-shield.xml index 80efe2c6e..3ea2f6442 100644 --- a/tests/visual_tests/styles/simple-shield.xml +++ b/tests/visual_tests/styles/simple-shield.xml @@ -1,6 +1,9 @@ + + 600,400 + My Style diff --git a/tests/visual_tests/styles/simple.xml b/tests/visual_tests/styles/simple.xml index a10fbdac5..7105f7cc8 100644 --- a/tests/visual_tests/styles/simple.xml +++ b/tests/visual_tests/styles/simple.xml @@ -1,11 +1,15 @@ + + 800, 100; 600, 100; 400, 100; 300, 100; 250, 100; 150, 100; 100, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv @@ -13,7 +17,7 @@ diff --git a/tests/visual_tests/styles/simplify-douglas-peucker.xml b/tests/visual_tests/styles/simplify-douglas-peucker.xml new file mode 100644 index 000000000..2553c3829 --- /dev/null +++ b/tests/visual_tests/styles/simplify-douglas-peucker.xml @@ -0,0 +1,24 @@ + + + 500, 1000 + + + + lines + + sqlite + ../../data/sqlite/world.sqlite + true + + (SELECT *, 'douglas-peucker' as algorithm, 2 as simplify, -375 as ty FROM world_merc UNION ALL + SELECT *, 'douglas-peucker' as algorithm, 4 as simplify, -125 as ty FROM world_merc UNION ALL + SELECT *, 'douglas-peucker' as algorithm, 8 as simplify, 125 as ty FROM world_merc UNION ALL + SELECT *, 'douglas-peucker' as algorithm, 16 as simplify, 375 as ty FROM world_merc) + + + + diff --git a/tests/visual_tests/styles/simplify-radial-distance.xml b/tests/visual_tests/styles/simplify-radial-distance.xml new file mode 100644 index 000000000..3ad3e3ec8 --- /dev/null +++ b/tests/visual_tests/styles/simplify-radial-distance.xml @@ -0,0 +1,24 @@ + + + 500, 1000 + + + + lines + + sqlite + ../../data/sqlite/world.sqlite + true + + (SELECT *, 'radial-distance' as algorithm, 10 as simplify, -375 as ty FROM world_merc UNION ALL + SELECT *, 'radial-distance' as algorithm, 40 as simplify, -125 as ty FROM world_merc UNION ALL + SELECT *, 'radial-distance' as algorithm, 160 as simplify, 125 as ty FROM world_merc UNION ALL + SELECT *, 'radial-distance' as algorithm, 640 as simplify, 375 as ty FROM world_merc) + + + + diff --git a/tests/visual_tests/styles/simplify-visvalingam-whyatt.xml b/tests/visual_tests/styles/simplify-visvalingam-whyatt.xml new file mode 100644 index 000000000..623857e45 --- /dev/null +++ b/tests/visual_tests/styles/simplify-visvalingam-whyatt.xml @@ -0,0 +1,24 @@ + + + 500, 1000 + + + + lines + + sqlite + ../../data/sqlite/world.sqlite + true + + (SELECT *, 'visvalingam-whyatt' as algorithm, 10 as simplify, -375 as ty FROM world_merc UNION ALL + SELECT *, 'visvalingam-whyatt' as algorithm, 20 as simplify, -125 as ty FROM world_merc UNION ALL + SELECT *, 'visvalingam-whyatt' as algorithm, 40 as simplify, 125 as ty FROM world_merc UNION ALL + SELECT *, 'visvalingam-whyatt' as algorithm, 80 as simplify, 375 as ty FROM world_merc) + + + + diff --git a/tests/visual_tests/styles/simplify-zhao-saalfeld.xml b/tests/visual_tests/styles/simplify-zhao-saalfeld.xml new file mode 100644 index 000000000..3f46226d2 --- /dev/null +++ b/tests/visual_tests/styles/simplify-zhao-saalfeld.xml @@ -0,0 +1,24 @@ + + + 500, 1000 + + + + lines + + sqlite + ../../data/sqlite/world.sqlite + true + + (SELECT *, 'zhao-saalfeld' as algorithm, 1 as simplify, -375 as ty FROM world_merc UNION ALL + SELECT *, 'zhao-saalfeld' as algorithm, 2 as simplify, -125 as ty FROM world_merc UNION ALL + SELECT *, 'zhao-saalfeld' as algorithm, 4 as simplify, 125 as ty FROM world_merc UNION ALL + SELECT *, 'zhao-saalfeld' as algorithm, 10 as simplify, 375 as ty FROM world_merc) + + + + diff --git a/tests/visual_tests/styles/style-level-compositing-tiled-0,0.xml b/tests/visual_tests/styles/style-level-compositing-tiled-0,0.xml index a3d8f32b1..e88d964c5 100644 --- a/tests/visual_tests/styles/style-level-compositing-tiled-0,0.xml +++ b/tests/visual_tests/styles/style-level-compositing-tiled-0,0.xml @@ -1,4 +1,8 @@ + + 512,512 + -20037508.342,0,0,20037508.342 + - \ No newline at end of file + diff --git a/tests/visual_tests/styles/text-charplacement.xml b/tests/visual_tests/styles/text-charplacement.xml index 5a8a705c4..3eb09d16c 100644 --- a/tests/visual_tests/styles/text-charplacement.xml +++ b/tests/visual_tests/styles/text-charplacement.xml @@ -1,5 +1,8 @@ + + 512,512 + diff --git a/tests/visual_tests/styles/text-halign-adjust-multiline.xml b/tests/visual_tests/styles/text-halign-adjust-multiline.xml index 0654bb1dd..0afef8839 100644 --- a/tests/visual_tests/styles/text-halign-adjust-multiline.xml +++ b/tests/visual_tests/styles/text-halign-adjust-multiline.xml @@ -2,6 +2,10 @@ + + 800, 800 + -0.05, -0.01, 0.95, 0.01 + My Style diff --git a/tests/visual_tests/styles/text-halign-adjust.xml b/tests/visual_tests/styles/text-halign-adjust.xml index 039f760bd..13b4020a1 100644 --- a/tests/visual_tests/styles/text-halign-adjust.xml +++ b/tests/visual_tests/styles/text-halign-adjust.xml @@ -2,6 +2,10 @@ + + 800, 800 + -0.05, -0.01, 0.95, 0.01 + My Style diff --git a/tests/visual_tests/styles/text-halign.xml b/tests/visual_tests/styles/text-halign.xml index d0e67dd20..668f12eee 100644 --- a/tests/visual_tests/styles/text-halign.xml +++ b/tests/visual_tests/styles/text-halign.xml @@ -2,6 +2,10 @@ + + 800, 800 + -0.05, -0.01, 0.95, 0.01 + My Style diff --git a/tests/visual_tests/styles/text-halo-opacity.xml b/tests/visual_tests/styles/text-halo-opacity.xml index d8cca1932..f9a7127fa 100644 --- a/tests/visual_tests/styles/text-halo-opacity.xml +++ b/tests/visual_tests/styles/text-halo-opacity.xml @@ -1,4 +1,7 @@ + + 512,512 + + diff --git a/tests/visual_tests/styles/text-line-wrap.xml b/tests/visual_tests/styles/text-line-wrap.xml index bb0f8743d..ab47aecdc 100644 --- a/tests/visual_tests/styles/text-line-wrap.xml +++ b/tests/visual_tests/styles/text-line-wrap.xml @@ -1,5 +1,8 @@ + + 512,512 + @@ -22,10 +25,10 @@ { "type": "FeatureCollection", - + "features": [ - - { "type": "Feature", + + { "type": "Feature", "properties": { "label": "this,that", "wrap-character":",", @@ -33,7 +36,7 @@ }, "geometry" : { "type": "Point", "coordinates": [ 2.5, 2.5 ] } }, - { "type": "Feature", + { "type": "Feature", "properties": { "label": "this-that", "wrap-character":"-", @@ -43,7 +46,7 @@ } ] } - + geojson @@ -71,4 +74,4 @@ x,y - \ No newline at end of file + diff --git a/tests/visual_tests/styles/text-malayalam.xml b/tests/visual_tests/styles/text-malayalam.xml index 48b24c955..689f884ac 100644 --- a/tests/visual_tests/styles/text-malayalam.xml +++ b/tests/visual_tests/styles/text-malayalam.xml @@ -2,13 +2,16 @@ + + 800, 100 + My Style csv + -0.05, -0.01, 0.95, 0.01 ../data/points.csv - -1,-1,1,1