From 92e06374736aa28637dc0e706455b65c8268a5e6 Mon Sep 17 00:00:00 2001 From: zverevgeny Date: Tue, 13 May 2025 19:00:02 +0300 Subject: Import matplotlib commit_hash:d59c2338025ef8fd1e1f961ed9d8d5fd52d0bd96 --- contrib/python/matplotlib/py2/.dist-info/METADATA | 38 + .../python/matplotlib/py2/.dist-info/top_level.txt | 3 + contrib/python/matplotlib/py2/LICENSE/LICENSE | 99 + contrib/python/matplotlib/py2/LICENSE/LICENSE.PIL | 12 + .../python/matplotlib/py2/LICENSE/LICENSE_AMSFONTS | 240 + .../python/matplotlib/py2/LICENSE/LICENSE_BAKOMA | 40 + .../matplotlib/py2/LICENSE/LICENSE_COLORBREWER | 38 + .../python/matplotlib/py2/LICENSE/LICENSE_CONDA | 51 + .../python/matplotlib/py2/LICENSE/LICENSE_JQUERY | 61 + .../matplotlib/py2/LICENSE/LICENSE_QT4_EDITOR | 30 + contrib/python/matplotlib/py2/LICENSE/LICENSE_STIX | 71 + .../python/matplotlib/py2/LICENSE/LICENSE_YORICK | 49 + .../matplotlib/py2/LICENSE/LICENSE_enthought.txt | 29 + .../python/matplotlib/py2/LICENSE/Solarized.txt | 20 + .../python/matplotlib/py2/LICENSE/pnpoly.license | 26 + contrib/python/matplotlib/py2/README.rst | 83 + .../extern/agg24-svn/include/agg_alpha_mask_u8.h | 499 + .../py2/extern/agg24-svn/include/agg_arc.h | 74 + .../py2/extern/agg24-svn/include/agg_array.h | 1119 ++ .../py2/extern/agg24-svn/include/agg_arrowhead.h | 82 + .../py2/extern/agg24-svn/include/agg_basics.h | 560 + .../py2/extern/agg24-svn/include/agg_bezier_arc.h | 159 + .../extern/agg24-svn/include/agg_bitset_iterator.h | 54 + .../py2/extern/agg24-svn/include/agg_blur.h | 1503 +++ .../extern/agg24-svn/include/agg_bounding_rect.h | 116 + .../py2/extern/agg24-svn/include/agg_bspline.h | 76 + .../agg24-svn/include/agg_clip_liang_barsky.h | 333 + .../py2/extern/agg24-svn/include/agg_color_gray.h | 1047 ++ .../py2/extern/agg24-svn/include/agg_color_rgba.h | 1353 +++ .../py2/extern/agg24-svn/include/agg_config.h | 44 + .../agg24-svn/include/agg_conv_adaptor_vcgen.h | 157 + .../agg24-svn/include/agg_conv_adaptor_vpgen.h | 159 + .../extern/agg24-svn/include/agg_conv_bspline.h | 48 + .../agg24-svn/include/agg_conv_clip_polygon.h | 63 + .../agg24-svn/include/agg_conv_clip_polyline.h | 63 + .../agg24-svn/include/agg_conv_close_polygon.h | 125 + .../py2/extern/agg24-svn/include/agg_conv_concat.h | 73 + .../extern/agg24-svn/include/agg_conv_contour.h | 65 + .../py2/extern/agg24-svn/include/agg_conv_curve.h | 201 + .../py2/extern/agg24-svn/include/agg_conv_dash.h | 68 + .../py2/extern/agg24-svn/include/agg_conv_gpc.h | 432 + .../py2/extern/agg24-svn/include/agg_conv_marker.h | 148 + .../agg24-svn/include/agg_conv_marker_adaptor.h | 51 + .../agg24-svn/include/agg_conv_segmentator.h | 48 + .../agg24-svn/include/agg_conv_shorten_path.h | 50 + .../agg24-svn/include/agg_conv_smooth_poly1.h | 80 + .../py2/extern/agg24-svn/include/agg_conv_stroke.h | 73 + .../extern/agg24-svn/include/agg_conv_transform.h | 68 + .../agg24-svn/include/agg_conv_unclose_polygon.h | 52 + .../py2/extern/agg24-svn/include/agg_curves.h | 693 ++ .../py2/extern/agg24-svn/include/agg_dda_line.h | 290 + .../py2/extern/agg24-svn/include/agg_ellipse.h | 123 + .../agg24-svn/include/agg_ellipse_bresenham.h | 113 + .../agg24-svn/include/agg_embedded_raster_fonts.h | 59 + .../agg24-svn/include/agg_font_cache_manager.h | 409 + .../agg24-svn/include/agg_font_cache_manager2.h | 311 + .../extern/agg24-svn/include/agg_gamma_functions.h | 132 + .../py2/extern/agg24-svn/include/agg_gamma_lut.h | 305 + .../agg24-svn/include/agg_glyph_raster_bin.h | 155 + .../extern/agg24-svn/include/agg_gradient_lut.h | 244 + .../py2/extern/agg24-svn/include/agg_gsv_text.h | 153 + .../extern/agg24-svn/include/agg_image_accessors.h | 481 + .../extern/agg24-svn/include/agg_image_filters.h | 448 + .../extern/agg24-svn/include/agg_line_aa_basics.h | 189 + .../py2/extern/agg24-svn/include/agg_math.h | 437 + .../py2/extern/agg24-svn/include/agg_math_stroke.h | 527 + .../py2/extern/agg24-svn/include/agg_path_length.h | 65 + .../extern/agg24-svn/include/agg_path_storage.h | 1545 +++ .../agg24-svn/include/agg_path_storage_integer.h | 295 + .../agg24-svn/include/agg_pattern_filters_rgba.h | 123 + .../agg24-svn/include/agg_pixfmt_amask_adaptor.h | 240 + .../py2/extern/agg24-svn/include/agg_pixfmt_base.h | 97 + .../py2/extern/agg24-svn/include/agg_pixfmt_gray.h | 737 ++ .../py2/extern/agg24-svn/include/agg_pixfmt_rgb.h | 994 ++ .../agg24-svn/include/agg_pixfmt_rgb_packed.h | 1312 +++ .../py2/extern/agg24-svn/include/agg_pixfmt_rgba.h | 2801 +++++ .../agg24-svn/include/agg_pixfmt_transposer.h | 157 + .../agg24-svn/include/agg_rasterizer_cells_aa.h | 743 ++ .../agg24-svn/include/agg_rasterizer_compound_aa.h | 663 ++ .../agg24-svn/include/agg_rasterizer_outline.h | 147 + .../agg24-svn/include/agg_rasterizer_outline_aa.h | 599 ++ .../agg24-svn/include/agg_rasterizer_scanline_aa.h | 481 + .../include/agg_rasterizer_scanline_aa_nogamma.h | 482 + .../agg24-svn/include/agg_rasterizer_sl_clip.h | 351 + .../extern/agg24-svn/include/agg_renderer_base.h | 731 ++ .../agg24-svn/include/agg_renderer_markers.h | 706 ++ .../extern/agg24-svn/include/agg_renderer_mclip.h | 349 + .../agg24-svn/include/agg_renderer_outline_aa.h | 1837 ++++ .../agg24-svn/include/agg_renderer_outline_image.h | 1036 ++ .../agg24-svn/include/agg_renderer_primitives.h | 224 + .../agg24-svn/include/agg_renderer_raster_text.h | 264 + .../agg24-svn/include/agg_renderer_scanline.h | 852 ++ .../agg24-svn/include/agg_rendering_buffer.h | 300 + .../include/agg_rendering_buffer_dynarow.h | 137 + .../extern/agg24-svn/include/agg_rounded_rect.h | 72 + .../extern/agg24-svn/include/agg_scanline_bin.h | 264 + .../include/agg_scanline_boolean_algebra.h | 1567 +++ .../py2/extern/agg24-svn/include/agg_scanline_p.h | 329 + .../agg24-svn/include/agg_scanline_storage_aa.h | 815 ++ .../agg24-svn/include/agg_scanline_storage_bin.h | 586 ++ .../py2/extern/agg24-svn/include/agg_scanline_u.h | 499 + .../extern/agg24-svn/include/agg_shorten_path.h | 66 + .../py2/extern/agg24-svn/include/agg_simul_eq.h | 147 + .../extern/agg24-svn/include/agg_span_allocator.h | 54 + .../extern/agg24-svn/include/agg_span_converter.h | 56 + .../extern/agg24-svn/include/agg_span_gouraud.h | 172 + .../agg24-svn/include/agg_span_gouraud_gray.h | 241 + .../agg24-svn/include/agg_span_gouraud_rgba.h | 277 + .../extern/agg24-svn/include/agg_span_gradient.h | 377 + .../agg24-svn/include/agg_span_gradient_alpha.h | 126 + .../agg24-svn/include/agg_span_gradient_contour.h | 362 + .../agg24-svn/include/agg_span_gradient_image.h | 188 + .../agg24-svn/include/agg_span_image_filter.h | 246 + .../agg24-svn/include/agg_span_image_filter_gray.h | 723 ++ .../agg24-svn/include/agg_span_image_filter_rgb.h | 861 ++ .../agg24-svn/include/agg_span_image_filter_rgba.h | 890 ++ .../include/agg_span_interpolator_adaptor.h | 77 + .../include/agg_span_interpolator_linear.h | 232 + .../include/agg_span_interpolator_persp.h | 462 + .../include/agg_span_interpolator_trans.h | 92 + .../agg24-svn/include/agg_span_pattern_gray.h | 93 + .../agg24-svn/include/agg_span_pattern_rgb.h | 96 + .../agg24-svn/include/agg_span_pattern_rgba.h | 94 + .../py2/extern/agg24-svn/include/agg_span_solid.h | 53 + .../agg24-svn/include/agg_span_subdiv_adaptor.h | 141 + .../extern/agg24-svn/include/agg_trans_affine.h | 518 + .../extern/agg24-svn/include/agg_trans_bilinear.h | 166 + .../agg24-svn/include/agg_trans_double_path.h | 131 + .../agg24-svn/include/agg_trans_perspective.h | 731 ++ .../agg24-svn/include/agg_trans_single_path.h | 97 + .../extern/agg24-svn/include/agg_trans_viewport.h | 303 + .../agg24-svn/include/agg_trans_warp_magnifier.h | 56 + .../extern/agg24-svn/include/agg_vcgen_bspline.h | 74 + .../extern/agg24-svn/include/agg_vcgen_contour.h | 94 + .../py2/extern/agg24-svn/include/agg_vcgen_dash.h | 93 + .../agg24-svn/include/agg_vcgen_markers_term.h | 66 + .../agg24-svn/include/agg_vcgen_smooth_poly1.h | 87 + .../extern/agg24-svn/include/agg_vcgen_stroke.h | 102 + .../agg24-svn/include/agg_vcgen_vertex_sequence.h | 135 + .../extern/agg24-svn/include/agg_vertex_sequence.h | 172 + .../agg24-svn/include/agg_vpgen_clip_polygon.h | 83 + .../agg24-svn/include/agg_vpgen_clip_polyline.h | 78 + .../agg24-svn/include/agg_vpgen_segmentator.h | 61 + .../agg24-svn/include/ctrl/agg_bezier_ctrl.h | 196 + .../extern/agg24-svn/include/ctrl/agg_cbox_ctrl.h | 112 + .../py2/extern/agg24-svn/include/ctrl/agg_ctrl.h | 118 + .../extern/agg24-svn/include/ctrl/agg_gamma_ctrl.h | 170 + .../agg24-svn/include/ctrl/agg_gamma_spline.h | 95 + .../agg24-svn/include/ctrl/agg_polygon_ctrl.h | 166 + .../extern/agg24-svn/include/ctrl/agg_rbox_ctrl.h | 141 + .../extern/agg24-svn/include/ctrl/agg_scale_ctrl.h | 146 + .../agg24-svn/include/ctrl/agg_slider_ctrl.h | 150 + .../agg24-svn/include/ctrl/agg_spline_ctrl.h | 159 + .../include/platform/agg_platform_support.h | 686 ++ .../agg24-svn/include/platform/mac/agg_mac_pmap.h | 87 + .../include/platform/win32/agg_win32_bmp.h | 117 + .../extern/agg24-svn/include/util/agg_color_conv.h | 128 + .../agg24-svn/include/util/agg_color_conv_rgb16.h | 285 + .../agg24-svn/include/util/agg_color_conv_rgb8.h | 476 + .../matplotlib/py2/extern/agg24-svn/src/ChangeLog | 0 .../py2/extern/agg24-svn/src/agg_arc.cpp | 106 + .../py2/extern/agg24-svn/src/agg_arrowhead.cpp | 110 + .../py2/extern/agg24-svn/src/agg_bezier_arc.cpp | 258 + .../py2/extern/agg24-svn/src/agg_bspline.cpp | 284 + .../py2/extern/agg24-svn/src/agg_color_rgba.cpp | 17 + .../py2/extern/agg24-svn/src/agg_curves.cpp | 613 ++ .../agg24-svn/src/agg_embedded_raster_fonts.cpp | 10426 +++++++++++++++++++ .../py2/extern/agg24-svn/src/agg_gsv_text.cpp | 675 ++ .../py2/extern/agg24-svn/src/agg_image_filters.cpp | 103 + .../extern/agg24-svn/src/agg_line_aa_basics.cpp | 82 + .../extern/agg24-svn/src/agg_line_profile_aa.cpp | 116 + .../py2/extern/agg24-svn/src/agg_rounded_rect.cpp | 164 + .../py2/extern/agg24-svn/src/agg_sqrt_tables.cpp | 115 + .../py2/extern/agg24-svn/src/agg_trans_affine.cpp | 194 + .../extern/agg24-svn/src/agg_trans_double_path.cpp | 273 + .../extern/agg24-svn/src/agg_trans_single_path.cpp | 202 + .../agg24-svn/src/agg_trans_warp_magnifier.cpp | 70 + .../py2/extern/agg24-svn/src/agg_vcgen_bspline.cpp | 194 + .../py2/extern/agg24-svn/src/agg_vcgen_contour.cpp | 165 + .../py2/extern/agg24-svn/src/agg_vcgen_dash.cpp | 235 + .../agg24-svn/src/agg_vcgen_markers_term.cpp | 103 + .../agg24-svn/src/agg_vcgen_smooth_poly1.cpp | 225 + .../py2/extern/agg24-svn/src/agg_vcgen_stroke.cpp | 213 + .../agg24-svn/src/agg_vpgen_clip_polygon.cpp | 133 + .../agg24-svn/src/agg_vpgen_clip_polyline.cpp | 77 + .../extern/agg24-svn/src/agg_vpgen_segmentator.cpp | 67 + .../matplotlib/py2/extern/agg24-svn/src/authors | 0 .../matplotlib/py2/extern/agg24-svn/src/copying | 11 + .../extern/agg24-svn/src/ctrl/agg_bezier_ctrl.cpp | 370 + .../extern/agg24-svn/src/ctrl/agg_cbox_ctrl.cpp | 214 + .../extern/agg24-svn/src/ctrl/agg_gamma_ctrl.cpp | 433 + .../extern/agg24-svn/src/ctrl/agg_gamma_spline.cpp | 130 + .../extern/agg24-svn/src/ctrl/agg_polygon_ctrl.cpp | 332 + .../extern/agg24-svn/src/ctrl/agg_rbox_ctrl.cpp | 325 + .../extern/agg24-svn/src/ctrl/agg_scale_ctrl.cpp | 454 + .../extern/agg24-svn/src/ctrl/agg_slider_ctrl.cpp | 349 + .../extern/agg24-svn/src/ctrl/agg_spline_ctrl.cpp | 407 + .../src/platform/AmigaOS/agg_platform_support.cpp | 977 ++ .../src/platform/BeOS/agg_platform_support.cpp | 990 ++ .../src/platform/X11/agg_platform_support.cpp | 1601 +++ .../agg24-svn/src/platform/mac/agg_mac_pmap.cpp | 298 + .../src/platform/mac/agg_platform_support.cpp | 1053 ++ .../src/platform/sdl/agg_platform_support.cpp | 708 ++ .../src/platform/win32/agg_platform_support.cpp | 1655 +++ .../agg24-svn/src/platform/win32/agg_win32_bmp.cpp | 631 ++ .../python/matplotlib/py2/extern/agg24-svn/ya.make | 24 + .../python/matplotlib/py2/extern/ttconv/pprdrv.h | 113 + .../matplotlib/py2/extern/ttconv/pprdrv_tt.cpp | 1484 +++ .../matplotlib/py2/extern/ttconv/pprdrv_tt2.cpp | 736 ++ .../python/matplotlib/py2/extern/ttconv/truetype.h | 129 + .../python/matplotlib/py2/extern/ttconv/ttutil.cpp | 82 + .../python/matplotlib/py2/extern/ttconv/ya.make | 15 + contrib/python/matplotlib/py2/extern/ya.make | 4 + .../python/matplotlib/py2/matplotlib/__init__.py | 1928 ++++ .../matplotlib/py2/matplotlib/_animation_data.py | 210 + contrib/python/matplotlib/py2/matplotlib/_cm.py | 1445 +++ .../python/matplotlib/py2/matplotlib/_cm_listed.py | 1298 +++ .../matplotlib/py2/matplotlib/_color_data.py | 1147 ++ .../py2/matplotlib/_constrained_layout.py | 666 ++ .../python/matplotlib/py2/matplotlib/_layoutbox.py | 739 ++ .../matplotlib/py2/matplotlib/_mathtext_data.py | 2548 +++++ .../matplotlib/py2/matplotlib/_pylab_helpers.py | 138 + .../python/matplotlib/py2/matplotlib/_version.py | 21 + contrib/python/matplotlib/py2/matplotlib/afm.py | 547 + .../python/matplotlib/py2/matplotlib/animation.py | 1778 ++++ contrib/python/matplotlib/py2/matplotlib/artist.py | 1482 +++ .../matplotlib/py2/matplotlib/axes/__init__.py | 5 + .../python/matplotlib/py2/matplotlib/axes/_axes.py | 8153 +++++++++++++++ .../python/matplotlib/py2/matplotlib/axes/_base.py | 4297 ++++++++ .../matplotlib/py2/matplotlib/axes/_subplots.py | 267 + contrib/python/matplotlib/py2/matplotlib/axis.py | 2509 +++++ .../matplotlib/py2/matplotlib/backend_bases.py | 3383 ++++++ .../matplotlib/py2/matplotlib/backend_managers.py | 436 + .../matplotlib/py2/matplotlib/backend_tools.py | 1081 ++ .../matplotlib/py2/matplotlib/backends/__init__.py | 97 + .../py2/matplotlib/backends/_backend_tk.py | 1075 ++ .../py2/matplotlib/backends/_gtk3_compat.py | 41 + .../py2/matplotlib/backends/backend_agg.py | 606 ++ .../py2/matplotlib/backends/backend_cairo.py | 520 + .../py2/matplotlib/backends/backend_gdk.py | 438 + .../py2/matplotlib/backends/backend_gtk.py | 1037 ++ .../py2/matplotlib/backends/backend_gtk3.py | 920 ++ .../py2/matplotlib/backends/backend_gtk3agg.py | 102 + .../py2/matplotlib/backends/backend_gtk3cairo.py | 55 + .../py2/matplotlib/backends/backend_gtkagg.py | 96 + .../py2/matplotlib/backends/backend_gtkcairo.py | 74 + .../py2/matplotlib/backends/backend_macosx.py | 210 + .../py2/matplotlib/backends/backend_mixed.py | 155 + .../py2/matplotlib/backends/backend_nbagg.py | 270 + .../py2/matplotlib/backends/backend_pdf.py | 2604 +++++ .../py2/matplotlib/backends/backend_pgf.py | 990 ++ .../py2/matplotlib/backends/backend_ps.py | 1762 ++++ .../py2/matplotlib/backends/backend_qt4.py | 15 + .../py2/matplotlib/backends/backend_qt4agg.py | 15 + .../py2/matplotlib/backends/backend_qt4cairo.py | 6 + .../py2/matplotlib/backends/backend_qt5.py | 1119 ++ .../py2/matplotlib/backends/backend_qt5agg.py | 105 + .../py2/matplotlib/backends/backend_qt5cairo.py | 49 + .../py2/matplotlib/backends/backend_svg.py | 1261 +++ .../py2/matplotlib/backends/backend_template.py | 278 + .../py2/matplotlib/backends/backend_tkagg.py | 34 + .../py2/matplotlib/backends/backend_tkcairo.py | 37 + .../py2/matplotlib/backends/backend_webagg.py | 350 + .../py2/matplotlib/backends/backend_webagg_core.py | 543 + .../py2/matplotlib/backends/backend_wx.py | 2002 ++++ .../py2/matplotlib/backends/backend_wxagg.py | 147 + .../py2/matplotlib/backends/backend_wxcairo.py | 53 + .../py2/matplotlib/backends/qt_compat.py | 176 + .../py2/matplotlib/backends/qt_editor/__init__.py | 2 + .../matplotlib/backends/qt_editor/figureoptions.py | 262 + .../matplotlib/backends/qt_editor/formlayout.py | 544 + .../backends/qt_editor/formsubplottool.py | 56 + .../matplotlib/py2/matplotlib/backends/tkagg.py | 44 + .../backends/web_backend/all_figures.html | 43 + .../backends/web_backend/css/boilerplate.css | 77 + .../matplotlib/backends/web_backend/css/fbm.css | 97 + .../matplotlib/backends/web_backend/css/page.css | 82 + .../web_backend/ipython_inline_figure.html | 34 + .../web_backend/jquery/js/jquery-1.11.3.js | 10351 ++++++++++++++++++ .../web_backend/jquery/js/jquery-1.11.3.min.js | 5 + .../py2/matplotlib/backends/web_backend/js/mpl.js | 554 + .../backends/web_backend/js/mpl_tornado.js | 7 + .../backends/web_backend/js/nbagg_mpl.js | 208 + .../backends/web_backend/nbagg_uat.ipynb | 640 ++ .../backends/web_backend/single_figure.html | 30 + .../py2/matplotlib/backends/windowing.py | 31 + .../py2/matplotlib/backends/wx_compat.py | 177 + contrib/python/matplotlib/py2/matplotlib/bezier.py | 495 + .../matplotlib/py2/matplotlib/blocking_input.py | 375 + .../python/matplotlib/py2/matplotlib/category.py | 211 + .../matplotlib/py2/matplotlib/cbook/__init__.py | 2888 +++++ .../matplotlib/py2/matplotlib/cbook/_backports.py | 147 + .../matplotlib/py2/matplotlib/cbook/deprecation.py | 222 + contrib/python/matplotlib/py2/matplotlib/cm.py | 392 + .../matplotlib/py2/matplotlib/collections.py | 1994 ++++ .../python/matplotlib/py2/matplotlib/colorbar.py | 1405 +++ contrib/python/matplotlib/py2/matplotlib/colors.py | 2030 ++++ .../matplotlib/py2/matplotlib/compat/__init__.py | 0 .../matplotlib/py2/matplotlib/compat/subprocess.py | 51 + .../python/matplotlib/py2/matplotlib/container.py | 194 + .../python/matplotlib/py2/matplotlib/contour.py | 1832 ++++ contrib/python/matplotlib/py2/matplotlib/dates.py | 1839 ++++ .../python/matplotlib/py2/matplotlib/docstring.py | 128 + .../python/matplotlib/py2/matplotlib/dviread.py | 1083 ++ contrib/python/matplotlib/py2/matplotlib/figure.py | 2532 +++++ .../matplotlib/py2/matplotlib/font_manager.py | 1481 +++ .../py2/matplotlib/fontconfig_pattern.py | 196 + .../python/matplotlib/py2/matplotlib/gridspec.py | 498 + contrib/python/matplotlib/py2/matplotlib/hatch.py | 220 + contrib/python/matplotlib/py2/matplotlib/image.py | 1534 +++ contrib/python/matplotlib/py2/matplotlib/legend.py | 1401 +++ .../matplotlib/py2/matplotlib/legend_handler.py | 730 ++ contrib/python/matplotlib/py2/matplotlib/lines.py | 1507 +++ .../python/matplotlib/py2/matplotlib/markers.py | 898 ++ .../python/matplotlib/py2/matplotlib/mathtext.py | 3445 ++++++ contrib/python/matplotlib/py2/matplotlib/mlab.py | 4041 +++++++ .../python/matplotlib/py2/matplotlib/offsetbox.py | 1811 ++++ .../python/matplotlib/py2/matplotlib/patches.py | 4720 +++++++++ contrib/python/matplotlib/py2/matplotlib/path.py | 1028 ++ .../matplotlib/py2/matplotlib/patheffects.py | 393 + .../py2/matplotlib/projections/__init__.py | 110 + .../matplotlib/py2/matplotlib/projections/geo.py | 547 + .../matplotlib/py2/matplotlib/projections/polar.py | 1537 +++ contrib/python/matplotlib/py2/matplotlib/pylab.py | 268 + contrib/python/matplotlib/py2/matplotlib/pyplot.py | 4099 ++++++++ contrib/python/matplotlib/py2/matplotlib/quiver.py | 1197 +++ .../python/matplotlib/py2/matplotlib/rcsetup.py | 1452 +++ contrib/python/matplotlib/py2/matplotlib/sankey.py | 833 ++ contrib/python/matplotlib/py2/matplotlib/scale.py | 607 ++ .../py2/matplotlib/sphinxext/__init__.py | 2 + .../matplotlib/py2/matplotlib/sphinxext/mathmpl.py | 126 + .../py2/matplotlib/sphinxext/only_directives.py | 75 + .../py2/matplotlib/sphinxext/plot_directive.py | 849 ++ .../py2/matplotlib/sphinxext/tests/__init__.py | 1 + .../py2/matplotlib/sphinxext/tests/conftest.py | 6 + .../matplotlib/sphinxext/tests/test_tinypages.py | 64 + .../sphinxext/tests/tinypages/.gitignore | 1 + .../matplotlib/sphinxext/tests/tinypages/README.md | 3 + .../sphinxext/tests/tinypages/_static/.gitignore | 0 .../sphinxext/tests/tinypages/_static/README.txt | 7 + .../matplotlib/sphinxext/tests/tinypages/conf.py | 264 + .../matplotlib/sphinxext/tests/tinypages/index.rst | 21 + .../matplotlib/sphinxext/tests/tinypages/range4.py | 5 + .../matplotlib/sphinxext/tests/tinypages/range6.py | 13 + .../sphinxext/tests/tinypages/some_plots.rst | 129 + contrib/python/matplotlib/py2/matplotlib/spines.py | 542 + .../python/matplotlib/py2/matplotlib/stackplot.py | 126 + .../python/matplotlib/py2/matplotlib/streamplot.py | 674 ++ .../matplotlib/py2/matplotlib/style/__init__.py | 3 + .../python/matplotlib/py2/matplotlib/style/core.py | 234 + contrib/python/matplotlib/py2/matplotlib/table.py | 702 ++ .../matplotlib/py2/matplotlib/testing/__init__.py | 59 + .../py2/matplotlib/testing/_nose/__init__.py | 78 + .../py2/matplotlib/testing/_nose/decorators.py | 33 + .../py2/matplotlib/testing/_nose/exceptions.py | 10 + .../matplotlib/testing/_nose/plugins/__init__.py | 0 .../testing/_nose/plugins/knownfailure.py | 49 + .../matplotlib/testing/_nose/plugins/performgc.py | 26 + .../matplotlib/py2/matplotlib/testing/compare.py | 489 + .../matplotlib/py2/matplotlib/testing/conftest.py | 100 + .../py2/matplotlib/testing/decorators.py | 589 ++ .../py2/matplotlib/testing/determinism.py | 145 + .../py2/matplotlib/testing/disable_internet.py | 150 + .../py2/matplotlib/testing/exceptions.py | 4 + .../py2/matplotlib/testing/jpl_units/Duration.py | 211 + .../py2/matplotlib/testing/jpl_units/Epoch.py | 238 + .../matplotlib/testing/jpl_units/EpochConverter.py | 165 + .../matplotlib/testing/jpl_units/StrConverter.py | 164 + .../py2/matplotlib/testing/jpl_units/UnitDbl.py | 297 + .../testing/jpl_units/UnitDblConverter.py | 159 + .../testing/jpl_units/UnitDblFormatter.py | 47 + .../py2/matplotlib/testing/jpl_units/__init__.py | 88 + .../py2/matplotlib/testing/noseclasses.py | 26 + .../python/matplotlib/py2/matplotlib/texmanager.py | 505 + contrib/python/matplotlib/py2/matplotlib/text.py | 2336 +++++ .../python/matplotlib/py2/matplotlib/textpath.py | 536 + contrib/python/matplotlib/py2/matplotlib/ticker.py | 2628 +++++ .../python/matplotlib/py2/matplotlib/tight_bbox.py | 87 + .../matplotlib/py2/matplotlib/tight_layout.py | 381 + .../python/matplotlib/py2/matplotlib/transforms.py | 3025 ++++++ .../matplotlib/py2/matplotlib/tri/__init__.py | 16 + .../python/matplotlib/py2/matplotlib/tri/_tri.cpp | 1999 ++++ .../python/matplotlib/py2/matplotlib/tri/_tri.h | 815 ++ .../matplotlib/py2/matplotlib/tri/_tri_wrapper.cpp | 550 + .../matplotlib/py2/matplotlib/tri/triangulation.py | 218 + .../matplotlib/py2/matplotlib/tri/tricontour.py | 283 + .../matplotlib/py2/matplotlib/tri/trifinder.py | 96 + .../py2/matplotlib/tri/triinterpolate.py | 1637 +++ .../matplotlib/py2/matplotlib/tri/tripcolor.py | 154 + .../matplotlib/py2/matplotlib/tri/triplot.py | 88 + .../matplotlib/py2/matplotlib/tri/trirefine.py | 323 + .../matplotlib/py2/matplotlib/tri/tritools.py | 304 + .../python/matplotlib/py2/matplotlib/tri/ya.make | 43 + .../python/matplotlib/py2/matplotlib/type1font.py | 334 + contrib/python/matplotlib/py2/matplotlib/units.py | 200 + .../python/matplotlib/py2/matplotlib/widgets.py | 2818 +++++ .../python/matplotlib/py2/matplotlibrc.template | 618 ++ .../python/matplotlib/py2/mpl_toolkits/__init__.py | 4 + .../py2/mpl_toolkits/axes_grid/ChangeLog | 13 + .../py2/mpl_toolkits/axes_grid/__init__.py | 15 + .../py2/mpl_toolkits/axes_grid/anchored_artists.py | 9 + .../py2/mpl_toolkits/axes_grid/angle_helper.py | 4 + .../py2/mpl_toolkits/axes_grid/axes_divider.py | 8 + .../py2/mpl_toolkits/axes_grid/axes_grid.py | 30 + .../py2/mpl_toolkits/axes_grid/axes_rgb.py | 11 + .../py2/mpl_toolkits/axes_grid/axes_size.py | 4 + .../py2/mpl_toolkits/axes_grid/axis_artist.py | 4 + .../py2/mpl_toolkits/axes_grid/axisline_style.py | 4 + .../py2/mpl_toolkits/axes_grid/axislines.py | 4 + .../py2/mpl_toolkits/axes_grid/clip_path.py | 4 + .../py2/mpl_toolkits/axes_grid/colorbar.py | 5 + .../py2/mpl_toolkits/axes_grid/floating_axes.py | 4 + .../py2/mpl_toolkits/axes_grid/grid_finder.py | 4 + .../axes_grid/grid_helper_curvelinear.py | 4 + .../py2/mpl_toolkits/axes_grid/inset_locator.py | 7 + .../py2/mpl_toolkits/axes_grid/parasite_axes.py | 18 + .../py2/mpl_toolkits/axes_grid1/__init__.py | 12 + .../mpl_toolkits/axes_grid1/anchored_artists.py | 376 + .../py2/mpl_toolkits/axes_grid1/axes_divider.py | 975 ++ .../py2/mpl_toolkits/axes_grid1/axes_grid.py | 771 ++ .../py2/mpl_toolkits/axes_grid1/axes_rgb.py | 228 + .../py2/mpl_toolkits/axes_grid1/axes_size.py | 323 + .../py2/mpl_toolkits/axes_grid1/colorbar.py | 836 ++ .../py2/mpl_toolkits/axes_grid1/inset_locator.py | 659 ++ .../py2/mpl_toolkits/axes_grid1/mpl_axes.py | 154 + .../py2/mpl_toolkits/axes_grid1/parasite_axes.py | 486 + .../py2/mpl_toolkits/axisartist/__init__.py | 26 + .../py2/mpl_toolkits/axisartist/angle_helper.py | 416 + .../py2/mpl_toolkits/axisartist/axes_divider.py | 9 + .../py2/mpl_toolkits/axisartist/axes_grid.py | 30 + .../py2/mpl_toolkits/axisartist/axes_rgb.py | 11 + .../py2/mpl_toolkits/axisartist/axis_artist.py | 1527 +++ .../py2/mpl_toolkits/axisartist/axisline_style.py | 168 + .../py2/mpl_toolkits/axisartist/axislines.py | 828 ++ .../py2/mpl_toolkits/axisartist/clip_path.py | 135 + .../py2/mpl_toolkits/axisartist/floating_axes.py | 544 + .../py2/mpl_toolkits/axisartist/grid_finder.py | 340 + .../axisartist/grid_helper_curvelinear.py | 475 + .../py2/mpl_toolkits/axisartist/parasite_axes.py | 18 + .../py2/mpl_toolkits/mplot3d/__init__.py | 6 + .../matplotlib/py2/mpl_toolkits/mplot3d/art3d.py | 774 ++ .../matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py | 2958 ++++++ .../matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py | 484 + .../matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py | 203 + contrib/python/matplotlib/py2/pylab.py | 3 + contrib/python/matplotlib/py2/src/_backend_agg.cpp | 234 + contrib/python/matplotlib/py2/src/_backend_agg.h | 1294 +++ .../matplotlib/py2/src/_backend_agg_basic_types.h | 127 + .../matplotlib/py2/src/_backend_agg_wrapper.cpp | 777 ++ contrib/python/matplotlib/py2/src/_backend_gdk.c | 72 + contrib/python/matplotlib/py2/src/_contour.cpp | 1790 ++++ contrib/python/matplotlib/py2/src/_contour.h | 530 + .../python/matplotlib/py2/src/_contour_wrapper.cpp | 203 + contrib/python/matplotlib/py2/src/_gtkagg.cpp | 155 + contrib/python/matplotlib/py2/src/_image.cpp | 175 + contrib/python/matplotlib/py2/src/_image.h | 200 + .../python/matplotlib/py2/src/_image_resample.h | 1013 ++ .../python/matplotlib/py2/src/_image_wrapper.cpp | 510 + contrib/python/matplotlib/py2/src/_macosx.m | 3174 ++++++ contrib/python/matplotlib/py2/src/_path.h | 1316 +++ .../python/matplotlib/py2/src/_path_wrapper.cpp | 900 ++ contrib/python/matplotlib/py2/src/_png.cpp | 793 ++ contrib/python/matplotlib/py2/src/_tkagg.cpp | 475 + contrib/python/matplotlib/py2/src/_tkmini.h | 128 + contrib/python/matplotlib/py2/src/_ttconv.cpp | 307 + contrib/python/matplotlib/py2/src/_windowing.cpp | 64 + contrib/python/matplotlib/py2/src/agg_workaround.h | 85 + contrib/python/matplotlib/py2/src/array.h | 80 + contrib/python/matplotlib/py2/src/file_compat.h | 240 + contrib/python/matplotlib/py2/src/ft2font.cpp | 808 ++ contrib/python/matplotlib/py2/src/ft2font.h | 139 + .../python/matplotlib/py2/src/ft2font_wrapper.cpp | 1808 ++++ contrib/python/matplotlib/py2/src/mplutils.cpp | 21 + contrib/python/matplotlib/py2/src/mplutils.h | 73 + contrib/python/matplotlib/py2/src/numpy_cpp.h | 569 + contrib/python/matplotlib/py2/src/path_cleanup.cpp | 113 + contrib/python/matplotlib/py2/src/path_cleanup.h | 27 + .../python/matplotlib/py2/src/path_converters.h | 1011 ++ contrib/python/matplotlib/py2/src/py_adaptors.h | 251 + .../python/matplotlib/py2/src/py_converters.cpp | 619 ++ contrib/python/matplotlib/py2/src/py_converters.h | 49 + contrib/python/matplotlib/py2/src/py_exceptions.h | 72 + contrib/python/matplotlib/py2/src/qhull_wrap.c | 378 + contrib/python/matplotlib/py2/src/ya.make | 68 + contrib/python/matplotlib/py2/ya.make | 243 + 485 files changed, 257277 insertions(+) create mode 100644 contrib/python/matplotlib/py2/.dist-info/METADATA create mode 100644 contrib/python/matplotlib/py2/.dist-info/top_level.txt create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE.PIL create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_AMSFONTS create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_BAKOMA create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_COLORBREWER create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_CONDA create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_JQUERY create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_QT4_EDITOR create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_STIX create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_YORICK create mode 100644 contrib/python/matplotlib/py2/LICENSE/LICENSE_enthought.txt create mode 100644 contrib/python/matplotlib/py2/LICENSE/Solarized.txt create mode 100644 contrib/python/matplotlib/py2/LICENSE/pnpoly.license create mode 100644 contrib/python/matplotlib/py2/README.rst create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_alpha_mask_u8.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arc.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_array.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arrowhead.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_basics.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bezier_arc.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bitset_iterator.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_blur.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bounding_rect.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bspline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_clip_liang_barsky.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_gray.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_config.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vcgen.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vpgen.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_bspline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polygon.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polyline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_close_polygon.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_concat.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_contour.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_curve.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_dash.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_gpc.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker_adaptor.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_segmentator.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_shorten_path.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_smooth_poly1.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_stroke.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_transform.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_unclose_polygon.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_curves.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_dda_line.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse_bresenham.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_embedded_raster_fonts.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager2.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_functions.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_lut.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_glyph_raster_bin.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gradient_lut.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gsv_text.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_accessors.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_filters.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_line_aa_basics.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math_stroke.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_length.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage_integer.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pattern_filters_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_amask_adaptor.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_base.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_gray.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb_packed.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_transposer.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_cells_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_compound_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa_nogamma.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_sl_clip.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_base.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_markers.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_mclip.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_image.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_primitives.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_raster_text.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_scanline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer_dynarow.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rounded_rect.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_bin.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_boolean_algebra.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_p.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_aa.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_bin.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_u.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_shorten_path.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_simul_eq.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_allocator.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_converter.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_gray.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_alpha.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_contour.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_image.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_gray.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgb.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_adaptor.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_linear.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_persp.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_trans.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_gray.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgb.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgba.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_solid.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_subdiv_adaptor.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_affine.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_bilinear.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_double_path.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_perspective.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_single_path.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_viewport.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_warp_magnifier.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_bspline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_contour.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_dash.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_markers_term.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_smooth_poly1.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_stroke.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_vertex_sequence.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vertex_sequence.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polygon.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polyline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_segmentator.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_bezier_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_cbox_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_spline.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_polygon_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_rbox_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_scale_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_slider_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_spline_ctrl.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/agg_platform_support.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/mac/agg_mac_pmap.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/win32/agg_win32_bmp.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb16.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb8.h create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ChangeLog create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arc.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arrowhead.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bezier_arc.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bspline.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_color_rgba.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_curves.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_embedded_raster_fonts.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_gsv_text.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_image_filters.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_aa_basics.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_profile_aa.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_rounded_rect.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_sqrt_tables.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_affine.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_double_path.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_single_path.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_warp_magnifier.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_bspline.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_contour.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_dash.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_markers_term.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_smooth_poly1.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_stroke.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polygon.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polyline.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_segmentator.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/authors create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/copying create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_bezier_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_cbox_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_spline.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_polygon_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_rbox_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_scale_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_slider_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_spline_ctrl.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/AmigaOS/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/BeOS/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/X11/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_mac_pmap.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/sdl/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_platform_support.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_win32_bmp.cpp create mode 100644 contrib/python/matplotlib/py2/extern/agg24-svn/ya.make create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/pprdrv.h create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt.cpp create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt2.cpp create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/truetype.h create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/ttutil.cpp create mode 100644 contrib/python/matplotlib/py2/extern/ttconv/ya.make create mode 100644 contrib/python/matplotlib/py2/extern/ya.make create mode 100644 contrib/python/matplotlib/py2/matplotlib/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_animation_data.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_cm.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_cm_listed.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_color_data.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_constrained_layout.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_layoutbox.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_mathtext_data.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_pylab_helpers.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/_version.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/afm.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/animation.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/artist.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/axes/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/axes/_axes.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/axes/_base.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/axes/_subplots.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/axis.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backend_bases.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backend_managers.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backend_tools.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/_backend_tk.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/_gtk3_compat.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_agg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_cairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gdk.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3agg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3cairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkcairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_macosx.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_mixed.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_nbagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_pdf.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_pgf.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_ps.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4agg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4cairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5agg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5cairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_svg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_template.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_tkagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_tkcairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg_core.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_wx.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_wxagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/backend_wxcairo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/qt_compat.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/figureoptions.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formlayout.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formsubplottool.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/tkagg.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/all_figures.html create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/boilerplate.css create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/fbm.css create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/page.css create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/ipython_inline_figure.html create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/jquery/js/jquery-1.11.3.js create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/jquery/js/jquery-1.11.3.min.js create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/js/mpl.js create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/js/mpl_tornado.js create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/js/nbagg_mpl.js create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/nbagg_uat.ipynb create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/web_backend/single_figure.html create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/windowing.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/backends/wx_compat.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/bezier.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/blocking_input.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/category.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/cbook/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/cbook/_backports.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/cbook/deprecation.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/cm.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/collections.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/colorbar.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/colors.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/compat/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/compat/subprocess.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/container.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/contour.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/dates.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/docstring.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/dviread.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/figure.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/font_manager.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/fontconfig_pattern.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/gridspec.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/hatch.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/image.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/legend.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/legend_handler.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/lines.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/markers.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/mathtext.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/mlab.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/offsetbox.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/patches.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/path.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/patheffects.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/projections/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/projections/geo.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/projections/polar.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/pylab.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/pyplot.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/quiver.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/rcsetup.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sankey.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/scale.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/mathmpl.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/only_directives.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/plot_directive.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/conftest.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/test_tinypages.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/.gitignore create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/README.md create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/_static/.gitignore create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/_static/README.txt create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/conf.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/index.rst create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/range4.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/range6.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/sphinxext/tests/tinypages/some_plots.rst create mode 100644 contrib/python/matplotlib/py2/matplotlib/spines.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/stackplot.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/streamplot.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/style/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/style/core.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/table.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/decorators.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/exceptions.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/plugins/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/plugins/knownfailure.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/_nose/plugins/performgc.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/compare.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/conftest.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/decorators.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/determinism.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/disable_internet.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/exceptions.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/Duration.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/Epoch.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/EpochConverter.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/StrConverter.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/UnitDbl.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/UnitDblConverter.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/UnitDblFormatter.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/jpl_units/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/testing/noseclasses.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/texmanager.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/text.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/textpath.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/ticker.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tight_bbox.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tight_layout.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/transforms.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/__init__.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/_tri.cpp create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/_tri.h create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/_tri_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/triangulation.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/tricontour.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/trifinder.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/triinterpolate.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/tripcolor.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/triplot.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/trirefine.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/tritools.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/tri/ya.make create mode 100644 contrib/python/matplotlib/py2/matplotlib/type1font.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/units.py create mode 100644 contrib/python/matplotlib/py2/matplotlib/widgets.py create mode 100644 contrib/python/matplotlib/py2/matplotlibrc.template create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/__init__.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/ChangeLog create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/__init__.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/anchored_artists.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/angle_helper.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_divider.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_grid.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_rgb.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axes_size.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axis_artist.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axisline_style.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/axislines.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/clip_path.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/colorbar.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/floating_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_finder.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/grid_helper_curvelinear.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/inset_locator.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid/parasite_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/__init__.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/anchored_artists.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_divider.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_grid.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_rgb.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/axes_size.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/colorbar.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/inset_locator.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/mpl_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axes_grid1/parasite_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/__init__.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/angle_helper.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_divider.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_grid.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axes_rgb.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axis_artist.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axisline_style.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/axislines.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/clip_path.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/floating_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_finder.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/grid_helper_curvelinear.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/axisartist/parasite_axes.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/__init__.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/art3d.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axes3d.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/axis3d.py create mode 100644 contrib/python/matplotlib/py2/mpl_toolkits/mplot3d/proj3d.py create mode 100644 contrib/python/matplotlib/py2/pylab.py create mode 100644 contrib/python/matplotlib/py2/src/_backend_agg.cpp create mode 100644 contrib/python/matplotlib/py2/src/_backend_agg.h create mode 100644 contrib/python/matplotlib/py2/src/_backend_agg_basic_types.h create mode 100644 contrib/python/matplotlib/py2/src/_backend_agg_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/src/_backend_gdk.c create mode 100644 contrib/python/matplotlib/py2/src/_contour.cpp create mode 100644 contrib/python/matplotlib/py2/src/_contour.h create mode 100644 contrib/python/matplotlib/py2/src/_contour_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/src/_gtkagg.cpp create mode 100644 contrib/python/matplotlib/py2/src/_image.cpp create mode 100644 contrib/python/matplotlib/py2/src/_image.h create mode 100644 contrib/python/matplotlib/py2/src/_image_resample.h create mode 100644 contrib/python/matplotlib/py2/src/_image_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/src/_macosx.m create mode 100644 contrib/python/matplotlib/py2/src/_path.h create mode 100644 contrib/python/matplotlib/py2/src/_path_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/src/_png.cpp create mode 100644 contrib/python/matplotlib/py2/src/_tkagg.cpp create mode 100644 contrib/python/matplotlib/py2/src/_tkmini.h create mode 100644 contrib/python/matplotlib/py2/src/_ttconv.cpp create mode 100644 contrib/python/matplotlib/py2/src/_windowing.cpp create mode 100644 contrib/python/matplotlib/py2/src/agg_workaround.h create mode 100644 contrib/python/matplotlib/py2/src/array.h create mode 100644 contrib/python/matplotlib/py2/src/file_compat.h create mode 100644 contrib/python/matplotlib/py2/src/ft2font.cpp create mode 100644 contrib/python/matplotlib/py2/src/ft2font.h create mode 100644 contrib/python/matplotlib/py2/src/ft2font_wrapper.cpp create mode 100644 contrib/python/matplotlib/py2/src/mplutils.cpp create mode 100644 contrib/python/matplotlib/py2/src/mplutils.h create mode 100644 contrib/python/matplotlib/py2/src/numpy_cpp.h create mode 100644 contrib/python/matplotlib/py2/src/path_cleanup.cpp create mode 100644 contrib/python/matplotlib/py2/src/path_cleanup.h create mode 100644 contrib/python/matplotlib/py2/src/path_converters.h create mode 100644 contrib/python/matplotlib/py2/src/py_adaptors.h create mode 100644 contrib/python/matplotlib/py2/src/py_converters.cpp create mode 100644 contrib/python/matplotlib/py2/src/py_converters.h create mode 100644 contrib/python/matplotlib/py2/src/py_exceptions.h create mode 100644 contrib/python/matplotlib/py2/src/qhull_wrap.c create mode 100644 contrib/python/matplotlib/py2/src/ya.make create mode 100644 contrib/python/matplotlib/py2/ya.make (limited to 'contrib/python/matplotlib/py2') diff --git a/contrib/python/matplotlib/py2/.dist-info/METADATA b/contrib/python/matplotlib/py2/.dist-info/METADATA new file mode 100644 index 00000000000..04815e86287 --- /dev/null +++ b/contrib/python/matplotlib/py2/.dist-info/METADATA @@ -0,0 +1,38 @@ +Metadata-Version: 2.1 +Name: matplotlib +Version: 2.2.5 +Summary: Python plotting package +Home-page: http://matplotlib.org +Author: John D. Hunter, Michael Droettboom +Author-email: matplotlib-users@python.org +License: PSF +Download-URL: http://matplotlib.org/users/installing.html +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: Python Software Foundation License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Topic :: Scientific/Engineering :: Visualization +Requires-Dist: numpy (>=1.7.1) +Requires-Dist: cycler (>=0.10) +Requires-Dist: pyparsing (!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1) +Requires-Dist: python-dateutil (>=2.1) +Requires-Dist: pytz +Requires-Dist: six (>=1.10) +Requires-Dist: kiwisolver (>=1.0.1) +Requires-Dist: backports.functools-lru-cache +Requires-Dist: subprocess32 + +matplotlib strives to produce publication quality 2D graphics +for interactive graphing, scientific publishing, user interface +development and web application servers targeting multiple user +interfaces and hardcopy output formats. There is a 'pylab' mode +which emulates matlab graphics. + + diff --git a/contrib/python/matplotlib/py2/.dist-info/top_level.txt b/contrib/python/matplotlib/py2/.dist-info/top_level.txt new file mode 100644 index 00000000000..0eb77e4d99b --- /dev/null +++ b/contrib/python/matplotlib/py2/.dist-info/top_level.txt @@ -0,0 +1,3 @@ +matplotlib +mpl_toolkits +pylab diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE b/contrib/python/matplotlib/py2/LICENSE/LICENSE new file mode 100644 index 00000000000..ec51537db27 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE @@ -0,0 +1,99 @@ +License agreement for matplotlib versions 1.3.0 and later +========================================================= + +1. This LICENSE AGREEMENT is between the Matplotlib Development Team +("MDT"), and the Individual or Organization ("Licensee") accessing and +otherwise using matplotlib software in source or binary form and its +associated documentation. + +2. Subject to the terms and conditions of this License Agreement, MDT +hereby grants Licensee a nonexclusive, royalty-free, world-wide license +to reproduce, analyze, test, perform and/or display publicly, prepare +derivative works, distribute, and otherwise use matplotlib +alone or in any derivative version, provided, however, that MDT's +License Agreement and MDT's notice of copyright, i.e., "Copyright (c) +2012- Matplotlib Development Team; All Rights Reserved" are retained in +matplotlib alone or in any derivative version prepared by +Licensee. + +3. In the event Licensee prepares a derivative work that is based on or +incorporates matplotlib or any part thereof, and wants to +make the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to matplotlib . + +4. MDT is making matplotlib available to Licensee on an "AS +IS" basis. MDT MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, MDT MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB +WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +5. MDT SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB + FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR +LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING +MATPLOTLIB , OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF +THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between MDT and +Licensee. This License Agreement does not grant permission to use MDT +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using matplotlib , +Licensee agrees to be bound by the terms and conditions of this License +Agreement. + +License agreement for matplotlib versions prior to 1.3.0 +======================================================== + +1. This LICENSE AGREEMENT is between John D. Hunter ("JDH"), and the +Individual or Organization ("Licensee") accessing and otherwise using +matplotlib software in source or binary form and its associated +documentation. + +2. Subject to the terms and conditions of this License Agreement, JDH +hereby grants Licensee a nonexclusive, royalty-free, world-wide license +to reproduce, analyze, test, perform and/or display publicly, prepare +derivative works, distribute, and otherwise use matplotlib +alone or in any derivative version, provided, however, that JDH's +License Agreement and JDH's notice of copyright, i.e., "Copyright (c) +2002-2011 John D. Hunter; All Rights Reserved" are retained in +matplotlib alone or in any derivative version prepared by +Licensee. + +3. In the event Licensee prepares a derivative work that is based on or +incorporates matplotlib or any part thereof, and wants to +make the derivative work available to others as provided herein, then +Licensee hereby agrees to include in any such work a brief summary of +the changes made to matplotlib. + +4. JDH is making matplotlib available to Licensee on an "AS +IS" basis. JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR +IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND +DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS +FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB +WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. + +5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB + FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR +LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING +MATPLOTLIB , OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF +THE POSSIBILITY THEREOF. + +6. This License Agreement will automatically terminate upon a material +breach of its terms and conditions. + +7. Nothing in this License Agreement shall be deemed to create any +relationship of agency, partnership, or joint venture between JDH and +Licensee. This License Agreement does not grant permission to use JDH +trademarks or trade name in a trademark sense to endorse or promote +products or services of Licensee, or any third party. + +8. By copying, installing or otherwise using matplotlib, +Licensee agrees to be bound by the terms and conditions of this License +Agreement. \ No newline at end of file diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE.PIL b/contrib/python/matplotlib/py2/LICENSE/LICENSE.PIL new file mode 100644 index 00000000000..3f77350b923 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE.PIL @@ -0,0 +1,12 @@ +Software License + +The Python Imaging Library (PIL) is + + Copyright © 1997-2011 by Secret Labs AB + Copyright © 1995-2011 by Fredrik Lundh + +By obtaining, using, and/or copying this software and/or its associated documentation, you agree that you have read, understood, and will comply with the following terms and conditions: + +Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Secret Labs AB or the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. + +SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_AMSFONTS b/contrib/python/matplotlib/py2/LICENSE/LICENSE_AMSFONTS new file mode 100644 index 00000000000..3627bb9bb61 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_AMSFONTS @@ -0,0 +1,240 @@ +The cmr10.pfb file is a Type-1 version of one of Knuth's Computer Modern fonts. +It is included here as test data only, but the following license applies. + +Copyright (c) 1997, 2009, American Mathematical Society (http://www.ams.org). +All Rights Reserved. + +"cmb10" is a Reserved Font Name for this Font Software. +"cmbsy10" is a Reserved Font Name for this Font Software. +"cmbsy5" is a Reserved Font Name for this Font Software. +"cmbsy6" is a Reserved Font Name for this Font Software. +"cmbsy7" is a Reserved Font Name for this Font Software. +"cmbsy8" is a Reserved Font Name for this Font Software. +"cmbsy9" is a Reserved Font Name for this Font Software. +"cmbx10" is a Reserved Font Name for this Font Software. +"cmbx12" is a Reserved Font Name for this Font Software. +"cmbx5" is a Reserved Font Name for this Font Software. +"cmbx6" is a Reserved Font Name for this Font Software. +"cmbx7" is a Reserved Font Name for this Font Software. +"cmbx8" is a Reserved Font Name for this Font Software. +"cmbx9" is a Reserved Font Name for this Font Software. +"cmbxsl10" is a Reserved Font Name for this Font Software. +"cmbxti10" is a Reserved Font Name for this Font Software. +"cmcsc10" is a Reserved Font Name for this Font Software. +"cmcsc8" is a Reserved Font Name for this Font Software. +"cmcsc9" is a Reserved Font Name for this Font Software. +"cmdunh10" is a Reserved Font Name for this Font Software. +"cmex10" is a Reserved Font Name for this Font Software. +"cmex7" is a Reserved Font Name for this Font Software. +"cmex8" is a Reserved Font Name for this Font Software. +"cmex9" is a Reserved Font Name for this Font Software. +"cmff10" is a Reserved Font Name for this Font Software. +"cmfi10" is a Reserved Font Name for this Font Software. +"cmfib8" is a Reserved Font Name for this Font Software. +"cminch" is a Reserved Font Name for this Font Software. +"cmitt10" is a Reserved Font Name for this Font Software. +"cmmi10" is a Reserved Font Name for this Font Software. +"cmmi12" is a Reserved Font Name for this Font Software. +"cmmi5" is a Reserved Font Name for this Font Software. +"cmmi6" is a Reserved Font Name for this Font Software. +"cmmi7" is a Reserved Font Name for this Font Software. +"cmmi8" is a Reserved Font Name for this Font Software. +"cmmi9" is a Reserved Font Name for this Font Software. +"cmmib10" is a Reserved Font Name for this Font Software. +"cmmib5" is a Reserved Font Name for this Font Software. +"cmmib6" is a Reserved Font Name for this Font Software. +"cmmib7" is a Reserved Font Name for this Font Software. +"cmmib8" is a Reserved Font Name for this Font Software. +"cmmib9" is a Reserved Font Name for this Font Software. +"cmr10" is a Reserved Font Name for this Font Software. +"cmr12" is a Reserved Font Name for this Font Software. +"cmr17" is a Reserved Font Name for this Font Software. +"cmr5" is a Reserved Font Name for this Font Software. +"cmr6" is a Reserved Font Name for this Font Software. +"cmr7" is a Reserved Font Name for this Font Software. +"cmr8" is a Reserved Font Name for this Font Software. +"cmr9" is a Reserved Font Name for this Font Software. +"cmsl10" is a Reserved Font Name for this Font Software. +"cmsl12" is a Reserved Font Name for this Font Software. +"cmsl8" is a Reserved Font Name for this Font Software. +"cmsl9" is a Reserved Font Name for this Font Software. +"cmsltt10" is a Reserved Font Name for this Font Software. +"cmss10" is a Reserved Font Name for this Font Software. +"cmss12" is a Reserved Font Name for this Font Software. +"cmss17" is a Reserved Font Name for this Font Software. +"cmss8" is a Reserved Font Name for this Font Software. +"cmss9" is a Reserved Font Name for this Font Software. +"cmssbx10" is a Reserved Font Name for this Font Software. +"cmssdc10" is a Reserved Font Name for this Font Software. +"cmssi10" is a Reserved Font Name for this Font Software. +"cmssi12" is a Reserved Font Name for this Font Software. +"cmssi17" is a Reserved Font Name for this Font Software. +"cmssi8" is a Reserved Font Name for this Font Software. +"cmssi9" is a Reserved Font Name for this Font Software. +"cmssq8" is a Reserved Font Name for this Font Software. +"cmssqi8" is a Reserved Font Name for this Font Software. +"cmsy10" is a Reserved Font Name for this Font Software. +"cmsy5" is a Reserved Font Name for this Font Software. +"cmsy6" is a Reserved Font Name for this Font Software. +"cmsy7" is a Reserved Font Name for this Font Software. +"cmsy8" is a Reserved Font Name for this Font Software. +"cmsy9" is a Reserved Font Name for this Font Software. +"cmtcsc10" is a Reserved Font Name for this Font Software. +"cmtex10" is a Reserved Font Name for this Font Software. +"cmtex8" is a Reserved Font Name for this Font Software. +"cmtex9" is a Reserved Font Name for this Font Software. +"cmti10" is a Reserved Font Name for this Font Software. +"cmti12" is a Reserved Font Name for this Font Software. +"cmti7" is a Reserved Font Name for this Font Software. +"cmti8" is a Reserved Font Name for this Font Software. +"cmti9" is a Reserved Font Name for this Font Software. +"cmtt10" is a Reserved Font Name for this Font Software. +"cmtt12" is a Reserved Font Name for this Font Software. +"cmtt8" is a Reserved Font Name for this Font Software. +"cmtt9" is a Reserved Font Name for this Font Software. +"cmu10" is a Reserved Font Name for this Font Software. +"cmvtt10" is a Reserved Font Name for this Font Software. +"euex10" is a Reserved Font Name for this Font Software. +"euex7" is a Reserved Font Name for this Font Software. +"euex8" is a Reserved Font Name for this Font Software. +"euex9" is a Reserved Font Name for this Font Software. +"eufb10" is a Reserved Font Name for this Font Software. +"eufb5" is a Reserved Font Name for this Font Software. +"eufb7" is a Reserved Font Name for this Font Software. +"eufm10" is a Reserved Font Name for this Font Software. +"eufm5" is a Reserved Font Name for this Font Software. +"eufm7" is a Reserved Font Name for this Font Software. +"eurb10" is a Reserved Font Name for this Font Software. +"eurb5" is a Reserved Font Name for this Font Software. +"eurb7" is a Reserved Font Name for this Font Software. +"eurm10" is a Reserved Font Name for this Font Software. +"eurm5" is a Reserved Font Name for this Font Software. +"eurm7" is a Reserved Font Name for this Font Software. +"eusb10" is a Reserved Font Name for this Font Software. +"eusb5" is a Reserved Font Name for this Font Software. +"eusb7" is a Reserved Font Name for this Font Software. +"eusm10" is a Reserved Font Name for this Font Software. +"eusm5" is a Reserved Font Name for this Font Software. +"eusm7" is a Reserved Font Name for this Font Software. +"lasy10" is a Reserved Font Name for this Font Software. +"lasy5" is a Reserved Font Name for this Font Software. +"lasy6" is a Reserved Font Name for this Font Software. +"lasy7" is a Reserved Font Name for this Font Software. +"lasy8" is a Reserved Font Name for this Font Software. +"lasy9" is a Reserved Font Name for this Font Software. +"lasyb10" is a Reserved Font Name for this Font Software. +"lcircle1" is a Reserved Font Name for this Font Software. +"lcirclew" is a Reserved Font Name for this Font Software. +"lcmss8" is a Reserved Font Name for this Font Software. +"lcmssb8" is a Reserved Font Name for this Font Software. +"lcmssi8" is a Reserved Font Name for this Font Software. +"line10" is a Reserved Font Name for this Font Software. +"linew10" is a Reserved Font Name for this Font Software. +"msam10" is a Reserved Font Name for this Font Software. +"msam5" is a Reserved Font Name for this Font Software. +"msam6" is a Reserved Font Name for this Font Software. +"msam7" is a Reserved Font Name for this Font Software. +"msam8" is a Reserved Font Name for this Font Software. +"msam9" is a Reserved Font Name for this Font Software. +"msbm10" is a Reserved Font Name for this Font Software. +"msbm5" is a Reserved Font Name for this Font Software. +"msbm6" is a Reserved Font Name for this Font Software. +"msbm7" is a Reserved Font Name for this Font Software. +"msbm8" is a Reserved Font Name for this Font Software. +"msbm9" is a Reserved Font Name for this Font Software. +"wncyb10" is a Reserved Font Name for this Font Software. +"wncyi10" is a Reserved Font Name for this Font Software. +"wncyr10" is a Reserved Font Name for this Font Software. +"wncysc10" is a Reserved Font Name for this Font Software. +"wncyss10" is a Reserved Font Name for this Font Software. + +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/contrib/python/matplotlib/py2/LICENSE/LICENSE_BAKOMA b/contrib/python/matplotlib/py2/LICENSE/LICENSE_BAKOMA new file mode 100644 index 00000000000..801e20cd736 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_BAKOMA @@ -0,0 +1,40 @@ + + BaKoMa Fonts Licence + -------------------- + + This licence covers two font packs (known as BaKoMa Fonts Colelction, + which is available at `CTAN:fonts/cm/ps-type1/bakoma/'): + + 1) BaKoMa-CM (1.1/12-Nov-94) + Computer Modern Fonts in PostScript Type 1 and TrueType font formats. + + 2) BaKoMa-AMS (1.2/19-Jan-95) + AMS TeX fonts in PostScript Type 1 and TrueType font formats. + + Copyright (C) 1994, 1995, Basil K. Malyshev. All Rights Reserved. + + Permission to copy and distribute these fonts for any purpose is + hereby granted without fee, provided that the above copyright notice, + author statement and this permission notice appear in all copies of + these fonts and related documentation. + + Permission to modify and distribute modified fonts for any purpose is + hereby granted without fee, provided that the copyright notice, + author statement, this permission notice and location of original + fonts (http://www.ctan.org/tex-archive/fonts/cm/ps-type1/bakoma) + appear in all copies of modified fonts and related documentation. + + Permission to use these fonts (embedding into PostScript, PDF, SVG + and printing by using any software) is hereby granted without fee. + It is not required to provide any notices about using these fonts. + + Basil K. Malyshev + INSTITUTE FOR HIGH ENERGY PHYSICS + IHEP, OMVT + Moscow Region + 142281 PROTVINO + RUSSIA + + E-Mail: bakoma@mail.ru + or malyshev@mail.ihep.ru + diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_COLORBREWER b/contrib/python/matplotlib/py2/LICENSE/LICENSE_COLORBREWER new file mode 100644 index 00000000000..568afe883ec --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_COLORBREWER @@ -0,0 +1,38 @@ +Apache-Style Software License for ColorBrewer Color Schemes + +Version 1.1 + +Copyright (c) 2002 Cynthia Brewer, Mark Harrower, and The Pennsylvania +State University. All rights reserved. Redistribution and use in source +and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +1. Redistributions as source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. The end-user documentation included with the redistribution, if any, +must include the following acknowledgment: "This product includes color +specifications and designs developed by Cynthia Brewer +(http://colorbrewer.org/)." Alternately, this acknowledgment may appear in +the software itself, if and wherever such third-party acknowledgments +normally appear. + +3. The name "ColorBrewer" must not be used to endorse or promote products +derived from this software without prior written permission. For written +permission, please contact Cynthia Brewer at cbrewer@psu.edu. + +4. Products derived from this software may not be called "ColorBrewer", +nor may "ColorBrewer" appear in their name, without prior written +permission of Cynthia Brewer. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +CYNTHIA BREWER, MARK HARROWER, OR THE PENNSYLVANIA STATE UNIVERSITY BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_CONDA b/contrib/python/matplotlib/py2/LICENSE/LICENSE_CONDA new file mode 100644 index 00000000000..8794a6d484a --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_CONDA @@ -0,0 +1,51 @@ +Except where noted below, conda is released under the following terms: + +(c) 2012 Continuum Analytics, Inc. / http://continuum.io +All Rights Reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Continuum Analytics, Inc. nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL CONTINUUM ANALYTICS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Exceptions +========== + +versioneer.py is Public Domain + +The ProgressBar package is released under the following terms: + +# progressbar - Text progress bar library for Python. +# Copyright (c) 2005 Nilton Volpato +# +# 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 \ No newline at end of file diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_JQUERY b/contrib/python/matplotlib/py2/LICENSE/LICENSE_JQUERY new file mode 100644 index 00000000000..f35387a3ab4 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_JQUERY @@ -0,0 +1,61 @@ +Comment found in jQuery source code: + +/*! + * jQuery JavaScript Library v1.11.3 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2015-04-28T16:19Z + */ + +Comment found in jQuery UI source code: + +/*! jQuery UI - v1.11.4 - 2015-03-11 +* http://jqueryui.com +* Includes: core.js, widget.js, mouse.js, position.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, draggable.js, droppable.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js, menu.js, progressbar.js, resizable.js, selectable.js, selectmenu.js, slider.js, sortable.js, spinner.js, tabs.js, tooltip.js +* Copyright 2015 jQuery Foundation and other contributors; Licensed MIT */ + +Text found at http://jquery.org/license: + + jQuery Foundation projects are released under the terms of the license + specified in the project's repository or if not specified, under the + MIT license. + + The MIT License is simple and easy to understand and it places almost + no restrictions on what you can do with a jQuery Foundation project. + + You are free to use any jQuery Foundation project in any other project + (even commercial projects) as long as the copyright header is left + intact. + +The text links to https://tldrlegal.com/license/mit-license +which includes the following as the "Full License Text": + + The MIT License (MIT) + + Copyright (c) + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_QT4_EDITOR b/contrib/python/matplotlib/py2/LICENSE/LICENSE_QT4_EDITOR new file mode 100644 index 00000000000..1c9d941973c --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_QT4_EDITOR @@ -0,0 +1,30 @@ + +Module creating PyQt4 form dialogs/layouts to edit various type of parameters + + +formlayout License Agreement (MIT License) +------------------------------------------ + +Copyright (c) 2009 Pierre Raybaut + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +""" diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_STIX b/contrib/python/matplotlib/py2/LICENSE/LICENSE_STIX new file mode 100644 index 00000000000..2f7aeea331c --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_STIX @@ -0,0 +1,71 @@ +TERMS AND CONDITIONS + + 1. Permission is hereby granted, free of charge, to any person +obtaining a copy of the STIX Fonts-TM set accompanying this license +(collectively, the "Fonts") and the associated documentation files +(collectively with the Fonts, the "Font Software"), to reproduce and +distribute the Font Software, including the rights to use, copy, merge +and publish copies of the Font Software, and to permit persons to whom +the Font Software is furnished to do so same, subject to the following +terms and conditions (the "License"). + + 2. The following copyright and trademark notice and these Terms and +Conditions shall be included in all copies of one or more of the Font +typefaces and any derivative work created as permitted under this +License: + + Copyright (c) 2001-2005 by the STI Pub Companies, consisting of +the American Institute of Physics, the American Chemical Society, the +American Mathematical Society, the American Physical Society, Elsevier, +Inc., and The Institute of Electrical and Electronic Engineers, Inc. +Portions copyright (c) 1998-2003 by MicroPress, Inc. Portions copyright +(c) 1990 by Elsevier, Inc. All rights reserved. STIX Fonts-TM is a +trademark of The Institute of Electrical and Electronics Engineers, Inc. + + 3. You may (a) convert the Fonts from one format to another (e.g., +from TrueType to PostScript), in which case the normal and reasonable +distortion that occurs during such conversion shall be permitted and (b) +embed or include a subset of the Fonts in a document for the purposes of +allowing users to read text in the document that utilizes the Fonts. In +each case, you may use the STIX Fonts-TM mark to designate the resulting +Fonts or subset of the Fonts. + + 4. You may also (a) add glyphs or characters to the Fonts, or modify +the shape of existing glyphs, so long as the base set of glyphs is not +removed and (b) delete glyphs or characters from the Fonts, provided +that the resulting font set is distributed with the following +disclaimer: "This [name] font does not include all the Unicode points +covered in the STIX Fonts-TM set but may include others." In each case, +the name used to denote the resulting font set shall not include the +term "STIX" or any similar term. + + 5. You may charge a fee in connection with the distribution of the +Font Software, provided that no copy of one or more of the individual +Font typefaces that form the STIX Fonts-TM set may be sold by itself. + + 6. 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 +MICROPRESS OR ANY OF THE STI PUB COMPANIES BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, INCLUDING, BUT NOT LIMITED TO, ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM OR OUT OF THE USE OR +INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT +SOFTWARE. + + 7. Except as contained in the notice set forth in Section 2, the +names MicroPress Inc. and STI Pub Companies, as well as the names of the +companies/organizations that compose the STI Pub Companies, shall not be +used in advertising or otherwise to promote the sale, use or other +dealings in the Font Software without the prior written consent of the +respective company or organization. + + 8. This License shall become null and void in the event of any +material breach of the Terms and Conditions herein by licensee. + + 9. A substantial portion of the STIX Fonts set was developed by +MicroPress Inc. for the STI Pub Companies. To obtain additional +mathematical fonts, please contact MicroPress, Inc., 68-30 Harrow +Street, Forest Hills, NY 11375, USA - Phone: (718) 575-1816. + diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_YORICK b/contrib/python/matplotlib/py2/LICENSE/LICENSE_YORICK new file mode 100644 index 00000000000..8c908509a73 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_YORICK @@ -0,0 +1,49 @@ +BSD-style license for gist/yorick colormaps. + +Copyright: + + Copyright (c) 1996. The Regents of the University of California. + All rights reserved. + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire +notice is included in all copies of any software which is or includes +a copy or modification of this software and in all copies of the +supporting documentation for such software. + +This work was produced at the University of California, Lawrence +Livermore National Laboratory under contract no. W-7405-ENG-48 between +the U.S. Department of Energy and The Regents of the University of +California for the operation of UC LLNL. + + + DISCLAIMER + +This software was prepared as an account of work sponsored by an +agency of the United States Government. Neither the United States +Government nor the University of California nor any of their +employees, makes any warranty, express or implied, or assumes any +liability or responsibility for the accuracy, completeness, or +usefulness of any information, apparatus, product, or process +disclosed, or represents that its use would not infringe +privately-owned rights. Reference herein to any specific commercial +products, process, or service by trade name, trademark, manufacturer, +or otherwise, does not necessarily constitute or imply its +endorsement, recommendation, or favoring by the United States +Government or the University of California. The views and opinions of +authors expressed herein do not necessarily state or reflect those of +the United States Government or the University of California, and +shall not be used for advertising or product endorsement purposes. + + + AUTHOR + +David H. Munro wrote Yorick and Gist. Berkeley Yacc (byacc) generated +the Yorick parser. The routines in Math are from LAPACK and FFTPACK; +MathC contains C translations by David H. Munro. The algorithms for +Yorick's random number generator and several special functions in +Yorick/include were taken from Numerical Recipes by Press, et. al., +although the Yorick implementations are unrelated to those in +Numerical Recipes. A small amount of code in Gist was adapted from +the X11R4 release, copyright M.I.T. -- the complete copyright notice +may be found in the (unused) file Gist/host.c. diff --git a/contrib/python/matplotlib/py2/LICENSE/LICENSE_enthought.txt b/contrib/python/matplotlib/py2/LICENSE/LICENSE_enthought.txt new file mode 100644 index 00000000000..27727c5eae9 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/LICENSE_enthought.txt @@ -0,0 +1,29 @@ +Copyright (c) 2001, 2002 Enthought, Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + a. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + b. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + c. Neither the name of the Enthought nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + diff --git a/contrib/python/matplotlib/py2/LICENSE/Solarized.txt b/contrib/python/matplotlib/py2/LICENSE/Solarized.txt new file mode 100644 index 00000000000..6e5a0475dd2 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/Solarized.txt @@ -0,0 +1,20 @@ +https://github.com/altercation/solarized/blob/master/LICENSE +Copyright (c) 2011 Ethan Schoonover + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/contrib/python/matplotlib/py2/LICENSE/pnpoly.license b/contrib/python/matplotlib/py2/LICENSE/pnpoly.license new file mode 100644 index 00000000000..0c838f9b011 --- /dev/null +++ b/contrib/python/matplotlib/py2/LICENSE/pnpoly.license @@ -0,0 +1,26 @@ +Copyright (c) 1970-2003, Wm. Randolph Franklin + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimers. + 2. Redistributions in binary form must reproduce the above + copyright notice in the documentation and/or other materials + provided with the distribution. + 3. The name of W. Randolph Franklin may not be used to endorse or + promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contrib/python/matplotlib/py2/README.rst b/contrib/python/matplotlib/py2/README.rst new file mode 100644 index 00000000000..b13658c300f --- /dev/null +++ b/contrib/python/matplotlib/py2/README.rst @@ -0,0 +1,83 @@ +|Travis|_ |AppVeyor|_ |Codecov|_ |PyPi|_ |Gitter|_ |NUMFocus|_ + + +.. |Travis| image:: https://travis-ci.org/matplotlib/matplotlib.svg?branch=master +.. _Travis: https://travis-ci.org/matplotlib/matplotlib + +.. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=master&svg=true +.. _AppVeyor: https://ci.appveyor.com/project/matplotlib/matplotlib + +.. |Codecov| image:: https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=master&service=github +.. _Codecov: https://codecov.io/github/matplotlib/matplotlib?branch=master + +.. |PyPi| image:: https://badge.fury.io/py/matplotlib.svg +.. _PyPi: https://badge.fury.io/py/matplotlib + +.. |Gitter| image:: https://badges.gitter.im/matplotlib/matplotlib.png +.. _Gitter: https://gitter.im/matplotlib/matplotlib + +.. |NUMFocus| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A +.. _NUMFocus: http://www.numfocus.org + + +########## +Matplotlib +########## + +Matplotlib is a Python 2D plotting library which produces publication-quality +figures in a variety of hardcopy formats and interactive environments across +platforms. Matplotlib can be used in Python scripts, the Python and IPython +shell (à la MATLAB or Mathematica), web application servers, and various +graphical user interface toolkits. + +`Home page `_ + +Installation +============ + +For installation instructions and requirements, see the INSTALL.rst file or the +`install `_ documentation. If you +think you may want to contribute to matplotlib, check out the `guide to +working with the source code +`_. + +Testing +======= + +After installation, you can launch the test suite:: + + py.test + +Or from the Python interpreter:: + + import matplotlib + matplotlib.test() + +Consider reading http://matplotlib.org/devel/coding_guide.html#testing for +more information. Note that the test suite requires pytest and, on Python 2.7, +mock. Please install with pip or your package manager of choice. + +Contact +======= +matplotlib's communication channels include active mailing lists: + +* `Users `_ mailing list: matplotlib-users@python.org +* `Announcement `_ mailing list: matplotlib-announce@python.org +* `Development `_ mailing list: matplotlib-devel@python.org + +The first is a good starting point for general questions and discussions. + +Gitter_ is for coordinating development and asking questions directly related +to contributing to matplotlib. + +Contribute +========== +You've discovered a bug or something else you want to change - excellent! + +You've worked out a way to fix it – even better! + +You want to tell us about it – best of all! + +Start at the `contributing guide `_! + +Developer notes are now at `_Developer Discussions `_ diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_alpha_mask_u8.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_alpha_mask_u8.h new file mode 100644 index 00000000000..e301c100880 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_alpha_mask_u8.h @@ -0,0 +1,499 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// scanline_u8 class +// +//---------------------------------------------------------------------------- +#ifndef AGG_ALPHA_MASK_U8_INCLUDED +#define AGG_ALPHA_MASK_U8_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //===================================================one_component_mask_u8 + struct one_component_mask_u8 + { + static unsigned calculate(const int8u* p) { return *p; } + }; + + + //=====================================================rgb_to_gray_mask_u8 + template + struct rgb_to_gray_mask_u8 + { + static unsigned calculate(const int8u* p) + { + return (p[R]*77 + p[G]*150 + p[B]*29) >> 8; + } + }; + + //==========================================================alpha_mask_u8 + template + class alpha_mask_u8 + { + public: + typedef int8u cover_type; + typedef alpha_mask_u8 self_type; + enum cover_scale_e + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + alpha_mask_u8() : m_rbuf(0) {} + explicit alpha_mask_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y < (int)m_rbuf->height()) + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset); + } + return 0; + } + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + if(x >= 0 && y >= 0 && + x < (int)m_rbuf->width() && + y < (int)m_rbuf->height()) + { + return (cover_type)((cover_full + val * + m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset)) >> + cover_shift); + } + return 0; + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--count); + } + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(y < 0 || y > ymax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(x < 0) + { + count += x; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -x * sizeof(cover_type)); + covers -= x; + x = 0; + } + + if(x + count > xmax) + { + int rest = x + count - xmax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers = (cover_type)((cover_full + (*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += Step; + } + while(--count); + } + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--count); + } + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + int xmax = m_rbuf->width() - 1; + int ymax = m_rbuf->height() - 1; + + int count = num_pix; + cover_type* covers = dst; + + if(x < 0 || x > xmax) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + + if(y < 0) + { + count += y; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers, 0, -y * sizeof(cover_type)); + covers -= y; + y = 0; + } + + if(y + count > ymax) + { + int rest = y + count - ymax - 1; + count -= rest; + if(count <= 0) + { + memset(dst, 0, num_pix * sizeof(cover_type)); + return; + } + memset(covers + count, 0, rest * sizeof(cover_type)); + } + + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *covers = (cover_type)((cover_full + (*covers) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++covers; + mask += m_rbuf->stride(); + } + while(--count); + } + + + private: + alpha_mask_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef alpha_mask_u8<1, 0> alpha_mask_gray8; //----alpha_mask_gray8 + + typedef alpha_mask_u8<3, 0> alpha_mask_rgb24r; //----alpha_mask_rgb24r + typedef alpha_mask_u8<3, 1> alpha_mask_rgb24g; //----alpha_mask_rgb24g + typedef alpha_mask_u8<3, 2> alpha_mask_rgb24b; //----alpha_mask_rgb24b + + typedef alpha_mask_u8<3, 2> alpha_mask_bgr24r; //----alpha_mask_bgr24r + typedef alpha_mask_u8<3, 1> alpha_mask_bgr24g; //----alpha_mask_bgr24g + typedef alpha_mask_u8<3, 0> alpha_mask_bgr24b; //----alpha_mask_bgr24b + + typedef alpha_mask_u8<4, 0> alpha_mask_rgba32r; //----alpha_mask_rgba32r + typedef alpha_mask_u8<4, 1> alpha_mask_rgba32g; //----alpha_mask_rgba32g + typedef alpha_mask_u8<4, 2> alpha_mask_rgba32b; //----alpha_mask_rgba32b + typedef alpha_mask_u8<4, 3> alpha_mask_rgba32a; //----alpha_mask_rgba32a + + typedef alpha_mask_u8<4, 1> alpha_mask_argb32r; //----alpha_mask_argb32r + typedef alpha_mask_u8<4, 2> alpha_mask_argb32g; //----alpha_mask_argb32g + typedef alpha_mask_u8<4, 3> alpha_mask_argb32b; //----alpha_mask_argb32b + typedef alpha_mask_u8<4, 0> alpha_mask_argb32a; //----alpha_mask_argb32a + + typedef alpha_mask_u8<4, 2> alpha_mask_bgra32r; //----alpha_mask_bgra32r + typedef alpha_mask_u8<4, 1> alpha_mask_bgra32g; //----alpha_mask_bgra32g + typedef alpha_mask_u8<4, 0> alpha_mask_bgra32b; //----alpha_mask_bgra32b + typedef alpha_mask_u8<4, 3> alpha_mask_bgra32a; //----alpha_mask_bgra32a + + typedef alpha_mask_u8<4, 3> alpha_mask_abgr32r; //----alpha_mask_abgr32r + typedef alpha_mask_u8<4, 2> alpha_mask_abgr32g; //----alpha_mask_abgr32g + typedef alpha_mask_u8<4, 1> alpha_mask_abgr32b; //----alpha_mask_abgr32b + typedef alpha_mask_u8<4, 0> alpha_mask_abgr32a; //----alpha_mask_abgr32a + + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgb24gray; //----alpha_mask_rgb24gray + typedef alpha_mask_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgr24gray; //----alpha_mask_bgr24gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_rgba32gray; //----alpha_mask_rgba32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > alpha_mask_argb32gray; //----alpha_mask_argb32gray + typedef alpha_mask_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_bgra32gray; //----alpha_mask_bgra32gray + typedef alpha_mask_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > alpha_mask_abgr32gray; //----alpha_mask_abgr32gray + + + + //==========================================================amask_no_clip_u8 + template + class amask_no_clip_u8 + { + public: + typedef int8u cover_type; + typedef amask_no_clip_u8 self_type; + enum cover_scale_e + { + cover_shift = 8, + cover_none = 0, + cover_full = 255 + }; + + amask_no_clip_u8() : m_rbuf(0) {} + explicit amask_no_clip_u8(rendering_buffer& rbuf) : m_rbuf(&rbuf) {} + + void attach(rendering_buffer& rbuf) { m_rbuf = &rbuf; } + + MaskF& mask_function() { return m_mask_function; } + const MaskF& mask_function() const { return m_mask_function; } + + + //-------------------------------------------------------------------- + cover_type pixel(int x, int y) const + { + return (cover_type)m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset); + } + + + //-------------------------------------------------------------------- + cover_type combine_pixel(int x, int y, cover_type val) const + { + return (cover_type)((cover_full + val * + m_mask_function.calculate( + m_rbuf->row_ptr(y) + x * Step + Offset)) >> + cover_shift); + } + + + //-------------------------------------------------------------------- + void fill_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += Step; + } + while(--num_pix); + } + + + + //-------------------------------------------------------------------- + void combine_hspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst = (cover_type)((cover_full + (*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += Step; + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void fill_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst++ = (cover_type)m_mask_function.calculate(mask); + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + + //-------------------------------------------------------------------- + void combine_vspan(int x, int y, cover_type* dst, int num_pix) const + { + const int8u* mask = m_rbuf->row_ptr(y) + x * Step + Offset; + do + { + *dst = (cover_type)((cover_full + (*dst) * + m_mask_function.calculate(mask)) >> + cover_shift); + ++dst; + mask += m_rbuf->stride(); + } + while(--num_pix); + } + + private: + amask_no_clip_u8(const self_type&); + const self_type& operator = (const self_type&); + + rendering_buffer* m_rbuf; + MaskF m_mask_function; + }; + + + typedef amask_no_clip_u8<1, 0> amask_no_clip_gray8; //----amask_no_clip_gray8 + + typedef amask_no_clip_u8<3, 0> amask_no_clip_rgb24r; //----amask_no_clip_rgb24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_rgb24g; //----amask_no_clip_rgb24g + typedef amask_no_clip_u8<3, 2> amask_no_clip_rgb24b; //----amask_no_clip_rgb24b + + typedef amask_no_clip_u8<3, 2> amask_no_clip_bgr24r; //----amask_no_clip_bgr24r + typedef amask_no_clip_u8<3, 1> amask_no_clip_bgr24g; //----amask_no_clip_bgr24g + typedef amask_no_clip_u8<3, 0> amask_no_clip_bgr24b; //----amask_no_clip_bgr24b + + typedef amask_no_clip_u8<4, 0> amask_no_clip_rgba32r; //----amask_no_clip_rgba32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_rgba32g; //----amask_no_clip_rgba32g + typedef amask_no_clip_u8<4, 2> amask_no_clip_rgba32b; //----amask_no_clip_rgba32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_rgba32a; //----amask_no_clip_rgba32a + + typedef amask_no_clip_u8<4, 1> amask_no_clip_argb32r; //----amask_no_clip_argb32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_argb32g; //----amask_no_clip_argb32g + typedef amask_no_clip_u8<4, 3> amask_no_clip_argb32b; //----amask_no_clip_argb32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_argb32a; //----amask_no_clip_argb32a + + typedef amask_no_clip_u8<4, 2> amask_no_clip_bgra32r; //----amask_no_clip_bgra32r + typedef amask_no_clip_u8<4, 1> amask_no_clip_bgra32g; //----amask_no_clip_bgra32g + typedef amask_no_clip_u8<4, 0> amask_no_clip_bgra32b; //----amask_no_clip_bgra32b + typedef amask_no_clip_u8<4, 3> amask_no_clip_bgra32a; //----amask_no_clip_bgra32a + + typedef amask_no_clip_u8<4, 3> amask_no_clip_abgr32r; //----amask_no_clip_abgr32r + typedef amask_no_clip_u8<4, 2> amask_no_clip_abgr32g; //----amask_no_clip_abgr32g + typedef amask_no_clip_u8<4, 1> amask_no_clip_abgr32b; //----amask_no_clip_abgr32b + typedef amask_no_clip_u8<4, 0> amask_no_clip_abgr32a; //----amask_no_clip_abgr32a + + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgb24gray; //----amask_no_clip_rgb24gray + typedef amask_no_clip_u8<3, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgr24gray; //----amask_no_clip_bgr24gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_rgba32gray; //----amask_no_clip_rgba32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<0, 1, 2> > amask_no_clip_argb32gray; //----amask_no_clip_argb32gray + typedef amask_no_clip_u8<4, 0, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_bgra32gray; //----amask_no_clip_bgra32gray + typedef amask_no_clip_u8<4, 1, rgb_to_gray_mask_u8<2, 1, 0> > amask_no_clip_abgr32gray; //----amask_no_clip_abgr32gray + + +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arc.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arc.h new file mode 100644 index 00000000000..17e1d434735 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arc.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc vertex generator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ARC_INCLUDED +#define AGG_ARC_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //=====================================================================arc + // + // See Implementation agg_arc.cpp + // + class arc + { + public: + arc() : m_scale(1.0), m_initialized(false) {} + arc(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void init(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw=true); + + void approximation_scale(double s); + double approximation_scale() const { return m_scale; } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + void normalize(double a1, double a2, bool ccw); + + double m_x; + double m_y; + double m_rx; + double m_ry; + double m_angle; + double m_start; + double m_end; + double m_scale; + double m_da; + bool m_ccw; + bool m_initialized; + unsigned m_path_cmd; + }; + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_array.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_array.h new file mode 100644 index 00000000000..8d56683840d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_array.h @@ -0,0 +1,1119 @@ +//---------------------------------------------------------------------------- +// 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_ARRAY_INCLUDED +#define AGG_ARRAY_INCLUDED + +#include +#include +#include "agg_basics.h" + +namespace agg +{ + + //-------------------------------------------------------pod_array_adaptor + template class pod_array_adaptor + { + public: + typedef T value_type; + pod_array_adaptor(T* array, unsigned size) : + m_array(array), m_size(size) {} + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T* m_array; + unsigned m_size; + }; + + + //---------------------------------------------------------pod_auto_array + template class pod_auto_array + { + public: + typedef T value_type; + typedef pod_auto_array self_type; + + pod_auto_array() {} + explicit pod_auto_array(const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + } + + const self_type& operator = (const T* c) + { + memcpy(m_array, c, sizeof(T) * Size); + return *this; + } + + static unsigned size() { return Size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + }; + + + //--------------------------------------------------------pod_auto_vector + template class pod_auto_vector + { + public: + typedef T value_type; + typedef pod_auto_vector self_type; + + pod_auto_vector() : m_size(0) {} + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void inc_size(unsigned size) { m_size += size; } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + private: + T m_array[Size]; + unsigned m_size; + }; + + + //---------------------------------------------------------------pod_array + template class pod_array + { + public: + typedef T value_type; + typedef pod_array self_type; + + ~pod_array() { pod_allocator::deallocate(m_array, m_size); } + pod_array() : m_array(0), m_size(0) {} + + pod_array(unsigned size) : + m_array(pod_allocator::allocate(size)), + m_size(size) + {} + + pod_array(const self_type& v) : + m_array(pod_allocator::allocate(v.m_size)), + m_size(v.m_size) + { + memcpy(m_array, v.m_array, sizeof(T) * m_size); + } + + void resize(unsigned size) + { + if(size != m_size) + { + pod_allocator::deallocate(m_array, m_size); + m_array = pod_allocator::allocate(m_size = size); + } + } + const self_type& operator = (const self_type& v) + { + resize(v.size()); + memcpy(m_array, v.m_array, sizeof(T) * m_size); + return *this; + } + + unsigned size() const { return m_size; } + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + private: + T* m_array; + unsigned m_size; + }; + + + + //--------------------------------------------------------------pod_vector + // A simple class template to store Plain Old Data, a vector + // of a fixed size. The data is continous in memory + //------------------------------------------------------------------------ + template class pod_vector + { + public: + typedef T value_type; + + ~pod_vector() { pod_allocator::deallocate(m_array, m_capacity); } + pod_vector() : m_size(0), m_capacity(0), m_array(0) {} + pod_vector(unsigned cap, unsigned extra_tail=0); + + // Copying + pod_vector(const pod_vector&); + const pod_vector& operator = (const pod_vector&); + + // Set new capacity. All data is lost, size is set to zero. + void capacity(unsigned cap, unsigned extra_tail=0); + unsigned capacity() const { return m_capacity; } + + // Allocate n elements. All data is lost, + // but elements can be accessed in range 0...size-1. + void allocate(unsigned size, unsigned extra_tail=0); + + // Resize keeping the content. + void resize(unsigned new_size); + + void zero() + { + memset(m_array, 0, sizeof(T) * m_size); + } + + void add(const T& v) { m_array[m_size++] = v; } + void push_back(const T& v) { m_array[m_size++] = v; } + void insert_at(unsigned pos, const T& val); + void inc_size(unsigned size) { m_size += size; } + unsigned size() const { return m_size; } + unsigned byte_size() const { return m_size * sizeof(T); } + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + const T& operator [] (unsigned i) const { return m_array[i]; } + T& operator [] (unsigned i) { return m_array[i]; } + const T& at(unsigned i) const { return m_array[i]; } + T& at(unsigned i) { return m_array[i]; } + T value_at(unsigned i) const { return m_array[i]; } + + const T* data() const { return m_array; } + T* data() { return m_array; } + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void cut_at(unsigned num) { if(num < m_size) m_size = num; } + + private: + unsigned m_size; + unsigned m_capacity; + T* m_array; + }; + + //------------------------------------------------------------------------ + template + void pod_vector::capacity(unsigned cap, unsigned extra_tail) + { + m_size = 0; + if(cap > m_capacity) + { + pod_allocator::deallocate(m_array, m_capacity); + m_capacity = cap + extra_tail; + m_array = m_capacity ? pod_allocator::allocate(m_capacity) : 0; + } + } + + //------------------------------------------------------------------------ + template + void pod_vector::allocate(unsigned size, unsigned extra_tail) + { + capacity(size, extra_tail); + m_size = size; + } + + + //------------------------------------------------------------------------ + template + void pod_vector::resize(unsigned new_size) + { + if(new_size > m_size) + { + if(new_size > m_capacity) + { + T* data = pod_allocator::allocate(new_size); + memcpy(data, m_array, m_size * sizeof(T)); + pod_allocator::deallocate(m_array, m_capacity); + m_array = data; + } + } + else + { + m_size = new_size; + } + } + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(unsigned cap, unsigned extra_tail) : + m_size(0), + m_capacity(cap + extra_tail), + m_array(pod_allocator::allocate(m_capacity)) {} + + //------------------------------------------------------------------------ + template pod_vector::pod_vector(const pod_vector& v) : + m_size(v.m_size), + m_capacity(v.m_capacity), + m_array(v.m_capacity ? pod_allocator::allocate(v.m_capacity) : 0) + { + memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + } + + //------------------------------------------------------------------------ + template const pod_vector& + pod_vector::operator = (const pod_vector&v) + { + allocate(v.m_size); + if(v.m_size) memcpy(m_array, v.m_array, sizeof(T) * v.m_size); + return *this; + } + + //------------------------------------------------------------------------ + template void pod_vector::serialize(int8u* ptr) const + { + if(m_size) memcpy(ptr, m_array, m_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template + void pod_vector::deserialize(const int8u* data, unsigned byte_size) + { + byte_size /= sizeof(T); + allocate(byte_size); + if(byte_size) memcpy(m_array, data, byte_size * sizeof(T)); + } + + //------------------------------------------------------------------------ + template + void pod_vector::insert_at(unsigned pos, const T& val) + { + if(pos >= m_size) + { + m_array[m_size] = val; + } + else + { + memmove(m_array + pos + 1, m_array + pos, (m_size - pos) * sizeof(T)); + m_array[pos] = val; + } + ++m_size; + } + + //---------------------------------------------------------------pod_bvector + // A simple class template to store Plain Old Data, similar to std::deque + // It doesn't reallocate memory but instead, uses blocks of data of size + // of (1 << S), that is, power of two. The data is NOT contiguous in memory, + // so the only valid access method is operator [] or curr(), prev(), next() + // + // There reallocs occure only when the pool of pointers to blocks needs + // to be extended (it happens very rarely). You can control the value + // of increment to reallocate the pointer buffer. See the second constructor. + // By default, the incremeent value equals (1 << S), i.e., the block size. + //------------------------------------------------------------------------ + template class pod_bvector + { + public: + enum block_scale_e + { + block_shift = S, + block_size = 1 << block_shift, + block_mask = block_size - 1 + }; + + typedef T value_type; + + ~pod_bvector(); + pod_bvector(); + pod_bvector(unsigned block_ptr_inc); + + // Copying + pod_bvector(const pod_bvector& v); + const pod_bvector& operator = (const pod_bvector& v); + + void remove_all() { m_size = 0; } + void clear() { m_size = 0; } + void free_all() { free_tail(0); } + void free_tail(unsigned size); + void add(const T& val); + void push_back(const T& val) { add(val); } + void modify_last(const T& val); + void remove_last(); + + int allocate_continuous_block(unsigned num_elements); + + void add_array(const T* ptr, unsigned num_elem) + { + while(num_elem--) + { + add(*ptr++); + } + } + + template void add_data(DataAccessor& data) + { + while(data.size()) + { + add(*data); + ++data; + } + } + + void cut_at(unsigned size) + { + if(size < m_size) m_size = size; + } + + unsigned size() const { return m_size; } + + const T& operator [] (unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& operator [] (unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T& at(unsigned i) + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + T value_at(unsigned i) const + { + return m_blocks[i >> block_shift][i & block_mask]; + } + + const T& curr(unsigned idx) const + { + return (*this)[idx]; + } + + T& curr(unsigned idx) + { + return (*this)[idx]; + } + + const T& prev(unsigned idx) const + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + T& prev(unsigned idx) + { + return (*this)[(idx + m_size - 1) % m_size]; + } + + const T& next(unsigned idx) const + { + return (*this)[(idx + 1) % m_size]; + } + + T& next(unsigned idx) + { + return (*this)[(idx + 1) % m_size]; + } + + const T& last() const + { + return (*this)[m_size - 1]; + } + + T& last() + { + return (*this)[m_size - 1]; + } + + unsigned byte_size() const; + void serialize(int8u* ptr) const; + void deserialize(const int8u* data, unsigned byte_size); + void deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size); + + template + void deserialize(ByteAccessor data) + { + remove_all(); + unsigned elem_size = data.size() / sizeof(T); + + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr = (int8u*)data_ptr(); + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + ++m_size; + } + } + + template + void deserialize(unsigned start, const T& empty_val, ByteAccessor data) + { + while(m_size < start) + { + add(empty_val); + } + + unsigned elem_size = data.size() / sizeof(T); + for(unsigned i = 0; i < elem_size; ++i) + { + int8u* ptr; + if(start + i < m_size) + { + ptr = (int8u*)(&((*this)[start + i])); + } + else + { + ptr = (int8u*)data_ptr(); + ++m_size; + } + for(unsigned j = 0; j < sizeof(T); ++j) + { + *ptr++ = *data; + ++data; + } + } + } + + const T* block(unsigned nb) const { return m_blocks[nb]; } + + private: + void allocate_block(unsigned nb); + T* data_ptr(); + + unsigned m_size; + unsigned m_num_blocks; + unsigned m_max_blocks; + T** m_blocks; + unsigned m_block_ptr_inc; + }; + + + //------------------------------------------------------------------------ + template pod_bvector::~pod_bvector() + { + if(m_num_blocks) + { + T** blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(*blk, block_size); + --blk; + } + } + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::free_tail(unsigned size) + { + if(size < m_size) + { + unsigned nb = (size + block_mask) >> block_shift; + while(m_num_blocks > nb) + { + pod_allocator::deallocate(m_blocks[--m_num_blocks], block_size); + } + if(m_num_blocks == 0) + { + pod_allocator::deallocate(m_blocks, m_max_blocks); + m_blocks = 0; + m_max_blocks = 0; + } + m_size = size; + } + } + + + //------------------------------------------------------------------------ + template pod_bvector::pod_bvector() : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_size) + { + } + + + //------------------------------------------------------------------------ + template + pod_bvector::pod_bvector(unsigned block_ptr_inc) : + m_size(0), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_block_ptr_inc(block_ptr_inc) + { + } + + + //------------------------------------------------------------------------ + template + pod_bvector::pod_bvector(const pod_bvector& v) : + m_size(v.m_size), + m_num_blocks(v.m_num_blocks), + m_max_blocks(v.m_max_blocks), + m_blocks(v.m_max_blocks ? + pod_allocator::allocate(v.m_max_blocks) : + 0), + m_block_ptr_inc(v.m_block_ptr_inc) + { + unsigned i; + for(i = 0; i < v.m_num_blocks; ++i) + { + m_blocks[i] = pod_allocator::allocate(block_size); + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + } + + + //------------------------------------------------------------------------ + template + const pod_bvector& + pod_bvector::operator = (const pod_bvector& v) + { + unsigned i; + for(i = m_num_blocks; i < v.m_num_blocks; ++i) + { + allocate_block(i); + } + for(i = 0; i < v.m_num_blocks; ++i) + { + memcpy(m_blocks[i], v.m_blocks[i], block_size * sizeof(T)); + } + m_size = v.m_size; + return *this; + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_blocks = pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(T*)); + + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + m_blocks[nb] = pod_allocator::allocate(block_size); + m_num_blocks++; + } + + + + //------------------------------------------------------------------------ + template + inline T* pod_bvector::data_ptr() + { + unsigned nb = m_size >> block_shift; + if(nb >= m_num_blocks) + { + allocate_block(nb); + } + return m_blocks[nb] + (m_size & block_mask); + } + + + + //------------------------------------------------------------------------ + template + inline void pod_bvector::add(const T& val) + { + *data_ptr() = val; + ++m_size; + } + + + //------------------------------------------------------------------------ + template + inline void pod_bvector::remove_last() + { + if(m_size) --m_size; + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::modify_last(const T& val) + { + remove_last(); + add(val); + } + + + //------------------------------------------------------------------------ + template + int pod_bvector::allocate_continuous_block(unsigned num_elements) + { + if(num_elements < block_size) + { + data_ptr(); // Allocate initial block if necessary + unsigned rest = block_size - (m_size & block_mask); + unsigned index; + if(num_elements <= rest) + { + // The rest of the block is good, we can use it + //----------------- + index = m_size; + m_size += num_elements; + return index; + } + + // New block + //--------------- + m_size += rest; + data_ptr(); + index = m_size; + m_size += num_elements; + return index; + } + return -1; // Impossible to allocate + } + + + //------------------------------------------------------------------------ + template + unsigned pod_bvector::byte_size() const + { + return m_size * sizeof(T); + } + + + //------------------------------------------------------------------------ + template + void pod_bvector::serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_size; i++) + { + memcpy(ptr, &(*this)[i], sizeof(T)); + ptr += sizeof(T); + } + } + + //------------------------------------------------------------------------ + template + void pod_bvector::deserialize(const int8u* data, unsigned byte_size) + { + remove_all(); + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + data += sizeof(T); + } + } + + + // Replace or add a number of elements starting from "start" position + //------------------------------------------------------------------------ + template + void pod_bvector::deserialize(unsigned start, const T& empty_val, + const int8u* data, unsigned byte_size) + { + while(m_size < start) + { + add(empty_val); + } + + byte_size /= sizeof(T); + for(unsigned i = 0; i < byte_size; ++i) + { + if(start + i < m_size) + { + memcpy(&((*this)[start + i]), data, sizeof(T)); + } + else + { + T* ptr = data_ptr(); + memcpy(ptr, data, sizeof(T)); + ++m_size; + } + data += sizeof(T); + } + } + + + //---------------------------------------------------------block_allocator + // Allocator for arbitrary POD data. Most usable in different cache + // systems for efficient memory allocations. + // Memory is allocated with blocks of fixed size ("block_size" in + // the constructor). If required size exceeds the block size the allocator + // creates a new block of the required size. However, the most efficient + // use is when the average reqired size is much less than the block size. + //------------------------------------------------------------------------ + class block_allocator + { + struct block_type + { + int8u* data; + unsigned size; + }; + + public: + void remove_all() + { + if(m_num_blocks) + { + block_type* blk = m_blocks + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(blk->data, blk->size); + --blk; + } + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_num_blocks = 0; + m_max_blocks = 0; + m_blocks = 0; + m_buf_ptr = 0; + m_rest = 0; + } + + ~block_allocator() + { + remove_all(); + } + + block_allocator(unsigned block_size, unsigned block_ptr_inc=256-8) : + m_block_size(block_size), + m_block_ptr_inc(block_ptr_inc), + m_num_blocks(0), + m_max_blocks(0), + m_blocks(0), + m_buf_ptr(0), + m_rest(0) + { + } + + + int8u* allocate(unsigned size, unsigned alignment=1) + { + if(size == 0) return 0; + if(size <= m_rest) + { + int8u* ptr = m_buf_ptr; + if(alignment > 1) + { + unsigned align = + (alignment - unsigned((size_t)ptr) % alignment) % alignment; + + size += align; + ptr += align; + if(size <= m_rest) + { + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size); + return allocate(size - align, alignment); + } + m_rest -= size; + m_buf_ptr += size; + return ptr; + } + allocate_block(size + alignment - 1); + return allocate(size, alignment); + } + + + private: + void allocate_block(unsigned size) + { + if(size < m_block_size) size = m_block_size; + if(m_num_blocks >= m_max_blocks) + { + block_type* new_blocks = + pod_allocator::allocate(m_max_blocks + m_block_ptr_inc); + + if(m_blocks) + { + memcpy(new_blocks, + m_blocks, + m_num_blocks * sizeof(block_type)); + pod_allocator::deallocate(m_blocks, m_max_blocks); + } + m_blocks = new_blocks; + m_max_blocks += m_block_ptr_inc; + } + + m_blocks[m_num_blocks].size = size; + m_blocks[m_num_blocks].data = + m_buf_ptr = + pod_allocator::allocate(size); + + m_num_blocks++; + m_rest = size; + } + + unsigned m_block_size; + unsigned m_block_ptr_inc; + unsigned m_num_blocks; + unsigned m_max_blocks; + block_type* m_blocks; + int8u* m_buf_ptr; + unsigned m_rest; + }; + + + + + + + + + //------------------------------------------------------------------------ + enum quick_sort_threshold_e + { + quick_sort_threshold = 9 + }; + + + //-----------------------------------------------------------swap_elements + template inline void swap_elements(T& a, T& b) + { + T temp = a; + a = b; + b = temp; + } + + + //--------------------------------------------------------------quick_sort + template + void quick_sort(Array& arr, Less less) + { + if(arr.size() < 2) return; + + typename Array::value_type* e1; + typename Array::value_type* e2; + + int stack[80]; + int* top = stack; + int limit = arr.size(); + int base = 0; + + for(;;) + { + int len = limit - base; + + int i; + int j; + int pivot; + + if(len > quick_sort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_elements(arr[base], arr[pivot]); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + e1 = &(arr[j]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[base]); + e2 = &(arr[i]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + e1 = &(arr[j]); + e2 = &(arr[base]); + if(less(*e1, *e2)) swap_elements(*e1, *e2); + + for(;;) + { + do i++; while( less(arr[i], arr[base]) ); + do j--; while( less(arr[base], arr[j]) ); + + if( i > j ) + { + break; + } + + swap_elements(arr[i], arr[j]); + } + + swap_elements(arr[base], arr[j]); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; less(*(e1 = &(arr[j + 1])), *(e2 = &(arr[j]))); j--) + { + swap_elements(*e1, *e2); + if(j == base) + { + break; + } + } + } + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + + + //------------------------------------------------------remove_duplicates + // Remove duplicates from a sorted array. It doesn't cut the + // tail of the array, it just returns the number of remaining elements. + //----------------------------------------------------------------------- + template + unsigned remove_duplicates(Array& arr, Equal equal) + { + if(arr.size() < 2) return arr.size(); + + unsigned i, j; + for(i = 1, j = 1; i < arr.size(); i++) + { + typename Array::value_type& e = arr[i]; + if(!equal(e, arr[i - 1])) + { + arr[j++] = e; + } + } + return j; + } + + //--------------------------------------------------------invert_container + template void invert_container(Array& arr) + { + int i = 0; + int j = arr.size() - 1; + while(i < j) + { + swap_elements(arr[i++], arr[j--]); + } + } + + //------------------------------------------------------binary_search_pos + template + unsigned binary_search_pos(const Array& arr, const Value& val, Less less) + { + if(arr.size() == 0) return 0; + + unsigned beg = 0; + unsigned end = arr.size() - 1; + + if(less(val, arr[0])) return 0; + if(less(arr[end], val)) return end + 1; + + while(end - beg > 1) + { + unsigned mid = (end + beg) >> 1; + if(less(val, arr[mid])) end = mid; + else beg = mid; + } + + //if(beg <= 0 && less(val, arr[0])) return 0; + //if(end >= arr.size() - 1 && less(arr[end], val)) ++end; + + return end; + } + + //----------------------------------------------------------range_adaptor + template class range_adaptor + { + public: + typedef typename Array::value_type value_type; + + range_adaptor(Array& array, unsigned start, unsigned size) : + m_array(array), m_start(start), m_size(size) + {} + + unsigned size() const { return m_size; } + const value_type& operator [] (unsigned i) const { return m_array[m_start + i]; } + value_type& operator [] (unsigned i) { return m_array[m_start + i]; } + const value_type& at(unsigned i) const { return m_array[m_start + i]; } + value_type& at(unsigned i) { return m_array[m_start + i]; } + value_type value_at(unsigned i) const { return m_array[m_start + i]; } + + private: + Array& m_array; + unsigned m_start; + unsigned m_size; + }; + + //---------------------------------------------------------------int_less + inline bool int_less(int a, int b) { return a < b; } + + //------------------------------------------------------------int_greater + inline bool int_greater(int a, int b) { return a > b; } + + //----------------------------------------------------------unsigned_less + inline bool unsigned_less(unsigned a, unsigned b) { return a < b; } + + //-------------------------------------------------------unsigned_greater + inline bool unsigned_greater(unsigned a, unsigned b) { return a > b; } +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arrowhead.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arrowhead.h new file mode 100644 index 00000000000..5e029ddee03 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_arrowhead.h @@ -0,0 +1,82 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Simple arrowhead/arrowtail generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_ARROWHEAD_INCLUDED +#define AGG_ARROWHEAD_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================================arrowhead + // + // See implementation agg_arrowhead.cpp + // + class arrowhead + { + public: + arrowhead(); + + void head(double d1, double d2, double d3, double d4) + { + m_head_d1 = d1; + m_head_d2 = d2; + m_head_d3 = d3; + m_head_d4 = d4; + m_head_flag = true; + } + + void head() { m_head_flag = true; } + void no_head() { m_head_flag = false; } + + void tail(double d1, double d2, double d3, double d4) + { + m_tail_d1 = d1; + m_tail_d2 = d2; + m_tail_d3 = d3; + m_tail_d4 = d4; + m_tail_flag = true; + } + + void tail() { m_tail_flag = true; } + void no_tail() { m_tail_flag = false; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + double m_head_d1; + double m_head_d2; + double m_head_d3; + double m_head_d4; + double m_tail_d1; + double m_tail_d2; + double m_tail_d3; + double m_tail_d4; + bool m_head_flag; + bool m_tail_flag; + double m_coord[16]; + unsigned m_cmd[8]; + unsigned m_curr_id; + unsigned m_curr_coord; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_basics.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_basics.h new file mode 100644 index 00000000000..309713002b3 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_basics.h @@ -0,0 +1,560 @@ +//---------------------------------------------------------------------------- +// 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_BASICS_INCLUDED +#define AGG_BASICS_INCLUDED + +#include +#include "agg_config.h" + +//---------------------------------------------------------AGG_CUSTOM_ALLOCATOR +#ifdef AGG_CUSTOM_ALLOCATOR +#include "agg_allocator.h" +#else +namespace agg +{ + // The policy of all AGG containers and memory allocation strategy + // in general is that no allocated data requires explicit construction. + // It means that the allocator can be really simple; you can even + // replace new/delete to malloc/free. The constructors and destructors + // won't be called in this case, however everything will remain working. + // The second argument of deallocate() is the size of the allocated + // block. You can use this information if you wish. + //------------------------------------------------------------pod_allocator + template struct pod_allocator + { + static T* allocate(unsigned num) { return new T [num]; } + static void deallocate(T* ptr, unsigned) { delete [] ptr; } + }; + + // Single object allocator. It's also can be replaced with your custom + // allocator. The difference is that it can only allocate a single + // object and the constructor and destructor must be called. + // In AGG there is no need to allocate an array of objects with + // calling their constructors (only single ones). So that, if you + // replace these new/delete to malloc/free make sure that the in-place + // new is called and take care of calling the destructor too. + //------------------------------------------------------------obj_allocator + template struct obj_allocator + { + static T* allocate() { return new T; } + static void deallocate(T* ptr) { delete ptr; } + }; +} +#endif + + +//-------------------------------------------------------- Default basic types +// +// If the compiler has different capacity of the basic types you can redefine +// them via the compiler command line or by generating agg_config.h that is +// empty by default. +// +#ifndef AGG_INT8 +#define AGG_INT8 signed char +#endif + +#ifndef AGG_INT8U +#define AGG_INT8U unsigned char +#endif + +#ifndef AGG_INT16 +#define AGG_INT16 short +#endif + +#ifndef AGG_INT16U +#define AGG_INT16U unsigned short +#endif + +#ifndef AGG_INT32 +#define AGG_INT32 int +#endif + +#ifndef AGG_INT32U +#define AGG_INT32U unsigned +#endif + +#ifndef AGG_INT64 +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64 signed __int64 +#else +#define AGG_INT64 signed long long +#endif +#endif + +#ifndef AGG_INT64U +#if defined(_MSC_VER) || defined(__BORLANDC__) +#define AGG_INT64U unsigned __int64 +#else +#define AGG_INT64U unsigned long long +#endif +#endif + +//------------------------------------------------ Some fixes for MS Visual C++ +#if defined(_MSC_VER) +#pragma warning(disable:4786) // Identifier was truncated... +#endif + +#if defined(_MSC_VER) +#define AGG_INLINE __forceinline +#else +#define AGG_INLINE inline +#endif + +namespace agg +{ + //------------------------------------------------------------------------- + typedef AGG_INT8 int8; //----int8 + typedef AGG_INT8U int8u; //----int8u + typedef AGG_INT16 int16; //----int16 + typedef AGG_INT16U int16u; //----int16u + typedef AGG_INT32 int32; //----int32 + typedef AGG_INT32U int32u; //----int32u + typedef AGG_INT64 int64; //----int64 + typedef AGG_INT64U int64u; //----int64u + +#if defined(AGG_FISTP) +#pragma warning(push) +#pragma warning(disable : 4035) //Disable warning "no return value" + AGG_INLINE int iround(double v) //-------iround + { + int t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } + AGG_INLINE unsigned uround(double v) //-------uround + { + unsigned t; + __asm fld qword ptr [v] + __asm fistp dword ptr [t] + __asm mov eax, dword ptr [t] + } +#pragma warning(pop) + AGG_INLINE int ifloor(double v) + { + return int(floor(v)); + } + AGG_INLINE unsigned ufloor(double v) //-------ufloor + { + return unsigned(floor(v)); + } + AGG_INLINE int iceil(double v) + { + return int(ceil(v)); + } + AGG_INLINE unsigned uceil(double v) //--------uceil + { + return unsigned(ceil(v)); + } +#elif defined(AGG_QIFIST) + AGG_INLINE int iround(double v) + { + return int(v); + } + AGG_INLINE int uround(double v) + { + return unsigned(v); + } + AGG_INLINE int ifloor(double v) + { + return int(floor(v)); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(floor(v)); + } + AGG_INLINE int iceil(double v) + { + return int(ceil(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#else + AGG_INLINE int iround(double v) + { + return int((v < 0.0) ? v - 0.5 : v + 0.5); + } + AGG_INLINE int uround(double v) + { + return unsigned(v + 0.5); + } + AGG_INLINE int ifloor(double v) + { + int i = int(v); + return i - (i > v); + } + AGG_INLINE unsigned ufloor(double v) + { + return unsigned(v); + } + AGG_INLINE int iceil(double v) + { + return int(ceil(v)); + } + AGG_INLINE unsigned uceil(double v) + { + return unsigned(ceil(v)); + } +#endif + + //---------------------------------------------------------------saturation + template struct saturation + { + AGG_INLINE static int iround(double v) + { + if(v < double(-Limit)) return -Limit; + if(v > double( Limit)) return Limit; + return agg::iround(v); + } + }; + + //------------------------------------------------------------------mul_one + template struct mul_one + { + AGG_INLINE static unsigned mul(unsigned a, unsigned b) + { + unsigned q = a * b + (1 << (Shift-1)); + return (q + (q >> Shift)) >> Shift; + } + }; + + //------------------------------------------------------------------------- + typedef unsigned char cover_type; //----cover_type + enum cover_scale_e + { + cover_shift = 8, //----cover_shift + cover_size = 1 << cover_shift, //----cover_size + cover_mask = cover_size - 1, //----cover_mask + cover_none = 0, //----cover_none + cover_full = cover_mask //----cover_full + }; + + //----------------------------------------------------poly_subpixel_scale_e + // These constants determine the subpixel accuracy, to be more precise, + // the number of bits of the fractional part of the coordinates. + // The possible coordinate capacity in bits can be calculated by formula: + // sizeof(int) * 8 - poly_subpixel_shift, i.e, for 32-bit integers and + // 8-bits fractional part the capacity is 24 bits. + enum poly_subpixel_scale_e + { + poly_subpixel_shift = 8, //----poly_subpixel_shift + poly_subpixel_scale = 1< struct rect_base + { + typedef T value_type; + typedef rect_base self_type; + T x1, y1, x2, y2; + + rect_base() {} + rect_base(T x1_, T y1_, T x2_, T y2_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_) {} + + void init(T x1_, T y1_, T x2_, T y2_) + { + x1 = x1_; y1 = y1_; x2 = x2_; y2 = y2_; + } + + const self_type& normalize() + { + T t; + if(x1 > x2) { t = x1; x1 = x2; x2 = t; } + if(y1 > y2) { t = y1; y1 = y2; y2 = t; } + return *this; + } + + bool clip(const self_type& r) + { + if(x2 > r.x2) x2 = r.x2; + if(y2 > r.y2) y2 = r.y2; + if(x1 < r.x1) x1 = r.x1; + if(y1 < r.y1) y1 = r.y1; + return x1 <= x2 && y1 <= y2; + } + + bool is_valid() const + { + return x1 <= x2 && y1 <= y2; + } + + bool hit_test(T x, T y) const + { + return (x >= x1 && x <= x2 && y >= y1 && y <= y2); + } + + bool overlaps(const self_type& r) const + { + return !(r.x1 > x2 || r.x2 < x1 + || r.y1 > y2 || r.y2 < y1); + } + }; + + //-----------------------------------------------------intersect_rectangles + template + inline Rect intersect_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + + // First process x2,y2 because the other order + // results in Internal Compiler Error under + // Microsoft Visual C++ .NET 2003 69462-335-0000007-18038 in + // case of "Maximize Speed" optimization option. + //----------------- + if(r.x2 > r2.x2) r.x2 = r2.x2; + if(r.y2 > r2.y2) r.y2 = r2.y2; + if(r.x1 < r2.x1) r.x1 = r2.x1; + if(r.y1 < r2.y1) r.y1 = r2.y1; + return r; + } + + + //---------------------------------------------------------unite_rectangles + template + inline Rect unite_rectangles(const Rect& r1, const Rect& r2) + { + Rect r = r1; + if(r.x2 < r2.x2) r.x2 = r2.x2; + if(r.y2 < r2.y2) r.y2 = r2.y2; + if(r.x1 > r2.x1) r.x1 = r2.x1; + if(r.y1 > r2.y1) r.y1 = r2.y1; + return r; + } + + typedef rect_base rect_i; //----rect_i + typedef rect_base rect_f; //----rect_f + typedef rect_base rect_d; //----rect_d + + //---------------------------------------------------------path_commands_e + enum path_commands_e + { + path_cmd_stop = 0, //----path_cmd_stop + path_cmd_move_to = 1, //----path_cmd_move_to + path_cmd_line_to = 2, //----path_cmd_line_to + path_cmd_curve3 = 3, //----path_cmd_curve3 + path_cmd_curve4 = 4, //----path_cmd_curve4 + path_cmd_curveN = 5, //----path_cmd_curveN + path_cmd_catrom = 6, //----path_cmd_catrom + path_cmd_ubspline = 7, //----path_cmd_ubspline + path_cmd_end_poly = 0x0F, //----path_cmd_end_poly + path_cmd_mask = 0x0F //----path_cmd_mask + }; + + //------------------------------------------------------------path_flags_e + enum path_flags_e + { + path_flags_none = 0, //----path_flags_none + path_flags_ccw = 0x10, //----path_flags_ccw + path_flags_cw = 0x20, //----path_flags_cw + path_flags_close = 0x40, //----path_flags_close + path_flags_mask = 0xF0 //----path_flags_mask + }; + + //---------------------------------------------------------------is_vertex + inline bool is_vertex(unsigned c) + { + return c >= path_cmd_move_to && c < path_cmd_end_poly; + } + + //--------------------------------------------------------------is_drawing + inline bool is_drawing(unsigned c) + { + return c >= path_cmd_line_to && c < path_cmd_end_poly; + } + + //-----------------------------------------------------------------is_stop + inline bool is_stop(unsigned c) + { + return c == path_cmd_stop; + } + + //--------------------------------------------------------------is_move_to + inline bool is_move_to(unsigned c) + { + return c == path_cmd_move_to; + } + + //--------------------------------------------------------------is_line_to + inline bool is_line_to(unsigned c) + { + return c == path_cmd_line_to; + } + + //----------------------------------------------------------------is_curve + inline bool is_curve(unsigned c) + { + return c == path_cmd_curve3 || c == path_cmd_curve4; + } + + //---------------------------------------------------------------is_curve3 + inline bool is_curve3(unsigned c) + { + return c == path_cmd_curve3; + } + + //---------------------------------------------------------------is_curve4 + inline bool is_curve4(unsigned c) + { + return c == path_cmd_curve4; + } + + //-------------------------------------------------------------is_end_poly + inline bool is_end_poly(unsigned c) + { + return (c & path_cmd_mask) == path_cmd_end_poly; + } + + //----------------------------------------------------------------is_close + inline bool is_close(unsigned c) + { + return (c & ~(path_flags_cw | path_flags_ccw)) == + (path_cmd_end_poly | path_flags_close); + } + + //------------------------------------------------------------is_next_poly + inline bool is_next_poly(unsigned c) + { + return is_stop(c) || is_move_to(c) || is_end_poly(c); + } + + //-------------------------------------------------------------------is_cw + inline bool is_cw(unsigned c) + { + return (c & path_flags_cw) != 0; + } + + //------------------------------------------------------------------is_ccw + inline bool is_ccw(unsigned c) + { + return (c & path_flags_ccw) != 0; + } + + //-------------------------------------------------------------is_oriented + inline bool is_oriented(unsigned c) + { + return (c & (path_flags_cw | path_flags_ccw)) != 0; + } + + //---------------------------------------------------------------is_closed + inline bool is_closed(unsigned c) + { + return (c & path_flags_close) != 0; + } + + //----------------------------------------------------------get_close_flag + inline unsigned get_close_flag(unsigned c) + { + return c & path_flags_close; + } + + //-------------------------------------------------------clear_orientation + inline unsigned clear_orientation(unsigned c) + { + return c & ~(path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------get_orientation + inline unsigned get_orientation(unsigned c) + { + return c & (path_flags_cw | path_flags_ccw); + } + + //---------------------------------------------------------set_orientation + inline unsigned set_orientation(unsigned c, unsigned o) + { + return clear_orientation(c) | o; + } + + //--------------------------------------------------------------point_base + template struct point_base + { + typedef T value_type; + T x,y; + point_base() {} + point_base(T x_, T y_) : x(x_), y(y_) {} + }; + typedef point_base point_i; //-----point_i + typedef point_base point_f; //-----point_f + typedef point_base point_d; //-----point_d + + //-------------------------------------------------------------vertex_base + template struct vertex_base + { + typedef T value_type; + T x,y; + unsigned cmd; + vertex_base() {} + vertex_base(T x_, T y_, unsigned cmd_) : x(x_), y(y_), cmd(cmd_) {} + }; + typedef vertex_base vertex_i; //-----vertex_i + typedef vertex_base vertex_f; //-----vertex_f + typedef vertex_base vertex_d; //-----vertex_d + + //----------------------------------------------------------------row_info + template struct row_info + { + int x1, x2; + T* ptr; + row_info() {} + row_info(int x1_, int x2_, T* ptr_) : x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //----------------------------------------------------------const_row_info + template struct const_row_info + { + int x1, x2; + const T* ptr; + const_row_info() {} + const_row_info(int x1_, int x2_, const T* ptr_) : + x1(x1_), x2(x2_), ptr(ptr_) {} + }; + + //------------------------------------------------------------is_equal_eps + template inline bool is_equal_eps(T v1, T v2, T epsilon) + { + return fabs(v1 - v2) <= double(epsilon); + } +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bezier_arc.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bezier_arc.h new file mode 100644 index 00000000000..6d98d1a9f0d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bezier_arc.h @@ -0,0 +1,159 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., +// 4, 7, 10, or 13 vertices. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_ARC_INCLUDED +#define AGG_BEZIER_ARC_INCLUDED + +#include "agg_conv_transform.h" + +namespace agg +{ + + //----------------------------------------------------------------------- + void arc_to_bezier(double cx, double cy, double rx, double ry, + double start_angle, double sweep_angle, + double* curve); + + + //==============================================================bezier_arc + // + // See implemantaion agg_bezier_arc.cpp + // + class bezier_arc + { + public: + //-------------------------------------------------------------------- + bezier_arc() : m_vertex(26), m_num_vertices(0), m_cmd(path_cmd_line_to) {} + bezier_arc(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle) + { + init(x, y, rx, ry, start_angle, sweep_angle); + } + + //-------------------------------------------------------------------- + void init(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle); + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_vertex >= m_num_vertices) return path_cmd_stop; + *x = m_vertices[m_vertex]; + *y = m_vertices[m_vertex + 1]; + m_vertex += 2; + return (m_vertex == 2) ? path_cmd_move_to : m_cmd; + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_num_vertices; } + const double* vertices() const { return m_vertices; } + double* vertices() { return m_vertices; } + + private: + unsigned m_vertex; + unsigned m_num_vertices; + double m_vertices[26]; + unsigned m_cmd; + }; + + + + //==========================================================bezier_arc_svg + // Compute an SVG-style bezier arc. + // + // Computes an elliptical arc from (x1, y1) to (x2, y2). The size and + // orientation of the ellipse are defined by two radii (rx, ry) + // and an x-axis-rotation, which indicates how the ellipse as a whole + // is rotated relative to the current coordinate system. The center + // (cx, cy) of the ellipse is calculated automatically to satisfy the + // constraints imposed by the other parameters. + // large-arc-flag and sweep-flag contribute to the automatic calculations + // and help determine how the arc is drawn. + class bezier_arc_svg + { + public: + //-------------------------------------------------------------------- + bezier_arc_svg() : m_arc(), m_radii_ok(false) {} + + bezier_arc_svg(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2) : + m_arc(), m_radii_ok(false) + { + init(x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2); + } + + //-------------------------------------------------------------------- + void init(double x1, double y1, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2); + + //-------------------------------------------------------------------- + bool radii_ok() const { return m_radii_ok; } + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_arc.rewind(0); + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + return m_arc.vertex(x, y); + } + + // Supplemantary functions. num_vertices() actually returns doubled + // number of vertices. That is, for 1 vertex it returns 2. + //-------------------------------------------------------------------- + unsigned num_vertices() const { return m_arc.num_vertices(); } + const double* vertices() const { return m_arc.vertices(); } + double* vertices() { return m_arc.vertices(); } + + private: + bezier_arc m_arc; + bool m_radii_ok; + }; + + + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bitset_iterator.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bitset_iterator.h new file mode 100644 index 00000000000..7382d5c3359 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bitset_iterator.h @@ -0,0 +1,54 @@ +//---------------------------------------------------------------------------- +// 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_BITSET_ITERATOR_INCLUDED +#define AGG_BITSET_ITERATOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + class bitset_iterator + { + public: + bitset_iterator(const int8u* bits, unsigned offset = 0) : + m_bits(bits + (offset >> 3)), + m_mask(0x80 >> (offset & 7)) + {} + + void operator ++ () + { + m_mask >>= 1; + if(m_mask == 0) + { + ++m_bits; + m_mask = 0x80; + } + } + + unsigned bit() const + { + return (*m_bits) & m_mask; + } + + private: + const int8u* m_bits; + int8u m_mask; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_blur.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_blur.h new file mode 100644 index 00000000000..cd5713f314f --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_blur.h @@ -0,0 +1,1503 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// The Stack Blur Algorithm was invented by Mario Klingemann, +// mario@quasimondo.com and described here: +// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php +// (search phrase "Stackblur: Fast But Goodlooking"). +// The major improvement is that there's no more division table +// that was very expensive to create for large blur radii. Insted, +// for 8-bit per channel and radius not exceeding 254 the division is +// replaced by multiplication and shift. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BLUR_INCLUDED +#define AGG_BLUR_INCLUDED + +#include "agg_array.h" +#include "agg_pixfmt_base.h" +#include "agg_pixfmt_transposer.h" + +namespace agg +{ + + template struct stack_blur_tables + { + static int16u const g_stack_blur8_mul[255]; + static int8u const g_stack_blur8_shr[255]; + }; + + //------------------------------------------------------------------------ + template + int16u const stack_blur_tables::g_stack_blur8_mul[255] = + { + 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, + 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, + 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, + 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, + 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, + 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, + 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, + 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, + 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, + 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, + 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, + 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, + 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, + 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, + 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, + 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 + }; + + //------------------------------------------------------------------------ + template + int8u const stack_blur_tables::g_stack_blur8_shr[255] = + { + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 + }; + + + + //==============================================================stack_blur + template class stack_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + + //-------------------------------------------------------------------- + template void blur_x(Img& img, unsigned radius) + { + if(radius < 1) return; + + unsigned x, y, xp, i; + unsigned stack_ptr; + unsigned stack_start; + + color_type pix; + color_type* stack_pix; + calculator_type sum; + calculator_type sum_in; + calculator_type sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned div = radius * 2 + 1; + + unsigned div_sum = (radius + 1) * (radius + 1); + unsigned mul_sum = 0; + unsigned shr_sum = 0; + unsigned max_val = color_type::base_mask; + + if(max_val <= 255 && radius < 255) + { + mul_sum = stack_blur_tables::g_stack_blur8_mul[radius]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[radius]; + } + + m_buf.allocate(w, 128); + m_stack.allocate(div, 32); + + for(y = 0; y < h; y++) + { + sum.clear(); + sum_in.clear(); + sum_out.clear(); + + pix = img.pixel(0, y); + for(i = 0; i <= radius; i++) + { + m_stack[i] = pix; + sum.add(pix, i + 1); + sum_out.add(pix); + } + for(i = 1; i <= radius; i++) + { + pix = img.pixel((i > wm) ? wm : i, y); + m_stack[i + radius] = pix; + sum.add(pix, radius + 1 - i); + sum_in.add(pix); + } + + stack_ptr = radius; + for(x = 0; x < w; x++) + { + if(mul_sum) sum.calc_pix(m_buf[x], mul_sum, shr_sum); + else sum.calc_pix(m_buf[x], div_sum); + + sum.sub(sum_out); + + stack_start = stack_ptr + div - radius; + if(stack_start >= div) stack_start -= div; + stack_pix = &m_stack[stack_start]; + + sum_out.sub(*stack_pix); + + xp = x + radius + 1; + if(xp > wm) xp = wm; + pix = img.pixel(xp, y); + + *stack_pix = pix; + + sum_in.add(pix); + sum.add(sum_in); + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = &m_stack[stack_ptr]; + + sum_out.add(*stack_pix); + sum_in.sub(*stack_pix); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template void blur_y(Img& img, unsigned radius) + { + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template void blur(Img& img, unsigned radius) + { + blur_x(img, radius); + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + private: + pod_vector m_buf; + pod_vector m_stack; + }; + + //====================================================stack_blur_calc_rgba + template struct stack_blur_calc_rgba + { + typedef T value_type; + value_type r,g,b,a; + + AGG_INLINE void clear() + { + r = g = b = a = 0; + } + + template AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + a += v.a; + } + + template AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + a += v.a * k; + } + + template AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + a -= v.a; + } + + template AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + v.a = value_type(a / div); + } + + template + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + v.a = value_type((a * mul) >> shr); + } + }; + + + //=====================================================stack_blur_calc_rgb + template struct stack_blur_calc_rgb + { + typedef T value_type; + value_type r,g,b; + + AGG_INLINE void clear() + { + r = g = b = 0; + } + + template AGG_INLINE void add(const ArgT& v) + { + r += v.r; + g += v.g; + b += v.b; + } + + template AGG_INLINE void add(const ArgT& v, unsigned k) + { + r += v.r * k; + g += v.g * k; + b += v.b * k; + } + + template AGG_INLINE void sub(const ArgT& v) + { + r -= v.r; + g -= v.g; + b -= v.b; + } + + template AGG_INLINE void calc_pix(ArgT& v, unsigned div) + { + typedef typename ArgT::value_type value_type; + v.r = value_type(r / div); + v.g = value_type(g / div); + v.b = value_type(b / div); + } + + template + AGG_INLINE void calc_pix(ArgT& v, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + v.r = value_type((r * mul) >> shr); + v.g = value_type((g * mul) >> shr); + v.b = value_type((b * mul) >> shr); + } + }; + + + //====================================================stack_blur_calc_gray + template struct stack_blur_calc_gray + { + typedef T value_type; + value_type v; + + AGG_INLINE void clear() + { + v = 0; + } + + template AGG_INLINE void add(const ArgT& a) + { + v += a.v; + } + + template AGG_INLINE void add(const ArgT& a, unsigned k) + { + v += a.v * k; + } + + template AGG_INLINE void sub(const ArgT& a) + { + v -= a.v; + } + + template AGG_INLINE void calc_pix(ArgT& a, unsigned div) + { + typedef typename ArgT::value_type value_type; + a.v = value_type(v / div); + } + + template + AGG_INLINE void calc_pix(ArgT& a, unsigned mul, unsigned shr) + { + typedef typename ArgT::value_type value_type; + a.v = value_type((v * mul) >> shr); + } + }; + + + + //========================================================stack_blur_gray8 + template + void stack_blur_gray8(Img& img, unsigned rx, unsigned ry) + { + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + unsigned pix; + unsigned stack_pix; + unsigned sum; + unsigned sum_in; + unsigned sum_out; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(0, y); + pix = *src_pix_ptr; + for(i = 0; i <= rx; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + pix = *src_pix_ptr; + stack[i + rx] = pix; + sum += pix * (rx + 1 - i); + sum_in += pix; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum -= sum_out; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + pix = *src_pix_ptr; + ++xp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum = sum_in = sum_out = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + pix = *src_pix_ptr; + for(i = 0; i <= ry; i++) + { + stack[i] = pix; + sum += pix * (i + 1); + sum_out += pix; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + pix = *src_pix_ptr; + stack[i + ry] = pix; + sum += pix * (ry + 1 - i); + sum_in += pix; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + *dst_pix_ptr = (sum * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum -= sum_out; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + sum_out -= stack[stack_start]; + + if(yp < hm) + { + src_pix_ptr += stride; + pix = *src_pix_ptr; + ++yp; + } + + stack[stack_start] = pix; + + sum_in += pix; + sum += sum_in; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix = stack[stack_ptr]; + + sum_out += stack_pix; + sum_in -= stack_pix; + } + } + } + } + + + + //========================================================stack_blur_rgb24 + template + void stack_blur_rgb24(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_in_r = + sum_in_g = + sum_in_b = + sum_out_r = + sum_out_g = + sum_out_b = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + } + } + } + } + + + + //=======================================================stack_blur_rgba32 + template + void stack_blur_rgba32(Img& img, unsigned rx, unsigned ry) + { + typedef typename Img::color_type color_type; + typedef typename Img::order_type order_type; + enum order_e + { + R = order_type::R, + G = order_type::G, + B = order_type::B, + A = order_type::A + }; + + unsigned x, y, xp, yp, i; + unsigned stack_ptr; + unsigned stack_start; + + const int8u* src_pix_ptr; + int8u* dst_pix_ptr; + color_type* stack_pix_ptr; + + unsigned sum_r; + unsigned sum_g; + unsigned sum_b; + unsigned sum_a; + unsigned sum_in_r; + unsigned sum_in_g; + unsigned sum_in_b; + unsigned sum_in_a; + unsigned sum_out_r; + unsigned sum_out_g; + unsigned sum_out_b; + unsigned sum_out_a; + + unsigned w = img.width(); + unsigned h = img.height(); + unsigned wm = w - 1; + unsigned hm = h - 1; + + unsigned div; + unsigned mul_sum; + unsigned shr_sum; + + pod_vector stack; + + if(rx > 0) + { + if(rx > 254) rx = 254; + div = rx * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[rx]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[rx]; + stack.allocate(div); + + for(y = 0; y < h; y++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(0, y); + for(i = 0; i <= rx; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= rx; i++) + { + if(i <= wm) src_pix_ptr += Img::pix_width; + stack_pix_ptr = &stack[i + rx]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (rx + 1 - i); + sum_g += src_pix_ptr[G] * (rx + 1 - i); + sum_b += src_pix_ptr[B] * (rx + 1 - i); + sum_a += src_pix_ptr[A] * (rx + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = rx; + xp = rx; + if(xp > wm) xp = wm; + src_pix_ptr = img.pix_ptr(xp, y); + dst_pix_ptr = img.pix_ptr(0, y); + for(x = 0; x < w; x++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += Img::pix_width; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - rx; + if(stack_start >= div) stack_start -= div; + stack_pix_ptr = &stack[stack_start]; + + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(xp < wm) + { + src_pix_ptr += Img::pix_width; + ++xp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + + if(ry > 0) + { + if(ry > 254) ry = 254; + div = ry * 2 + 1; + mul_sum = stack_blur_tables::g_stack_blur8_mul[ry]; + shr_sum = stack_blur_tables::g_stack_blur8_shr[ry]; + stack.allocate(div); + + int stride = img.stride(); + for(x = 0; x < w; x++) + { + sum_r = + sum_g = + sum_b = + sum_a = + sum_in_r = + sum_in_g = + sum_in_b = + sum_in_a = + sum_out_r = + sum_out_g = + sum_out_b = + sum_out_a = 0; + + src_pix_ptr = img.pix_ptr(x, 0); + for(i = 0; i <= ry; i++) + { + stack_pix_ptr = &stack[i]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (i + 1); + sum_g += src_pix_ptr[G] * (i + 1); + sum_b += src_pix_ptr[B] * (i + 1); + sum_a += src_pix_ptr[A] * (i + 1); + sum_out_r += src_pix_ptr[R]; + sum_out_g += src_pix_ptr[G]; + sum_out_b += src_pix_ptr[B]; + sum_out_a += src_pix_ptr[A]; + } + for(i = 1; i <= ry; i++) + { + if(i <= hm) src_pix_ptr += stride; + stack_pix_ptr = &stack[i + ry]; + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + sum_r += src_pix_ptr[R] * (ry + 1 - i); + sum_g += src_pix_ptr[G] * (ry + 1 - i); + sum_b += src_pix_ptr[B] * (ry + 1 - i); + sum_a += src_pix_ptr[A] * (ry + 1 - i); + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + } + + stack_ptr = ry; + yp = ry; + if(yp > hm) yp = hm; + src_pix_ptr = img.pix_ptr(x, yp); + dst_pix_ptr = img.pix_ptr(x, 0); + for(y = 0; y < h; y++) + { + dst_pix_ptr[R] = (sum_r * mul_sum) >> shr_sum; + dst_pix_ptr[G] = (sum_g * mul_sum) >> shr_sum; + dst_pix_ptr[B] = (sum_b * mul_sum) >> shr_sum; + dst_pix_ptr[A] = (sum_a * mul_sum) >> shr_sum; + dst_pix_ptr += stride; + + sum_r -= sum_out_r; + sum_g -= sum_out_g; + sum_b -= sum_out_b; + sum_a -= sum_out_a; + + stack_start = stack_ptr + div - ry; + if(stack_start >= div) stack_start -= div; + + stack_pix_ptr = &stack[stack_start]; + sum_out_r -= stack_pix_ptr->r; + sum_out_g -= stack_pix_ptr->g; + sum_out_b -= stack_pix_ptr->b; + sum_out_a -= stack_pix_ptr->a; + + if(yp < hm) + { + src_pix_ptr += stride; + ++yp; + } + + stack_pix_ptr->r = src_pix_ptr[R]; + stack_pix_ptr->g = src_pix_ptr[G]; + stack_pix_ptr->b = src_pix_ptr[B]; + stack_pix_ptr->a = src_pix_ptr[A]; + + sum_in_r += src_pix_ptr[R]; + sum_in_g += src_pix_ptr[G]; + sum_in_b += src_pix_ptr[B]; + sum_in_a += src_pix_ptr[A]; + sum_r += sum_in_r; + sum_g += sum_in_g; + sum_b += sum_in_b; + sum_a += sum_in_a; + + ++stack_ptr; + if(stack_ptr >= div) stack_ptr = 0; + stack_pix_ptr = &stack[stack_ptr]; + + sum_out_r += stack_pix_ptr->r; + sum_out_g += stack_pix_ptr->g; + sum_out_b += stack_pix_ptr->b; + sum_out_a += stack_pix_ptr->a; + sum_in_r -= stack_pix_ptr->r; + sum_in_g -= stack_pix_ptr->g; + sum_in_b -= stack_pix_ptr->b; + sum_in_a -= stack_pix_ptr->a; + } + } + } + } + + + + //===========================================================recursive_blur + template class recursive_blur + { + public: + typedef ColorT color_type; + typedef CalculatorT calculator_type; + typedef typename color_type::value_type value_type; + typedef typename calculator_type::value_type calc_type; + + //-------------------------------------------------------------------- + template void blur_x(Img& img, double radius) + { + if(radius < 0.62) return; + if(img.width() < 3) return; + + calc_type s = calc_type(radius * 0.5); + calc_type q = calc_type((s < 2.5) ? + 3.97156 - 4.14554 * sqrt(1 - 0.26891 * s) : + 0.98711 * s - 0.96330); + + calc_type q2 = calc_type(q * q); + calc_type q3 = calc_type(q2 * q); + + calc_type b0 = calc_type(1.0 / (1.578250 + + 2.444130 * q + + 1.428100 * q2 + + 0.422205 * q3)); + + calc_type b1 = calc_type( 2.44413 * q + + 2.85619 * q2 + + 1.26661 * q3); + + calc_type b2 = calc_type(-1.42810 * q2 + + -1.26661 * q3); + + calc_type b3 = calc_type(0.422205 * q3); + + calc_type b = calc_type(1 - (b1 + b2 + b3) * b0); + + b1 *= b0; + b2 *= b0; + b3 *= b0; + + int w = img.width(); + int h = img.height(); + int wm = w-1; + int x, y; + + m_sum1.allocate(w); + m_sum2.allocate(w); + m_buf.allocate(w); + + for(y = 0; y < h; y++) + { + calculator_type c; + c.from_pix(img.pixel(0, y)); + m_sum1[0].calc(b, b1, b2, b3, c, c, c, c); + c.from_pix(img.pixel(1, y)); + m_sum1[1].calc(b, b1, b2, b3, c, m_sum1[0], m_sum1[0], m_sum1[0]); + c.from_pix(img.pixel(2, y)); + m_sum1[2].calc(b, b1, b2, b3, c, m_sum1[1], m_sum1[0], m_sum1[0]); + + for(x = 3; x < w; ++x) + { + c.from_pix(img.pixel(x, y)); + m_sum1[x].calc(b, b1, b2, b3, c, m_sum1[x-1], m_sum1[x-2], m_sum1[x-3]); + } + + m_sum2[wm ].calc(b, b1, b2, b3, m_sum1[wm ], m_sum1[wm ], m_sum1[wm], m_sum1[wm]); + m_sum2[wm-1].calc(b, b1, b2, b3, m_sum1[wm-1], m_sum2[wm ], m_sum2[wm], m_sum2[wm]); + m_sum2[wm-2].calc(b, b1, b2, b3, m_sum1[wm-2], m_sum2[wm-1], m_sum2[wm], m_sum2[wm]); + m_sum2[wm ].to_pix(m_buf[wm ]); + m_sum2[wm-1].to_pix(m_buf[wm-1]); + m_sum2[wm-2].to_pix(m_buf[wm-2]); + + for(x = wm-3; x >= 0; --x) + { + m_sum2[x].calc(b, b1, b2, b3, m_sum1[x], m_sum2[x+1], m_sum2[x+2], m_sum2[x+3]); + m_sum2[x].to_pix(m_buf[x]); + } + img.copy_color_hspan(0, y, w, &m_buf[0]); + } + } + + //-------------------------------------------------------------------- + template void blur_y(Img& img, double radius) + { + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + //-------------------------------------------------------------------- + template void blur(Img& img, double radius) + { + blur_x(img, radius); + pixfmt_transposer img2(img); + blur_x(img2, radius); + } + + private: + agg::pod_vector m_sum1; + agg::pod_vector m_sum2; + agg::pod_vector m_buf; + }; + + + //=================================================recursive_blur_calc_rgba + template struct recursive_blur_calc_rgba + { + typedef T value_type; + typedef recursive_blur_calc_rgba self_type; + + value_type r,g,b,a; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + a = c.a; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + a = b1*c1.a + b2*c2.a + b3*c3.a + b4*c4.a; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = cv_type(r); + c.g = cv_type(g); + c.b = cv_type(b); + c.a = cv_type(a); + } + }; + + + //=================================================recursive_blur_calc_rgb + template struct recursive_blur_calc_rgb + { + typedef T value_type; + typedef recursive_blur_calc_rgb self_type; + + value_type r,g,b; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + r = c.r; + g = c.g; + b = c.b; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + r = b1*c1.r + b2*c2.r + b3*c3.r + b4*c4.r; + g = b1*c1.g + b2*c2.g + b3*c3.g + b4*c4.g; + b = b1*c1.b + b2*c2.b + b3*c3.b + b4*c4.b; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.r = cv_type(r); + c.g = cv_type(g); + c.b = cv_type(b); + } + }; + + + //================================================recursive_blur_calc_gray + template struct recursive_blur_calc_gray + { + typedef T value_type; + typedef recursive_blur_calc_gray self_type; + + value_type v; + + template + AGG_INLINE void from_pix(const ColorT& c) + { + v = c.v; + } + + AGG_INLINE void calc(value_type b1, + value_type b2, + value_type b3, + value_type b4, + const self_type& c1, + const self_type& c2, + const self_type& c3, + const self_type& c4) + { + v = b1*c1.v + b2*c2.v + b3*c3.v + b4*c4.v; + } + + template + AGG_INLINE void to_pix(ColorT& c) const + { + typedef typename ColorT::value_type cv_type; + c.v = cv_type(v); + } + }; + + //================================================slight_blur + // Special-purpose filter for applying a Gaussian blur with a radius small enough + // that the blur only affects adjacent pixels. A Gaussian curve with a standard + // deviation of r/2 is used, as per the HTML/CSS spec. At 3 standard deviations, + // the contribution drops to less than 0.005, i.e. less than half a percent, + // therefore the radius can be at least 1.33 before errors become significant. + // This filter is useful for smoothing artifacts caused by detail rendered + // at the pixel scale, e.g. single-pixel lines. Note that the filter should + // only be used with premultiplied pixel formats (or those without alpha). + // See the "line_thickness" example for a demonstration. + template + class slight_blur + { + public: + typedef typename PixFmt::pixel_type pixel_type; + typedef typename PixFmt::value_type value_type; + typedef typename PixFmt::order_type order_type; + + slight_blur(double r = 1.33) + { + radius(r); + } + + void radius(double r) + { + if (r > 0) + { + // Sample the gaussian curve at 0 and r/2 standard deviations. + // At 3 standard deviations, the response is < 0.005. + double pi = 3.14159; + double n = 2 / r; + m_g0 = 1 / sqrt(2 * pi); + m_g1 = m_g0 * exp(-n * n); + + // Normalize. + double sum = m_g0 + 2 * m_g1; + m_g0 /= sum; + m_g1 /= sum; + } + else + { + m_g0 = 1; + m_g1 = 0; + } + } + + void blur(PixFmt& img, rect_i bounds) + { + // Make sure we stay within the image area. + bounds.clip(rect_i(0, 0, img.width() - 1, img.height() - 1)); + + int w = bounds.x2 - bounds.x1 + 1; + int h = bounds.y2 - bounds.y1 + 1; + + if (w < 3 || h < 3) return; + + // Allocate 3 rows of buffer space. + m_buf.allocate(w * 3); + + // Set up row pointers + pixel_type * begin = &m_buf[0]; + pixel_type * r0 = begin; + pixel_type * r1 = r0 + w; + pixel_type * r2 = r1 + w; + pixel_type * end = r2 + w; + + // Horizontally blur the first two input rows. + calc_row(img, bounds.x1, bounds.y1, w, r0); + memcpy(r1, r0, w * sizeof(pixel_type)); + + for (int y = 0; ; ) + { + // Get pointer to first pixel. + pixel_type* p = img.pix_value_ptr(bounds.x1, bounds.y1 + y, bounds.x1 + w); + + // Horizontally blur the row below. + if (y + 1 < h) + { + calc_row(img, bounds.x1, bounds.y1 + y + 1, w, r2); + } + else + { + memcpy(r2, r1, w * sizeof(pixel_type)); // duplicate bottom row + } + + // Combine blurred rows into destination. + for (int x = 0; x < w; ++x) + { + calc_pixel(*r0++, *r1++, *r2++, *p++); + } + + if (++y >= h) break; + + // Wrap bottom row pointer around to top of buffer. + if (r2 == end) r2 = begin; + else if (r1 == end) r1 = begin; + else if (r0 == end) r0 = begin; + } + } + + private: + void calc_row(PixFmt& img, int x, int y, int w, pixel_type* row) + { + const int wm = w - 1; + + pixel_type* p = img.pix_value_ptr(x, y, w); + + pixel_type c[3]; + pixel_type* p0 = c; + pixel_type* p1 = c + 1; + pixel_type* p2 = c + 2; + pixel_type* end = c + 3; + *p0 = *p1 = *p; + + for (int x = 0; x < wm; ++x) + { + *p2 = *(p = p->next()); + + calc_pixel(*p0++, *p1++, *p2++, *row++); + + if (p0 == end) p0 = c; + else if (p1 == end) p1 = c; + else if (p2 == end) p2 = c; + } + + calc_pixel(*p0, *p1, *p1, *row); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x) + { + calc_pixel(c1, c2, c3, x, PixFmt::pixfmt_category()); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_gray_tag) + { + x.c[0] = calc_value(c1.c[0], c2.c[0], c3.c[0]); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_rgb_tag) + { + enum { R = order_type::R, G = order_type::G, B = order_type::B }; + x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]); + x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]); + x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]); + } + + void calc_pixel( + pixel_type const & c1, + pixel_type const & c2, + pixel_type const & c3, + pixel_type & x, + pixfmt_rgba_tag) + { + enum { R = order_type::R, G = order_type::G, B = order_type::B, A = order_type::A }; + x.c[R] = calc_value(c1.c[R], c2.c[R], c3.c[R]); + x.c[G] = calc_value(c1.c[G], c2.c[G], c3.c[G]); + x.c[B] = calc_value(c1.c[B], c2.c[B], c3.c[B]); + x.c[A] = calc_value(c1.c[A], c2.c[A], c3.c[A]); + } + + value_type calc_value(value_type v1, value_type v2, value_type v3) + { + return value_type(m_g1 * v1 + m_g0 * v2 + m_g1 * v3); + } + + double m_g0, m_g1; + pod_vector m_buf; + }; + + // Helper functions for applying blur to a surface without having to create an intermediate object. + + template + void apply_slight_blur(PixFmt& img, const rect_i& bounds, double r = 1) + { + if (r > 0) slight_blur(r).blur(img, bounds); + } + + template + void apply_slight_blur(PixFmt& img, double r = 1) + { + if (r > 0) slight_blur(r).blur(img, rect_i(0, 0, img.width() - 1, img.height() - 1)); + } + + template + void apply_slight_blur(renderer_base& img, const rect_i& bounds, double r = 1) + { + if (r > 0) slight_blur(r).blur(img.ren(), bounds); + } + + template + void apply_slight_blur(renderer_base& img, double r = 1) + { + if (r > 0) slight_blur(r).blur(img.ren(), img.clip_box()); + } +} + + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bounding_rect.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bounding_rect.h new file mode 100644 index 00000000000..f13b863f0fc --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bounding_rect.h @@ -0,0 +1,116 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// bounding_rect function template +// +//---------------------------------------------------------------------------- +#ifndef AGG_BOUNDING_RECT_INCLUDED +#define AGG_BOUNDING_RECT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------------bounding_rect + template + bool bounding_rect(VertexSource& vs, GetId& gi, + unsigned start, unsigned num, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + unsigned i; + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + for(i = 0; i < num; i++) + { + vs.rewind(gi[start + i]); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + + //-----------------------------------------------------bounding_rect_single + template + bool bounding_rect_single(VertexSource& vs, unsigned path_id, + CoordT* x1, CoordT* y1, CoordT* x2, CoordT* y2) + { + double x; + double y; + bool first = true; + + *x1 = CoordT(1); + *y1 = CoordT(1); + *x2 = CoordT(0); + *y2 = CoordT(0); + + vs.rewind(path_id); + unsigned cmd; + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(first) + { + *x1 = CoordT(x); + *y1 = CoordT(y); + *x2 = CoordT(x); + *y2 = CoordT(y); + first = false; + } + else + { + if(CoordT(x) < *x1) *x1 = CoordT(x); + if(CoordT(y) < *y1) *y1 = CoordT(y); + if(CoordT(x) > *x2) *x2 = CoordT(x); + if(CoordT(y) > *y2) *y2 = CoordT(y); + } + } + } + return *x1 <= *x2 && *y1 <= *y2; + } + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bspline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bspline.h new file mode 100644 index 00000000000..2c1ed9a38cc --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_bspline.h @@ -0,0 +1,76 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class bspline +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BSPLINE_INCLUDED +#define AGG_BSPLINE_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //----------------------------------------------------------------bspline + // A very simple class of Bi-cubic Spline interpolation. + // First call init(num, x[], y[]) where num - number of source points, + // x, y - arrays of X and Y values respectively. Here Y must be a function + // of X. It means that all the X-coordinates must be arranged in the ascending + // order. + // Then call get(x) that calculates a value Y for the respective X. + // The class supports extrapolation, i.e. you can call get(x) where x is + // outside the given with init() X-range. Extrapolation is a simple linear + // function. + // + // See Implementation agg_bspline.cpp + //------------------------------------------------------------------------ + class bspline + { + public: + bspline(); + bspline(int num); + bspline(int num, const double* x, const double* y); + + void init(int num); + void add_point(double x, double y); + void prepare(); + + void init(int num, const double* x, const double* y); + + double get(double x) const; + double get_stateful(double x) const; + + private: + bspline(const bspline&); + const bspline& operator = (const bspline&); + + static void bsearch(int n, const double *x, double x0, int *i); + double extrapolation_left(double x) const; + double extrapolation_right(double x) const; + double interpolation(double x, int i) const; + + int m_max; + int m_num; + double* m_x; + double* m_y; + pod_array m_am; + mutable int m_last_idx; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_clip_liang_barsky.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_clip_liang_barsky.h new file mode 100644 index 00000000000..4b5fedbab5f --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_clip_liang_barsky.h @@ -0,0 +1,333 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Liang-Barsky clipping +// +//---------------------------------------------------------------------------- +#ifndef AGG_CLIP_LIANG_BARSKY_INCLUDED +#define AGG_CLIP_LIANG_BARSKY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + enum clipping_flags_e + { + clipping_flags_x1_clipped = 4, + clipping_flags_x2_clipped = 1, + clipping_flags_y1_clipped = 8, + clipping_flags_y2_clipped = 2, + clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped, + clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped + }; + + //----------------------------------------------------------clipping_flags + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + template + inline unsigned clipping_flags(T x, T y, const rect_base& clip_box) + { + return (x > clip_box.x2) | + ((y > clip_box.y2) << 1) | + ((x < clip_box.x1) << 2) | + ((y < clip_box.y1) << 3); + } + + //--------------------------------------------------------clipping_flags_x + template + inline unsigned clipping_flags_x(T x, const rect_base& clip_box) + { + return (x > clip_box.x2) | ((x < clip_box.x1) << 2); + } + + + //--------------------------------------------------------clipping_flags_y + template + inline unsigned clipping_flags_y(T y, const rect_base& clip_box) + { + return ((y > clip_box.y2) << 1) | ((y < clip_box.y1) << 3); + } + + + //-------------------------------------------------------clip_liang_barsky + template + inline unsigned clip_liang_barsky(T x1, T y1, T x2, T y2, + const rect_base& clip_box, + T* x, T* y) + { + const double nearzero = 1e-30; + + double deltax = x2 - x1; + double deltay = y2 - y1; + double xin; + double xout; + double yin; + double yout; + double tinx; + double tiny; + double toutx; + double touty; + double tin1; + double tin2; + double tout1; + unsigned np = 0; + + if(deltax == 0.0) + { + // bump off of the vertical + deltax = (x1 > clip_box.x1) ? -nearzero : nearzero; + } + + if(deltay == 0.0) + { + // bump off of the horizontal + deltay = (y1 > clip_box.y1) ? -nearzero : nearzero; + } + + if(deltax > 0.0) + { + // points to right + xin = clip_box.x1; + xout = clip_box.x2; + } + else + { + xin = clip_box.x2; + xout = clip_box.x1; + } + + if(deltay > 0.0) + { + // points up + yin = clip_box.y1; + yout = clip_box.y2; + } + else + { + yin = clip_box.y2; + yout = clip_box.y1; + } + + tinx = (xin - x1) / deltax; + tiny = (yin - y1) / deltay; + + if (tinx < tiny) + { + // hits x first + tin1 = tinx; + tin2 = tiny; + } + else + { + // hits y first + tin1 = tiny; + tin2 = tinx; + } + + if(tin1 <= 1.0) + { + if(0.0 < tin1) + { + *x++ = (T)xin; + *y++ = (T)yin; + ++np; + } + + if(tin2 <= 1.0) + { + toutx = (xout - x1) / deltax; + touty = (yout - y1) / deltay; + + tout1 = (toutx < touty) ? toutx : touty; + + if(tin2 > 0.0 || tout1 > 0.0) + { + if(tin2 <= tout1) + { + if(tin2 > 0.0) + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)(y1 + tinx * deltay); + } + else + { + *x++ = (T)(x1 + tiny * deltax); + *y++ = (T)yin; + } + ++np; + } + + if(tout1 < 1.0) + { + if(toutx < touty) + { + *x++ = (T)xout; + *y++ = (T)(y1 + toutx * deltay); + } + else + { + *x++ = (T)(x1 + touty * deltax); + *y++ = (T)yout; + } + } + else + { + *x++ = x2; + *y++ = y2; + } + ++np; + } + else + { + if(tinx > tiny) + { + *x++ = (T)xin; + *y++ = (T)yout; + } + else + { + *x++ = (T)xout; + *y++ = (T)yin; + } + ++np; + } + } + } + } + return np; + } + + + //---------------------------------------------------------------------------- + template + bool clip_move_point(T x1, T y1, T x2, T y2, + const rect_base& clip_box, + T* x, T* y, unsigned flags) + { + T bound; + + if(flags & clipping_flags_x_clipped) + { + if(x1 == x2) + { + return false; + } + bound = (flags & clipping_flags_x1_clipped) ? clip_box.x1 : clip_box.x2; + *y = (T)(double(bound - x1) * (y2 - y1) / (x2 - x1) + y1); + *x = bound; + } + + flags = clipping_flags_y(*y, clip_box); + if(flags & clipping_flags_y_clipped) + { + if(y1 == y2) + { + return false; + } + bound = (flags & clipping_flags_y1_clipped) ? clip_box.y1 : clip_box.y2; + *x = (T)(double(bound - y1) * (x2 - x1) / (y2 - y1) + x1); + *y = bound; + } + return true; + } + + //-------------------------------------------------------clip_line_segment + // Returns: ret >= 4 - Fully clipped + // (ret & 1) != 0 - First point has been moved + // (ret & 2) != 0 - Second point has been moved + // + template + unsigned clip_line_segment(T* x1, T* y1, T* x2, T* y2, + const rect_base& clip_box) + { + unsigned f1 = clipping_flags(*x1, *y1, clip_box); + unsigned f2 = clipping_flags(*x2, *y2, clip_box); + unsigned ret = 0; + + if((f2 | f1) == 0) + { + // Fully visible + return 0; + } + + if((f1 & clipping_flags_x_clipped) != 0 && + (f1 & clipping_flags_x_clipped) == (f2 & clipping_flags_x_clipped)) + { + // Fully clipped + return 4; + } + + if((f1 & clipping_flags_y_clipped) != 0 && + (f1 & clipping_flags_y_clipped) == (f2 & clipping_flags_y_clipped)) + { + // Fully clipped + return 4; + } + + T tx1 = *x1; + T ty1 = *y1; + T tx2 = *x2; + T ty2 = *y2; + if(f1) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x1, y1, f1)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 1; + } + if(f2) + { + if(!clip_move_point(tx1, ty1, tx2, ty2, clip_box, x2, y2, f2)) + { + return 4; + } + if(*x1 == *x2 && *y1 == *y2) + { + return 4; + } + ret |= 2; + } + return ret; + } + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_gray.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_gray.h new file mode 100644 index 00000000000..8d5f2ed8d04 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_gray.h @@ -0,0 +1,1047 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_GRAY_INCLUDED +#define AGG_COLOR_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" + +namespace agg +{ + + //===================================================================gray8 + template + struct gray8T + { + 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() {} + + //-------------------------------------------------------------------- + explicit 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.0f; + return rgba32(v32, v32, v32, a / 255.0f); + } + + 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) + { + 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, 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) 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) ? (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 = 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); } + }; + + 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() {} + + //-------------------------------------------------------------------- + explicit 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 rgba32() const + { + rgba32::value_type v32 = v / 65535.0f; + return rgba32(v32, v32, v32, a / 65535.0f); + } + + //-------------------------------------------------------------------- + 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; + + // 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); + } + + static value_type luminance(const rgba& c) + { + return luminance(c.r, c.g, c.b); + } + + static value_type luminance(const rgba32& c) + { + return luminance(c.r, c.g, c.b); + } + + static value_type luminance(const rgba8& c) + { + return luminance(c.r / 255.0, c.g / 255.0, c.g / 255.0); + } + + static value_type luminance(const rgba16& c) + { + return luminance(c.r / 65535.0, c.g / 65535.0, c.g / 65535.0); + } + + //-------------------------------------------------------------------- + gray32() {} + + //-------------------------------------------------------------------- + explicit 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 rgba(v, v, v, a); + } + + //-------------------------------------------------------------------- + operator gray8() const + { + 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)); + } + + //-------------------------------------------------------------------- + operator rgba32() const + { + return rgba32(v, v, v, a); + } + + //-------------------------------------------------------------------- + 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); } + }; +} + + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_rgba.h new file mode 100644 index 00000000000..74f871be17b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_color_rgba.h @@ -0,0 +1,1353 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// 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 +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_RGBA_INCLUDED +#define AGG_COLOR_RGBA_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_gamma_lut.h" + +namespace agg +{ + // Supported component orders for RGB and RGBA pixel formats + //======================================================================= + struct order_rgb { enum rgb_e { R=0, G=1, B=2, N=3 }; }; + struct order_bgr { enum bgr_e { B=0, G=1, R=2, N=3 }; }; + struct order_rgba { enum rgba_e { R=0, G=1, B=2, A=3, N=4 }; }; + struct order_argb { enum argb_e { A=0, R=1, G=2, B=3, N=4 }; }; + struct order_abgr { enum abgr_e { A=0, B=1, G=2, R=3, N=4 }; }; + struct order_bgra { enum bgra_e { B=0, G=1, R=2, A=3, N=4 }; }; + + // 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() + { + r = g = b = a = 0; + return *this; + } + + //-------------------------------------------------------------------- + rgba& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + rgba& opacity(double a_) + { + if (a_ < 0) a = 0; + else if (a_ > 1) a = 1; + else a = a_; + return *this; + } + + //-------------------------------------------------------------------- + double opacity() const + { + return a; + } + + //-------------------------------------------------------------------- + rgba& premultiply() + { + r *= a; + g *= a; + b *= a; + return *this; + } + + //-------------------------------------------------------------------- + rgba& premultiply(double a_) + { + if (a <= 0 || a_ <= 0) + { + r = g = b = a = 0; + } + else + { + a_ /= a; + r *= a_; + g *= a_; + b *= a_; + a = a_; + } + return *this; + } + + //-------------------------------------------------------------------- + rgba& demultiply() + { + if (a == 0) + { + r = g = b = 0; + } + else + { + double a_ = 1.0 / a; + r *= a_; + g *= a_; + b *= a_; + } + 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& operator+=(const rgba& c) + { + r += c.r; + g += c.g; + b += c.b; + a += c.a; + return *this; + } + + rgba& operator*=(double k) + { + r *= k; + g *= k; + b *= k; + a *= k; + return *this; + } + + //-------------------------------------------------------------------- + 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; + + + value_type r; + value_type g; + value_type b; + value_type a; + + static void convert(rgba8T& dst, const rgba8T& src) + { + 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; + } + + static void convert(rgba8T& dst, const rgba8T& src) + { + 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; + } + + static void convert(rgba8T& dst, const rgba& src) + { + 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) + { + 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, 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) + { + r = g = b = 0; + } + else + { + 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 + 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.0) + { + return self_type(rgba::from_wavelength(wl, gamma)); + } + }; + + typedef rgba8T rgba8; + typedef rgba8T srgba8; + + + //-------------------------------------------------------------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(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 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); + } + + //-------------------------------------------------------------------- + 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) + { + if (a == 0) + { + r = g = b = 0; + } + else + { + 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 + 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.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)); + } + }; +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_config.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_config.h new file mode 100644 index 00000000000..fa1dae2ba7b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_config.h @@ -0,0 +1,44 @@ +#ifndef AGG_CONFIG_INCLUDED +#define AGG_CONFIG_INCLUDED + +// This file can be used to redefine certain data types. + +//--------------------------------------- +// 1. Default basic types such as: +// +// AGG_INT8 +// AGG_INT8U +// AGG_INT16 +// AGG_INT16U +// AGG_INT32 +// AGG_INT32U +// AGG_INT64 +// AGG_INT64U +// +// Just replace this file with new defines if necessary. +// For example, if your compiler doesn't have a 64 bit integer type +// you can still use AGG if you define the follows: +// +// #define AGG_INT64 int +// #define AGG_INT64U unsigned +// +// It will result in overflow in 16 bit-per-component image/pattern resampling +// but it won't result any crash and the rest of the library will remain +// fully functional. + + +//--------------------------------------- +// 2. Default rendering_buffer type. Can be: +// +// Provides faster access for massive pixel operations, +// such as blur, image filtering: +// #define AGG_RENDERING_BUFFER row_ptr_cache +// +// Provides cheaper creation and destruction (no mem allocs): +// #define AGG_RENDERING_BUFFER row_accessor +// +// You can still use both of them simultaneously in your applications +// This #define is used only for default rendering_buffer type, +// in short hand typedefs like pixfmt_rgba32. + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vcgen.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vcgen.h new file mode 100644 index 00000000000..a79f2208c61 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vcgen.h @@ -0,0 +1,157 @@ +//---------------------------------------------------------------------------- +// 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_CONV_ADAPTOR_VCGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VCGEN_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //------------------------------------------------------------null_markers + struct null_markers + { + void remove_all() {} + void add_vertex(double, double, unsigned) {} + void prepare_src() {} + + void rewind(unsigned) {} + unsigned vertex(double*, double*) { return path_cmd_stop; } + }; + + + //------------------------------------------------------conv_adaptor_vcgen + template class conv_adaptor_vcgen + { + enum status + { + initial, + accumulate, + generate + }; + + public: + explicit conv_adaptor_vcgen(VertexSource& source) : + m_source(&source), + m_status(initial) + {} + void attach(VertexSource& source) { m_source = &source; } + + Generator& generator() { return m_generator; } + const Generator& generator() const { return m_generator; } + + Markers& markers() { return m_markers; } + const Markers& markers() const { return m_markers; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_status = initial; + } + + unsigned vertex(double* x, double* y); + + private: + // Prohibit copying + conv_adaptor_vcgen(const conv_adaptor_vcgen&); + const conv_adaptor_vcgen& + operator = (const conv_adaptor_vcgen&); + + VertexSource* m_source; + Generator m_generator; + Markers m_markers; + status m_status; + unsigned m_last_cmd; + double m_start_x; + double m_start_y; + }; + + + + + + //------------------------------------------------------------------------ + template + unsigned conv_adaptor_vcgen::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + bool done = false; + while(!done) + { + switch(m_status) + { + case initial: + m_markers.remove_all(); + m_last_cmd = m_source->vertex(&m_start_x, &m_start_y); + m_status = accumulate; + + case accumulate: + if(is_stop(m_last_cmd)) return path_cmd_stop; + + m_generator.remove_all(); + m_generator.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + m_markers.add_vertex(m_start_x, m_start_y, path_cmd_move_to); + + for(;;) + { + cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_last_cmd = cmd; + if(is_move_to(cmd)) + { + m_start_x = *x; + m_start_y = *y; + break; + } + m_generator.add_vertex(*x, *y, cmd); + m_markers.add_vertex(*x, *y, path_cmd_line_to); + } + else + { + if(is_stop(cmd)) + { + m_last_cmd = path_cmd_stop; + break; + } + if(is_end_poly(cmd)) + { + m_generator.add_vertex(*x, *y, cmd); + break; + } + } + } + m_generator.rewind(0); + m_status = generate; + + case generate: + cmd = m_generator.vertex(x, y); + if(is_stop(cmd)) + { + m_status = accumulate; + break; + } + done = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vpgen.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vpgen.h new file mode 100644 index 00000000000..d6b545ef1f2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_adaptor_vpgen.h @@ -0,0 +1,159 @@ +//---------------------------------------------------------------------------- +// 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_CONV_ADAPTOR_VPGEN_INCLUDED +#define AGG_CONV_ADAPTOR_VPGEN_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================conv_adaptor_vpgen + template class conv_adaptor_vpgen + { + public: + explicit conv_adaptor_vpgen(VertexSource& source) : m_source(&source) {} + void attach(VertexSource& source) { m_source = &source; } + + VPGen& vpgen() { return m_vpgen; } + const VPGen& vpgen() const { return m_vpgen; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_adaptor_vpgen(const conv_adaptor_vpgen&); + const conv_adaptor_vpgen& + operator = (const conv_adaptor_vpgen&); + + VertexSource* m_source; + VPGen m_vpgen; + double m_start_x; + double m_start_y; + unsigned m_poly_flags; + int m_vertices; + }; + + + + //------------------------------------------------------------------------ + template + void conv_adaptor_vpgen::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vpgen.reset(); + m_start_x = 0; + m_start_y = 0; + m_poly_flags = 0; + m_vertices = 0; + } + + + //------------------------------------------------------------------------ + template + unsigned conv_adaptor_vpgen::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + cmd = m_vpgen.vertex(x, y); + if(!is_stop(cmd)) break; + + if(m_poly_flags && !m_vpgen.auto_unclose()) + { + *x = 0.0; + *y = 0.0; + cmd = m_poly_flags; + m_poly_flags = 0; + break; + } + + if(m_vertices < 0) + { + if(m_vertices < -1) + { + m_vertices = 0; + return path_cmd_stop; + } + m_vpgen.move_to(m_start_x, m_start_y); + m_vertices = 1; + continue; + } + + double tx, ty; + cmd = m_source->vertex(&tx, &ty); + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_start_x = tx; + m_start_y = ty; + m_vertices = -1; + continue; + } + m_vpgen.move_to(tx, ty); + m_start_x = tx; + m_start_y = ty; + m_vertices = 1; + } + else + { + m_vpgen.line_to(tx, ty); + ++m_vertices; + } + } + else + { + if(is_end_poly(cmd)) + { + m_poly_flags = cmd; + if(is_closed(cmd) || m_vpgen.auto_close()) + { + if(m_vpgen.auto_close()) m_poly_flags |= path_flags_close; + if(m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + } + else + { + // path_cmd_stop + if(m_vpgen.auto_close() && m_vertices > 2) + { + m_vpgen.line_to(m_start_x, m_start_y); + m_poly_flags = path_cmd_end_poly | path_flags_close; + m_vertices = -2; + continue; + } + break; + } + } + } + return cmd; + } + + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_bspline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_bspline.h new file mode 100644 index 00000000000..13d22d92979 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_bspline.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------------- +// 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_CONV_BSPLINE_INCLUDED +#define AGG_CONV_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_bspline.h" +#include "agg_conv_adaptor_vcgen.h" + + +namespace agg +{ + + //---------------------------------------------------------conv_bspline + template + struct conv_bspline : public conv_adaptor_vcgen + { + typedef conv_adaptor_vcgen base_type; + + conv_bspline(VertexSource& vs) : + conv_adaptor_vcgen(vs) {} + + void interpolation_step(double v) { base_type::generator().interpolation_step(v); } + double interpolation_step() const { return base_type::generator().interpolation_step(); } + + private: + conv_bspline(const conv_bspline&); + const conv_bspline& + operator = (const conv_bspline&); + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polygon.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polygon.h new file mode 100644 index 00000000000..87537638dce --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polygon.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Polygon clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polygon into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_POLYGON_INCLUDED +#define AGG_CONV_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polygon.h" + +namespace agg +{ + + //=======================================================conv_clip_polygon + template + struct conv_clip_polygon : public conv_adaptor_vpgen + { + typedef conv_adaptor_vpgen base_type; + + conv_clip_polygon(VertexSource& vs) : + conv_adaptor_vpgen(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + private: + conv_clip_polygon(const conv_clip_polygon&); + const conv_clip_polygon& + operator = (const conv_clip_polygon&); + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polyline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polyline.h new file mode 100644 index 00000000000..f3fc2888c23 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_clip_polyline.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// polyline clipping converter +// There an optimized Liang-Basky algorithm is used. +// The algorithm doesn't optimize the degenerate edges, i.e. it will never +// break a closed polyline into two or more ones, instead, there will be +// degenerate edges coinciding with the respective clipping boundaries. +// This is a sub-optimal solution, because that optimization would require +// extra, rather expensive math while the rasterizer tolerates it quite well, +// without any considerable overhead. +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CLIP_polyline_INCLUDED +#define AGG_CONV_CLIP_polyline_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_clip_polyline.h" + +namespace agg +{ + + //=======================================================conv_clip_polyline + template + struct conv_clip_polyline : public conv_adaptor_vpgen + { + typedef conv_adaptor_vpgen base_type; + + conv_clip_polyline(VertexSource& vs) : + conv_adaptor_vpgen(vs) {} + + void clip_box(double x1, double y1, double x2, double y2) + { + base_type::vpgen().clip_box(x1, y1, x2, y2); + } + + double x1() const { return base_type::vpgen().x1(); } + double y1() const { return base_type::vpgen().y1(); } + double x2() const { return base_type::vpgen().x2(); } + double y2() const { return base_type::vpgen().y2(); } + + private: + conv_clip_polyline(const conv_clip_polyline&); + const conv_clip_polyline& + operator = (const conv_clip_polyline&); + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_close_polygon.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_close_polygon.h new file mode 100644 index 00000000000..c46594fdfbe --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_close_polygon.h @@ -0,0 +1,125 @@ +//---------------------------------------------------------------------------- +// 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_CONV_CLOSE_POLYGON_INCLUDED +#define AGG_CONV_CLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================conv_close_polygon + template class conv_close_polygon + { + public: + explicit conv_close_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_close_polygon(const conv_close_polygon&); + const conv_close_polygon& + operator = (const conv_close_polygon&); + + VertexSource* m_source; + unsigned m_cmd[2]; + double m_x[2]; + double m_y[2]; + unsigned m_vertex; + bool m_line_to; + }; + + + + //------------------------------------------------------------------------ + template + void conv_close_polygon::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_vertex = 2; + m_line_to = false; + } + + + + //------------------------------------------------------------------------ + template + unsigned conv_close_polygon::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + for(;;) + { + if(m_vertex < 2) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + cmd = m_cmd[m_vertex]; + ++m_vertex; + break; + } + + cmd = m_source->vertex(x, y); + + if(is_end_poly(cmd)) + { + cmd |= path_flags_close; + break; + } + + if(is_stop(cmd)) + { + if(m_line_to) + { + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_cmd[1] = path_cmd_stop; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_move_to(cmd)) + { + if(m_line_to) + { + m_x[0] = 0.0; + m_y[0] = 0.0; + m_cmd[0] = path_cmd_end_poly | path_flags_close; + m_x[1] = *x; + m_y[1] = *y; + m_cmd[1] = cmd; + m_vertex = 0; + m_line_to = false; + continue; + } + break; + } + + if(is_vertex(cmd)) + { + m_line_to = true; + break; + } + } + return cmd; + } + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_concat.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_concat.h new file mode 100644 index 00000000000..745d349c6f7 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_concat.h @@ -0,0 +1,73 @@ +//---------------------------------------------------------------------------- +// 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_CONV_CONCAT_INCLUDED +#define AGG_CONV_CONCAT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=============================================================conv_concat + // Concatenation of two paths. Usually used to combine lines or curves + // with markers such as arrowheads + template class conv_concat + { + public: + conv_concat(VS1& source1, VS2& source2) : + m_source1(&source1), m_source2(&source2), m_status(2) {} + void attach1(VS1& source) { m_source1 = &source; } + void attach2(VS2& source) { m_source2 = &source; } + + + void rewind(unsigned path_id) + { + m_source1->rewind(path_id); + m_source2->rewind(0); + m_status = 0; + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd; + if(m_status == 0) + { + cmd = m_source1->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 1; + } + if(m_status == 1) + { + cmd = m_source2->vertex(x, y); + if(!is_stop(cmd)) return cmd; + m_status = 2; + } + return path_cmd_stop; + } + + private: + conv_concat(const conv_concat&); + const conv_concat& + operator = (const conv_concat&); + + VS1* m_source1; + VS2* m_source2; + int m_status; + + }; +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_contour.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_contour.h new file mode 100644 index 00000000000..b4b5a9047e9 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_contour.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_stroke +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_CONTOUR_INCLUDED +#define AGG_CONV_CONTOUR_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_contour.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-----------------------------------------------------------conv_contour + template + struct conv_contour : public conv_adaptor_vcgen + { + typedef conv_adaptor_vcgen base_type; + + conv_contour(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } + void width(double w) { base_type::generator().width(w); } + void miter_limit(double ml) { base_type::generator().miter_limit(ml); } + void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + void auto_detect_orientation(bool v) { base_type::generator().auto_detect_orientation(v); } + + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } + double width() const { return base_type::generator().width(); } + double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + bool auto_detect_orientation() const { return base_type::generator().auto_detect_orientation(); } + + private: + conv_contour(const conv_contour&); + const conv_contour& + operator = (const conv_contour&); + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_curve.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_curve.h new file mode 100644 index 00000000000..d5b475de7a1 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_curve.h @@ -0,0 +1,201 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes conv_curve +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_CURVE_INCLUDED +#define AGG_CONV_CURVE_INCLUDED + +#include "agg_basics.h" +#include "agg_curves.h" + +namespace agg +{ + + + //---------------------------------------------------------------conv_curve + // Curve converter class. Any path storage can have Bezier curves defined + // by their control points. There're two types of curves supported: curve3 + // and curve4. Curve3 is a conic Bezier curve with 2 endpoints and 1 control + // point. Curve4 has 2 control points (4 points in total) and can be used + // to interpolate more complicated curves. Curve4, unlike curve3 can be used + // to approximate arcs, both circular and elliptical. Curves are approximated + // with straight lines and one of the approaches is just to store the whole + // sequence of vertices that approximate our curve. It takes additional + // memory, and at the same time the consecutive vertices can be calculated + // on demand. + // + // Initially, path storages are not suppose to keep all the vertices of the + // curves (although, nothing prevents us from doing so). Instead, path_storage + // keeps only vertices, needed to calculate a curve on demand. Those vertices + // are marked with special commands. So, if the path_storage contains curves + // (which are not real curves yet), and we render this storage directly, + // all we will see is only 2 or 3 straight line segments (for curve3 and + // curve4 respectively). If we need to see real curves drawn we need to + // include this class into the conversion pipeline. + // + // Class conv_curve recognizes commands path_cmd_curve3 and path_cmd_curve4 + // and converts these vertices into a move_to/line_to sequence. + //----------------------------------------------------------------------- + template class conv_curve + { + public: + typedef Curve3 curve3_type; + typedef Curve4 curve4_type; + typedef conv_curve self_type; + + explicit conv_curve(VertexSource& source) : + m_source(&source), m_last_x(0.0), m_last_y(0.0) {} + void attach(VertexSource& source) { m_source = &source; } + + void approximation_method(curve_approximation_method_e v) + { + m_curve3.approximation_method(v); + m_curve4.approximation_method(v); + } + + curve_approximation_method_e approximation_method() const + { + return m_curve4.approximation_method(); + } + + void approximation_scale(double s) + { + m_curve3.approximation_scale(s); + m_curve4.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve4.approximation_scale(); + } + + void angle_tolerance(double v) + { + m_curve3.angle_tolerance(v); + m_curve4.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve4.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve3.cusp_limit(v); + m_curve4.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve4.cusp_limit(); + } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_curve(const self_type&); + const self_type& operator = (const self_type&); + + VertexSource* m_source; + double m_last_x; + double m_last_y; + curve3_type m_curve3; + curve4_type m_curve4; + }; + + + + //------------------------------------------------------------------------ + template + void conv_curve::rewind(unsigned path_id) + { + m_source->rewind(path_id); + m_last_x = 0.0; + m_last_y = 0.0; + m_curve3.reset(); + m_curve4.reset(); + } + + + //------------------------------------------------------------------------ + template + unsigned conv_curve::vertex(double* x, double* y) + { + if(!is_stop(m_curve3.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + if(!is_stop(m_curve4.vertex(x, y))) + { + m_last_x = *x; + m_last_y = *y; + return path_cmd_line_to; + } + + double ct2_x; + double ct2_y; + double end_x; + double end_y; + + unsigned cmd = m_source->vertex(x, y); + switch(cmd) + { + case path_cmd_curve3: + m_source->vertex(&end_x, &end_y); + + m_curve3.init(m_last_x, m_last_y, + *x, *y, + end_x, end_y); + + m_curve3.vertex(x, y); // First call returns path_cmd_move_to + m_curve3.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + + case path_cmd_curve4: + m_source->vertex(&ct2_x, &ct2_y); + m_source->vertex(&end_x, &end_y); + + m_curve4.init(m_last_x, m_last_y, + *x, *y, + ct2_x, ct2_y, + end_x, end_y); + + m_curve4.vertex(x, y); // First call returns path_cmd_move_to + m_curve4.vertex(x, y); // This is the first vertex of the curve + cmd = path_cmd_line_to; + break; + } + m_last_x = *x; + m_last_y = *y; + return cmd; + } + + +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_dash.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_dash.h new file mode 100644 index 00000000000..23c13ad0ab3 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_dash.h @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_dash +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_DASH_INCLUDED +#define AGG_CONV_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_dash.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //---------------------------------------------------------------conv_dash + template + struct conv_dash : public conv_adaptor_vcgen + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen base_type; + + conv_dash(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void remove_all_dashes() + { + base_type::generator().remove_all_dashes(); + } + + void add_dash(double dash_len, double gap_len) + { + base_type::generator().add_dash(dash_len, gap_len); + } + + void dash_start(double ds) + { + base_type::generator().dash_start(ds); + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_dash(const conv_dash&); + const conv_dash& + operator = (const conv_dash&); + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_gpc.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_gpc.h new file mode 100644 index 00000000000..2acada342d8 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_gpc.h @@ -0,0 +1,432 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// General Polygon Clipper based on the GPC library by Alan Murta +// Union, Intersection, XOR, A-B, B-A +// Contact the author if you intend to use it in commercial applications! +// http://www.cs.man.ac.uk/aig/staff/alan/software/ +// Alan Murta (email: gpc@cs.man.ac.uk) +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CONV_GPC_INCLUDED +#define AGG_CONV_GPC_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_array.h" + +extern "C" +{ +#include "gpc.h" +} + +namespace agg +{ + enum gpc_op_e + { + gpc_or, + gpc_and, + gpc_xor, + gpc_a_minus_b, + gpc_b_minus_a + }; + + + //================================================================conv_gpc + template class conv_gpc + { + enum status + { + status_move_to, + status_line_to, + status_stop + }; + + struct contour_header_type + { + int num_vertices; + int hole_flag; + gpc_vertex* vertices; + }; + + typedef pod_bvector vertex_array_type; + typedef pod_bvector contour_header_array_type; + + + public: + typedef VSA source_a_type; + typedef VSB source_b_type; + typedef conv_gpc self_type; + + ~conv_gpc() + { + free_gpc_data(); + } + + conv_gpc(source_a_type& a, source_b_type& b, gpc_op_e op = gpc_or) : + m_src_a(&a), + m_src_b(&b), + m_status(status_move_to), + m_vertex(-1), + m_contour(-1), + m_operation(op) + { + memset(&m_poly_a, 0, sizeof(m_poly_a)); + memset(&m_poly_b, 0, sizeof(m_poly_b)); + memset(&m_result, 0, sizeof(m_result)); + } + + void attach1(VSA& source) { m_src_a = &source; } + void attach2(VSB& source) { m_src_b = &source; } + + void operation(gpc_op_e v) { m_operation = v; } + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_gpc(const conv_gpc&); + const conv_gpc& operator = (const conv_gpc&); + + //-------------------------------------------------------------------- + void free_polygon(gpc_polygon& p); + void free_result(); + void free_gpc_data(); + void start_contour(); + void add_vertex(double x, double y); + void end_contour(unsigned orientation); + void make_polygon(gpc_polygon& p); + void start_extracting(); + bool next_contour(); + bool next_vertex(double* x, double* y); + + + //-------------------------------------------------------------------- + template void add(VS& src, gpc_polygon& p) + { + unsigned cmd; + double x, y; + double start_x = 0.0; + double start_y = 0.0; + bool line_to = false; + unsigned orientation = 0; + + m_contour_accumulator.remove_all(); + + while(!is_stop(cmd = src.vertex(&x, &y))) + { + if(is_vertex(cmd)) + { + if(is_move_to(cmd)) + { + if(line_to) + { + end_contour(orientation); + orientation = 0; + } + start_contour(); + start_x = x; + start_y = y; + } + add_vertex(x, y); + line_to = true; + } + else + { + if(is_end_poly(cmd)) + { + orientation = get_orientation(cmd); + if(line_to && is_closed(cmd)) + { + add_vertex(start_x, start_y); + } + } + } + } + if(line_to) + { + end_contour(orientation); + } + make_polygon(p); + } + + + private: + //-------------------------------------------------------------------- + source_a_type* m_src_a; + source_b_type* m_src_b; + status m_status; + int m_vertex; + int m_contour; + gpc_op_e m_operation; + vertex_array_type m_vertex_accumulator; + contour_header_array_type m_contour_accumulator; + gpc_polygon m_poly_a; + gpc_polygon m_poly_b; + gpc_polygon m_result; + }; + + + + + + //------------------------------------------------------------------------ + template + void conv_gpc::free_polygon(gpc_polygon& p) + { + int i; + for(i = 0; i < p.num_contours; i++) + { + pod_allocator::deallocate(p.contour[i].vertex, + p.contour[i].num_vertices); + } + pod_allocator::deallocate(p.contour, p.num_contours); + memset(&p, 0, sizeof(gpc_polygon)); + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::free_result() + { + if(m_result.contour) + { + gpc_free_polygon(&m_result); + } + memset(&m_result, 0, sizeof(m_result)); + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::free_gpc_data() + { + free_polygon(m_poly_a); + free_polygon(m_poly_b); + free_result(); + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::start_contour() + { + contour_header_type h; + memset(&h, 0, sizeof(h)); + m_contour_accumulator.add(h); + m_vertex_accumulator.remove_all(); + } + + + //------------------------------------------------------------------------ + template + inline void conv_gpc::add_vertex(double x, double y) + { + gpc_vertex v; + v.x = x; + v.y = y; + m_vertex_accumulator.add(v); + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::end_contour(unsigned orientation) + { + if(m_contour_accumulator.size()) + { + if(m_vertex_accumulator.size() > 2) + { + contour_header_type& h = + m_contour_accumulator[m_contour_accumulator.size() - 1]; + + h.num_vertices = m_vertex_accumulator.size(); + h.hole_flag = 0; + + // TO DO: Clarify the "holes" + //if(is_cw(orientation)) h.hole_flag = 1; + + h.vertices = pod_allocator::allocate(h.num_vertices); + gpc_vertex* d = h.vertices; + int i; + for(i = 0; i < h.num_vertices; i++) + { + const gpc_vertex& s = m_vertex_accumulator[i]; + d->x = s.x; + d->y = s.y; + ++d; + } + } + else + { + m_vertex_accumulator.remove_last(); + } + } + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::make_polygon(gpc_polygon& p) + { + free_polygon(p); + if(m_contour_accumulator.size()) + { + p.num_contours = m_contour_accumulator.size(); + + p.hole = 0; + p.contour = pod_allocator::allocate(p.num_contours); + + int i; + gpc_vertex_list* pv = p.contour; + for(i = 0; i < p.num_contours; i++) + { + const contour_header_type& h = m_contour_accumulator[i]; + pv->num_vertices = h.num_vertices; + pv->vertex = h.vertices; + ++pv; + } + } + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::start_extracting() + { + m_status = status_move_to; + m_contour = -1; + m_vertex = -1; + } + + + //------------------------------------------------------------------------ + template + bool conv_gpc::next_contour() + { + if(++m_contour < m_result.num_contours) + { + m_vertex = -1; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template + inline bool conv_gpc::next_vertex(double* x, double* y) + { + const gpc_vertex_list& vlist = m_result.contour[m_contour]; + if(++m_vertex < vlist.num_vertices) + { + const gpc_vertex& v = vlist.vertex[m_vertex]; + *x = v.x; + *y = v.y; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + template + void conv_gpc::rewind(unsigned path_id) + { + free_result(); + m_src_a->rewind(path_id); + m_src_b->rewind(path_id); + add(*m_src_a, m_poly_a); + add(*m_src_b, m_poly_b); + switch(m_operation) + { + case gpc_or: + gpc_polygon_clip(GPC_UNION, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_and: + gpc_polygon_clip(GPC_INT, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_xor: + gpc_polygon_clip(GPC_XOR, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_a_minus_b: + gpc_polygon_clip(GPC_DIFF, + &m_poly_a, + &m_poly_b, + &m_result); + break; + + case gpc_b_minus_a: + gpc_polygon_clip(GPC_DIFF, + &m_poly_b, + &m_poly_a, + &m_result); + break; + } + start_extracting(); + } + + + //------------------------------------------------------------------------ + template + unsigned conv_gpc::vertex(double* x, double* y) + { + if(m_status == status_move_to) + { + if(next_contour()) + { + if(next_vertex(x, y)) + { + m_status = status_line_to; + return path_cmd_move_to; + } + m_status = status_stop; + return path_cmd_end_poly | path_flags_close; + } + } + else + { + if(next_vertex(x, y)) + { + return path_cmd_line_to; + } + else + { + m_status = status_move_to; + } + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker.h new file mode 100644 index 00000000000..2cd3cb403f4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker.h @@ -0,0 +1,148 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_marker +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_MARKER_INCLUDED +#define AGG_CONV_MARKER_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" + +namespace agg +{ + //-------------------------------------------------------------conv_marker + template + class conv_marker + { + public: + conv_marker(MarkerLocator& ml, MarkerShapes& ms); + + trans_affine& transform() { return m_transform; } + const trans_affine& transform() const { return m_transform; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + conv_marker(const conv_marker&); + const conv_marker& + operator = (const conv_marker&); + + enum status_e + { + initial, + markers, + polygon, + stop + }; + + MarkerLocator* m_marker_locator; + MarkerShapes* m_marker_shapes; + trans_affine m_transform; + trans_affine m_mtx; + status_e m_status; + unsigned m_marker; + unsigned m_num_markers; + }; + + + //------------------------------------------------------------------------ + template + conv_marker::conv_marker(MarkerLocator& ml, MarkerShapes& ms) : + m_marker_locator(&ml), + m_marker_shapes(&ms), + m_status(initial), + m_marker(0), + m_num_markers(1) + { + } + + + //------------------------------------------------------------------------ + template + void conv_marker::rewind(unsigned) + { + m_status = initial; + m_marker = 0; + m_num_markers = 1; + } + + + //------------------------------------------------------------------------ + template + unsigned conv_marker::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_move_to; + double x1, y1, x2, y2; + + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + if(m_num_markers == 0) + { + cmd = path_cmd_stop; + break; + } + m_marker_locator->rewind(m_marker); + ++m_marker; + m_num_markers = 0; + m_status = markers; + + case markers: + if(is_stop(m_marker_locator->vertex(&x1, &y1))) + { + m_status = initial; + break; + } + if(is_stop(m_marker_locator->vertex(&x2, &y2))) + { + m_status = initial; + break; + } + ++m_num_markers; + m_mtx = m_transform; + m_mtx *= trans_affine_rotation(atan2(y2 - y1, x2 - x1)); + m_mtx *= trans_affine_translation(x1, y1); + m_marker_shapes->rewind(m_marker - 1); + m_status = polygon; + + case polygon: + cmd = m_marker_shapes->vertex(x, y); + if(is_stop(cmd)) + { + cmd = path_cmd_move_to; + m_status = markers; + break; + } + m_mtx.transform(x, y); + return cmd; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker_adaptor.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker_adaptor.h new file mode 100644 index 00000000000..4486d6ace9d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_marker_adaptor.h @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +// 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_CONV_MARKER_ADAPTOR_INCLUDED +#define AGG_CONV_MARKER_ADAPTOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=====================================================conv_marker_adaptor + template + struct conv_marker_adaptor : + public conv_adaptor_vcgen + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen base_type; + + conv_marker_adaptor(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_marker_adaptor(const conv_marker_adaptor&); + const conv_marker_adaptor& + operator = (const conv_marker_adaptor&); + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_segmentator.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_segmentator.h new file mode 100644 index 00000000000..e69a9e7d7d0 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_segmentator.h @@ -0,0 +1,48 @@ +//---------------------------------------------------------------------------- +// 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_CONV_SEGMENTATOR_INCLUDED +#define AGG_CONV_SEGMENTATOR_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vpgen.h" +#include "agg_vpgen_segmentator.h" + +namespace agg +{ + + //========================================================conv_segmentator + template + struct conv_segmentator : public conv_adaptor_vpgen + { + typedef conv_adaptor_vpgen base_type; + + conv_segmentator(VertexSource& vs) : + conv_adaptor_vpgen(vs) {} + + void approximation_scale(double s) { base_type::vpgen().approximation_scale(s); } + double approximation_scale() const { return base_type::vpgen().approximation_scale(); } + + private: + conv_segmentator(const conv_segmentator&); + const conv_segmentator& + operator = (const conv_segmentator&); + }; + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_shorten_path.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_shorten_path.h new file mode 100644 index 00000000000..5617e51d17e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_shorten_path.h @@ -0,0 +1,50 @@ +//---------------------------------------------------------------------------- +// 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_CONV_SHORTEN_PATH_INCLUDED +#define AGG_CONV_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_vcgen_vertex_sequence.h" + +namespace agg +{ + + //=======================================================conv_shorten_path + template class conv_shorten_path : + public conv_adaptor_vcgen + { + public: + typedef conv_adaptor_vcgen base_type; + + conv_shorten_path(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_shorten_path(const conv_shorten_path&); + const conv_shorten_path& + operator = (const conv_shorten_path&); + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_smooth_poly1.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_smooth_poly1.h new file mode 100644 index 00000000000..4ac4e3d6e29 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_smooth_poly1.h @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Smooth polygon generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_SMOOTH_POLY1_INCLUDED +#define AGG_CONV_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_smooth_poly1.h" +#include "agg_conv_adaptor_vcgen.h" +#include "agg_conv_curve.h" + + +namespace agg +{ + + //-------------------------------------------------------conv_smooth_poly1 + template + struct conv_smooth_poly1 : + public conv_adaptor_vcgen + { + typedef conv_adaptor_vcgen base_type; + + conv_smooth_poly1(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void smooth_value(double v) { base_type::generator().smooth_value(v); } + double smooth_value() const { return base_type::generator().smooth_value(); } + + private: + conv_smooth_poly1(const conv_smooth_poly1&); + const conv_smooth_poly1& + operator = (const conv_smooth_poly1&); + }; + + + + //-------------------------------------------------conv_smooth_poly1_curve + template + struct conv_smooth_poly1_curve : + public conv_curve > + { + conv_smooth_poly1_curve(VertexSource& vs) : + conv_curve >(m_smooth), + m_smooth(vs) + { + } + + void smooth_value(double v) { m_smooth.generator().smooth_value(v); } + double smooth_value() const { return m_smooth.generator().smooth_value(); } + + private: + conv_smooth_poly1_curve(const conv_smooth_poly1_curve&); + const conv_smooth_poly1_curve& + operator = (const conv_smooth_poly1_curve&); + + conv_smooth_poly1 m_smooth; + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_stroke.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_stroke.h new file mode 100644 index 00000000000..e19a6b61f40 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_stroke.h @@ -0,0 +1,73 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// conv_stroke +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_STROKE_INCLUDED +#define AGG_CONV_STROKE_INCLUDED + +#include "agg_basics.h" +#include "agg_vcgen_stroke.h" +#include "agg_conv_adaptor_vcgen.h" + +namespace agg +{ + + //-------------------------------------------------------------conv_stroke + template + struct conv_stroke : + public conv_adaptor_vcgen + { + typedef Markers marker_type; + typedef conv_adaptor_vcgen base_type; + + conv_stroke(VertexSource& vs) : + conv_adaptor_vcgen(vs) + { + } + + void line_cap(line_cap_e lc) { base_type::generator().line_cap(lc); } + void line_join(line_join_e lj) { base_type::generator().line_join(lj); } + void inner_join(inner_join_e ij) { base_type::generator().inner_join(ij); } + + line_cap_e line_cap() const { return base_type::generator().line_cap(); } + line_join_e line_join() const { return base_type::generator().line_join(); } + inner_join_e inner_join() const { return base_type::generator().inner_join(); } + + void width(double w) { base_type::generator().width(w); } + void miter_limit(double ml) { base_type::generator().miter_limit(ml); } + void miter_limit_theta(double t) { base_type::generator().miter_limit_theta(t); } + void inner_miter_limit(double ml) { base_type::generator().inner_miter_limit(ml); } + void approximation_scale(double as) { base_type::generator().approximation_scale(as); } + + double width() const { return base_type::generator().width(); } + double miter_limit() const { return base_type::generator().miter_limit(); } + double inner_miter_limit() const { return base_type::generator().inner_miter_limit(); } + double approximation_scale() const { return base_type::generator().approximation_scale(); } + + void shorten(double s) { base_type::generator().shorten(s); } + double shorten() const { return base_type::generator().shorten(); } + + private: + conv_stroke(const conv_stroke&); + const conv_stroke& + operator = (const conv_stroke&); + + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_transform.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_transform.h new file mode 100644 index 00000000000..0c88a245bda --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_transform.h @@ -0,0 +1,68 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class conv_transform +// +//---------------------------------------------------------------------------- +#ifndef AGG_CONV_TRANSFORM_INCLUDED +#define AGG_CONV_TRANSFORM_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //----------------------------------------------------------conv_transform + template class conv_transform + { + public: + conv_transform(VertexSource& source, Transformer& tr) : + m_source(&source), m_trans(&tr) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_vertex(cmd)) + { + m_trans->transform(x, y); + } + return cmd; + } + + void transformer(Transformer& tr) + { + m_trans = &tr; + } + + private: + conv_transform(const conv_transform&); + const conv_transform& + operator = (const conv_transform&); + + VertexSource* m_source; + Transformer* m_trans; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_unclose_polygon.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_unclose_polygon.h new file mode 100644 index 00000000000..fe5c263810e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_conv_unclose_polygon.h @@ -0,0 +1,52 @@ +//---------------------------------------------------------------------------- +// 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_CONV_UNCLOSE_POLYGON_INCLUDED +#define AGG_CONV_UNCLOSE_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //====================================================conv_unclose_polygon + template class conv_unclose_polygon + { + public: + explicit conv_unclose_polygon(VertexSource& vs) : m_source(&vs) {} + void attach(VertexSource& source) { m_source = &source; } + + void rewind(unsigned path_id) + { + m_source->rewind(path_id); + } + + unsigned vertex(double* x, double* y) + { + unsigned cmd = m_source->vertex(x, y); + if(is_end_poly(cmd)) cmd &= ~path_flags_close; + return cmd; + } + + private: + conv_unclose_polygon(const conv_unclose_polygon&); + const conv_unclose_polygon& + operator = (const conv_unclose_polygon&); + + VertexSource* m_source; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_curves.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_curves.h new file mode 100644 index 00000000000..1ef02e87834 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_curves.h @@ -0,0 +1,693 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) +// Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.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_CURVES_INCLUDED +#define AGG_CURVES_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + // See Implementation agg_curves.cpp + + //--------------------------------------------curve_approximation_method_e + enum curve_approximation_method_e + { + curve_inc, + curve_div + }; + + //--------------------------------------------------------------curve3_inc + class curve3_inc + { + public: + curve3_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve3_inc(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + }; + + + + + + //-------------------------------------------------------------curve3_div + class curve3_div + { + public: + curve3_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + {} + + curve3_div(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3); + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_div; } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3); + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + unsigned m_count; + pod_bvector m_points; + }; + + + + + + + + //-------------------------------------------------------------curve4_points + struct curve4_points + { + double cp[8]; + curve4_points() {} + curve4_points(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2; + cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4; + } + double operator [] (unsigned i) const { return cp[i]; } + double& operator [] (unsigned i) { return cp[i]; } + }; + + + + //-------------------------------------------------------------curve4_inc + class curve4_inc + { + public: + curve4_inc() : + m_num_steps(0), m_step(0), m_scale(1.0) { } + + curve4_inc(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_inc(const curve4_points& cp) : + m_num_steps(0), m_step(0), m_scale(1.0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_num_steps = 0; m_step = -1; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + curve_approximation_method_e approximation_method() const { return curve_inc; } + + void approximation_scale(double s); + double approximation_scale() const; + + void angle_tolerance(double) {} + double angle_tolerance() const { return 0.0; } + + void cusp_limit(double) {} + double cusp_limit() const { return 0.0; } + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + int m_num_steps; + int m_step; + double m_scale; + double m_start_x; + double m_start_y; + double m_end_x; + double m_end_y; + double m_fx; + double m_fy; + double m_dfx; + double m_dfy; + double m_ddfx; + double m_ddfy; + double m_dddfx; + double m_dddfy; + double m_saved_fx; + double m_saved_fy; + double m_saved_dfx; + double m_saved_dfy; + double m_saved_ddfx; + double m_saved_ddfy; + }; + + + + //-------------------------------------------------------catrom_to_bezier + inline curve4_points catrom_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Catmull-Rom to Bezier + // + // 0 1 0 0 + // -1/6 1 1/6 0 + // 0 1/6 1 -1/6 + // 0 0 1 0 + // + return curve4_points( + x2, + y2, + (-x1 + 6*x2 + x3) / 6, + (-y1 + 6*y2 + y3) / 6, + ( x2 + 6*x3 - x4) / 6, + ( y2 + 6*y3 - y4) / 6, + x3, + y3); + } + + + //----------------------------------------------------------------------- + inline curve4_points + catrom_to_bezier(const curve4_points& cp) + { + return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + //-----------------------------------------------------ubspline_to_bezier + inline curve4_points ubspline_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Uniform BSpline to Bezier + // + // 1/6 4/6 1/6 0 + // 0 4/6 2/6 0 + // 0 2/6 4/6 0 + // 0 1/6 4/6 1/6 + // + return curve4_points( + (x1 + 4*x2 + x3) / 6, + (y1 + 4*y2 + y3) / 6, + (4*x2 + 2*x3) / 6, + (4*y2 + 2*y3) / 6, + (2*x2 + 4*x3) / 6, + (2*y2 + 4*y3) / 6, + (x2 + 4*x3 + x4) / 6, + (y2 + 4*y3 + y4) / 6); + } + + + //----------------------------------------------------------------------- + inline curve4_points + ubspline_to_bezier(const curve4_points& cp) + { + return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + + + //------------------------------------------------------hermite_to_bezier + inline curve4_points hermite_to_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + // Trans. matrix Hermite to Bezier + // + // 1 0 0 0 + // 1 0 1/3 0 + // 0 1 0 -1/3 + // 0 1 0 0 + // + return curve4_points( + x1, + y1, + (3*x1 + x3) / 3, + (3*y1 + y3) / 3, + (3*x2 - x4) / 3, + (3*y2 - y4) / 3, + x2, + y2); + } + + + + //----------------------------------------------------------------------- + inline curve4_points + hermite_to_bezier(const curve4_points& cp) + { + return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3], + cp[4], cp[5], cp[6], cp[7]); + } + + + //-------------------------------------------------------------curve4_div + class curve4_div + { + public: + curve4_div() : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + {} + + curve4_div(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_cusp_limit(0.0), + m_count(0) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4_div(const curve4_points& cp) : + m_approximation_scale(1.0), + m_angle_tolerance(0.0), + m_count(0) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() { m_points.remove_all(); m_count = 0; } + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e) {} + + curve_approximation_method_e approximation_method() const + { + return curve_div; + } + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + void angle_tolerance(double a) { m_angle_tolerance = a; } + double angle_tolerance() const { return m_angle_tolerance; } + + void cusp_limit(double v) + { + m_cusp_limit = (v == 0.0) ? 0.0 : pi - v; + } + + double cusp_limit() const + { + return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit; + } + + void rewind(unsigned) + { + m_count = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_count >= m_points.size()) return path_cmd_stop; + const point_d& p = m_points[m_count++]; + *x = p.x; + *y = p.y; + return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + void bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + + void recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level); + + double m_approximation_scale; + double m_distance_tolerance_square; + double m_angle_tolerance; + double m_cusp_limit; + unsigned m_count; + pod_bvector m_points; + }; + + + //-----------------------------------------------------------------curve3 + class curve3 + { + public: + curve3() : m_approximation_method(curve_div) {} + curve3(double x1, double y1, + double x2, double y2, + double x3, double y3) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3); + } + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + + double approximation_scale() const + { + return m_curve_inc.approximation_scale(); + } + + void angle_tolerance(double a) + { + m_curve_div.angle_tolerance(a); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve3_inc m_curve_inc; + curve3_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + + + //-----------------------------------------------------------------curve4 + class curve4 + { + public: + curve4() : m_approximation_method(curve_div) {} + curve4(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) : + m_approximation_method(curve_div) + { + init(x1, y1, x2, y2, x3, y3, x4, y4); + } + + curve4(const curve4_points& cp) : + m_approximation_method(curve_div) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void reset() + { + m_curve_inc.reset(); + m_curve_div.reset(); + } + + void init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + else + { + m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4); + } + } + + void init(const curve4_points& cp) + { + init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); + } + + void approximation_method(curve_approximation_method_e v) + { + m_approximation_method = v; + } + + curve_approximation_method_e approximation_method() const + { + return m_approximation_method; + } + + void approximation_scale(double s) + { + m_curve_inc.approximation_scale(s); + m_curve_div.approximation_scale(s); + } + double approximation_scale() const { return m_curve_inc.approximation_scale(); } + + void angle_tolerance(double v) + { + m_curve_div.angle_tolerance(v); + } + + double angle_tolerance() const + { + return m_curve_div.angle_tolerance(); + } + + void cusp_limit(double v) + { + m_curve_div.cusp_limit(v); + } + + double cusp_limit() const + { + return m_curve_div.cusp_limit(); + } + + void rewind(unsigned path_id) + { + if(m_approximation_method == curve_inc) + { + m_curve_inc.rewind(path_id); + } + else + { + m_curve_div.rewind(path_id); + } + } + + unsigned vertex(double* x, double* y) + { + if(m_approximation_method == curve_inc) + { + return m_curve_inc.vertex(x, y); + } + return m_curve_div.vertex(x, y); + } + + private: + curve4_inc m_curve_inc; + curve4_div m_curve_div; + curve_approximation_method_e m_approximation_method; + }; + + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_dda_line.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_dda_line.h new file mode 100644 index 00000000000..f589e76b83d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_dda_line.h @@ -0,0 +1,290 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes dda_line_interpolator, dda2_line_interpolator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_DDA_LINE_INCLUDED +#define AGG_DDA_LINE_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //===================================================dda_line_interpolator + template class dda_line_interpolator + { + public: + //-------------------------------------------------------------------- + dda_line_interpolator() {} + + //-------------------------------------------------------------------- + dda_line_interpolator(int y1, int y2, unsigned count) : + m_y(y1), + m_inc(((y2 - y1) << FractionShift) / int(count)), + m_dy(0) + { + } + + //-------------------------------------------------------------------- + void operator ++ () + { + m_dy += m_inc; + } + + //-------------------------------------------------------------------- + void operator -- () + { + m_dy -= m_inc; + } + + //-------------------------------------------------------------------- + void operator += (unsigned n) + { + m_dy += m_inc * n; + } + + //-------------------------------------------------------------------- + void operator -= (unsigned n) + { + m_dy -= m_inc * n; + } + + + //-------------------------------------------------------------------- + int y() const { return m_y + (m_dy >> (FractionShift-YShift)); } + int dy() const { return m_dy; } + + + private: + int m_y; + int m_inc; + int m_dy; + }; + + + + + + //=================================================dda2_line_interpolator + class dda2_line_interpolator + { + public: + typedef int save_data_type; + enum save_size_e { save_size = 2 }; + + //-------------------------------------------------------------------- + dda2_line_interpolator() {} + + //-------------------------------------------- Forward-adjusted line + dda2_line_interpolator(int y1, int y2, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + m_mod -= count; + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int y1, int y2, int count, int) : + m_cnt(count <= 0 ? 1 : count), + m_lft((y2 - y1) / m_cnt), + m_rem((y2 - y1) % m_cnt), + m_mod(m_rem), + m_y(y1) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + //-------------------------------------------- Backward-adjusted line + dda2_line_interpolator(int y, int count) : + m_cnt(count <= 0 ? 1 : count), + m_lft(y / m_cnt), + m_rem(y % m_cnt), + m_mod(m_rem), + m_y(0) + { + if(m_mod <= 0) + { + m_mod += count; + m_rem += count; + m_lft--; + } + } + + + //-------------------------------------------------------------------- + void save(save_data_type* data) const + { + data[0] = m_mod; + data[1] = m_y; + } + + //-------------------------------------------------------------------- + void load(const save_data_type* data) + { + m_mod = data[0]; + m_y = data[1]; + } + + //-------------------------------------------------------------------- + void operator++() + { + m_mod += m_rem; + m_y += m_lft; + if(m_mod > 0) + { + m_mod -= m_cnt; + m_y++; + } + } + + //-------------------------------------------------------------------- + void operator--() + { + if(m_mod <= m_rem) + { + m_mod += m_cnt; + m_y--; + } + m_mod -= m_rem; + m_y -= m_lft; + } + + //-------------------------------------------------------------------- + void adjust_forward() + { + m_mod -= m_cnt; + } + + //-------------------------------------------------------------------- + void adjust_backward() + { + m_mod += m_cnt; + } + + //-------------------------------------------------------------------- + int mod() const { return m_mod; } + int rem() const { return m_rem; } + int lft() const { return m_lft; } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + + private: + int m_cnt; + int m_lft; + int m_rem; + int m_mod; + int m_y; + }; + + + + + + + + //---------------------------------------------line_bresenham_interpolator + class line_bresenham_interpolator + { + public: + enum subpixel_scale_e + { + subpixel_shift = 8, + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 + }; + + //-------------------------------------------------------------------- + static int line_lr(int v) { return v >> subpixel_shift; } + + //-------------------------------------------------------------------- + line_bresenham_interpolator(int x1, int y1, int x2, int y2) : + m_x1_lr(line_lr(x1)), + m_y1_lr(line_lr(y1)), + m_x2_lr(line_lr(x2)), + m_y2_lr(line_lr(y2)), + m_ver(abs(m_x2_lr - m_x1_lr) < abs(m_y2_lr - m_y1_lr)), + m_len(m_ver ? abs(m_y2_lr - m_y1_lr) : + abs(m_x2_lr - m_x1_lr)), + m_inc(m_ver ? ((y2 > y1) ? 1 : -1) : ((x2 > x1) ? 1 : -1)), + m_interpolator(m_ver ? x1 : y1, + m_ver ? x2 : y2, + m_len) + { + } + + //-------------------------------------------------------------------- + bool is_ver() const { return m_ver; } + unsigned len() const { return m_len; } + int inc() const { return m_inc; } + + //-------------------------------------------------------------------- + void hstep() + { + ++m_interpolator; + m_x1_lr += m_inc; + } + + //-------------------------------------------------------------------- + void vstep() + { + ++m_interpolator; + m_y1_lr += m_inc; + } + + //-------------------------------------------------------------------- + int x1() const { return m_x1_lr; } + int y1() const { return m_y1_lr; } + int x2() const { return line_lr(m_interpolator.y()); } + int y2() const { return line_lr(m_interpolator.y()); } + int x2_hr() const { return m_interpolator.y(); } + int y2_hr() const { return m_interpolator.y(); } + + private: + int m_x1_lr; + int m_y1_lr; + int m_x2_lr; + int m_y2_lr; + bool m_ver; + unsigned m_len; + int m_inc; + dda2_line_interpolator m_interpolator; + + }; + + +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse.h new file mode 100644 index 00000000000..e78ce27dd94 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class ellipse +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_INCLUDED +#define AGG_ELLIPSE_INCLUDED + +#include "agg_basics.h" +#include + +namespace agg +{ + + //----------------------------------------------------------------ellipse + class ellipse + { + public: + ellipse() : + m_x(0.0), m_y(0.0), m_rx(1.0), m_ry(1.0), m_scale(1.0), + m_num(4), m_step(0), m_cw(false) {} + + ellipse(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false) : + m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0), + m_num(num_steps), m_step(0), m_cw(cw) + { + if(m_num == 0) calc_num_steps(); + } + + void init(double x, double y, double rx, double ry, + unsigned num_steps=0, bool cw=false); + + void approximation_scale(double scale); + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_num_steps(); + + double m_x; + double m_y; + double m_rx; + double m_ry; + double m_scale; + unsigned m_num; + unsigned m_step; + bool m_cw; + }; + + //------------------------------------------------------------------------ + inline void ellipse::init(double x, double y, double rx, double ry, + unsigned num_steps, bool cw) + { + m_x = x; + m_y = y; + m_rx = rx; + m_ry = ry; + m_num = num_steps; + m_step = 0; + m_cw = cw; + if(m_num == 0) calc_num_steps(); + } + + //------------------------------------------------------------------------ + inline void ellipse::approximation_scale(double scale) + { + m_scale = scale; + calc_num_steps(); + } + + //------------------------------------------------------------------------ + inline void ellipse::calc_num_steps() + { + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + double da = acos(ra / (ra + 0.125 / m_scale)) * 2; + m_num = uround(2*pi / da); + } + + //------------------------------------------------------------------------ + inline void ellipse::rewind(unsigned) + { + m_step = 0; + } + + //------------------------------------------------------------------------ + inline unsigned ellipse::vertex(double* x, double* y) + { + if(m_step == m_num) + { + ++m_step; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + } + if(m_step > m_num) return path_cmd_stop; + double angle = double(m_step) / double(m_num) * 2.0 * pi; + if(m_cw) angle = 2.0 * pi - angle; + *x = m_x + cos(angle) * m_rx; + *y = m_y + sin(angle) * m_ry; + m_step++; + return ((m_step == 1) ? path_cmd_move_to : path_cmd_line_to); + } + +} + + + +#endif + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse_bresenham.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse_bresenham.h new file mode 100644 index 00000000000..ee3b9c4638f --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_ellipse_bresenham.h @@ -0,0 +1,113 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Simple Bresenham interpolator for ellipsees +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ELLIPSE_BRESENHAM_INCLUDED +#define AGG_ELLIPSE_BRESENHAM_INCLUDED + + +#include "agg_basics.h" + + +namespace agg +{ + + //------------------------------------------ellipse_bresenham_interpolator + class ellipse_bresenham_interpolator + { + public: + ellipse_bresenham_interpolator(int rx, int ry) : + m_rx2(rx * rx), + m_ry2(ry * ry), + m_two_rx2(m_rx2 << 1), + m_two_ry2(m_ry2 << 1), + m_dx(0), + m_dy(0), + m_inc_x(0), + m_inc_y(-ry * m_two_rx2), + m_cur_f(0) + {} + + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + void operator++ () + { + int mx, my, mxy, min_m; + int fx, fy, fxy; + + mx = fx = m_cur_f + m_inc_x + m_ry2; + if(mx < 0) mx = -mx; + + my = fy = m_cur_f + m_inc_y + m_rx2; + if(my < 0) my = -my; + + mxy = fxy = m_cur_f + m_inc_x + m_ry2 + m_inc_y + m_rx2; + if(mxy < 0) mxy = -mxy; + + min_m = mx; + bool flag = true; + + if(min_m > my) + { + min_m = my; + flag = false; + } + + m_dx = m_dy = 0; + + if(min_m > mxy) + { + m_inc_x += m_two_ry2; + m_inc_y += m_two_rx2; + m_cur_f = fxy; + m_dx = 1; + m_dy = 1; + return; + } + + if(flag) + { + m_inc_x += m_two_ry2; + m_cur_f = fx; + m_dx = 1; + return; + } + + m_inc_y += m_two_rx2; + m_cur_f = fy; + m_dy = 1; + } + + private: + int m_rx2; + int m_ry2; + int m_two_rx2; + int m_two_ry2; + int m_dx; + int m_dy; + int m_inc_x; + int m_inc_y; + int m_cur_f; + + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_embedded_raster_fonts.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_embedded_raster_fonts.h new file mode 100644 index 00000000000..9d522d671c7 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_embedded_raster_fonts.h @@ -0,0 +1,59 @@ +//---------------------------------------------------------------------------- +// 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_EMBEDDED_RASTER_FONTS_INCLUDED +#define AGG_EMBEDDED_RASTER_FONTS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + extern const int8u gse4x6[]; + extern const int8u gse4x8[]; + extern const int8u gse5x7[]; + extern const int8u gse5x9[]; + extern const int8u gse6x12[]; + extern const int8u gse6x9[]; + extern const int8u gse7x11[]; + extern const int8u gse7x11_bold[]; + extern const int8u gse7x15[]; + extern const int8u gse7x15_bold[]; + extern const int8u gse8x16[]; + extern const int8u gse8x16_bold[]; + extern const int8u mcs11_prop[]; + extern const int8u mcs11_prop_condensed[]; + extern const int8u mcs12_prop[]; + extern const int8u mcs13_prop[]; + extern const int8u mcs5x10_mono[]; + extern const int8u mcs5x11_mono[]; + extern const int8u mcs6x10_mono[]; + extern const int8u mcs6x11_mono[]; + extern const int8u mcs7x12_mono_high[]; + extern const int8u mcs7x12_mono_low[]; + extern const int8u verdana12[]; + extern const int8u verdana12_bold[]; + extern const int8u verdana13[]; + extern const int8u verdana13_bold[]; + extern const int8u verdana14[]; + extern const int8u verdana14_bold[]; + extern const int8u verdana16[]; + extern const int8u verdana16_bold[]; + extern const int8u verdana17[]; + extern const int8u verdana17_bold[]; + extern const int8u verdana18[]; + extern const int8u verdana18_bold[]; +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager.h new file mode 100644 index 00000000000..fe9a9280faa --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager.h @@ -0,0 +1,409 @@ +//---------------------------------------------------------------------------- +// 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_FONT_CACHE_MANAGER_INCLUDED +#define AGG_FONT_CACHE_MANAGER_INCLUDED + +#include +#include "agg_array.h" + +namespace agg +{ + + //---------------------------------------------------------glyph_data_type + enum glyph_data_type + { + glyph_data_invalid = 0, + glyph_data_mono = 1, + glyph_data_gray8 = 2, + glyph_data_outline = 3 + }; + + + //-------------------------------------------------------------glyph_cache + struct glyph_cache + { + unsigned glyph_index; + int8u* data; + unsigned data_size; + glyph_data_type data_type; + rect_i bounds; + double advance_x; + double advance_y; + }; + + + //--------------------------------------------------------------font_cache + class font_cache + { + public: + enum block_size_e { block_size = 16384-16 }; + + //-------------------------------------------------------------------- + font_cache() : + m_allocator(block_size), + m_font_signature(0) + {} + + //-------------------------------------------------------------------- + void signature(const char* font_signature) + { + m_font_signature = (char*)m_allocator.allocate(strlen(font_signature) + 1); + strcpy(m_font_signature, font_signature); + memset(m_glyphs, 0, sizeof(m_glyphs)); + } + + //-------------------------------------------------------------------- + bool font_is(const char* font_signature) const + { + return strcmp(font_signature, m_font_signature) == 0; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb]) + { + return m_glyphs[msb][glyph_code & 0xFF]; + } + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect_i& bounds, + double advance_x, + double advance_y) + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb] == 0) + { + m_glyphs[msb] = + (glyph_cache**)m_allocator.allocate(sizeof(glyph_cache*) * 256, + sizeof(glyph_cache*)); + memset(m_glyphs[msb], 0, sizeof(glyph_cache*) * 256); + } + + unsigned lsb = glyph_code & 0xFF; + if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite + + glyph_cache* glyph = + (glyph_cache*)m_allocator.allocate(sizeof(glyph_cache), + sizeof(double)); + + glyph->glyph_index = glyph_index; + glyph->data = m_allocator.allocate(data_size); + glyph->data_size = data_size; + glyph->data_type = data_type; + glyph->bounds = bounds; + glyph->advance_x = advance_x; + glyph->advance_y = advance_y; + return m_glyphs[msb][lsb] = glyph; + } + + private: + block_allocator m_allocator; + glyph_cache** m_glyphs[256]; + char* m_font_signature; + }; + + + + + + + + //---------------------------------------------------------font_cache_pool + class font_cache_pool + { + public: + //-------------------------------------------------------------------- + ~font_cache_pool() + { + unsigned i; + for(i = 0; i < m_num_fonts; ++i) + { + obj_allocator::deallocate(m_fonts[i]); + } + pod_allocator::deallocate(m_fonts, m_max_fonts); + } + + //-------------------------------------------------------------------- + font_cache_pool(unsigned max_fonts=32) : + m_fonts(pod_allocator::allocate(max_fonts)), + m_max_fonts(max_fonts), + m_num_fonts(0), + m_cur_font(0) + {} + + + //-------------------------------------------------------------------- + void font(const char* font_signature, bool reset_cache = false) + { + int idx = find_font(font_signature); + if(idx >= 0) + { + if(reset_cache) + { + obj_allocator::deallocate(m_fonts[idx]); + m_fonts[idx] = obj_allocator::allocate(); + m_fonts[idx]->signature(font_signature); + } + m_cur_font = m_fonts[idx]; + } + else + { + if(m_num_fonts >= m_max_fonts) + { + obj_allocator::deallocate(m_fonts[0]); + memcpy(m_fonts, + m_fonts + 1, + (m_max_fonts - 1) * sizeof(font_cache*)); + m_num_fonts = m_max_fonts - 1; + } + m_fonts[m_num_fonts] = obj_allocator::allocate(); + m_fonts[m_num_fonts]->signature(font_signature); + m_cur_font = m_fonts[m_num_fonts]; + ++m_num_fonts; + } + } + + //-------------------------------------------------------------------- + const font_cache* font() const + { + return m_cur_font; + } + + //-------------------------------------------------------------------- + const glyph_cache* find_glyph(unsigned glyph_code) const + { + if(m_cur_font) return m_cur_font->find_glyph(glyph_code); + return 0; + } + + //-------------------------------------------------------------------- + glyph_cache* cache_glyph(unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect_i& bounds, + double advance_x, + double advance_y) + { + if(m_cur_font) + { + return m_cur_font->cache_glyph(glyph_code, + glyph_index, + data_size, + data_type, + bounds, + advance_x, + advance_y); + } + return 0; + } + + + //-------------------------------------------------------------------- + int find_font(const char* font_signature) + { + unsigned i; + for(i = 0; i < m_num_fonts; i++) + { + if(m_fonts[i]->font_is(font_signature)) return int(i); + } + return -1; + } + + private: + font_cache** m_fonts; + unsigned m_max_fonts; + unsigned m_num_fonts; + font_cache* m_cur_font; + }; + + + + + //------------------------------------------------------------------------ + enum glyph_rendering + { + glyph_ren_native_mono, + glyph_ren_native_gray8, + glyph_ren_outline, + glyph_ren_agg_mono, + glyph_ren_agg_gray8 + }; + + + + + //------------------------------------------------------font_cache_manager + template class font_cache_manager + { + public: + typedef FontEngine font_engine_type; + typedef font_cache_manager self_type; + typedef typename font_engine_type::path_adaptor_type path_adaptor_type; + typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; + typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; + typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; + typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; + + //-------------------------------------------------------------------- + font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) : + m_fonts(max_fonts), + m_engine(engine), + m_change_stamp(-1), + m_prev_glyph(0), + m_last_glyph(0) + {} + + //-------------------------------------------------------------------- + void reset_last_glyph() + { + m_prev_glyph = m_last_glyph = 0; + } + + //-------------------------------------------------------------------- + const glyph_cache* glyph(unsigned glyph_code) + { + synchronize(); + const glyph_cache* gl = m_fonts.find_glyph(glyph_code); + if(gl) + { + m_prev_glyph = m_last_glyph; + return m_last_glyph = gl; + } + else + { + if(m_engine.prepare_glyph(glyph_code)) + { + m_prev_glyph = m_last_glyph; + m_last_glyph = m_fonts.cache_glyph(glyph_code, + m_engine.glyph_index(), + m_engine.data_size(), + m_engine.data_type(), + m_engine.bounds(), + m_engine.advance_x(), + m_engine.advance_y()); + m_engine.write_glyph_to(m_last_glyph->data); + return m_last_glyph; + } + } + return 0; + } + + //-------------------------------------------------------------------- + void init_embedded_adaptors(const glyph_cache* gl, + double x, double y, + double scale=1.0) + { + if(gl) + { + switch(gl->data_type) + { + default: return; + case glyph_data_mono: + m_mono_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_gray8: + m_gray8_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_outline: + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); + break; + } + } + } + + + //-------------------------------------------------------------------- + path_adaptor_type& path_adaptor() { return m_path_adaptor; } + gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } + gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } + mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } + mono_scanline_type& mono_scanline() { return m_mono_scanline; } + + //-------------------------------------------------------------------- + const glyph_cache* perv_glyph() const { return m_prev_glyph; } + const glyph_cache* last_glyph() const { return m_last_glyph; } + + //-------------------------------------------------------------------- + bool add_kerning(double* x, double* y) + { + if(m_prev_glyph && m_last_glyph) + { + return m_engine.add_kerning(m_prev_glyph->glyph_index, + m_last_glyph->glyph_index, + x, y); + } + return false; + } + + //-------------------------------------------------------------------- + void precache(unsigned from, unsigned to) + { + for(; from <= to; ++from) glyph(from); + } + + //-------------------------------------------------------------------- + void reset_cache() + { + m_fonts.font(m_engine.font_signature(), true); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); + const self_type& operator = (const self_type&); + + //-------------------------------------------------------------------- + void synchronize() + { + if(m_change_stamp != m_engine.change_stamp()) + { + m_fonts.font(m_engine.font_signature()); + m_change_stamp = m_engine.change_stamp(); + m_prev_glyph = m_last_glyph = 0; + } + } + + font_cache_pool m_fonts; + font_engine_type& m_engine; + int m_change_stamp; + double m_dx; + double m_dy; + const glyph_cache* m_prev_glyph; + const glyph_cache* m_last_glyph; + path_adaptor_type m_path_adaptor; + gray8_adaptor_type m_gray8_adaptor; + gray8_scanline_type m_gray8_scanline; + mono_adaptor_type m_mono_adaptor; + mono_scanline_type m_mono_scanline; + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager2.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager2.h new file mode 100644 index 00000000000..75d311eff79 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_font_cache_manager2.h @@ -0,0 +1,311 @@ +//---------------------------------------------------------------------------- +// 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_FONT_CACHE_MANAGER2_INCLUDED +#define AGG_FONT_CACHE_MANAGER2_INCLUDED + +#include +#include +#include +#include "agg_array.h" + +namespace agg { + +namespace fman { + //---------------------------------------------------------glyph_data_type + enum glyph_data_type + { + glyph_data_invalid = 0, + glyph_data_mono = 1, + glyph_data_gray8 = 2, + glyph_data_outline = 3 + }; + + + //-------------------------------------------------------------cached_glyph + struct cached_glyph + { + void * cached_font; + unsigned glyph_code; + unsigned glyph_index; + int8u* data; + unsigned data_size; + glyph_data_type data_type; + rect_i bounds; + double advance_x; + double advance_y; + }; + + + //--------------------------------------------------------------cached_glyphs + class cached_glyphs + { + public: + enum block_size_e { block_size = 16384-16 }; + + //-------------------------------------------------------------------- + cached_glyphs() + : m_allocator(block_size) + { memset(m_glyphs, 0, sizeof(m_glyphs)); } + + //-------------------------------------------------------------------- + const cached_glyph* find_glyph(unsigned glyph_code) const + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb]) + { + return m_glyphs[msb][glyph_code & 0xFF]; + } + return 0; + } + + //-------------------------------------------------------------------- + cached_glyph* cache_glyph( + void * cached_font, + unsigned glyph_code, + unsigned glyph_index, + unsigned data_size, + glyph_data_type data_type, + const rect_i& bounds, + double advance_x, + double advance_y) + { + unsigned msb = (glyph_code >> 8) & 0xFF; + if(m_glyphs[msb] == 0) + { + m_glyphs[msb] = + (cached_glyph**)m_allocator.allocate(sizeof(cached_glyph*) * 256, + sizeof(cached_glyph*)); + memset(m_glyphs[msb], 0, sizeof(cached_glyph*) * 256); + } + + unsigned lsb = glyph_code & 0xFF; + if(m_glyphs[msb][lsb]) return 0; // Already exists, do not overwrite + + cached_glyph* glyph = + (cached_glyph*)m_allocator.allocate(sizeof(cached_glyph), + sizeof(double)); + + glyph->cached_font = cached_font; + glyph->glyph_code = glyph_code; + glyph->glyph_index = glyph_index; + glyph->data = m_allocator.allocate(data_size); + glyph->data_size = data_size; + glyph->data_type = data_type; + glyph->bounds = bounds; + glyph->advance_x = advance_x; + glyph->advance_y = advance_y; + return m_glyphs[msb][lsb] = glyph; + } + + private: + block_allocator m_allocator; + cached_glyph** m_glyphs[256]; + }; + + + + //------------------------------------------------------------------------ + enum glyph_rendering + { + glyph_ren_native_mono, + glyph_ren_native_gray8, + glyph_ren_outline, + glyph_ren_agg_mono, + glyph_ren_agg_gray8 + }; + + + + + //------------------------------------------------------font_cache_manager + template class font_cache_manager + { + public: + typedef FontEngine font_engine_type; + typedef font_cache_manager self_type; + typedef typename font_engine_type::path_adaptor_type path_adaptor_type; + typedef typename font_engine_type::gray8_adaptor_type gray8_adaptor_type; + typedef typename gray8_adaptor_type::embedded_scanline gray8_scanline_type; + typedef typename font_engine_type::mono_adaptor_type mono_adaptor_type; + typedef typename mono_adaptor_type::embedded_scanline mono_scanline_type; + + struct cached_font + { + cached_font( + font_engine_type& engine, + typename FontEngine::loaded_face *face, + double height, + double width, + bool hinting, + glyph_rendering rendering ) + : m_engine( engine ) + , m_face( face ) + , m_height( height ) + , m_width( width ) + , m_hinting( hinting ) + , m_rendering( rendering ) + { + select_face(); + m_face_height=m_face->height(); + m_face_width=m_face->width(); + m_face_ascent=m_face->ascent(); + m_face_descent=m_face->descent(); + m_face_ascent_b=m_face->ascent_b(); + m_face_descent_b=m_face->descent_b(); + } + + double height() const + { + return m_face_height; + } + + double width() const + { + return m_face_width; + } + + double ascent() const + { + return m_face_ascent; + } + + double descent() const + { + return m_face_descent; + } + + double ascent_b() const + { + return m_face_ascent_b; + } + + double descent_b() const + { + return m_face_descent_b; + } + + bool add_kerning( const cached_glyph *first, const cached_glyph *second, double* x, double* y) + { + if( !first || !second ) + return false; + select_face(); + return m_face->add_kerning( + first->glyph_index, second->glyph_index, x, y ); + } + + void select_face() + { + m_face->select_instance( m_height, m_width, m_hinting, m_rendering ); + } + + const cached_glyph *get_glyph(unsigned cp) + { + const cached_glyph *glyph=m_glyphs.find_glyph(cp); + if( glyph==0 ) + { + typename FontEngine::prepared_glyph prepared; + select_face(); + bool success=m_face->prepare_glyph(cp, &prepared); + if( success ) + { + glyph=m_glyphs.cache_glyph( + this, + prepared.glyph_code, + prepared.glyph_index, + prepared.data_size, + prepared.data_type, + prepared.bounds, + prepared.advance_x, + prepared.advance_y ); + assert( glyph!=0 ); + m_face->write_glyph_to(&prepared,glyph->data); + } + } + return glyph; + } + + font_engine_type& m_engine; + typename FontEngine::loaded_face *m_face; + double m_height; + double m_width; + bool m_hinting; + glyph_rendering m_rendering; + double m_face_height; + double m_face_width; + double m_face_ascent; + double m_face_descent; + double m_face_ascent_b; + double m_face_descent_b; + cached_glyphs m_glyphs; + }; + + //-------------------------------------------------------------------- + font_cache_manager(font_engine_type& engine, unsigned max_fonts=32) + :m_engine(engine) + { } + + //-------------------------------------------------------------------- + void init_embedded_adaptors(const cached_glyph* gl, + double x, double y, + double scale=1.0) + { + if(gl) + { + switch(gl->data_type) + { + default: return; + case glyph_data_mono: + m_mono_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_gray8: + m_gray8_adaptor.init(gl->data, gl->data_size, x, y); + break; + + case glyph_data_outline: + m_path_adaptor.init(gl->data, gl->data_size, x, y, scale); + break; + } + } + } + + + //-------------------------------------------------------------------- + path_adaptor_type& path_adaptor() { return m_path_adaptor; } + gray8_adaptor_type& gray8_adaptor() { return m_gray8_adaptor; } + gray8_scanline_type& gray8_scanline() { return m_gray8_scanline; } + mono_adaptor_type& mono_adaptor() { return m_mono_adaptor; } + mono_scanline_type& mono_scanline() { return m_mono_scanline; } + + + private: + //-------------------------------------------------------------------- + font_cache_manager(const self_type&); + const self_type& operator = (const self_type&); + + font_engine_type& m_engine; + path_adaptor_type m_path_adaptor; + gray8_adaptor_type m_gray8_adaptor; + gray8_scanline_type m_gray8_scanline; + mono_adaptor_type m_mono_adaptor; + mono_scanline_type m_mono_scanline; + }; + +} +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_functions.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_functions.h new file mode 100644 index 00000000000..5d720daa9a7 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_functions.h @@ -0,0 +1,132 @@ +//---------------------------------------------------------------------------- +// 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_GAMMA_FUNCTIONS_INCLUDED +#define AGG_GAMMA_FUNCTIONS_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + //===============================================================gamma_none + struct gamma_none + { + double operator()(double x) const { return x; } + }; + + + //==============================================================gamma_power + class gamma_power + { + public: + gamma_power() : m_gamma(1.0) {} + gamma_power(double g) : m_gamma(g) {} + + void gamma(double g) { m_gamma = g; } + double gamma() const { return m_gamma; } + + double operator() (double x) const + { + return pow(x, m_gamma); + } + + private: + double m_gamma; + }; + + + //==========================================================gamma_threshold + class gamma_threshold + { + public: + gamma_threshold() : m_threshold(0.5) {} + gamma_threshold(double t) : m_threshold(t) {} + + void threshold(double t) { m_threshold = t; } + double threshold() const { return m_threshold; } + + double operator() (double x) const + { + return (x < m_threshold) ? 0.0 : 1.0; + } + + private: + double m_threshold; + }; + + + //============================================================gamma_linear + class gamma_linear + { + public: + gamma_linear() : m_start(0.0), m_end(1.0) {} + gamma_linear(double s, double e) : m_start(s), m_end(e) {} + + void set(double s, double e) { m_start = s; m_end = e; } + void start(double s) { m_start = s; } + void end(double e) { m_end = e; } + double start() const { return m_start; } + double end() const { return m_end; } + + double operator() (double x) const + { + if(x < m_start) return 0.0; + if(x > m_end) return 1.0; + return (x - m_start) / (m_end - m_start); + } + + private: + double m_start; + double m_end; + }; + + + //==========================================================gamma_multiply + class gamma_multiply + { + public: + gamma_multiply() : m_mul(1.0) {} + gamma_multiply(double v) : m_mul(v) {} + + void value(double v) { m_mul = v; } + double value() const { return m_mul; } + + double operator() (double x) const + { + double y = x * m_mul; + if(y > 1.0) y = 1.0; + return y; + } + + private: + 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/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_lut.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_lut.h new file mode 100644 index 00000000000..ef1e38d8092 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gamma_lut.h @@ -0,0 +1,305 @@ +//---------------------------------------------------------------------------- +// 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_GAMMA_LUT_INCLUDED +#define AGG_GAMMA_LUT_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_gamma_functions.h" + +namespace agg +{ + template class gamma_lut + { + public: + typedef gamma_lut self_type; + + enum gamma_scale_e + { + gamma_shift = GammaShift, + gamma_size = 1 << gamma_shift, + gamma_mask = gamma_size - 1 + }; + + enum hi_res_scale_e + { + hi_res_shift = HiResShift, + hi_res_size = 1 << hi_res_shift, + hi_res_mask = hi_res_size - 1 + }; + + ~gamma_lut() + { + pod_allocator::deallocate(m_inv_gamma, hi_res_size); + pod_allocator::deallocate(m_dir_gamma, gamma_size); + } + + gamma_lut() : + m_gamma(1.0), + m_dir_gamma(pod_allocator::allocate(gamma_size)), + m_inv_gamma(pod_allocator::allocate(hi_res_size)) + { + unsigned i; + for(i = 0; i < gamma_size; i++) + { + m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift)); + } + + for(i = 0; i < hi_res_size; i++) + { + m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift)); + } + } + + gamma_lut(double g) : + 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) + { + m_gamma = g; + + unsigned i; + for(i = 0; i < gamma_size; i++) + { + m_dir_gamma[i] = (HiResT) + uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask)); + } + + double inv_g = 1.0 / g; + for(i = 0; i < hi_res_size; i++) + { + m_inv_gamma[i] = (LoResT) + uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask)); + } + } + + double gamma() const + { + return m_gamma; + } + + HiResT dir(LoResT v) const + { + return m_dir_gamma[unsigned(v)]; + } + + LoResT inv(HiResT v) const + { + return m_inv_gamma[unsigned(v)]; + } + + private: + gamma_lut(const self_type&); + const self_type& operator = (const self_type&); + + double m_gamma; + 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/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_glyph_raster_bin.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_glyph_raster_bin.h new file mode 100644 index 00000000000..b0bf858efd6 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_glyph_raster_bin.h @@ -0,0 +1,155 @@ +//---------------------------------------------------------------------------- +// 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_GLYPH_RASTER_BIN_INCLUDED +#define AGG_GLYPH_RASTER_BIN_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //========================================================glyph_raster_bin + template class glyph_raster_bin + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + struct glyph_rect + { + int x1,y1,x2,y2; + double dx, dy; + }; + + //-------------------------------------------------------------------- + glyph_raster_bin(const int8u* font) : + m_font(font), + m_big_endian(false) + { + int t = 1; + if(*(char*)&t == 0) m_big_endian = true; + memset(m_span, 0, sizeof(m_span)); + } + + //-------------------------------------------------------------------- + const int8u* font() const { return m_font; } + void font(const int8u* f) { m_font = f; } + + //-------------------------------------------------------------------- + double height() const { return m_font[0]; } + double base_line() const { return m_font[1]; } + + //-------------------------------------------------------------------- + template + double width(const CharT* str) const + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + unsigned w = 0; + while(*str) + { + unsigned glyph = *str; + const int8u* bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + w += *bits; + ++str; + } + return w; + } + + //-------------------------------------------------------------------- + void prepare(glyph_rect* r, double x, double y, unsigned glyph, bool flip) + { + unsigned start_char = m_font[2]; + unsigned num_chars = m_font[3]; + + m_bits = m_font + 4 + num_chars * 2 + + value(m_font + 4 + (glyph - start_char) * 2); + + m_glyph_width = *m_bits++; + m_glyph_byte_width = (m_glyph_width + 7) >> 3; + + r->x1 = int(x); + r->x2 = r->x1 + m_glyph_width - 1; + if(flip) + { + r->y1 = int(y) - m_font[0] + m_font[1]; + r->y2 = r->y1 + m_font[0] - 1; + } + else + { + r->y1 = int(y) - m_font[1] + 1; + r->y2 = r->y1 + m_font[0] - 1; + } + r->dx = m_glyph_width; + r->dy = 0; + } + + //-------------------------------------------------------------------- + const cover_type* span(unsigned i) + { + i = m_font[0] - i - 1; + const int8u* bits = m_bits + i * m_glyph_byte_width; + unsigned j; + unsigned val = *bits; + unsigned nb = 0; + for(j = 0; j < m_glyph_width; ++j) + { + m_span[j] = (cover_type)((val & 0x80) ? cover_full : cover_none); + val <<= 1; + if(++nb >= 8) + { + val = *++bits; + nb = 0; + } + } + return m_span; + } + + private: + //-------------------------------------------------------------------- + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + + //-------------------------------------------------------------------- + const int8u* m_font; + bool m_big_endian; + cover_type m_span[32]; + const int8u* m_bits; + unsigned m_glyph_width; + unsigned m_glyph_byte_width; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gradient_lut.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gradient_lut.h new file mode 100644 index 00000000000..9aaa426815e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gradient_lut.h @@ -0,0 +1,244 @@ +//---------------------------------------------------------------------------- +// 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_GRADIENT_LUT_INCLUDED +#define AGG_GRADIENT_LUT_INCLUDED + +#include "agg_array.h" +#include "agg_dda_line.h" +#include "agg_color_rgba.h" +#include "agg_color_gray.h" + +namespace agg +{ + + //======================================================color_interpolator + template struct color_interpolator + { + public: + typedef ColorT color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + m_c1(c1), + m_c2(c2), + m_len(len), + m_count(0) + {} + + void operator ++ () + { + ++m_count; + } + + color_type color() const + { + return m_c1.gradient(m_c2, double(m_count) / m_len); + } + + private: + color_type m_c1; + color_type m_c2; + unsigned m_len; + unsigned m_count; + }; + + //======================================================================== + // Fast specialization for rgba8 + template<> struct color_interpolator + { + public: + typedef rgba8 color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + r(c1.r, c2.r, len), + g(c1.g, c2.g, len), + b(c1.b, c2.b, len), + a(c1.a, c2.a, len) + {} + + void operator ++ () + { + ++r; ++g; ++b; ++a; + } + + color_type color() const + { + return color_type(r.y(), g.y(), b.y(), a.y()); + } + + private: + agg::dda_line_interpolator<14> r, g, b, a; + }; + + //======================================================================== + // Fast specialization for gray8 + template<> struct color_interpolator + { + public: + typedef gray8 color_type; + + color_interpolator(const color_type& c1, + const color_type& c2, + unsigned len) : + v(c1.v, c2.v, len), + a(c1.a, c2.a, len) + {} + + void operator ++ () + { + ++v; ++a; + } + + color_type color() const + { + return color_type(v.y(), a.y()); + } + + private: + agg::dda_line_interpolator<14> v,a; + }; + + //============================================================gradient_lut + template class gradient_lut + { + public: + typedef ColorInterpolator interpolator_type; + typedef typename interpolator_type::color_type color_type; + enum { color_lut_size = ColorLutSize }; + + //-------------------------------------------------------------------- + gradient_lut() : m_color_lut(color_lut_size) {} + + // Build Gradient Lut + // First, call remove_all(), then add_color() at least twice, + // then build_lut(). Argument "offset" in add_color must be + // in range [0...1] and defines a color stop as it is described + // in SVG specification, section Gradients and Patterns. + // The simplest linear gradient is: + // gradient_lut.add_color(0.0, start_color); + // gradient_lut.add_color(1.0, end_color); + //-------------------------------------------------------------------- + void remove_all(); + void add_color(double offset, const color_type& color); + void build_lut(); + + // Size-index Interface. This class can be used directly as the + // ColorF in span_gradient. All it needs is two access methods + // size() and operator []. + //-------------------------------------------------------------------- + static unsigned size() + { + return color_lut_size; + } + const color_type& operator [] (unsigned i) const + { + return m_color_lut[i]; + } + + private: + //-------------------------------------------------------------------- + struct color_point + { + double offset; + color_type color; + + color_point() {} + color_point(double off, const color_type& c) : + offset(off), color(c) + { + if(offset < 0.0) offset = 0.0; + if(offset > 1.0) offset = 1.0; + } + }; + typedef agg::pod_bvector color_profile_type; + typedef agg::pod_array color_lut_type; + + static bool offset_less(const color_point& a, const color_point& b) + { + return a.offset < b.offset; + } + static bool offset_equal(const color_point& a, const color_point& b) + { + return a.offset == b.offset; + } + + //-------------------------------------------------------------------- + color_profile_type m_color_profile; + color_lut_type m_color_lut; + }; + + + + //------------------------------------------------------------------------ + template + void gradient_lut::remove_all() + { + m_color_profile.remove_all(); + } + + //------------------------------------------------------------------------ + template + void gradient_lut::add_color(double offset, const color_type& color) + { + m_color_profile.add(color_point(offset, color)); + } + + //------------------------------------------------------------------------ + template + void gradient_lut::build_lut() + { + quick_sort(m_color_profile, offset_less); + m_color_profile.cut_at(remove_duplicates(m_color_profile, offset_equal)); + if(m_color_profile.size() >= 2) + { + unsigned i; + unsigned start = uround(m_color_profile[0].offset * color_lut_size); + unsigned end; + color_type c = m_color_profile[0].color; + for(i = 0; i < start; i++) + { + m_color_lut[i] = c; + } + for(i = 1; i < m_color_profile.size(); i++) + { + end = uround(m_color_profile[i].offset * color_lut_size); + interpolator_type ci(m_color_profile[i-1].color, + m_color_profile[i ].color, + end - start + 1); + while(start < end) + { + m_color_lut[start] = ci.color(); + ++ci; + ++start; + } + } + c = m_color_profile.last().color; + for(; end < m_color_lut.size(); end++) + { + m_color_lut[end] = c; + } + } + } +} + + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gsv_text.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gsv_text.h new file mode 100644 index 00000000000..16b3aeb33d8 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_gsv_text.h @@ -0,0 +1,153 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Class gsv_text +// +//---------------------------------------------------------------------------- + +#ifndef AGG_GSV_TEXT_INCLUDED +#define AGG_GSV_TEXT_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_conv_transform.h" + +namespace agg +{ + + + //---------------------------------------------------------------gsv_text + // + // See Implementation agg_gsv_text.cpp + // + class gsv_text + { + enum status + { + initial, + next_char, + start_glyph, + glyph + }; + + public: + gsv_text(); + + void font(const void* font); + void flip(bool flip_y) { m_flip = flip_y; } + void load_font(const char* file); + void size(double height, double width=0.0); + void space(double space); + void line_space(double line_space); + void start_point(double x, double y); + void text(const char* text); + + double text_width(); + + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + // not supposed to be copied + gsv_text(const gsv_text&); + const gsv_text& operator = (const gsv_text&); + + int16u value(const int8u* p) const + { + int16u v; + if(m_big_endian) + { + *(int8u*)&v = p[1]; + *((int8u*)&v + 1) = p[0]; + } + else + { + *(int8u*)&v = p[0]; + *((int8u*)&v + 1) = p[1]; + } + return v; + } + + private: + double m_x; + double m_y; + double m_start_x; + double m_width; + double m_height; + double m_space; + double m_line_space; + char m_chr[2]; + char* m_text; + pod_array m_text_buf; + char* m_cur_chr; + const void* m_font; + pod_array m_loaded_font; + status m_status; + bool m_big_endian; + bool m_flip; + int8u* m_indices; + int8* m_glyphs; + int8* m_bglyph; + int8* m_eglyph; + double m_w; + double m_h; + }; + + + + + //--------------------------------------------------------gsv_text_outline + template class gsv_text_outline + { + public: + gsv_text_outline(gsv_text& text, Transformer& trans) : + m_polyline(text), + m_trans(m_polyline, trans) + { + } + + void width(double w) + { + m_polyline.width(w); + } + + void transformer(const Transformer* trans) + { + m_trans->transformer(trans); + } + + void rewind(unsigned path_id) + { + m_trans.rewind(path_id); + m_polyline.line_join(round_join); + m_polyline.line_cap(round_cap); + } + + unsigned vertex(double* x, double* y) + { + return m_trans.vertex(x, y); + } + + private: + conv_stroke m_polyline; + conv_transform, Transformer> m_trans; + }; + + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_accessors.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_accessors.h new file mode 100644 index 00000000000..c651d6d2e8d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_accessors.h @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// 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_IMAGE_ACCESSORS_INCLUDED +#define AGG_IMAGE_ACCESSORS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //-----------------------------------------------------image_accessor_clip + template class image_accessor_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clip() {} + explicit image_accessor_clip(pixfmt_type& pixf, + const color_type& bk) : + m_pixf(&pixf) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + void background_color(const color_type& bk) + { + pixfmt_type::make_pix(m_bk_buf, bk); + } + + private: + AGG_INLINE const int8u* pixel() const + { + if(m_y >= 0 && m_y < (int)m_pixf->height() && + m_x >= 0 && m_x < (int)m_pixf->width()) + { + return m_pixf->pix_ptr(m_x, m_y); + } + return m_bk_buf; + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+(int)len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int8u m_bk_buf[pix_width]; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + //--------------------------------------------------image_accessor_no_clip + template class image_accessor_no_clip + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_no_clip() {} + explicit image_accessor_no_clip(pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_y = y; + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + + AGG_INLINE const int8u* next_x() + { + return m_pix_ptr += pix_width; + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_y; + const int8u* m_pix_ptr; + }; + + + + + //----------------------------------------------------image_accessor_clone + template class image_accessor_clone + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_clone() {} + explicit image_accessor_clone(pixfmt_type& pixf) : + m_pixf(&pixf) + {} + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + private: + AGG_INLINE const int8u* pixel() const + { + int x = m_x; + int y = m_y; + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x >= (int)m_pixf->width()) x = m_pixf->width() - 1; + if(y >= (int)m_pixf->height()) y = m_pixf->height() - 1; + return m_pixf->pix_ptr(x, y); + } + + public: + AGG_INLINE const int8u* span(int x, int y, unsigned len) + { + m_x = m_x0 = x; + m_y = y; + if(y >= 0 && y < (int)m_pixf->height() && + x >= 0 && x+len <= (int)m_pixf->width()) + { + return m_pix_ptr = m_pixf->pix_ptr(x, y); + } + m_pix_ptr = 0; + return pixel(); + } + + AGG_INLINE const int8u* next_x() + { + if(m_pix_ptr) return m_pix_ptr += pix_width; + ++m_x; + return pixel(); + } + + AGG_INLINE const int8u* next_y() + { + ++m_y; + m_x = m_x0; + if(m_pix_ptr && + m_y >= 0 && m_y < (int)m_pixf->height()) + { + return m_pix_ptr = m_pixf->pix_ptr(m_x, m_y); + } + m_pix_ptr = 0; + return pixel(); + } + + private: + const pixfmt_type* m_pixf; + int m_x, m_x0, m_y; + const int8u* m_pix_ptr; + }; + + + + + + //-----------------------------------------------------image_accessor_wrap + template class image_accessor_wrap + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::order_type order_type; + typedef typename pixfmt_type::value_type value_type; + enum pix_width_e { pix_width = pixfmt_type::pix_width }; + + image_accessor_wrap() {} + explicit image_accessor_wrap(pixfmt_type& pixf) : + m_pixf(&pixf), + m_wrap_x(pixf.width()), + m_wrap_y(pixf.height()) + {} + + void attach(pixfmt_type& pixf) + { + m_pixf = &pixf; + } + + AGG_INLINE const int8u* span(int x, int y, unsigned) + { + m_x = x; + m_row_ptr = m_pixf->pix_ptr(0, m_wrap_y(y)); + return m_row_ptr + m_wrap_x(x) * pix_width; + } + + AGG_INLINE const int8u* next_x() + { + int x = ++m_wrap_x; + return m_row_ptr + x * pix_width; + } + + AGG_INLINE const int8u* next_y() + { + m_row_ptr = m_pixf->pix_ptr(0, ++m_wrap_y); + return m_row_ptr + m_wrap_x(m_x) * pix_width; + } + + private: + const pixfmt_type* m_pixf; + const int8u* m_row_ptr; + int m_x; + WrapX m_wrap_x; + WrapY m_wrap_y; + }; + + + + + //--------------------------------------------------------wrap_mode_repeat + class wrap_mode_repeat + { + public: + wrap_mode_repeat() {} + wrap_mode_repeat(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + return m_value = (unsigned(v) + m_add) % m_size; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + private: + unsigned m_size; + unsigned m_add; + unsigned m_value; + }; + + + //---------------------------------------------------wrap_mode_repeat_pow2 + class wrap_mode_repeat_pow2 + { + public: + wrap_mode_repeat_pow2() {} + wrap_mode_repeat_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + while(m_mask < size) m_mask = (m_mask << 1) | 1; + m_mask >>= 1; + } + AGG_INLINE unsigned operator() (int v) + { + return m_value = unsigned(v) & m_mask; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value > m_mask) m_value = 0; + return m_value; + } + private: + unsigned m_mask; + unsigned m_value; + }; + + + //----------------------------------------------wrap_mode_repeat_auto_pow2 + class wrap_mode_repeat_auto_pow2 + { + public: + wrap_mode_repeat_auto_pow2() {} + wrap_mode_repeat_auto_pow2(unsigned size) : + m_size(size), + m_add(size * (0x3FFFFFFF / size)), + m_mask((m_size & (m_size-1)) ? 0 : m_size-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + if(m_mask) return m_value = unsigned(v) & m_mask; + return m_value = (unsigned(v) + m_add) % m_size; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size) m_value = 0; + return m_value; + } + + private: + unsigned m_size; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + + //-------------------------------------------------------wrap_mode_reflect + class wrap_mode_reflect + { + public: + wrap_mode_reflect() {} + wrap_mode_reflect(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_value; + }; + + + + //--------------------------------------------------wrap_mode_reflect_pow2 + class wrap_mode_reflect_pow2 + { + public: + wrap_mode_reflect_pow2() {} + wrap_mode_reflect_pow2(unsigned size) : m_value(0) + { + m_mask = 1; + m_size = 1; + while(m_mask < size) + { + m_mask = (m_mask << 1) | 1; + m_size <<= 1; + } + } + AGG_INLINE unsigned operator() (int v) + { + m_value = unsigned(v) & m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + m_value &= m_mask; + if(m_value >= m_size) return m_mask - m_value; + return m_value; + } + private: + unsigned m_size; + unsigned m_mask; + unsigned m_value; + }; + + + + //---------------------------------------------wrap_mode_reflect_auto_pow2 + class wrap_mode_reflect_auto_pow2 + { + public: + wrap_mode_reflect_auto_pow2() {} + wrap_mode_reflect_auto_pow2(unsigned size) : + m_size(size), + m_size2(size * 2), + m_add(m_size2 * (0x3FFFFFFF / m_size2)), + m_mask((m_size2 & (m_size2-1)) ? 0 : m_size2-1), + m_value(0) + {} + + AGG_INLINE unsigned operator() (int v) + { + m_value = m_mask ? unsigned(v) & m_mask : + (unsigned(v) + m_add) % m_size2; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + AGG_INLINE unsigned operator++ () + { + ++m_value; + if(m_value >= m_size2) m_value = 0; + if(m_value >= m_size) return m_size2 - m_value - 1; + return m_value; + } + + private: + unsigned m_size; + unsigned m_size2; + unsigned m_add; + unsigned m_mask; + unsigned m_value; + }; + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_filters.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_filters.h new file mode 100644 index 00000000000..8e1bc8f0dba --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_image_filters.h @@ -0,0 +1,448 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Image transformation filters, +// Filtering classes (image_filter_lut, image_filter), +// Basic filter shape classes +//---------------------------------------------------------------------------- +#ifndef AGG_IMAGE_FILTERS_INCLUDED +#define AGG_IMAGE_FILTERS_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" + +namespace agg +{ + + // See Implementation agg_image_filters.cpp + + enum image_filter_scale_e + { + image_filter_shift = 14, //----image_filter_shift + image_filter_scale = 1 << image_filter_shift, //----image_filter_scale + image_filter_mask = image_filter_scale - 1 //----image_filter_mask + }; + + enum image_subpixel_scale_e + { + image_subpixel_shift = 8, //----image_subpixel_shift + image_subpixel_scale = 1 << image_subpixel_shift, //----image_subpixel_scale + image_subpixel_mask = image_subpixel_scale - 1 //----image_subpixel_mask + }; + + + //-----------------------------------------------------image_filter_lut + class image_filter_lut + { + public: + template void calculate(const FilterF& filter, + bool normalization=true) + { + double r = filter.radius(); + realloc_lut(r); + unsigned i; + unsigned pivot = diameter() << (image_subpixel_shift - 1); + for(i = 0; i < pivot; i++) + { + double x = double(i) / double(image_subpixel_scale); + double y = filter.calc_weight(x); + m_weight_array[pivot + i] = + m_weight_array[pivot - i] = (int16)iround(y * image_filter_scale); + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + if(normalization) + { + normalize(); + } + } + + image_filter_lut() : m_radius(0), m_diameter(0), m_start(0) {} + + template image_filter_lut(const FilterF& filter, + bool normalization=true) + { + calculate(filter, normalization); + } + + double radius() const { return m_radius; } + unsigned diameter() const { return m_diameter; } + int start() const { return m_start; } + const int16* weight_array() const { return &m_weight_array[0]; } + void normalize(); + + private: + void realloc_lut(double radius); + image_filter_lut(const image_filter_lut&); + const image_filter_lut& operator = (const image_filter_lut&); + + double m_radius; + unsigned m_diameter; + int m_start; + pod_array m_weight_array; + }; + + + + //--------------------------------------------------------image_filter + template class image_filter : public image_filter_lut + { + public: + image_filter() + { + calculate(m_filter_function); + } + private: + FilterF m_filter_function; + }; + + + //-----------------------------------------------image_filter_bilinear + struct image_filter_bilinear + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 1.0 - x; + } + }; + + + //-----------------------------------------------image_filter_hanning + struct image_filter_hanning + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.5 + 0.5 * cos(pi * x); + } + }; + + + //-----------------------------------------------image_filter_hamming + struct image_filter_hamming + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return 0.54 + 0.46 * cos(pi * x); + } + }; + + //-----------------------------------------------image_filter_hermite + struct image_filter_hermite + { + static double radius() { return 1.0; } + static double calc_weight(double x) + { + return (2.0 * x - 3.0) * x * x + 1.0; + } + }; + + //------------------------------------------------image_filter_quadric + struct image_filter_quadric + { + static double radius() { return 1.5; } + static double calc_weight(double x) + { + double t; + if(x < 0.5) return 0.75 - x * x; + if(x < 1.5) {t = x - 1.5; return 0.5 * t * t;} + return 0.0; + } + }; + + //------------------------------------------------image_filter_bicubic + class image_filter_bicubic + { + static double pow3(double x) + { + return (x <= 0.0) ? 0.0 : x * x * x; + } + + public: + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return + (1.0/6.0) * + (pow3(x + 2) - 4 * pow3(x + 1) + 6 * pow3(x) - 4 * pow3(x - 1)); + } + }; + + //-------------------------------------------------image_filter_kaiser + class image_filter_kaiser + { + double a; + double i0a; + double epsilon; + + public: + image_filter_kaiser(double b = 6.33) : + a(b), epsilon(1e-12) + { + i0a = 1.0 / bessel_i0(b); + } + + static double radius() { return 1.0; } + double calc_weight(double x) const + { + return bessel_i0(a * sqrt(1. - x * x)) * i0a; + } + + private: + double bessel_i0(double x) const + { + int i; + double sum, y, t; + + sum = 1.; + y = x * x / 4.; + t = y; + + for(i = 2; t > epsilon; i++) + { + sum += t; + t *= (double)y / (i * i); + } + return sum; + } + }; + + //----------------------------------------------image_filter_catrom + struct image_filter_catrom + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) return 0.5 * (2.0 + x * x * (-5.0 + x * 3.0)); + if(x < 2.0) return 0.5 * (4.0 + x * (-8.0 + x * (5.0 - x))); + return 0.; + } + }; + + //---------------------------------------------image_filter_mitchell + class image_filter_mitchell + { + double p0, p2, p3; + double q0, q1, q2, q3; + + public: + image_filter_mitchell(double b = 1.0/3.0, double c = 1.0/3.0) : + p0((6.0 - 2.0 * b) / 6.0), + p2((-18.0 + 12.0 * b + 6.0 * c) / 6.0), + p3((12.0 - 9.0 * b - 6.0 * c) / 6.0), + q0((8.0 * b + 24.0 * c) / 6.0), + q1((-12.0 * b - 48.0 * c) / 6.0), + q2((6.0 * b + 30.0 * c) / 6.0), + q3((-b - 6.0 * c) / 6.0) + {} + + static double radius() { return 2.0; } + double calc_weight(double x) const + { + if(x < 1.0) return p0 + x * x * (p2 + x * p3); + if(x < 2.0) return q0 + x * (q1 + x * (q2 + x * q3)); + return 0.0; + } + }; + + + //----------------------------------------------image_filter_spline16 + struct image_filter_spline16 + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((x - 9.0/5.0 ) * x - 1.0/5.0 ) * x + 1.0; + } + return ((-1.0/3.0 * (x-1) + 4.0/5.0) * (x-1) - 7.0/15.0 ) * (x-1); + } + }; + + + //---------------------------------------------image_filter_spline36 + struct image_filter_spline36 + { + static double radius() { return 3.0; } + static double calc_weight(double x) + { + if(x < 1.0) + { + return ((13.0/11.0 * x - 453.0/209.0) * x - 3.0/209.0) * x + 1.0; + } + if(x < 2.0) + { + return ((-6.0/11.0 * (x-1) + 270.0/209.0) * (x-1) - 156.0/ 209.0) * (x-1); + } + return ((1.0/11.0 * (x-2) - 45.0/209.0) * (x-2) + 26.0/209.0) * (x-2); + } + }; + + + //----------------------------------------------image_filter_gaussian + struct image_filter_gaussian + { + static double radius() { return 2.0; } + static double calc_weight(double x) + { + return exp(-2.0 * x * x) * sqrt(2.0 / pi); + } + }; + + + //------------------------------------------------image_filter_bessel + struct image_filter_bessel + { + static double radius() { return 3.2383; } + static double calc_weight(double x) + { + return (x == 0.0) ? pi / 4.0 : besj(pi * x, 1) / (2.0 * x); + } + }; + + + //-------------------------------------------------image_filter_sinc + class image_filter_sinc + { + public: + image_filter_sinc(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + x *= pi; + return sin(x) / x; + } + private: + double m_radius; + }; + + + //-----------------------------------------------image_filter_lanczos + class image_filter_lanczos + { + public: + image_filter_lanczos(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (sin(xr) / xr); + } + private: + double m_radius; + }; + + + //----------------------------------------------image_filter_blackman + class image_filter_blackman + { + public: + image_filter_blackman(double r) : m_radius(r < 2.0 ? 2.0 : r) {} + double radius() const { return m_radius; } + double calc_weight(double x) const + { + if(x == 0.0) return 1.0; + if(x > m_radius) return 0.0; + x *= pi; + double xr = x / m_radius; + return (sin(x) / x) * (0.42 + 0.5*cos(xr) + 0.08*cos(2*xr)); + } + private: + double m_radius; + }; + + //------------------------------------------------image_filter_sinc36 + class image_filter_sinc36 : public image_filter_sinc + { public: image_filter_sinc36() : image_filter_sinc(3.0){} }; + + //------------------------------------------------image_filter_sinc64 + class image_filter_sinc64 : public image_filter_sinc + { public: image_filter_sinc64() : image_filter_sinc(4.0){} }; + + //-----------------------------------------------image_filter_sinc100 + class image_filter_sinc100 : public image_filter_sinc + { public: image_filter_sinc100() : image_filter_sinc(5.0){} }; + + //-----------------------------------------------image_filter_sinc144 + class image_filter_sinc144 : public image_filter_sinc + { public: image_filter_sinc144() : image_filter_sinc(6.0){} }; + + //-----------------------------------------------image_filter_sinc196 + class image_filter_sinc196 : public image_filter_sinc + { public: image_filter_sinc196() : image_filter_sinc(7.0){} }; + + //-----------------------------------------------image_filter_sinc256 + class image_filter_sinc256 : public image_filter_sinc + { public: image_filter_sinc256() : image_filter_sinc(8.0){} }; + + //---------------------------------------------image_filter_lanczos36 + class image_filter_lanczos36 : public image_filter_lanczos + { public: image_filter_lanczos36() : image_filter_lanczos(3.0){} }; + + //---------------------------------------------image_filter_lanczos64 + class image_filter_lanczos64 : public image_filter_lanczos + { public: image_filter_lanczos64() : image_filter_lanczos(4.0){} }; + + //--------------------------------------------image_filter_lanczos100 + class image_filter_lanczos100 : public image_filter_lanczos + { public: image_filter_lanczos100() : image_filter_lanczos(5.0){} }; + + //--------------------------------------------image_filter_lanczos144 + class image_filter_lanczos144 : public image_filter_lanczos + { public: image_filter_lanczos144() : image_filter_lanczos(6.0){} }; + + //--------------------------------------------image_filter_lanczos196 + class image_filter_lanczos196 : public image_filter_lanczos + { public: image_filter_lanczos196() : image_filter_lanczos(7.0){} }; + + //--------------------------------------------image_filter_lanczos256 + class image_filter_lanczos256 : public image_filter_lanczos + { public: image_filter_lanczos256() : image_filter_lanczos(8.0){} }; + + //--------------------------------------------image_filter_blackman36 + class image_filter_blackman36 : public image_filter_blackman + { public: image_filter_blackman36() : image_filter_blackman(3.0){} }; + + //--------------------------------------------image_filter_blackman64 + class image_filter_blackman64 : public image_filter_blackman + { public: image_filter_blackman64() : image_filter_blackman(4.0){} }; + + //-------------------------------------------image_filter_blackman100 + class image_filter_blackman100 : public image_filter_blackman + { public: image_filter_blackman100() : image_filter_blackman(5.0){} }; + + //-------------------------------------------image_filter_blackman144 + class image_filter_blackman144 : public image_filter_blackman + { public: image_filter_blackman144() : image_filter_blackman(6.0){} }; + + //-------------------------------------------image_filter_blackman196 + class image_filter_blackman196 : public image_filter_blackman + { public: image_filter_blackman196() : image_filter_blackman(7.0){} }; + + //-------------------------------------------image_filter_blackman256 + class image_filter_blackman256 : public image_filter_blackman + { public: image_filter_blackman256() : image_filter_blackman(8.0){} }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_line_aa_basics.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_line_aa_basics.h new file mode 100644 index 00000000000..c5acb18e796 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_line_aa_basics.h @@ -0,0 +1,189 @@ +//---------------------------------------------------------------------------- +// 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_LINE_AA_BASICS_INCLUDED +#define AGG_LINE_AA_BASICS_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + // See Implementation agg_line_aa_basics.cpp + + //------------------------------------------------------------------------- + enum line_subpixel_scale_e + { + line_subpixel_shift = 8, //----line_subpixel_shift + line_subpixel_scale = 1 << line_subpixel_shift, //----line_subpixel_scale + line_subpixel_mask = line_subpixel_scale - 1, //----line_subpixel_mask + line_max_coord = (1 << 28) - 1, //----line_max_coord + line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length + }; + + //------------------------------------------------------------------------- + enum line_mr_subpixel_scale_e + { + line_mr_subpixel_shift = 4, //----line_mr_subpixel_shift + line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale + line_mr_subpixel_mask = line_mr_subpixel_scale - 1 //----line_mr_subpixel_mask + }; + + //------------------------------------------------------------------line_mr + AGG_INLINE int line_mr(int x) + { + return x >> (line_subpixel_shift - line_mr_subpixel_shift); + } + + //-------------------------------------------------------------------line_hr + AGG_INLINE int line_hr(int x) + { + return x << (line_subpixel_shift - line_mr_subpixel_shift); + } + + //---------------------------------------------------------------line_dbl_hr + AGG_INLINE int line_dbl_hr(int x) + { + return x << line_subpixel_shift; + } + + //---------------------------------------------------------------line_coord + struct line_coord + { + AGG_INLINE static int conv(double x) + { + return iround(x * line_subpixel_scale); + } + }; + + //-----------------------------------------------------------line_coord_sat + struct line_coord_sat + { + AGG_INLINE static int conv(double x) + { + return saturation::iround(x * line_subpixel_scale); + } + }; + + //==========================================================line_parameters + struct line_parameters + { + //--------------------------------------------------------------------- + line_parameters() {} + line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) : + x1(x1_), y1(y1_), x2(x2_), y2(y2_), + dx(abs(x2_ - x1_)), + dy(abs(y2_ - y1_)), + sx((x2_ > x1_) ? 1 : -1), + sy((y2_ > y1_) ? 1 : -1), + vertical(dy >= dx), + inc(vertical ? sy : sx), + len(len_), + octant((sy & 4) | (sx & 2) | int(vertical)) + { + } + + //--------------------------------------------------------------------- + unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; } + unsigned diagonal_quadrant() const { return s_diagonal_quadrant[octant]; } + + //--------------------------------------------------------------------- + bool same_orthogonal_quadrant(const line_parameters& lp) const + { + return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + bool same_diagonal_quadrant(const line_parameters& lp) const + { + return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant]; + } + + //--------------------------------------------------------------------- + void divide(line_parameters& lp1, line_parameters& lp2) const + { + int xmid = (x1 + x2) >> 1; + int ymid = (y1 + y2) >> 1; + int len2 = len >> 1; + + lp1 = *this; + lp2 = *this; + + lp1.x2 = xmid; + lp1.y2 = ymid; + lp1.len = len2; + lp1.dx = abs(lp1.x2 - lp1.x1); + lp1.dy = abs(lp1.y2 - lp1.y1); + + lp2.x1 = xmid; + lp2.y1 = ymid; + lp2.len = len2; + lp2.dx = abs(lp2.x2 - lp2.x1); + lp2.dy = abs(lp2.y2 - lp2.y1); + } + + //--------------------------------------------------------------------- + int x1, y1, x2, y2, dx, dy, sx, sy; + bool vertical; + int inc; + int len; + int octant; + + //--------------------------------------------------------------------- + static const int8u s_orthogonal_quadrant[8]; + static const int8u s_diagonal_quadrant[8]; + }; + + + + // See Implementation agg_line_aa_basics.cpp + + //----------------------------------------------------------------bisectrix + void bisectrix(const line_parameters& l1, + const line_parameters& l2, + int* x, int* y); + + + //-------------------------------------------fix_degenerate_bisectrix_start + void inline fix_degenerate_bisectrix_start(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x1 + (lp.y2 - lp.y1); + *y = lp.y1 - (lp.x2 - lp.x1); + } + } + + + //---------------------------------------------fix_degenerate_bisectrix_end + void inline fix_degenerate_bisectrix_end(const line_parameters& lp, + int* x, int* y) + { + int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) - + double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len); + if(d < line_subpixel_scale/2) + { + *x = lp.x2 + (lp.y2 - lp.y1); + *y = lp.y2 - (lp.x2 - lp.x1); + } + } + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math.h new file mode 100644 index 00000000000..2ec49cf3ff8 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math.h @@ -0,0 +1,437 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// Bessel function (besj) was adapted for use in AGG library by Andy Wilk +// Contact: castor.vulgaris@gmail.com +//---------------------------------------------------------------------------- + +#ifndef AGG_MATH_INCLUDED +#define AGG_MATH_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------vertex_dist_epsilon + // Coinciding points maximal distance (Epsilon) + const double vertex_dist_epsilon = 1e-14; + + //-----------------------------------------------------intersection_epsilon + // See calc_intersection + const double intersection_epsilon = 1.0e-30; + + //------------------------------------------------------------cross_product + AGG_INLINE double cross_product(double x1, double y1, + double x2, double y2, + double x, double y) + { + return (x - x2) * (y2 - y1) - (y - y2) * (x2 - x1); + } + + //--------------------------------------------------------point_in_triangle + AGG_INLINE bool point_in_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x, double y) + { + bool cp1 = cross_product(x1, y1, x2, y2, x, y) < 0.0; + bool cp2 = cross_product(x2, y2, x3, y3, x, y) < 0.0; + bool cp3 = cross_product(x3, y3, x1, y1, x, y) < 0.0; + return cp1 == cp2 && cp2 == cp3 && cp3 == cp1; + } + + //-----------------------------------------------------------calc_distance + AGG_INLINE double calc_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return sqrt(dx * dx + dy * dy); + } + + //--------------------------------------------------------calc_sq_distance + AGG_INLINE double calc_sq_distance(double x1, double y1, double x2, double y2) + { + double dx = x2-x1; + double dy = y2-y1; + return dx * dx + dy * dy; + } + + //------------------------------------------------calc_line_point_distance + AGG_INLINE double calc_line_point_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2-x1; + double dy = y2-y1; + double d = sqrt(dx * dx + dy * dy); + if(d < vertex_dist_epsilon) + { + return calc_distance(x1, y1, x, y); + } + return ((x - x2) * dy - (y - y2) * dx) / d; + } + + //-------------------------------------------------------calc_line_point_u + AGG_INLINE double calc_segment_point_u(double x1, double y1, + double x2, double y2, + double x, double y) + { + double dx = x2 - x1; + double dy = y2 - y1; + + if(dx == 0 && dy == 0) + { + return 0; + } + + double pdx = x - x1; + double pdy = y - y1; + + return (pdx * dx + pdy * dy) / (dx * dx + dy * dy); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y, + double u) + { + if(u <= 0) + { + return calc_sq_distance(x, y, x1, y1); + } + else + if(u >= 1) + { + return calc_sq_distance(x, y, x2, y2); + } + return calc_sq_distance(x, y, x1 + u * (x2 - x1), y1 + u * (y2 - y1)); + } + + //---------------------------------------------calc_line_point_sq_distance + AGG_INLINE double calc_segment_point_sq_distance(double x1, double y1, + double x2, double y2, + double x, double y) + { + return + calc_segment_point_sq_distance( + x1, y1, x2, y2, x, y, + calc_segment_point_u(x1, y1, x2, y2, x, y)); + } + + //-------------------------------------------------------calc_intersection + AGG_INLINE bool calc_intersection(double ax, double ay, double bx, double by, + double cx, double cy, double dx, double dy, + double* x, double* y) + { + double num = (ay-cy) * (dx-cx) - (ax-cx) * (dy-cy); + double den = (bx-ax) * (dy-cy) - (by-ay) * (dx-cx); + if(fabs(den) < intersection_epsilon) return false; + double r = num / den; + *x = ax + r * (bx-ax); + *y = ay + r * (by-ay); + return true; + } + + //-----------------------------------------------------intersection_exists + AGG_INLINE bool intersection_exists(double x1, double y1, double x2, double y2, + double x3, double y3, double x4, double y4) + { + // It's less expensive but you can't control the + // boundary conditions: Less or LessEqual + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x4 - x3; + double dy2 = y4 - y3; + return ((x3 - x2) * dy1 - (y3 - y2) * dx1 < 0.0) != + ((x4 - x2) * dy1 - (y4 - y2) * dx1 < 0.0) && + ((x1 - x4) * dy2 - (y1 - y4) * dx2 < 0.0) != + ((x2 - x4) * dy2 - (y2 - y4) * dx2 < 0.0); + + // It's is more expensive but more flexible + // in terms of boundary conditions. + //-------------------- + //double den = (x2-x1) * (y4-y3) - (y2-y1) * (x4-x3); + //if(fabs(den) < intersection_epsilon) return false; + //double nom1 = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3); + //double nom2 = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3); + //double ua = nom1 / den; + //double ub = nom2 / den; + //return ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0; + } + + //--------------------------------------------------------calc_orthogonal + AGG_INLINE void calc_orthogonal(double thickness, + double x1, double y1, + double x2, double y2, + double* x, double* y) + { + double dx = x2 - x1; + double dy = y2 - y1; + double d = sqrt(dx*dx + dy*dy); + *x = thickness * dy / d; + *y = -thickness * dx / d; + } + + //--------------------------------------------------------dilate_triangle + AGG_INLINE void dilate_triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double *x, double* y, + double d) + { + double dx1=0.0; + double dy1=0.0; + double dx2=0.0; + double dy2=0.0; + double dx3=0.0; + double dy3=0.0; + double loc = cross_product(x1, y1, x2, y2, x3, y3); + if(fabs(loc) > intersection_epsilon) + { + if(cross_product(x1, y1, x2, y2, x3, y3) > 0.0) + { + d = -d; + } + calc_orthogonal(d, x1, y1, x2, y2, &dx1, &dy1); + calc_orthogonal(d, x2, y2, x3, y3, &dx2, &dy2); + calc_orthogonal(d, x3, y3, x1, y1, &dx3, &dy3); + } + *x++ = x1 + dx1; *y++ = y1 + dy1; + *x++ = x2 + dx1; *y++ = y2 + dy1; + *x++ = x2 + dx2; *y++ = y2 + dy2; + *x++ = x3 + dx2; *y++ = y3 + dy2; + *x++ = x3 + dx3; *y++ = y3 + dy3; + *x++ = x1 + dx3; *y++ = y1 + dy3; + } + + //------------------------------------------------------calc_triangle_area + AGG_INLINE double calc_triangle_area(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + return (x1*y2 - x2*y1 + x2*y3 - x3*y2 + x3*y1 - x1*y3) * 0.5; + } + + //-------------------------------------------------------calc_polygon_area + template double calc_polygon_area(const Storage& st) + { + unsigned i; + double sum = 0.0; + double x = st[0].x; + double y = st[0].y; + double xs = x; + double ys = y; + + for(i = 1; i < st.size(); i++) + { + const typename Storage::value_type& v = st[i]; + sum += x * v.y - y * v.x; + x = v.x; + y = v.y; + } + return (sum + x * ys - y * xs) * 0.5; + } + + //------------------------------------------------------------------------ + // Tables for fast sqrt + extern int16u g_sqrt_table[1024]; + extern int8 g_elder_bit_table[256]; + + + //---------------------------------------------------------------fast_sqrt + //Fast integer Sqrt - really fast: no cycles, divisions or multiplications + #if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4035) //Disable warning "no return value" + #endif + AGG_INLINE unsigned fast_sqrt(unsigned val) + { + #if defined(_M_IX86) && defined(_MSC_VER) && !defined(AGG_NO_ASM) + //For Ix86 family processors this assembler code is used. + //The key command here is bsr - determination the number of the most + //significant bit of the value. For other processors + //(and maybe compilers) the pure C "#else" section is used. + __asm + { + mov ebx, val + mov edx, 11 + bsr ecx, ebx + sub ecx, 9 + jle less_than_9_bits + shr ecx, 1 + adc ecx, 0 + sub edx, ecx + shl ecx, 1 + shr ebx, cl + less_than_9_bits: + xor eax, eax + mov ax, g_sqrt_table[ebx*2] + mov ecx, edx + shr eax, cl + } + #else + + //This code is actually pure C and portable to most + //arcitectures including 64bit ones. + unsigned t = val; + int bit=0; + unsigned shift = 11; + + //The following piece of code is just an emulation of the + //Ix86 assembler command "bsr" (see above). However on old + //Intels (like Intel MMX 233MHz) this code is about twice + //faster (sic!) then just one "bsr". On PIII and PIV the + //bsr is optimized quite well. + bit = t >> 24; + if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } + + //This code calculates the sqrt. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; + #endif + } + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + + + + + //--------------------------------------------------------------------besj + // Function BESJ calculates Bessel function of first kind of order n + // Arguments: + // n - an integer (>=0), the order + // x - value at which the Bessel function is required + //-------------------- + // C++ Mathematical Library + // Convereted from equivalent FORTRAN library + // Converetd by Gareth Walker for use by course 392 computational project + // All functions tested and yield the same results as the corresponding + // FORTRAN versions. + // + // If you have any problems using these functions please report them to + // M.Muldoon@UMIST.ac.uk + // + // Documentation available on the web + // http://www.ma.umist.ac.uk/mrm/Teaching/392/libs/392.html + // Version 1.0 8/98 + // 29 October, 1999 + //-------------------- + // Adapted for use in AGG library by Andy Wilk (castor.vulgaris@gmail.com) + //------------------------------------------------------------------------ + inline double besj(double x, int n) + { + if(n < 0) + { + return 0; + } + double d = 1E-6; + double b = 0; + if(fabs(x) <= d) + { + if(n != 0) return 0; + return 1; + } + double b1 = 0; // b1 is the value from the previous iteration + // Set up a starting order for recurrence + int m1 = (int)fabs(x) + 6; + if(fabs(x) > 5) + { + m1 = (int)(fabs(1.4 * x + 60 / x)); + } + int m2 = (int)(n + 2 + fabs(x) / 4); + if (m1 > m2) + { + m2 = m1; + } + + // Apply recurrence down from curent max order + for(;;) + { + double c3 = 0; + double c2 = 1E-30; + double c4 = 0; + int m8 = 1; + if (m2 / 2 * 2 == m2) + { + m8 = -1; + } + int imax = m2 - 2; + for (int i = 1; i <= imax; i++) + { + double c6 = 2 * (m2 - i) * c2 / x - c3; + c3 = c2; + c2 = c6; + if(m2 - i - 1 == n) + { + b = c6; + } + m8 = -1 * m8; + if (m8 > 0) + { + c4 = c4 + 2 * c6; + } + } + double c6 = 2 * c2 / x - c3; + if(n == 0) + { + b = c6; + } + c4 += c6; + b /= c4; + if(fabs(b - b1) < d) + { + return b; + } + b1 = b; + m2 += 3; + } + } + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math_stroke.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math_stroke.h new file mode 100644 index 00000000000..4871d96cef6 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_math_stroke.h @@ -0,0 +1,527 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Stroke math +// +//---------------------------------------------------------------------------- + +#ifndef AGG_STROKE_MATH_INCLUDED +#define AGG_STROKE_MATH_INCLUDED + +#include "agg_math.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + //-------------------------------------------------------------line_cap_e + enum line_cap_e + { + butt_cap, + square_cap, + round_cap + }; + + //------------------------------------------------------------line_join_e + enum line_join_e + { + miter_join = 0, + miter_join_revert = 1, + round_join = 2, + bevel_join = 3, + miter_join_round = 4 + }; + + + //-----------------------------------------------------------inner_join_e + enum inner_join_e + { + inner_bevel, + inner_miter, + inner_jag, + inner_round + }; + + //------------------------------------------------------------math_stroke + template class math_stroke + { + public: + typedef typename VertexConsumer::value_type coord_type; + + math_stroke(); + + void line_cap(line_cap_e lc) { m_line_cap = lc; } + void line_join(line_join_e lj) { m_line_join = lj; } + void inner_join(inner_join_e ij) { m_inner_join = ij; } + + line_cap_e line_cap() const { return m_line_cap; } + line_join_e line_join() const { return m_line_join; } + inner_join_e inner_join() const { return m_inner_join; } + + void width(double w); + void miter_limit(double ml) { m_miter_limit = ml; } + void miter_limit_theta(double t); + void inner_miter_limit(double ml) { m_inner_miter_limit = ml; } + void approximation_scale(double as) { m_approx_scale = as; } + + double width() const { return m_width * 2.0; } + double miter_limit() const { return m_miter_limit; } + double inner_miter_limit() const { return m_inner_miter_limit; } + double approximation_scale() const { return m_approx_scale; } + + void calc_cap(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len); + + void calc_join(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2); + + private: + AGG_INLINE void add_vertex(VertexConsumer& vc, double x, double y) + { + vc.add(coord_type(x, y)); + } + + void calc_arc(VertexConsumer& vc, + double x, double y, + double dx1, double dy1, + double dx2, double dy2); + + void calc_miter(VertexConsumer& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel); + + double m_width; + double m_width_abs; + double m_width_eps; + int m_width_sign; + double m_miter_limit; + double m_inner_miter_limit; + double m_approx_scale; + line_cap_e m_line_cap; + line_join_e m_line_join; + inner_join_e m_inner_join; + }; + + //----------------------------------------------------------------------- + template math_stroke::math_stroke() : + m_width(0.5), + m_width_abs(0.5), + m_width_eps(0.5/1024.0), + m_width_sign(1), + m_miter_limit(4.0), + m_inner_miter_limit(1.01), + m_approx_scale(1.0), + m_line_cap(butt_cap), + m_line_join(miter_join), + m_inner_join(inner_miter) + { + } + + //----------------------------------------------------------------------- + template void math_stroke::width(double w) + { + m_width = w * 0.5; + if(m_width < 0) + { + m_width_abs = -m_width; + m_width_sign = -1; + } + else + { + m_width_abs = m_width; + m_width_sign = 1; + } + m_width_eps = m_width / 1024.0; + } + + //----------------------------------------------------------------------- + template void math_stroke::miter_limit_theta(double t) + { + m_miter_limit = 1.0 / sin(t * 0.5) ; + } + + //----------------------------------------------------------------------- + template + void math_stroke::calc_arc(VC& vc, + double x, double y, + double dx1, double dy1, + double dx2, double dy2) + { + double a1 = atan2(dy1 * m_width_sign, dx1 * m_width_sign); + double a2 = atan2(dy2 * m_width_sign, dx2 * m_width_sign); + double da = a1 - a2; + int i, n; + + da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; + + add_vertex(vc, x + dx1, y + dy1); + if(m_width_sign > 0) + { + if(a1 > a2) a2 += 2 * pi; + n = int((a2 - a1) / da); + da = (a2 - a1) / (n + 1); + a1 += da; + for(i = 0; i < n; i++) + { + add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); + a1 += da; + } + } + else + { + if(a1 < a2) a2 -= 2 * pi; + n = int((a1 - a2) / da); + da = (a1 - a2) / (n + 1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, x + cos(a1) * m_width, y + sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, x + dx2, y + dy2); + } + + //----------------------------------------------------------------------- + template + void math_stroke::calc_miter(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double dx1, double dy1, + double dx2, double dy2, + line_join_e lj, + double mlimit, + double dbevel) + { + double xi = v1.x; + double yi = v1.y; + double di = 1; + double lim = m_width_abs * mlimit; + bool miter_limit_exceeded = true; // Assume the worst + bool intersection_failed = true; // Assume the worst + + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &xi, &yi)) + { + // Calculation of the intersection succeeded + //--------------------- + di = calc_distance(v1.x, v1.y, xi, yi); + if(di <= lim) + { + // Inside the miter limit + //--------------------- + add_vertex(vc, xi, yi); + miter_limit_exceeded = false; + } + intersection_failed = false; + } + else + { + // Calculation of the intersection failed, most probably + // the three points lie one straight line. + // First check if v0 and v2 lie on the opposite sides of vector: + // (v1.x, v1.y) -> (v1.x+dx1, v1.y-dy1), that is, the perpendicular + // to the line determined by vertices v0 and v1. + // This condition determines whether the next line segments continues + // the previous one or goes back. + //---------------- + double x2 = v1.x + dx1; + double y2 = v1.y - dy1; + if((cross_product(v0.x, v0.y, v1.x, v1.y, x2, y2) < 0.0) == + (cross_product(v1.x, v1.y, v2.x, v2.y, x2, y2) < 0.0)) + { + // This case means that the next segment continues + // the previous one (straight line) + //----------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + miter_limit_exceeded = false; + } + } + + if(miter_limit_exceeded) + { + // Miter limit exceeded + //------------------------ + switch(lj) + { + case miter_join_revert: + // For the compatibility with SVG, PDF, etc, + // we use a simple bevel join instead of + // "smart" bevel + //------------------- + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case miter_join_round: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: + // If no miter-revert, calculate new dx1, dy1, dx2, dy2 + //---------------- + if(intersection_failed) + { + mlimit *= m_width_sign; + add_vertex(vc, v1.x + dx1 + dy1 * mlimit, + v1.y - dy1 + dx1 * mlimit); + add_vertex(vc, v1.x + dx2 - dy2 * mlimit, + v1.y - dy2 - dx2 * mlimit); + } + else + { + double x1 = v1.x + dx1; + double y1 = v1.y - dy1; + double x2 = v1.x + dx2; + double y2 = v1.y - dy2; + di = (lim - dbevel) / (di - dbevel); + add_vertex(vc, x1 + (xi - x1) * di, + y1 + (yi - y1) * di); + add_vertex(vc, x2 + (xi - x2) * di, + y2 + (yi - y2) * di); + } + break; + } + } + } + + //--------------------------------------------------------stroke_calc_cap + template + void math_stroke::calc_cap(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + double len) + { + vc.remove_all(); + + double dx1 = (v1.y - v0.y) / len; + double dy1 = (v1.x - v0.x) / len; + double dx2 = 0; + double dy2 = 0; + + dx1 *= m_width; + dy1 *= m_width; + + if(m_line_cap != round_cap) + { + if(m_line_cap == square_cap) + { + dx2 = dy1 * m_width_sign; + dy2 = dx1 * m_width_sign; + } + add_vertex(vc, v0.x - dx1 - dx2, v0.y + dy1 - dy2); + add_vertex(vc, v0.x + dx1 - dx2, v0.y - dy1 - dy2); + } + else + { + double da = acos(m_width_abs / (m_width_abs + 0.125 / m_approx_scale)) * 2; + double a1; + int i; + int n = int(pi / da); + + da = pi / (n + 1); + add_vertex(vc, v0.x - dx1, v0.y + dy1); + if(m_width_sign > 0) + { + a1 = atan2(dy1, -dx1); + a1 += da; + for(i = 0; i < n; i++) + { + add_vertex(vc, v0.x + cos(a1) * m_width, + v0.y + sin(a1) * m_width); + a1 += da; + } + } + else + { + a1 = atan2(-dy1, dx1); + a1 -= da; + for(i = 0; i < n; i++) + { + add_vertex(vc, v0.x + cos(a1) * m_width, + v0.y + sin(a1) * m_width); + a1 -= da; + } + } + add_vertex(vc, v0.x + dx1, v0.y - dy1); + } + } + + //----------------------------------------------------------------------- + template + void math_stroke::calc_join(VC& vc, + const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + double len1, + double len2) + { + double dx1 = m_width * (v1.y - v0.y) / len1; + double dy1 = m_width * (v1.x - v0.x) / len1; + double dx2 = m_width * (v2.y - v1.y) / len2; + double dy2 = m_width * (v2.x - v1.x) / len2; + + vc.remove_all(); + + double cp = cross_product(v0.x, v0.y, v1.x, v1.y, v2.x, v2.y); + if ((cp > agg::vertex_dist_epsilon && m_width > 0) || + (cp < -agg::vertex_dist_epsilon && m_width < 0)) + { + // Inner join + //--------------- + double limit = ((len1 < len2) ? len1 : len2) / m_width_abs; + if(limit < m_inner_miter_limit) + { + limit = m_inner_miter_limit; + } + + switch(m_inner_join) + { + default: // inner_bevel + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + + case inner_miter: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + break; + + case inner_jag: + case inner_round: + cp = (dx1-dx2) * (dx1-dx2) + (dy1-dy2) * (dy1-dy2); + if(cp < len1 * len1 && cp < len2 * len2) + { + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + miter_join_revert, + limit, 0); + } + else + { + if(m_inner_join == inner_jag) + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x, v1.y ); + calc_arc(vc, v1.x, v1.y, dx2, -dy2, dx1, -dy1); + add_vertex(vc, v1.x, v1.y ); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + } + } + break; + } + } + else + { + // Outer join + //--------------- + + // Calculate the distance between v1 and + // the central point of the bevel line segment + //--------------- + double dx = (dx1 + dx2) / 2; + double dy = (dy1 + dy2) / 2; + double dbevel = sqrt(dx * dx + dy * dy); + + if(m_line_join == round_join || m_line_join == bevel_join) + { + // This is an optimization that reduces the number of points + // in cases of almost collinear segments. If there's no + // visible difference between bevel and miter joins we'd rather + // use miter join because it adds only one point instead of two. + // + // Here we calculate the middle point between the bevel points + // and then, the distance between v1 and this middle point. + // At outer joins this distance always less than stroke width, + // because it's actually the height of an isosceles triangle of + // v1 and its two bevel points. If the difference between this + // width and this value is small (no visible bevel) we can + // add just one point. + // + // The constant in the expression makes the result approximately + // the same as in round joins and caps. You can safely comment + // out this entire "if". + //------------------- + if(m_approx_scale * (m_width_abs - dbevel) < m_width_eps) + { + if(calc_intersection(v0.x + dx1, v0.y - dy1, + v1.x + dx1, v1.y - dy1, + v1.x + dx2, v1.y - dy2, + v2.x + dx2, v2.y - dy2, + &dx, &dy)) + { + add_vertex(vc, dx, dy); + } + else + { + add_vertex(vc, v1.x + dx1, v1.y - dy1); + } + return; + } + } + + switch(m_line_join) + { + case miter_join: + case miter_join_revert: + case miter_join_round: + calc_miter(vc, + v0, v1, v2, dx1, dy1, dx2, dy2, + m_line_join, + m_miter_limit, + dbevel); + break; + + case round_join: + calc_arc(vc, v1.x, v1.y, dx1, -dy1, dx2, -dy2); + break; + + default: // Bevel join + add_vertex(vc, v1.x + dx1, v1.y - dy1); + add_vertex(vc, v1.x + dx2, v1.y - dy2); + break; + } + } + } + + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_length.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_length.h new file mode 100644 index 00000000000..740ba31df27 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_length.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// 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_PATH_LENGTH_INCLUDED +#define AGG_PATH_LENGTH_INCLUDED + +#include "agg_math.h" + +namespace agg +{ + template + double path_length(VertexSource& vs, unsigned path_id = 0) + { + double len = 0.0; + double start_x = 0.0; + double start_y = 0.0; + double x1 = 0.0; + double y1 = 0.0; + double x2 = 0.0; + double y2 = 0.0; + bool first = true; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x2, &y2))) + { + if(is_vertex(cmd)) + { + if(first || is_move_to(cmd)) + { + start_x = x2; + start_y = y2; + } + else + { + len += calc_distance(x1, y1, x2, y2); + } + x1 = x2; + y1 = y2; + first = false; + } + else + { + if(is_close(cmd) && !first) + { + len += calc_distance(x1, y1, start_x, start_y); + } + } + } + return len; + } +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage.h new file mode 100644 index 00000000000..c01b867f26c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage.h @@ -0,0 +1,1545 @@ +//---------------------------------------------------------------------------- +// 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_PATH_STORAGE_INCLUDED +#define AGG_PATH_STORAGE_INCLUDED + +#include +#include +#include "agg_math.h" +#include "agg_array.h" +#include "agg_bezier_arc.h" + +namespace agg +{ + + + //----------------------------------------------------vertex_block_storage + template + class vertex_block_storage + { + public: + // Allocation parameters + enum block_scale_e + { + block_shift = BlockShift, + block_size = 1 << block_shift, + block_mask = block_size - 1, + block_pool = BlockPool + }; + + typedef T value_type; + typedef vertex_block_storage self_type; + + ~vertex_block_storage(); + vertex_block_storage(); + vertex_block_storage(const self_type& v); + const self_type& operator = (const self_type& ps); + + void remove_all(); + void free_all(); + + void add_vertex(double x, double y, unsigned cmd); + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + void swap_vertices(unsigned v1, unsigned v2); + + unsigned last_command() const; + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned total_vertices() const; + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + private: + void allocate_block(unsigned nb); + int8u* storage_ptrs(T** xy_ptr); + + private: + unsigned m_total_vertices; + unsigned m_total_blocks; + unsigned m_max_blocks; + T** m_coord_blocks; + int8u** m_cmd_blocks; + }; + + + //------------------------------------------------------------------------ + template + void vertex_block_storage::free_all() + { + if(m_total_blocks) + { + T** coord_blk = m_coord_blocks + m_total_blocks - 1; + while(m_total_blocks--) + { + pod_allocator::deallocate( + *coord_blk, + block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + --coord_blk; + } + pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + m_total_blocks = 0; + m_max_blocks = 0; + m_coord_blocks = 0; + m_cmd_blocks = 0; + m_total_vertices = 0; + } + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::~vertex_block_storage() + { + free_all(); + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::vertex_block_storage() : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + } + + //------------------------------------------------------------------------ + template + vertex_block_storage::vertex_block_storage(const vertex_block_storage& v) : + m_total_vertices(0), + m_total_blocks(0), + m_max_blocks(0), + m_coord_blocks(0), + m_cmd_blocks(0) + { + *this = v; + } + + //------------------------------------------------------------------------ + template + const vertex_block_storage& + vertex_block_storage::operator = (const vertex_block_storage& v) + { + remove_all(); + unsigned i; + for(i = 0; i < v.total_vertices(); i++) + { + double x, y; + unsigned cmd = v.vertex(i, &x, &y); + add_vertex(x, y, cmd); + } + return *this; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::remove_all() + { + m_total_vertices = 0; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::add_vertex(double x, double y, + unsigned cmd) + { + T* coord_ptr = 0; + *storage_ptrs(&coord_ptr) = (int8u)cmd; + coord_ptr[0] = T(x); + coord_ptr[1] = T(y); + m_total_vertices++; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_vertex(unsigned idx, + double x, double y) + { + T* pv = m_coord_blocks[idx >> block_shift] + ((idx & block_mask) << 1); + pv[0] = T(x); + pv[1] = T(y); + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_vertex(unsigned idx, + double x, double y, + unsigned cmd) + { + unsigned block = idx >> block_shift; + unsigned offset = idx & block_mask; + T* pv = m_coord_blocks[block] + (offset << 1); + pv[0] = T(x); + pv[1] = T(y); + m_cmd_blocks[block][offset] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::modify_command(unsigned idx, + unsigned cmd) + { + m_cmd_blocks[idx >> block_shift][idx & block_mask] = (int8u)cmd; + } + + //------------------------------------------------------------------------ + template + inline void vertex_block_storage::swap_vertices(unsigned v1, unsigned v2) + { + unsigned b1 = v1 >> block_shift; + unsigned b2 = v2 >> block_shift; + unsigned o1 = v1 & block_mask; + unsigned o2 = v2 & block_mask; + T* pv1 = m_coord_blocks[b1] + (o1 << 1); + T* pv2 = m_coord_blocks[b2] + (o2 << 1); + T val; + val = pv1[0]; pv1[0] = pv2[0]; pv2[0] = val; + val = pv1[1]; pv1[1] = pv2[1]; pv2[1] = val; + int8u cmd = m_cmd_blocks[b1][o1]; + m_cmd_blocks[b1][o1] = m_cmd_blocks[b2][o2]; + m_cmd_blocks[b2][o2] = cmd; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::last_command() const + { + if(m_total_vertices) return command(m_total_vertices - 1); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::last_vertex(double* x, double* y) const + { + if(m_total_vertices) return vertex(m_total_vertices - 1, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::prev_vertex(double* x, double* y) const + { + if(m_total_vertices > 1) return vertex(m_total_vertices - 2, x, y); + return path_cmd_stop; + } + + //------------------------------------------------------------------------ + template + inline double vertex_block_storage::last_x() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][(idx & block_mask) << 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template + inline double vertex_block_storage::last_y() const + { + if(m_total_vertices) + { + unsigned idx = m_total_vertices - 1; + return m_coord_blocks[idx >> block_shift][((idx & block_mask) << 1) + 1]; + } + return 0.0; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::total_vertices() const + { + return m_total_vertices; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::vertex(unsigned idx, + double* x, double* y) const + { + unsigned nb = idx >> block_shift; + const T* pv = m_coord_blocks[nb] + ((idx & block_mask) << 1); + *x = pv[0]; + *y = pv[1]; + return m_cmd_blocks[nb][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template + inline unsigned vertex_block_storage::command(unsigned idx) const + { + return m_cmd_blocks[idx >> block_shift][idx & block_mask]; + } + + //------------------------------------------------------------------------ + template + void vertex_block_storage::allocate_block(unsigned nb) + { + if(nb >= m_max_blocks) + { + T** new_coords = + pod_allocator::allocate((m_max_blocks + block_pool) * 2); + + unsigned char** new_cmds = + (unsigned char**)(new_coords + m_max_blocks + block_pool); + + if(m_coord_blocks) + { + memcpy(new_coords, + m_coord_blocks, + m_max_blocks * sizeof(T*)); + + memcpy(new_cmds, + m_cmd_blocks, + m_max_blocks * sizeof(unsigned char*)); + + pod_allocator::deallocate(m_coord_blocks, m_max_blocks * 2); + } + m_coord_blocks = new_coords; + m_cmd_blocks = new_cmds; + m_max_blocks += block_pool; + } + m_coord_blocks[nb] = + pod_allocator::allocate(block_size * 2 + + block_size / (sizeof(T) / sizeof(unsigned char))); + + m_cmd_blocks[nb] = + (unsigned char*)(m_coord_blocks[nb] + block_size * 2); + + m_total_blocks++; + } + + //------------------------------------------------------------------------ + template + int8u* vertex_block_storage::storage_ptrs(T** xy_ptr) + { + unsigned nb = m_total_vertices >> block_shift; + if(nb >= m_total_blocks) + { + allocate_block(nb); + } + *xy_ptr = m_coord_blocks[nb] + ((m_total_vertices & block_mask) << 1); + return m_cmd_blocks[nb] + (m_total_vertices & block_mask); + } + + + + + //-----------------------------------------------------poly_plain_adaptor + template class poly_plain_adaptor + { + public: + typedef T value_type; + + poly_plain_adaptor() : + m_data(0), + m_ptr(0), + m_end(0), + m_closed(false), + m_stop(false) + {} + + poly_plain_adaptor(const T* data, unsigned num_points, bool closed) : + m_data(data), + m_ptr(data), + m_end(data + num_points * 2), + m_closed(closed), + m_stop(false) + {} + + void init(const T* data, unsigned num_points, bool closed) + { + m_data = data; + m_ptr = data; + m_end = data + num_points * 2; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_ptr = m_data; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_ptr < m_end) + { + bool first = m_ptr == m_data; + *x = *m_ptr++; + *y = *m_ptr++; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const T* m_data; + const T* m_ptr; + const T* m_end; + bool m_closed; + bool m_stop; + }; + + + + + + //-------------------------------------------------poly_container_adaptor + template class poly_container_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_adaptor() : + m_container(0), + m_index(0), + m_closed(false), + m_stop(false) + {} + + poly_container_adaptor(const Container& data, bool closed) : + m_container(&data), + m_index(0), + m_closed(closed), + m_stop(false) + {} + + void init(const Container& data, bool closed) + { + m_container = &data; + m_index = 0; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = 0; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index < m_container->size()) + { + bool first = m_index == 0; + const vertex_type& v = (*m_container)[m_index++]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + const Container* m_container; + unsigned m_index; + bool m_closed; + bool m_stop; + }; + + + + //-----------------------------------------poly_container_reverse_adaptor + template class poly_container_reverse_adaptor + { + public: + typedef typename Container::value_type vertex_type; + + poly_container_reverse_adaptor() : + m_container(0), + m_index(-1), + m_closed(false), + m_stop(false) + {} + + poly_container_reverse_adaptor(Container& data, bool closed) : + m_container(&data), + m_index(-1), + m_closed(closed), + m_stop(false) + {} + + void init(Container& data, bool closed) + { + m_container = &data; + m_index = m_container->size() - 1; + m_closed = closed; + m_stop = false; + } + + void rewind(unsigned) + { + m_index = m_container->size() - 1; + m_stop = false; + } + + unsigned vertex(double* x, double* y) + { + if(m_index >= 0) + { + bool first = m_index == int(m_container->size() - 1); + const vertex_type& v = (*m_container)[m_index--]; + *x = v.x; + *y = v.y; + return first ? path_cmd_move_to : path_cmd_line_to; + } + *x = *y = 0.0; + if(m_closed && !m_stop) + { + m_stop = true; + return path_cmd_end_poly | path_flags_close; + } + return path_cmd_stop; + } + + private: + Container* m_container; + int m_index; + bool m_closed; + bool m_stop; + }; + + + + + + //--------------------------------------------------------line_adaptor + class line_adaptor + { + public: + typedef double value_type; + + line_adaptor() : m_line(m_coord, 2, false) {} + line_adaptor(double x1, double y1, double x2, double y2) : + m_line(m_coord, 2, false) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + } + + void init(double x1, double y1, double x2, double y2) + { + m_coord[0] = x1; + m_coord[1] = y1; + m_coord[2] = x2; + m_coord[3] = y2; + m_line.rewind(0); + } + + void rewind(unsigned) + { + m_line.rewind(0); + } + + unsigned vertex(double* x, double* y) + { + return m_line.vertex(x, y); + } + + private: + double m_coord[4]; + poly_plain_adaptor m_line; + }; + + + + + + + + + + + + + + //---------------------------------------------------------------path_base + // A container to store vertices with their flags. + // A path consists of a number of contours separated with "move_to" + // commands. The path storage can keep and maintain more than one + // path. + // To navigate to the beginning of a particular path, use rewind(path_id); + // Where path_id is what start_new_path() returns. So, when you call + // start_new_path() you need to store its return value somewhere else + // to navigate to the path afterwards. + // + // See also: vertex_source concept + //------------------------------------------------------------------------ + template class path_base + { + public: + typedef VertexContainer container_type; + typedef path_base self_type; + + //-------------------------------------------------------------------- + path_base() : m_vertices(), m_iterator(0) {} + void remove_all() { m_vertices.remove_all(); m_iterator = 0; } + void free_all() { m_vertices.free_all(); m_iterator = 0; } + + // Make path functions + //-------------------------------------------------------------------- + unsigned start_new_path(); + + void move_to(double x, double y); + void move_rel(double dx, double dy); + + void line_to(double x, double y); + void line_rel(double dx, double dy); + + void hline_to(double x); + void hline_rel(double dx); + + void vline_to(double y); + void vline_rel(double dy); + + void arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y); + + void arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy); + + void curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to); + + void curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to); + + void curve3(double x_to, double y_to); + + void curve3_rel(double dx_to, double dy_to); + + void curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to); + + void curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + void curve4_rel(double x_ctrl2, double y_ctrl2, + double x_to, double y_to); + + + void end_poly(unsigned flags = path_flags_close); + void close_polygon(unsigned flags = path_flags_none); + + // Accessors + //-------------------------------------------------------------------- + const container_type& vertices() const { return m_vertices; } + container_type& vertices() { return m_vertices; } + + unsigned total_vertices() const; + + void rel_to_abs(double* x, double* y) const; + + unsigned last_vertex(double* x, double* y) const; + unsigned prev_vertex(double* x, double* y) const; + + double last_x() const; + double last_y() const; + + unsigned vertex(unsigned idx, double* x, double* y) const; + unsigned command(unsigned idx) const; + + void modify_vertex(unsigned idx, double x, double y); + void modify_vertex(unsigned idx, double x, double y, unsigned cmd); + void modify_command(unsigned idx, unsigned cmd); + + // VertexSource interface + //-------------------------------------------------------------------- + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + // Arrange the orientation of a polygon, all polygons in a path, + // or in all paths. After calling arrange_orientations() or + // arrange_orientations_all_paths(), all the polygons will have + // the same orientation, i.e. path_flags_cw or path_flags_ccw + //-------------------------------------------------------------------- + unsigned arrange_polygon_orientation(unsigned start, path_flags_e orientation); + unsigned arrange_orientations(unsigned path_id, path_flags_e orientation); + void arrange_orientations_all_paths(path_flags_e orientation); + void invert_polygon(unsigned start); + + // Flip all vertices horizontally or vertically, + // between x1 and x2, or between y1 and y2 respectively + //-------------------------------------------------------------------- + void flip_x(double x1, double x2); + void flip_y(double y1, double y2); + + // Concatenate path. The path is added as is. + //-------------------------------------------------------------------- + template + void concat_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + // Join path. The path is joined with the existing one, that is, + // it behaves as if the pen of a plotter was always down (drawing) + template + void join_path(VertexSource& vs, unsigned path_id = 0) + { + double x, y; + unsigned cmd; + vs.rewind(path_id); + cmd = vs.vertex(&x, &y); + if(!is_stop(cmd)) + { + if(is_vertex(cmd)) + { + double x0, y0; + unsigned cmd0 = last_vertex(&x0, &y0); + if(is_vertex(cmd0)) + { + if(calc_distance(x, y, x0, y0) > vertex_dist_epsilon) + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + m_vertices.add_vertex(x, y, cmd); + } + } + else + { + if(is_stop(cmd0)) + { + cmd = path_cmd_move_to; + } + else + { + if(is_move_to(cmd)) cmd = path_cmd_line_to; + } + m_vertices.add_vertex(x, y, cmd); + } + } + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + m_vertices.add_vertex(x, y, is_move_to(cmd) ? + unsigned(path_cmd_line_to) : + cmd); + } + } + } + + // Concatenate polygon/polyline. + //-------------------------------------------------------------------- + template void concat_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor poly(data, num_points, closed); + concat_path(poly); + } + + // Join polygon/polyline continuously. + //-------------------------------------------------------------------- + template void join_poly(const T* data, + unsigned num_points, + bool closed) + { + poly_plain_adaptor poly(data, num_points, closed); + join_path(poly); + } + + //-------------------------------------------------------------------- + void translate(double dx, double dy, unsigned path_id=0); + void translate_all_paths(double dx, double dy); + + //-------------------------------------------------------------------- + template + void transform(const Trans& trans, unsigned path_id=0) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //-------------------------------------------------------------------- + template + void transform_all_paths(const Trans& trans) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + trans.transform(&x, &y); + m_vertices.modify_vertex(idx, x, y); + } + } + } + + + + private: + unsigned perceive_polygon_orientation(unsigned start, unsigned end); + void invert_polygon(unsigned start, unsigned end); + + VertexContainer m_vertices; + unsigned m_iterator; + }; + + //------------------------------------------------------------------------ + template + unsigned path_base::start_new_path() + { + if(!is_stop(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_stop); + } + return m_vertices.total_vertices(); + } + + + //------------------------------------------------------------------------ + template + inline void path_base::rel_to_abs(double* x, double* y) const + { + if(m_vertices.total_vertices()) + { + double x2; + double y2; + if(is_vertex(m_vertices.last_vertex(&x2, &y2))) + { + *x += x2; + *y += y2; + } + } + } + + //------------------------------------------------------------------------ + template + inline void path_base::move_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::move_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_move_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::line_to(double x, double y) + { + m_vertices.add_vertex(x, y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::line_rel(double dx, double dy) + { + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::hline_to(double x) + { + m_vertices.add_vertex(x, last_y(), path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::hline_rel(double dx) + { + double dy = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::vline_to(double y) + { + m_vertices.add_vertex(last_x(), y, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::vline_rel(double dy) + { + double dx = 0; + rel_to_abs(&dx, &dy); + m_vertices.add_vertex(dx, dy, path_cmd_line_to); + } + + //------------------------------------------------------------------------ + template + void path_base::arc_to(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x, double y) + { + if(m_vertices.total_vertices() && is_vertex(m_vertices.last_command())) + { + const double epsilon = 1e-30; + double x0 = 0.0; + double y0 = 0.0; + m_vertices.last_vertex(&x0, &y0); + + rx = fabs(rx); + ry = fabs(ry); + + // Ensure radii are valid + //------------------------- + if(rx < epsilon || ry < epsilon) + { + line_to(x, y); + return; + } + + if(calc_distance(x0, y0, x, y) < epsilon) + { + // If the endpoints (x, y) and (x0, y0) are identical, then this + // is equivalent to omitting the elliptical arc segment entirely. + return; + } + bezier_arc_svg a(x0, y0, rx, ry, angle, large_arc_flag, sweep_flag, x, y); + if(a.radii_ok()) + { + join_path(a); + } + else + { + line_to(x, y); + } + } + else + { + move_to(x, y); + } + } + + //------------------------------------------------------------------------ + template + void path_base::arc_rel(double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double dx, double dy) + { + rel_to_abs(&dx, &dy); + arc_to(rx, ry, angle, large_arc_flag, sweep_flag, dx, dy); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3(double x_ctrl, double y_ctrl, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl, y_ctrl, path_cmd_curve3); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3_rel(double dx_ctrl, double dy_ctrl, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl, &dy_ctrl); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl, dy_ctrl, path_cmd_curve3); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve3); + } + + //------------------------------------------------------------------------ + template + void path_base::curve3(double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(m_vertices.last_vertex(&x0, &y0))) + { + double x_ctrl; + double y_ctrl; + unsigned cmd = m_vertices.prev_vertex(&x_ctrl, &y_ctrl); + if(is_curve(cmd)) + { + x_ctrl = x0 + x0 - x_ctrl; + y_ctrl = y0 + y0 - y_ctrl; + } + else + { + x_ctrl = x0; + y_ctrl = y0; + } + curve3(x_ctrl, y_ctrl, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template + void path_base::curve3_rel(double dx_to, double dy_to) + { + rel_to_abs(&dx_to, &dy_to); + curve3(dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4(double x_ctrl1, double y_ctrl1, + double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + m_vertices.add_vertex(x_ctrl1, y_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(x_ctrl2, y_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(x_to, y_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4_rel(double dx_ctrl1, double dy_ctrl1, + double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl1, &dy_ctrl1); + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + m_vertices.add_vertex(dx_ctrl1, dy_ctrl1, path_cmd_curve4); + m_vertices.add_vertex(dx_ctrl2, dy_ctrl2, path_cmd_curve4); + m_vertices.add_vertex(dx_to, dy_to, path_cmd_curve4); + } + + //------------------------------------------------------------------------ + template + void path_base::curve4(double x_ctrl2, double y_ctrl2, + double x_to, double y_to) + { + double x0; + double y0; + if(is_vertex(last_vertex(&x0, &y0))) + { + double x_ctrl1; + double y_ctrl1; + unsigned cmd = prev_vertex(&x_ctrl1, &y_ctrl1); + if(is_curve(cmd)) + { + x_ctrl1 = x0 + x0 - x_ctrl1; + y_ctrl1 = y0 + y0 - y_ctrl1; + } + else + { + x_ctrl1 = x0; + y_ctrl1 = y0; + } + curve4(x_ctrl1, y_ctrl1, x_ctrl2, y_ctrl2, x_to, y_to); + } + } + + //------------------------------------------------------------------------ + template + void path_base::curve4_rel(double dx_ctrl2, double dy_ctrl2, + double dx_to, double dy_to) + { + rel_to_abs(&dx_ctrl2, &dy_ctrl2); + rel_to_abs(&dx_to, &dy_to); + curve4(dx_ctrl2, dy_ctrl2, dx_to, dy_to); + } + + //------------------------------------------------------------------------ + template + inline void path_base::end_poly(unsigned flags) + { + if(is_vertex(m_vertices.last_command())) + { + m_vertices.add_vertex(0.0, 0.0, path_cmd_end_poly | flags); + } + } + + //------------------------------------------------------------------------ + template + inline void path_base::close_polygon(unsigned flags) + { + end_poly(path_flags_close | flags); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::total_vertices() const + { + return m_vertices.total_vertices(); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::last_vertex(double* x, double* y) const + { + return m_vertices.last_vertex(x, y); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::prev_vertex(double* x, double* y) const + { + return m_vertices.prev_vertex(x, y); + } + + //------------------------------------------------------------------------ + template + inline double path_base::last_x() const + { + return m_vertices.last_x(); + } + + //------------------------------------------------------------------------ + template + inline double path_base::last_y() const + { + return m_vertices.last_y(); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::vertex(unsigned idx, double* x, double* y) const + { + return m_vertices.vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::command(unsigned idx) const + { + return m_vertices.command(idx); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_vertex(unsigned idx, double x, double y) + { + m_vertices.modify_vertex(idx, x, y); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + m_vertices.modify_vertex(idx, x, y, cmd); + } + + //------------------------------------------------------------------------ + template + void path_base::modify_command(unsigned idx, unsigned cmd) + { + m_vertices.modify_command(idx, cmd); + } + + //------------------------------------------------------------------------ + template + inline void path_base::rewind(unsigned path_id) + { + m_iterator = path_id; + } + + //------------------------------------------------------------------------ + template + inline unsigned path_base::vertex(double* x, double* y) + { + if(m_iterator >= m_vertices.total_vertices()) return path_cmd_stop; + return m_vertices.vertex(m_iterator++, x, y); + } + + //------------------------------------------------------------------------ + template + unsigned path_base::perceive_polygon_orientation(unsigned start, + unsigned end) + { + // Calculate signed area (double area to be exact) + //--------------------- + unsigned np = end - start; + double area = 0.0; + unsigned i; + for(i = 0; i < np; i++) + { + double x1, y1, x2, y2; + m_vertices.vertex(start + i, &x1, &y1); + m_vertices.vertex(start + (i + 1) % np, &x2, &y2); + area += x1 * y2 - y1 * x2; + } + return (area < 0.0) ? path_flags_cw : path_flags_ccw; + } + + //------------------------------------------------------------------------ + template + void path_base::invert_polygon(unsigned start, unsigned end) + { + unsigned i; + unsigned tmp_cmd = m_vertices.command(start); + + --end; // Make "end" inclusive + + // Shift all commands to one position + for(i = start; i < end; i++) + { + m_vertices.modify_command(i, m_vertices.command(i + 1)); + } + + // Assign starting command to the ending command + m_vertices.modify_command(end, tmp_cmd); + + // Reverse the polygon + while(end > start) + { + m_vertices.swap_vertices(start++, end--); + } + } + + //------------------------------------------------------------------------ + template + void path_base::invert_polygon(unsigned start) + { + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + invert_polygon(start, end); + } + + //------------------------------------------------------------------------ + template + unsigned path_base::arrange_polygon_orientation(unsigned start, + path_flags_e orientation) + { + if(orientation == path_flags_none) return start; + + // Skip all non-vertices at the beginning + while(start < m_vertices.total_vertices() && + !is_vertex(m_vertices.command(start))) ++start; + + // Skip all insignificant move_to + while(start+1 < m_vertices.total_vertices() && + is_move_to(m_vertices.command(start)) && + is_move_to(m_vertices.command(start+1))) ++start; + + // Find the last vertex + unsigned end = start + 1; + while(end < m_vertices.total_vertices() && + !is_next_poly(m_vertices.command(end))) ++end; + + if(end - start > 2) + { + if(perceive_polygon_orientation(start, end) != unsigned(orientation)) + { + // Invert polygon, set orientation flag, and skip all end_poly + invert_polygon(start, end); + unsigned cmd; + while(end < m_vertices.total_vertices() && + is_end_poly(cmd = m_vertices.command(end))) + { + m_vertices.modify_command(end++, set_orientation(cmd, orientation)); + } + } + } + return end; + } + + //------------------------------------------------------------------------ + template + unsigned path_base::arrange_orientations(unsigned start, + path_flags_e orientation) + { + if(orientation != path_flags_none) + { + while(start < m_vertices.total_vertices()) + { + start = arrange_polygon_orientation(start, orientation); + if(is_stop(m_vertices.command(start))) + { + ++start; + break; + } + } + } + return start; + } + + //------------------------------------------------------------------------ + template + void path_base::arrange_orientations_all_paths(path_flags_e orientation) + { + if(orientation != path_flags_none) + { + unsigned start = 0; + while(start < m_vertices.total_vertices()) + { + start = arrange_orientations(start, orientation); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::flip_x(double x1, double x2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x2 - x + x1, y); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::flip_y(double y1, double y2) + { + unsigned i; + double x, y; + for(i = 0; i < m_vertices.total_vertices(); i++) + { + unsigned cmd = m_vertices.vertex(i, &x, &y); + if(is_vertex(cmd)) + { + m_vertices.modify_vertex(i, x, y2 - y + y1); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::translate(double dx, double dy, unsigned path_id) + { + unsigned num_ver = m_vertices.total_vertices(); + for(; path_id < num_ver; path_id++) + { + double x, y; + unsigned cmd = m_vertices.vertex(path_id, &x, &y); + if(is_stop(cmd)) break; + if(is_vertex(cmd)) + { + x += dx; + y += dy; + m_vertices.modify_vertex(path_id, x, y); + } + } + } + + //------------------------------------------------------------------------ + template + void path_base::translate_all_paths(double dx, double dy) + { + unsigned idx; + unsigned num_ver = m_vertices.total_vertices(); + for(idx = 0; idx < num_ver; idx++) + { + double x, y; + if(is_vertex(m_vertices.vertex(idx, &x, &y))) + { + x += dx; + y += dy; + m_vertices.modify_vertex(idx, x, y); + } + } + } + + //-----------------------------------------------------vertex_stl_storage + template class vertex_stl_storage + { + public: + typedef typename Container::value_type vertex_type; + typedef typename vertex_type::value_type value_type; + + void remove_all() { m_vertices.clear(); } + void free_all() { m_vertices.clear(); } + + void add_vertex(double x, double y, unsigned cmd) + { + m_vertices.push_back(vertex_type(value_type(x), + value_type(y), + int8u(cmd))); + } + + void modify_vertex(unsigned idx, double x, double y) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + } + + void modify_vertex(unsigned idx, double x, double y, unsigned cmd) + { + vertex_type& v = m_vertices[idx]; + v.x = value_type(x); + v.y = value_type(y); + v.cmd = int8u(cmd); + } + + void modify_command(unsigned idx, unsigned cmd) + { + m_vertices[idx].cmd = int8u(cmd); + } + + void swap_vertices(unsigned v1, unsigned v2) + { + vertex_type t = m_vertices[v1]; + m_vertices[v1] = m_vertices[v2]; + m_vertices[v2] = t; + } + + unsigned last_command() const + { + return m_vertices.size() ? + m_vertices[m_vertices.size() - 1].cmd : + path_cmd_stop; + } + + unsigned last_vertex(double* x, double* y) const + { + if(m_vertices.size() == 0) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 1, x, y); + } + + unsigned prev_vertex(double* x, double* y) const + { + if(m_vertices.size() < 2) + { + *x = *y = 0.0; + return path_cmd_stop; + } + return vertex(m_vertices.size() - 2, x, y); + } + + double last_x() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].x : 0.0; + } + + double last_y() const + { + return m_vertices.size() ? m_vertices[m_vertices.size() - 1].y : 0.0; + } + + unsigned total_vertices() const + { + return m_vertices.size(); + } + + unsigned vertex(unsigned idx, double* x, double* y) const + { + const vertex_type& v = m_vertices[idx]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + unsigned command(unsigned idx) const + { + return m_vertices[idx].cmd; + } + + private: + Container m_vertices; + }; + + //-----------------------------------------------------------path_storage + typedef path_base > path_storage; + + // Example of declarations path_storage with pod_bvector as a container + //----------------------------------------------------------------------- + //typedef path_base > > path_storage; + +} + + + +// Example of declarations path_storage with std::vector as a container +//--------------------------------------------------------------------------- +//#include +//namespace agg +//{ +// typedef path_base > > stl_path_storage; +//} + + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage_integer.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage_integer.h new file mode 100644 index 00000000000..7c48355993b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_path_storage_integer.h @@ -0,0 +1,295 @@ +//---------------------------------------------------------------------------- +// 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_PATH_STORAGE_INTEGER_INCLUDED +#define AGG_PATH_STORAGE_INTEGER_INCLUDED + +#include +#include "agg_array.h" + +namespace agg +{ + //---------------------------------------------------------vertex_integer + template struct vertex_integer + { + enum path_cmd + { + cmd_move_to = 0, + cmd_line_to = 1, + cmd_curve3 = 2, + cmd_curve4 = 3 + }; + + enum coord_scale_e + { + coord_shift = CoordShift, + coord_scale = 1 << coord_shift + }; + + T x,y; + vertex_integer() {} + vertex_integer(T x_, T y_, unsigned flag) : + x(((x_ << 1) & ~1) | (flag & 1)), + y(((y_ << 1) & ~1) | (flag >> 1)) {} + + unsigned vertex(double* x_, double* y_, + double dx=0, double dy=0, + double scale=1.0) const + { + *x_ = dx + (double(x >> 1) / coord_scale) * scale; + *y_ = dy + (double(y >> 1) / coord_scale) * scale; + switch(((y & 1) << 1) | (x & 1)) + { + case cmd_move_to: return path_cmd_move_to; + case cmd_line_to: return path_cmd_line_to; + case cmd_curve3: return path_cmd_curve3; + case cmd_curve4: return path_cmd_curve4; + } + return path_cmd_stop; + } + }; + + + //---------------------------------------------------path_storage_integer + template class path_storage_integer + { + public: + typedef T value_type; + typedef vertex_integer vertex_integer_type; + + //-------------------------------------------------------------------- + path_storage_integer() : m_storage(), m_vertex_idx(0), m_closed(true) {} + + //-------------------------------------------------------------------- + void remove_all() { m_storage.remove_all(); } + + //-------------------------------------------------------------------- + void move_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_move_to)); + } + + //-------------------------------------------------------------------- + void line_to(T x, T y) + { + m_storage.add(vertex_integer_type(x, y, vertex_integer_type::cmd_line_to)); + } + + //-------------------------------------------------------------------- + void curve3(T x_ctrl, T y_ctrl, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl, y_ctrl, vertex_integer_type::cmd_curve3)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve3)); + } + + //-------------------------------------------------------------------- + void curve4(T x_ctrl1, T y_ctrl1, + T x_ctrl2, T y_ctrl2, + T x_to, T y_to) + { + m_storage.add(vertex_integer_type(x_ctrl1, y_ctrl1, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_ctrl2, y_ctrl2, vertex_integer_type::cmd_curve4)); + m_storage.add(vertex_integer_type(x_to, y_to, vertex_integer_type::cmd_curve4)); + } + + //-------------------------------------------------------------------- + void close_polygon() {} + + //-------------------------------------------------------------------- + unsigned size() const { return m_storage.size(); } + unsigned vertex(unsigned idx, double* x, double* y) const + { + return m_storage[idx].vertex(x, y); + } + + //-------------------------------------------------------------------- + unsigned byte_size() const { return m_storage.size() * sizeof(vertex_integer_type); } + void serialize(int8u* ptr) const + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + memcpy(ptr, &m_storage[i], sizeof(vertex_integer_type)); + ptr += sizeof(vertex_integer_type); + } + } + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_vertex_idx = 0; + m_closed = true; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_storage.size() < 2 || m_vertex_idx > m_storage.size()) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + if(m_vertex_idx == m_storage.size()) + { + *x = 0; + *y = 0; + ++m_vertex_idx; + return path_cmd_end_poly | path_flags_close; + } + unsigned cmd = m_storage[m_vertex_idx].vertex(x, y); + if(is_move_to(cmd) && !m_closed) + { + *x = 0; + *y = 0; + m_closed = true; + return path_cmd_end_poly | path_flags_close; + } + m_closed = false; + ++m_vertex_idx; + return cmd; + } + + //-------------------------------------------------------------------- + rect_d bounding_rect() const + { + rect_d bounds(1e100, 1e100, -1e100, -1e100); + if(m_storage.size() == 0) + { + bounds.x1 = bounds.y1 = bounds.x2 = bounds.y2 = 0.0; + } + else + { + unsigned i; + for(i = 0; i < m_storage.size(); i++) + { + double x, y; + m_storage[i].vertex(&x, &y); + if(x < bounds.x1) bounds.x1 = x; + if(y < bounds.y1) bounds.y1 = y; + if(x > bounds.x2) bounds.x2 = x; + if(y > bounds.y2) bounds.y2 = y; + } + } + return bounds; + } + + private: + pod_bvector m_storage; + unsigned m_vertex_idx; + bool m_closed; + }; + + + + + //-----------------------------------------serialized_integer_path_adaptor + template class serialized_integer_path_adaptor + { + public: + typedef vertex_integer vertex_integer_type; + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0.0), + m_dy(0.0), + m_scale(1.0), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + serialized_integer_path_adaptor(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(dx), + m_dy(dy), + m_vertices(0) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, + double dx, double dy, double scale=1.0) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = dx; + m_dy = dy; + m_scale = scale; + m_vertices = 0; + } + + + //-------------------------------------------------------------------- + void rewind(unsigned) + { + m_ptr = m_data; + m_vertices = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + if(m_data == 0 || m_ptr > m_end) + { + *x = 0; + *y = 0; + return path_cmd_stop; + } + + if(m_ptr == m_end) + { + *x = 0; + *y = 0; + m_ptr += sizeof(vertex_integer_type); + return path_cmd_end_poly | path_flags_close; + } + + vertex_integer_type v; + memcpy(&v, m_ptr, sizeof(vertex_integer_type)); + unsigned cmd = v.vertex(x, y, m_dx, m_dy, m_scale); + if(is_move_to(cmd) && m_vertices > 2) + { + *x = 0; + *y = 0; + m_vertices = 0; + return path_cmd_end_poly | path_flags_close; + } + ++m_vertices; + m_ptr += sizeof(vertex_integer_type); + return cmd; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + double m_dx; + double m_dy; + double m_scale; + unsigned m_vertices; + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pattern_filters_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pattern_filters_rgba.h new file mode 100644 index 00000000000..c1d174cacbf --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pattern_filters_rgba.h @@ -0,0 +1,123 @@ +//---------------------------------------------------------------------------- +// 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_PATTERN_FILTERS_RGBA8_INCLUDED +#define AGG_PATTERN_FILTERS_RGBA8_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_color_rgba.h" + + +namespace agg +{ + + //=======================================================pattern_filter_nn + template struct pattern_filter_nn + { + typedef ColorT color_type; + static unsigned dilation() { return 0; } + + static void AGG_INLINE pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static void AGG_INLINE pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y >> line_subpixel_shift] + [x >> line_subpixel_shift]; + } + }; + + typedef pattern_filter_nn pattern_filter_nn_rgba8; + typedef pattern_filter_nn pattern_filter_nn_rgba16; + + + //===========================================pattern_filter_bilinear_rgba + template struct pattern_filter_bilinear_rgba + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + + static unsigned dilation() { return 1; } + + static AGG_INLINE void pixel_low_res(color_type const* const* buf, + color_type* p, int x, int y) + { + *p = buf[y][x]; + } + + static AGG_INLINE void pixel_high_res(color_type const* const* buf, + color_type* p, int x, int y) + { + calc_type r, g, b, a; + r = g = b = a = 0; + + calc_type weight; + int x_lr = x >> line_subpixel_shift; + int y_lr = y >> line_subpixel_shift; + + x &= line_subpixel_mask; + y &= line_subpixel_mask; + const color_type* ptr = buf[y_lr] + x_lr; + + weight = (line_subpixel_scale - x) * + (line_subpixel_scale - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * (line_subpixel_scale - y); + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ptr = buf[y_lr + 1] + x_lr; + + weight = (line_subpixel_scale - x) * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + ++ptr; + + weight = x * y; + r += weight * ptr->r; + g += weight * ptr->g; + b += weight * ptr->b; + a += weight * ptr->a; + + p->r = (value_type)color_type::downshift(r, line_subpixel_shift * 2); + p->g = (value_type)color_type::downshift(g, line_subpixel_shift * 2); + p->b = (value_type)color_type::downshift(b, line_subpixel_shift * 2); + p->a = (value_type)color_type::downshift(a, line_subpixel_shift * 2); + } + }; + + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba8; + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba16; + typedef pattern_filter_bilinear_rgba pattern_filter_bilinear_rgba32; +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_amask_adaptor.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_amask_adaptor.h new file mode 100644 index 00000000000..cf39c54ad55 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_amask_adaptor.h @@ -0,0 +1,240 @@ +//---------------------------------------------------------------------------- +// 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_AMASK_ADAPTOR_INCLUDED +#define AGG_PIXFMT_AMASK_ADAPTOR_INCLUDED + + +#include +#include "agg_array.h" +#include "agg_rendering_buffer.h" + + +namespace agg +{ + //==================================================pixfmt_amask_adaptor + template class pixfmt_amask_adaptor + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef AlphaMask amask_type; + typedef typename amask_type::cover_type cover_type; + + private: + enum span_extra_tail_e { span_extra_tail = 256 }; + + void realloc_span(unsigned len) + { + if(len > m_span.size()) + { + m_span.resize(len + span_extra_tail); + } + } + + void init_span(unsigned len) + { + realloc_span(len); + memset(&m_span[0], amask_type::cover_full, len * sizeof(cover_type)); + } + + void init_span(unsigned len, const cover_type* covers) + { + realloc_span(len); + memcpy(&m_span[0], covers, len * sizeof(cover_type)); + } + + + public: + pixfmt_amask_adaptor(pixfmt_type& pixf, amask_type& mask) : + m_pixf(&pixf), m_mask(&mask), m_span() + {} + + void attach_pixfmt(pixfmt_type& pixf) { m_pixf = &pixf; } + void attach_alpha_mask(amask_type& mask) { m_mask = &mask; } + + //-------------------------------------------------------------------- + template + bool attach_pixfmt(PixFmt2& pixf, int x1, int y1, int x2, int y2) + { + return m_pixf->attach(pixf, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_pixf->width(); } + unsigned height() const { return m_pixf->height(); } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) + { + return m_pixf->pixel(x, y); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->blend_pixel(x, y, c, m_mask->pixel(x, y)); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + m_pixf->blend_pixel(x, y, c, m_mask->combine_pixel(x, y, cover)); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + cover_type cover) + { + init_span(len); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + cover_type cover) + { + init_span(len); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + m_pixf->copy_from(from, xdst, ydst, xsrc, ysrc, len); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const cover_type* covers) + { + init_span(len, covers); + m_mask->combine_hspan(x, y, &m_span[0], len); + m_pixf->blend_solid_hspan(x, y, len, c, &m_span[0]); + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const cover_type* covers) + { + init_span(len, covers); + m_mask->combine_vspan(x, y, &m_span[0], len); + m_pixf->blend_solid_vspan(x, y, len, c, &m_span[0]); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover_full); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover_full); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(covers) + { + init_span(len, covers); + m_mask->combine_hspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); + m_mask->fill_hspan(x, y, &m_span[0], len); + } + m_pixf->blend_color_hspan(x, y, len, colors, &m_span[0], cover); + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + if(covers) + { + init_span(len, covers); + m_mask->combine_vspan(x, y, &m_span[0], len); + } + else + { + realloc_span(len); + m_mask->fill_vspan(x, y, &m_span[0], len); + } + m_pixf->blend_color_vspan(x, y, len, colors, &m_span[0], cover); + } + + private: + pixfmt_type* m_pixf; + const amask_type* m_mask; + pod_array m_span; + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_base.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_base.h new file mode 100644 index 00000000000..57ae19cfe04 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/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/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_gray.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_gray.h new file mode 100644 index 00000000000..438f04d33d4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_gray.h @@ -0,0 +1,737 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_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; + typedef typename color_type::long_type long_type; + + // 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) + { + 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); + } + }; + + + //======================================================blender_gray_pre + template struct blender_gray_pre + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // 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) + { + blend_pix(p, color_type::mult_cover(cv, cover), color_type::mult_cover(alpha, cover)); + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type cv, value_type alpha) + { + *p = color_type::prelerp(*p, cv, alpha); + } + }; + + + + //=====================================================apply_gamma_dir_gray + template class apply_gamma_dir_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.dir(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_gray + template class apply_gamma_inv_gray + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_gray(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + *p = m_gamma.inv(*p); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=================================================pixfmt_alpha_blend_gray + 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; + typedef typename blender_type::color_type color_type; + typedef int order_type; // A fake one + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + pix_width = sizeof(value_type) * Step, + pix_step = Step, + pix_offset = Offset, + }; + struct pixel_type + { + value_type c[pix_step]; + + 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 this + 1; + } + + const pixel_type* next() const + { + return this + 1; + } + + pixel_type* advance(int n) + { + return this + n; + } + + const pixel_type* advance(int n) const + { + return this + n; + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type v, value_type a, + unsigned cover) + { + 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()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c); + } + else + { + blend_pix(p, c); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_gray(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + //-------------------------------------------------------------------- + + template + 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))) + { + int stride = pixf.stride(); + 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); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + 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); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + 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) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + 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) + { + 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(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(c); + p = p->next(); + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (c.is_opaque() && cover == cover_mask) + { + do + { + p->set(c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for (y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_gray(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_gray(g)); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + 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, + const color_type& color, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + 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)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + 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, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + private: + rbuf_type* m_rbuf; + }; + + typedef blender_gray blender_gray8; + typedef blender_gray blender_sgray8; + typedef blender_gray blender_gray16; + typedef blender_gray blender_gray32; + + 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/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb.h new file mode 100644 index 00000000000..7095fbce58d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb.h @@ -0,0 +1,994 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_RGB_INCLUDED +#define AGG_PIXFMT_RGB_INCLUDED + +#include +#include "agg_pixfmt_base.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //=====================================================apply_gamma_dir_rgb + template class apply_gamma_dir_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + + //=====================================================apply_gamma_inv_rgb + template class apply_gamma_inv_rgb + { + public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgb(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + //=========================================================blender_rgb + template + struct blender_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // 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 cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::lerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::lerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::lerp(p[Order::B], cb, alpha); + } + }; + + //======================================================blender_rgb_pre + template + struct blender_rgb_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, + color_type::mult_cover(cr, cover), + color_type::mult_cover(cg, cover), + color_type::mult_cover(cb, cover), + color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha); + } + }; + + //===================================================blender_rgb_gamma + template + class blender_rgb_gamma : public blender_base + { + public: + typedef ColorT color_type; + typedef Order order_type; + typedef Gamma gamma_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + blender_rgb_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + calc_type r = m_gamma->dir(p[Order::R]); + calc_type g = m_gamma->dir(p[Order::G]); + calc_type b = m_gamma->dir(p[Order::B]); + p[Order::R] = m_gamma->inv(color_type::downscale((m_gamma->dir(cr) - r) * alpha) + r); + p[Order::G] = m_gamma->inv(color_type::downscale((m_gamma->dir(cg) - g) * alpha) + g); + p[Order::B] = m_gamma->inv(color_type::downscale((m_gamma->dir(cb) - b) * alpha) + b); + } + + private: + const gamma_type* m_gamma; + }; + + + //==================================================pixfmt_alpha_blend_rgb + template + class pixfmt_alpha_blend_rgb + { + public: + typedef pixfmt_rgb_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef Blender blender_type; + typedef typename rbuf_type::row_data row_data; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + pix_step = Step, + pix_offset = Offset, + pix_width = sizeof(value_type) * pix_step + }; + struct pixel_type + { + value_type c[pix_step]; + + void set(value_type r, value_type g, value_type b) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b); + } + + void get(value_type& r, value_type& g, value_type& b) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B]); + } + + pixel_type* next() + { + return this + 1; + } + + const pixel_type* next() const + { + return this + 1; + } + + pixel_type* advance(int n) + { + return this + n; + } + + const pixel_type* advance(int n) const + { + return this + n; + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type r, value_type g, value_type b, value_type a, + unsigned cover) + { + m_blender.blend_pix(p->c, r, g, b, a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, + value_type r, value_type g, value_type b, value_type a) + { + m_blender.blend_pix(p->c, r, g, b, a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c); + } + else + { + blend_pix(p, c); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb(rbuf_type& rb) : + m_rbuf(&rb) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + 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))) + { + int stride = pixf.stride(); + 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); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step + pix_offset); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + 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) + { + // RGB 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) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + 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) + { + 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(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(c); + p = p->next(); + } + while(--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (c.is_opaque() && cover == cover_mask) + { + do + { + p->set(c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + do + { + pix_value_ptr(x, y++, 1)->set(c); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + for (unsigned y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgb(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgb(g)); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from an RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + typedef typename SrcPixelFormatRenderer::order_type src_order; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + value_type alpha = psrc->c[src_order::A]; + if (alpha <= color_type::empty_value()) + { + if (alpha >= color_type::full_value()) + { + pdst->c[order_type::R] = psrc->c[src_order::R]; + pdst->c[order_type::G] = psrc->c[src_order::G]; + pdst->c[order_type::B] = psrc->c[src_order::B]; + } + else + { + blend_pix(pdst, + psrc->c[src_order::R], + psrc->c[src_order::G], + psrc->c[src_order::B], + alpha); + } + } + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(pdst, psrc->get(), cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. + template + 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::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)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + 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, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + const color_type& color = color_lut[psrc->c[0]]; + blend_pix(pdst, color); + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + else + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while(--len); + } + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + //----------------------------------------------------------------------- + typedef blender_rgb blender_rgb24; + typedef blender_rgb blender_bgr24; + typedef blender_rgb blender_srgb24; + typedef blender_rgb blender_sbgr24; + typedef blender_rgb blender_rgb48; + typedef blender_rgb blender_bgr48; + typedef blender_rgb blender_rgb96; + typedef blender_rgb blender_bgr96; + + typedef blender_rgb_pre blender_rgb24_pre; + typedef blender_rgb_pre blender_bgr24_pre; + typedef blender_rgb_pre blender_srgb24_pre; + typedef blender_rgb_pre blender_sbgr24_pre; + typedef blender_rgb_pre blender_rgb48_pre; + typedef blender_rgb_pre blender_bgr48_pre; + typedef blender_rgb_pre blender_rgb96_pre; + typedef blender_rgb_pre blender_bgr96_pre; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgb24; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr24; + typedef pixfmt_alpha_blend_rgb pixfmt_srgb24; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgr24; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb48; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr48; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb96; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr96; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgb24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_srgb24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgr24_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb48_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr48_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgb96_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgr96_pre; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx32; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb32; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr32; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx32; + typedef pixfmt_alpha_blend_rgb pixfmt_srgbx32; + typedef pixfmt_alpha_blend_rgb pixfmt_sxrgb32; + typedef pixfmt_alpha_blend_rgb pixfmt_sxbgr32; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgrx32; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx64; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb64; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr64; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx64; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx128; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb128; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr128; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx128; + + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_srgbx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sxrgb32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sxbgr32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_sbgrx32_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx64_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_rgbx128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xrgb128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_xbgr128_pre; + typedef pixfmt_alpha_blend_rgb pixfmt_bgrx128_pre; + + + //-----------------------------------------------------pixfmt_rgb24_gamma + template class pixfmt_rgb24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_rgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_srgb24_gamma + template class pixfmt_srgb24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_srgb24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr24_gamma + template class pixfmt_bgr24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_bgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_sbgr24_gamma + template class pixfmt_sbgr24_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_sbgr24_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_rgb48_gamma + template class pixfmt_rgb48_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_rgb48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + + //-----------------------------------------------------pixfmt_bgr48_gamma + template class pixfmt_bgr48_gamma : + public pixfmt_alpha_blend_rgb, rendering_buffer, 3> + { + public: + pixfmt_bgr48_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb, rendering_buffer, 3>(rb) + { + this->blender().gamma(g); + } + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb_packed.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb_packed.h new file mode 100644 index 00000000000..d879517de6e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgb_packed.h @@ -0,0 +1,1312 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_RGB_PACKED_INCLUDED +#define AGG_PIXFMT_RGB_PACKED_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + //=========================================================blender_rgb555 + struct blender_rgb555 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) >> 1) & 0x7C00) | + ((((cg - g) * alpha + (g << 8)) >> 6) & 0x03E0) | + (((cb - b) * alpha + (b << 8)) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + //=====================================================blender_rgb555_pre + struct blender_rgb555_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 7) & 0xF8; + calc_type g = (rgb >> 2) & 0xF8; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 1) & 0x7C00) | + (((g * alpha + cg * cover) >> 6) & 0x03E0) | + ((b * alpha + cb * cover) >> 11) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + }; + + + + + //=====================================================blender_rgb555_gamma + template class blender_rgb555_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb555_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 7) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 2) & 0xF8); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 7) & 0x7C00) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 2) & 0x03E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3) | 0x8000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 7) | + ((g & 0xF8) << 2) | + (b >> 3) | 0x8000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 7) & 0xF8, + (p >> 2) & 0xF8, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + + + //=========================================================blender_rgb565 + struct blender_rgb565 + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 8)) ) & 0xF800) | + ((((cg - g) * alpha + (g << 8)) >> 5) & 0x07E0) | + (((cb - b) * alpha + (b << 8)) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_pre + struct blender_rgb565_pre + { + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + pixel_type rgb = *p; + calc_type r = (rgb >> 8) & 0xF8; + calc_type g = (rgb >> 3) & 0xFC; + calc_type b = (rgb << 3) & 0xF8; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xF800) | + (((g * alpha + cg * cover) >> 5 ) & 0x07E0) | + ((b * alpha + cb * cover) >> 11)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + }; + + + + //=====================================================blender_rgb565_gamma + template class blender_rgb565_gamma + { + public: + typedef rgba8 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int16u pixel_type; + typedef Gamma gamma_type; + + blender_rgb565_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 8) & 0xF8); + calc_type g = m_gamma->dir((rgb >> 3) & 0xFC); + calc_type b = m_gamma->dir((rgb << 3) & 0xF8); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 8)) >> 8) << 8) & 0xF800) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 8)) >> 8) << 3) & 0x07E0) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 8)) >> 8) >> 3)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 8) & 0xF8, + (p >> 3) & 0xFC, + (p << 3) & 0xF8); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbAAA + struct blender_rgbAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //==================================================blender_rgbAAA_pre + struct blender_rgbAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 14) & 0xFFC0; + calc_type g = (rgb >> 4) & 0xFFC0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((b * alpha + cb * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbAAA_gamma + template class blender_rgbAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((rgb >> 4) & 0xFFC0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (b >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 14) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p << 6) & 0xFFC0); + } + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrAAA + struct blender_bgrAAA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) >> 2) & 0x3FF00000) | + ((((cg - g) * alpha + (g << 16)) >> 12) & 0x000FFC00) | + (((cr - r) * alpha + (r << 16)) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_pre + struct blender_bgrAAA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 14) & 0xFFC0; + calc_type g = (bgr >> 4) & 0xFFC0; + calc_type r = (bgr << 6) & 0xFFC0; + *p = (pixel_type) + ((((b * alpha + cb * cover) >> 2) & 0x3FF00000) | + (((g * alpha + cg * cover) >> 12) & 0x000FFC00) | + ((r * alpha + cr * cover) >> 22) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrAAA_gamma + template class blender_bgrAAA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrAAA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 14) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 4) & 0xFFC0); + calc_type r = m_gamma->dir((bgr << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 14) & 0x3FF00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 4 ) & 0x000FFC00) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 6 ) | 0xC0000000); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 14) | + ((g & 0xFFC0) << 4) | + (r >> 6) | 0xC0000000); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 6) & 0xFFC0, + (p >> 4) & 0xFFC0, + (p >> 14) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //=====================================================blender_rgbBBA + struct blender_rgbBBA + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + (((((cr - r) * alpha + (r << 16)) ) & 0xFFE00000) | + ((((cg - g) * alpha + (g << 16)) >> 11) & 0x001FFC00) | + (((cb - b) * alpha + (b << 16)) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + //=================================================blender_rgbBBA_pre + struct blender_rgbBBA_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type rgb = *p; + calc_type r = (rgb >> 16) & 0xFFE0; + calc_type g = (rgb >> 5) & 0xFFE0; + calc_type b = (rgb << 6) & 0xFFC0; + *p = (pixel_type) + ((((r * alpha + cr * cover) ) & 0xFFE00000) | + (((g * alpha + cg * cover) >> 11) & 0x001FFC00) | + ((b * alpha + cb * cover) >> 22)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + }; + + + + //=================================================blender_rgbBBA_gamma + template class blender_rgbBBA_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_rgbBBA_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type rgb = *p; + calc_type r = m_gamma->dir((rgb >> 16) & 0xFFE0); + calc_type g = m_gamma->dir((rgb >> 5) & 0xFFE0); + calc_type b = m_gamma->dir((rgb << 6) & 0xFFC0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) << 16) & 0xFFE00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 5 ) & 0x001FFC00) | + (m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) >> 6 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((r & 0xFFE0) << 16) | ((g & 0xFFE0) << 5) | (b >> 6)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p >> 16) & 0xFFE0, + (p >> 5) & 0xFFE0, + (p << 6) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + //=====================================================blender_bgrABB + struct blender_bgrABB + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + (((((cb - b) * alpha + (b << 16)) ) & 0xFFC00000) | + ((((cg - g) * alpha + (g << 16)) >> 10) & 0x003FF800) | + (((cr - r) * alpha + (r << 16)) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + //=================================================blender_bgrABB_pre + struct blender_bgrABB_pre + { + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + + static AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) + { + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (color_type::base_shift - 8); + pixel_type bgr = *p; + calc_type b = (bgr >> 16) & 0xFFC0; + calc_type g = (bgr >> 6) & 0xFFE0; + calc_type r = (bgr << 5) & 0xFFE0; + *p = (pixel_type) + ((((b * alpha + cb * cover) ) & 0xFFC00000) | + (((g * alpha + cg * cover) >> 10) & 0x003FF800) | + ((r * alpha + cr * cover) >> 21)); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + }; + + + + //=================================================blender_bgrABB_gamma + template class blender_bgrABB_gamma + { + public: + typedef rgba16 color_type; + typedef color_type::value_type value_type; + typedef color_type::calc_type calc_type; + typedef int32u pixel_type; + typedef Gamma gamma_type; + + blender_bgrABB_gamma() : m_gamma(0) {} + void gamma(const gamma_type& g) { m_gamma = &g; } + + AGG_INLINE void blend_pix(pixel_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned) + { + pixel_type bgr = *p; + calc_type b = m_gamma->dir((bgr >> 16) & 0xFFC0); + calc_type g = m_gamma->dir((bgr >> 6) & 0xFFE0); + calc_type r = m_gamma->dir((bgr << 5) & 0xFFE0); + *p = (pixel_type) + (((m_gamma->inv(((m_gamma->dir(cb) - b) * alpha + (b << 16)) >> 16) << 16) & 0xFFC00000) | + ((m_gamma->inv(((m_gamma->dir(cg) - g) * alpha + (g << 16)) >> 16) << 6 ) & 0x003FF800) | + (m_gamma->inv(((m_gamma->dir(cr) - r) * alpha + (r << 16)) >> 16) >> 5 )); + } + + static AGG_INLINE pixel_type make_pix(unsigned r, unsigned g, unsigned b) + { + return (pixel_type)(((b & 0xFFC0) << 16) | ((g & 0xFFE0) << 6) | (r >> 5)); + } + + static AGG_INLINE color_type make_color(pixel_type p) + { + return color_type((p << 5) & 0xFFE0, + (p >> 6) & 0xFFE0, + (p >> 16) & 0xFFC0); + } + + private: + const Gamma* m_gamma; + }; + + + + //===========================================pixfmt_alpha_blend_rgb_packed + template class pixfmt_alpha_blend_rgb_packed + { + public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::pixel_type pixel_type; + 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 + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type), + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + *p = m_blender.make_pix(c.r, c.g, c.b); + } + else + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + } + } + + public: + //-------------------------------------------------------------------- + explicit pixfmt_alpha_blend_rgb_packed(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + 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))) + { + int stride = pixf.stride(); + 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); + return true; + } + return false; + } + + Blender& blender() { return m_blender; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + AGG_INLINE void make_pix(int8u* p, const color_type& c) + { + *(pixel_type*)p = m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_blender.make_color(((pixel_type*)m_rbuf->row_ptr(y))[x]); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + ((pixel_type*) + m_rbuf->row_ptr(x, y, 1))[x] = + m_blender.make_pix(c.r, c.g, c.b); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y, 1) + x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = v; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + *p++ = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix(p, c.r, c.g, c.b, alpha, cover); + ++p; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) + { + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v = m_blender.make_pix(c.r, c.g, c.b); + do + { + ((pixel_type*)m_rbuf->row_ptr(x, y++, 1))[x] = v; + } + while(--len); + } + else + { + do + { + m_blender.blend_pix( + (pixel_type*)m_rbuf->row_ptr(x, y++, 1), + c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p, c, *covers++); + ++p; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + c, *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + *p++ = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x; + *p = m_blender.make_pix(colors->r, colors->g, colors->b); + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = (pixel_type*)m_rbuf->row_ptr(x, y, len) + x; + do + { + copy_or_blend_pix(p++, *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + copy_or_blend_pix((pixel_type*)m_rbuf->row_ptr(x, y++, 1) + x, + *colors++, covers ? *covers++ : cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + template + 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) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * 4; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + do + { + value_type alpha = psrc[src_order::A]; + if(alpha) + { + if(alpha == base_mask && cover == 255) + { + *pdst = m_blender.make_pix(psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B]); + } + else + { + m_blender.blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + alpha, + cover); + } + } + psrc += 4; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + 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; + typedef typename SrcPixelFormatRenderer::color_type src_color_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + psrc += SrcPixelFormatRenderer::pix_step; + ++pdst; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + 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) + { + psrc += xsrc * SrcPixelFormatRenderer::pix_step + SrcPixelFormatRenderer::pix_offset; + pixel_type* pdst = + (pixel_type*)m_rbuf->row_ptr(xdst, ydst, len) + xdst; + + do + { + const color_type& color = color_lut[*psrc]; + m_blender.blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); + psrc += SrcPixelFormatRenderer::pix_step; + ++pdst; + } + while(--len); + } + } + + + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb555; //----pixfmt_rgb555 + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb565; //----pixfmt_rgb565 + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb555_pre; //----pixfmt_rgb555_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgb565_pre; //----pixfmt_rgb565_pre + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbAAA; //----pixfmt_rgbAAA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrAAA; //----pixfmt_bgrAAA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbBBA; //----pixfmt_rgbBBA + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrABB; //----pixfmt_bgrABB + + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbAAA_pre; //----pixfmt_rgbAAA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrAAA_pre; //----pixfmt_bgrAAA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_rgbBBA_pre; //----pixfmt_rgbBBA_pre + typedef pixfmt_alpha_blend_rgb_packed pixfmt_bgrABB_pre; //----pixfmt_bgrABB_pre + + + //-----------------------------------------------------pixfmt_rgb555_gamma + template class pixfmt_rgb555_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgb555_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgb565_gamma + template class pixfmt_rgb565_gamma : + public pixfmt_alpha_blend_rgb_packed, rendering_buffer> + { + public: + pixfmt_rgb565_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbAAA_gamma + template class pixfmt_rgbAAA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgbAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrAAA_gamma + template class pixfmt_bgrAAA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_bgrAAA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_rgbBBA_gamma + template class pixfmt_rgbBBA_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_rgbBBA_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + + //-----------------------------------------------------pixfmt_bgrABB_gamma + template class pixfmt_bgrABB_gamma : + public pixfmt_alpha_blend_rgb_packed, + rendering_buffer> + { + public: + pixfmt_bgrABB_gamma(rendering_buffer& rb, const Gamma& g) : + pixfmt_alpha_blend_rgb_packed, + rendering_buffer>(rb) + { + this->blender().gamma(g); + } + }; + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgba.h new file mode 100644 index 00000000000..e9cd523b375 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_rgba.h @@ -0,0 +1,2801 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_RGBA_INCLUDED +#define AGG_PIXFMT_RGBA_INCLUDED + +#include +#include +#include "agg_pixfmt_base.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + template inline T sd_min(T a, T b) { return (a < b) ? a : b; } + template inline T sd_max(T a, T b) { return (a > b) ? a : b; } + + inline rgba & clip(rgba & c) + { + if (c.a > 1) c.a = 1; else if (c.a < 0) c.a = 0; + if (c.r > c.a) c.r = c.a; else if (c.r < 0) c.r = 0; + if (c.g > c.a) c.g = c.a; else if (c.g < 0) c.g = 0; + if (c.b > c.a) c.b = c.a; else if (c.b < 0) c.b = 0; + return c; + } + + //=========================================================multiplier_rgba + template + struct multiplier_rgba + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) + { + value_type a = p[Order::A]; + p[Order::R] = color_type::multiply(p[Order::R], a); + p[Order::G] = color_type::multiply(p[Order::G], a); + p[Order::B] = color_type::multiply(p[Order::B], a); + } + + + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + value_type a = p[Order::A]; + p[Order::R] = color_type::demultiply(p[Order::R], a); + p[Order::G] = color_type::demultiply(p[Order::G], a); + p[Order::B] = color_type::demultiply(p[Order::B], a); + } + }; + + //=====================================================apply_gamma_dir_rgba + template + class apply_gamma_dir_rgba + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + //=====================================================apply_gamma_inv_rgba + template class apply_gamma_inv_rgba + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + + private: + const GammaLut& m_gamma; + }; + + + template + struct conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void set_plain_color(value_type* p, color_type c) + { + c.premultiply(); + p[Order::R] = c.r; + p[Order::G] = c.g; + p[Order::B] = c.b; + p[Order::A] = c.a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE color_type get_plain_color(const value_type* p) + { + return color_type( + p[Order::R], + p[Order::G], + p[Order::B], + p[Order::A]).demultiply(); + } + }; + + template + struct conv_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void set_plain_color(value_type* p, color_type c) + { + p[Order::R] = c.r; + p[Order::G] = c.g; + p[Order::B] = c.b; + p[Order::A] = c.a; + } + + //-------------------------------------------------------------------- + static AGG_INLINE color_type get_plain_color(const value_type* p) + { + return color_type( + p[Order::R], + p[Order::G], + p[Order::B], + p[Order::A]); + } + }; + + //=============================================================blender_rgba + // Blends "plain" (i.e. non-premultiplied) colors into a premultiplied buffer. + template + struct blender_rgba : conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. Since the render buffer is in fact premultiplied + // we omit the initial premultiplication and final demultiplication. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::lerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::lerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::lerp(p[Order::B], cb, alpha); + p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha); + } + }; + + + //========================================================blender_rgba_pre + // Blends premultiplied colors into a premultiplied buffer. + template + struct blender_rgba_pre : conv_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, + color_type::mult_cover(cr, cover), + color_type::mult_cover(cg, cover), + color_type::mult_cover(cb, cover), + color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + p[Order::R] = color_type::prelerp(p[Order::R], cr, alpha); + p[Order::G] = color_type::prelerp(p[Order::G], cg, alpha); + p[Order::B] = color_type::prelerp(p[Order::B], cb, alpha); + p[Order::A] = color_type::prelerp(p[Order::A], alpha, alpha); + } + }; + + //======================================================blender_rgba_plain + // Blends "plain" (non-premultiplied) colors into a plain (non-premultiplied) buffer. + template + struct blender_rgba_plain : conv_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + // Blend pixels using the non-premultiplied form of Alvy-Ray Smith's + // compositing function. + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha, cover_type cover) + { + blend_pix(p, cr, cg, cb, color_type::mult_cover(alpha, cover)); + } + + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + value_type cr, value_type cg, value_type cb, value_type alpha) + { + if (alpha > color_type::empty_value()) + { + calc_type a = p[Order::A]; + calc_type r = color_type::multiply(p[Order::R], a); + calc_type g = color_type::multiply(p[Order::G], a); + calc_type b = color_type::multiply(p[Order::B], a); + p[Order::R] = color_type::lerp(r, cr, alpha); + p[Order::G] = color_type::lerp(g, cg, alpha); + p[Order::B] = color_type::lerp(b, cb, alpha); + p[Order::A] = color_type::prelerp(a, alpha, alpha); + multiplier_rgba::demultiply(p); + } + } + }; + + // SVG compositing operations. + // For specifications, see http://www.w3.org/TR/SVGCompositing/ + + //=========================================================comp_op_rgba_clear + template + struct comp_op_rgba_clear : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = 0 + // Da' = 0 + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + if (cover >= cover_full) + { + p[0] = p[1] = p[2] = p[3] = color_type::empty_value(); + } + else if (cover > cover_none) + { + set(p, get(p, cover_full - cover)); + } + } + }; + + //===========================================================comp_op_rgba_src + template + struct comp_op_rgba_src : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + if (cover >= cover_full) + { + set(p, r, g, b, a); + } + else + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + d.r += s.r; + d.g += s.g; + d.b += s.b; + d.a += s.a; + set(p, d); + } + } + }; + + //===========================================================comp_op_rgba_dst + template + struct comp_op_rgba_dst : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + + // Dca' = Dca.Sa + Dca.(1 - Sa) = Dca + // Da' = Da.Sa + Da.(1 - Sa) = Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + // Well, that was easy! + } + }; + + //======================================================comp_op_rgba_src_over + template + struct comp_op_rgba_src_over : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca.(1 - Sa) = Dca + Sca - Dca.Sa + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { +#if 1 + blender_rgba_pre::blend_pix(p, r, g, b, a, cover); +#else + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + d.r += s.r - d.r * s.a; + d.g += s.g - d.g * s.a; + d.b += s.b - d.b * s.a; + d.a += s.a - d.a * s.a; + set(p, d); +#endif + } + }; + + //======================================================comp_op_rgba_dst_over + template + struct comp_op_rgba_dst_over : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da = Da + Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double d1a = 1 - d.a; + d.r += s.r * d1a; + d.g += s.g * d1a; + d.b += s.b * d1a; + d.a += s.a * d1a; + set(p, d); + } + }; + + //======================================================comp_op_rgba_src_in + template + struct comp_op_rgba_src_in : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + double da = ColorT::to_double(p[Order::A]); + if (da > 0) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + d.r += s.r * da; + d.g += s.g * da; + d.b += s.b * da; + d.a += s.a * da; + set(p, d); + } + } + }; + + //======================================================comp_op_rgba_dst_in + template + struct comp_op_rgba_dst_in : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + double sa = ColorT::to_double(a); + rgba d = get(p, cover_full - cover); + rgba d2 = get(p, cover); + d.r += d2.r * sa; + d.g += d2.g * sa; + d.b += d2.b * sa; + d.a += d2.a * sa; + set(p, d); + } + }; + + //======================================================comp_op_rgba_src_out + template + struct comp_op_rgba_src_out : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p, cover_full - cover); + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r += s.r * d1a; + d.g += s.g * d1a; + d.b += s.b * d1a; + d.a += s.a * d1a; + set(p, d); + } + }; + + //======================================================comp_op_rgba_dst_out + template + struct comp_op_rgba_dst_out : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba d = get(p, cover_full - cover); + rgba dc = get(p, cover); + double s1a = 1 - ColorT::to_double(a); + d.r += dc.r * s1a; + d.g += dc.g * s1a; + d.b += dc.b * s1a; + d.a += dc.a * s1a; + set(p, d); + } + }; + + //=====================================================comp_op_rgba_src_atop + template + struct comp_op_rgba_src_atop : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double s1a = 1 - s.a; + d.r = s.r * d.a + d.r * s1a; + d.g = s.g * d.a + d.g * s1a; + d.b = s.b * d.a + d.g * s1a; + set(p, d); + } + }; + + //=====================================================comp_op_rgba_dst_atop + template + struct comp_op_rgba_dst_atop : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba sc = get(r, g, b, a, cover); + rgba dc = get(p, cover); + rgba d = get(p, cover_full - cover); + double sa = ColorT::to_double(a); + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r += dc.r * sa + sc.r * d1a; + d.g += dc.g * sa + sc.g * d1a; + d.b += dc.b * sa + sc.b * d1a; + d.a += sc.a; + set(p, d); + } + }; + + //=========================================================comp_op_rgba_xor + template + struct comp_op_rgba_xor : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + rgba d = get(p); + double s1a = 1 - s.a; + double d1a = 1 - ColorT::to_double(p[Order::A]); + d.r = s.r * d1a + d.r * s1a; + d.g = s.g * d1a + d.g * s1a; + d.b = s.b * d1a + d.b * s1a; + d.a = s.a + d.a - 2 * s.a * d.a; + set(p, d); + } + }; + + //=========================================================comp_op_rgba_plus + template + struct comp_op_rgba_plus : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.a = sd_min(d.a + s.a, 1.0); + d.r = sd_min(d.r + s.r, d.a); + d.g = sd_min(d.g + s.g, d.a); + d.b = sd_min(d.b + s.b, d.a); + set(p, clip(d)); + } + } + }; + + //========================================================comp_op_rgba_minus + // Note: not included in SVG spec. + template + struct comp_op_rgba_minus : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) = Da + Sa - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.a += s.a - s.a * d.a; + d.r = sd_max(d.r - s.r, 0.0); + d.g = sd_max(d.g - s.g, 0.0); + d.b = sd_max(d.b - s.b, 0.0); + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_multiply + template + struct comp_op_rgba_multiply : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = s.r * d.r + s.r * d1a + d.r * s1a; + d.g = s.g * d.g + s.g * d1a + d.g * s1a; + d.b = s.b * d.b + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_screen + template + struct comp_op_rgba_screen : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.r += s.r - s.r * d.r; + d.g += s.g - s.g * d.g; + d.b += s.b - s.b * d.b; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_overlay + template + struct comp_op_rgba_overlay : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Dca <= Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + return (2 * dca <= da) ? + 2 * sca * dca + sca * d1a + dca * s1a : + sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + double sada = s.a * d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_darken + template + struct comp_op_rgba_darken : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = sd_min(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a; + d.g = sd_min(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a; + d.b = sd_min(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_lighten + template + struct comp_op_rgba_lighten : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = sd_max(s.r * d.a, d.r * s.a) + s.r * d1a + d.r * s1a; + d.g = sd_max(s.g * d.a, d.g * s.a) + s.g * d1a + d.g * s1a; + d.b = sd_max(s.b * d.a, d.b * s.a) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_color_dodge + template + struct comp_op_rgba_color_dodge : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if Sca == Sa and Dca == 0 + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) = Sca.(1 - Da) + // otherwise if Sca == Sa + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if Sca < Sa + // Dca' = Sa.Da.min(1, Dca/Da.Sa/(Sa - Sca)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + if (sca < sa) return sada * sd_min(1.0, (dca / da) * sa / (sa - sca)) + sca * d1a + dca * s1a; + if (dca > 0) return sada + sca * d1a + dca * s1a; + return sca * d1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_color_burn + template + struct comp_op_rgba_color_burn : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if Sca == 0 and Dca == Da + // Dca' = Sa.Da + Dca.(1 - Sa) + // otherwise if Sca == 0 + // Dca' = Dca.(1 - Sa) + // otherwise if Sca > 0 + // Dca' = Sa.Da.(1 - min(1, (1 - Dca/Da).Sa/Sca)) + Sca.(1 - Da) + Dca.(1 - Sa) + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + if (sca > 0) return sada * (1 - sd_min(1.0, (1 - dca / da) * sa / sca)) + sca * d1a + dca * s1a; + if (dca > da) return sada + dca * s1a; + return dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_hard_light + template + struct comp_op_rgba_hard_light : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + return (2 * sca < sa) ? + 2 * sca * dca + sca * d1a + dca * s1a : + sada - 2 * (da - dca) * (sa - sca) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + double sada = s.a * d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_soft_light + template + struct comp_op_rgba_soft_light : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // if 2.Sca <= Sa + // Dca' = Dca.Sa - (Sa.Da - 2.Sca.Da).Dca.Sa.(Sa.Da - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 2.Sca > Sa and 4.Dca <= Da + // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((((16.Dsa.Sa - 12).Dsa.Sa + 4).Dsa.Da) - Dsa.Da) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 2.Sca > Sa and 4.Dca > Da + // Dca' = Dca.Sa + (2.Sca.Da - Sa.Da).((Dca.Sa)^0.5 - Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE double calc(double dca, double sca, double da, double sa, double sada, double d1a, double s1a) + { + double dcasa = dca * sa; + if (2 * sca <= sa) return dcasa - (sada - 2 * sca * da) * dcasa * (sada - dcasa) + sca * d1a + dca * s1a; + if (4 * dca <= da) return dcasa + (2 * sca * da - sada) * ((((16 * dcasa - 12) * dcasa + 4) * dca * da) - dca * da) + sca * d1a + dca * s1a; + return dcasa + (2 * sca * da - sada) * (sqrt(dcasa) - dcasa) + sca * d1a + dca * s1a; + } + + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + if (d.a > 0) + { + double sada = s.a * d.a; + double s1a = 1 - s.a; + double d1a = 1 - d.a; + d.r = calc(d.r, s.r, d.a, s.a, sada, d1a, s1a); + d.g = calc(d.g, s.g, d.a, s.a, sada, d1a, s1a); + d.b = calc(d.b, s.b, d.a, s.a, sada, d1a, s1a); + d.a += s.a - sada; + set(p, clip(d)); + } + else set(p, s); + } + } + }; + + //=====================================================comp_op_rgba_difference + template + struct comp_op_rgba_difference : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + d.r += s.r - 2 * sd_min(s.r * d.a, d.r * s.a); + d.g += s.g - 2 * sd_min(s.g * d.a, d.g * s.a); + d.b += s.b - 2 * sd_min(s.b * d.a, d.b * s.a); + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + + //=====================================================comp_op_rgba_exclusion + template + struct comp_op_rgba_exclusion : blender_base + { + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + using blender_base::get; + using blender_base::set; + + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + rgba s = get(r, g, b, a, cover); + if (s.a > 0) + { + rgba d = get(p); + double d1a = 1 - d.a; + double s1a = 1 - s.a; + d.r = (s.r * d.a + d.r * s.a - 2 * s.r * d.r) + s.r * d1a + d.r * s1a; + d.g = (s.g * d.a + d.g * s.a - 2 * s.g * d.g) + s.g * d1a + d.g * s1a; + d.b = (s.b * d.a + d.b * s.a - 2 * s.b * d.b) + s.b * d1a + d.b * s1a; + d.a += s.a - s.a * d.a; + set(p, clip(d)); + } + } + }; + +#if 0 + //=====================================================comp_op_rgba_contrast + template struct comp_op_rgba_contrast + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; + + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; + + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } + }; + + //=====================================================comp_op_rgba_invert + template struct comp_op_rgba_invert + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + sa = (sa * cover + 255) >> 8; + if (sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; + + //=================================================comp_op_rgba_invert_rgb + template struct comp_op_rgba_invert_rgb + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } + }; +#endif + + + //======================================================comp_op_table_rgba + template struct comp_op_table_rgba + { + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; + typedef void (*comp_op_func_type)(value_type* p, + value_type cr, + value_type cg, + value_type cb, + value_type ca, + cover_type cover); + static comp_op_func_type g_comp_op_func[]; + }; + + //==========================================================g_comp_op_func + template + typename comp_op_table_rgba::comp_op_func_type + comp_op_table_rgba::g_comp_op_func[] = + { + comp_op_rgba_clear ::blend_pix, + comp_op_rgba_src ::blend_pix, + comp_op_rgba_dst ::blend_pix, + comp_op_rgba_src_over ::blend_pix, + comp_op_rgba_dst_over ::blend_pix, + comp_op_rgba_src_in ::blend_pix, + comp_op_rgba_dst_in ::blend_pix, + comp_op_rgba_src_out ::blend_pix, + comp_op_rgba_dst_out ::blend_pix, + comp_op_rgba_src_atop ::blend_pix, + comp_op_rgba_dst_atop ::blend_pix, + comp_op_rgba_xor ::blend_pix, + comp_op_rgba_plus ::blend_pix, + //comp_op_rgba_minus ::blend_pix, + comp_op_rgba_multiply ::blend_pix, + comp_op_rgba_screen ::blend_pix, + comp_op_rgba_overlay ::blend_pix, + comp_op_rgba_darken ::blend_pix, + comp_op_rgba_lighten ::blend_pix, + comp_op_rgba_color_dodge::blend_pix, + comp_op_rgba_color_burn ::blend_pix, + comp_op_rgba_hard_light ::blend_pix, + comp_op_rgba_soft_light ::blend_pix, + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + //comp_op_rgba_contrast ::blend_pix, + //comp_op_rgba_invert ::blend_pix, + //comp_op_rgba_invert_rgb ::blend_pix, + 0 + }; + + + //==============================================================comp_op_e + enum comp_op_e + { + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + //comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + //comp_op_contrast, //----comp_op_contrast + //comp_op_invert, //----comp_op_invert + //comp_op_invert_rgb, //----comp_op_invert_rgb + + end_of_comp_op_e + }; + + + + + + + + //====================================================comp_op_adaptor_rgba + template + struct comp_op_adaptor_rgba + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, a), + color_type::multiply(g, a), + color_type::multiply(b, a), + a, cover); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba + template + struct comp_op_adaptor_clip_to_dst_rgba + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + r = color_type::multiply(r, a); + g = color_type::multiply(g, a); + b = color_type::multiply(b, a); + value_type da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //================================================comp_op_adaptor_rgba_pre + template + struct comp_op_adaptor_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, r, g, b, a, cover); + } + }; + + //=====================================comp_op_adaptor_clip_to_dst_rgba_pre + template + struct comp_op_adaptor_clip_to_dst_rgba_pre + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + value_type da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op](p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //====================================================comp_op_adaptor_rgba_plain + template + struct comp_op_adaptor_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_op_adaptor_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //=========================================comp_op_adaptor_clip_to_dst_rgba_plain + template + struct comp_op_adaptor_clip_to_dst_rgba_plain + { + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_op_adaptor_clip_to_dst_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //=======================================================comp_adaptor_rgba + template + struct comp_adaptor_rgba + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + BlenderPre::blend_pix(p, + color_type::multiply(r, a), + color_type::multiply(g, a), + color_type::multiply(b, a), + a, cover); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba + template + struct comp_adaptor_clip_to_dst_rgba + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + r = color_type::multiply(r, a); + g = color_type::multiply(g, a); + b = color_type::multiply(b, a); + value_type da = p[order_type::A]; + BlenderPre::blend_pix(p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), cover); + } + }; + + //=======================================================comp_adaptor_rgba_pre + template + struct comp_adaptor_rgba_pre + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + BlenderPre::blend_pix(p, r, g, b, a, cover); + } + }; + + //======================================comp_adaptor_clip_to_dst_rgba_pre + template + struct comp_adaptor_clip_to_dst_rgba_pre + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + color_type::multiply(r, da), + color_type::multiply(g, da), + color_type::multiply(b, da), + color_type::multiply(a, da), + cover); + } + }; + + //=======================================================comp_adaptor_rgba_plain + template + struct comp_adaptor_rgba_plain + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_adaptor_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + //==========================================comp_adaptor_clip_to_dst_rgba_plain + template + struct comp_adaptor_clip_to_dst_rgba_plain + { + typedef typename BlenderPre::color_type color_type; + typedef typename BlenderPre::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + value_type r, value_type g, value_type b, value_type a, cover_type cover) + { + multiplier_rgba::premultiply(p); + comp_adaptor_clip_to_dst_rgba::blend_pix(op, p, r, g, b, a, cover); + multiplier_rgba::demultiply(p); + } + }; + + + //=================================================pixfmt_alpha_blend_rgba + template + class pixfmt_alpha_blend_rgba + { + public: + typedef pixfmt_rgba_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + pix_step = 4, + pix_width = sizeof(value_type) * pix_step, + }; + struct pixel_type + { + value_type c[pix_step]; + + void set(value_type r, value_type g, value_type b, value_type a) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + c[order_type::A] = a; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b, color.a); + } + + void get(value_type& r, value_type& g, value_type& b, value_type& a) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + a = c[order_type::A]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B], + c[order_type::A]); + } + + pixel_type* next() + { + return this + 1; + } + + const pixel_type* next() const + { + return this + 1; + } + + pixel_type* advance(int n) + { + return this + n; + } + + const pixel_type* advance(int n) const + { + return this + n; + } + }; + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c) + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a, cover); + } + } + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c) + { + if (!c.is_transparent()) + { + if (c.is_opaque()) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + m_blender.blend_pix(p->c, c.r, c.g, c.b, c.a); + } + } + } + + public: + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + 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))) + { + int stride = pixf.stride(); + 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); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + // 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)); + } + + // 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)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)p; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)p; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void write_plain_color(void* p, color_type c) + { + blender_type::set_plain_color(pix_value_ptr(p)->c, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static color_type read_plain_color(const void* p) + { + return blender_type::get_plain_color(pix_value_ptr(p)->c); + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + 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) + { + 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(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + pixel_type* p = pix_value_ptr(x, y, len); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + if (c.is_opaque() && cover == cover_mask) + { + pixel_type v; + v.set(c); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + blend_pix(p, c); + p = p->next(); + } + while (--len); + } + else + { + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, c.a); + } + while (--len); + } + else + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + p = p->next(); + ++covers; + } + while (--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (!c.is_transparent()) + { + do + { + pixel_type* p = pix_value_ptr(x, y++, 1); + if (c.is_opaque() && *covers == cover_mask) + { + p->set(c); + } + else + { + blend_pix(p, c, *covers); + } + ++covers; + } + while (--len); + } + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + if (covers) + { + do + { + copy_or_blend_pix(p, *colors++, *covers++); + p = p->next(); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(p, *colors++); + p = p->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(p, *colors++, cover); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + if (covers) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, *covers++); + } + while (--len); + } + else + { + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pix_value_ptr(x, y++, 1), *colors++, cover); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + for (unsigned y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from another RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + int srcinc = 1; + int dstinc = 1; + + if (xdst > xsrc) + { + psrc = psrc->advance(len - 1); + pdst = pdst->advance(len - 1); + srcinc = -1; + dstinc = -1; + } + + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pdst, psrc->get()); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pdst, psrc->get(), cover); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + // Combine single color with grayscale surface and blend. + template + 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::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)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + copy_or_blend_pix(pdst, color, + src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + 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, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + if (cover == cover_mask) + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]]); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + else + { + do + { + copy_or_blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + }; + + //================================================pixfmt_custom_blend_rgba + template class pixfmt_custom_blend_rgba + { + public: + typedef pixfmt_rgba_tag pixfmt_category; + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum + { + pix_step = 4, + pix_width = sizeof(value_type) * pix_step, + }; + struct pixel_type + { + value_type c[pix_step]; + + void set(value_type r, value_type g, value_type b, value_type a) + { + c[order_type::R] = r; + c[order_type::G] = g; + c[order_type::B] = b; + c[order_type::A] = a; + } + + void set(const color_type& color) + { + set(color.r, color.g, color.b, color.a); + } + + void get(value_type& r, value_type& g, value_type& b, value_type& a) const + { + r = c[order_type::R]; + g = c[order_type::G]; + b = c[order_type::B]; + a = c[order_type::A]; + } + + color_type get() const + { + return color_type( + c[order_type::R], + c[order_type::G], + c[order_type::B], + c[order_type::A]); + } + + pixel_type* next() + { + return this + 1; + } + + const pixel_type* next() const + { + return this + 1; + } + + pixel_type* advance(int n) + { + return this + n; + } + + const pixel_type* advance(int n) const + { + return this + n; + } + }; + + + private: + //-------------------------------------------------------------------- + AGG_INLINE void blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) + { + m_blender.blend_pix(m_comp_op, p->c, c.r, c.g, c.b, c.a, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_or_blend_pix(pixel_type* p, const color_type& c, unsigned cover = cover_full) + { + if (!c.is_transparent()) + { + if (c.is_opaque() && cover == cover_mask) + { + p->set(c.r, c.g, c.b, c.a); + } + else + { + blend_pix(p, c, cover); + } + } + } + + public: + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + 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))) + { + int stride = pixf.stride(); + 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); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + sizeof(value_type) * (x * pix_step); + } + + // 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)); + } + + // 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)) : 0; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static pixel_type* pix_value_ptr(void* p) + { + return (pixel_type*)p; + } + + // Get pixel pointer from raw buffer pointer. + AGG_INLINE static const pixel_type* pix_value_ptr(const void* p) + { + return (const pixel_type*)p; + } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((pixel_type*)p)->set(c); + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + 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) + { + make_pix(pix_value_ptr(x, y, 1), c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blend_pix(pix_value_ptr(x, y, 1), c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + pixel_type* p = pix_value_ptr(x, y, len); + do + { + *p = v; + p = p->next(); + } + while (--len); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + v.set(c); + do + { + *pix_value_ptr(x, y++, 1) = v; + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + pixel_type* p = pix_value_ptr(x, y, len); + do + { + blend_pix(p, c, cover); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, cover); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + blend_pix(p, c, *covers++); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), c, *covers++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + p->set(*colors++); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + pix_value_ptr(x, y++, 1)->set(*colors++); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + pixel_type* p = pix_value_ptr(x, y, len); + + do + { + blend_pix(p, *colors++, covers ? *covers++ : cover); + p = p->next(); + } + while (--len); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blend_pix(pix_value_ptr(x, y++, 1), *colors++, covers ? *covers++ : cover); + } + while (--len); + + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for (y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if (r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + pixel_type* p = pix_value_ptr(r.x1, y, len); + do + { + f(p->c); + p = p->next(); + } + while (--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + if (const int8u* p = from.row_ptr(ysrc)) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + // Blend from another RGBA surface. + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + int srcinc = 1; + int dstinc = 1; + + if (xdst > xsrc) + { + psrc = psrc->advance(len - 1); + pdst = pdst->advance(len - 1); + srcinc = -1; + dstinc = -1; + } + + do + { + blend_pix(pdst, psrc->get(), cover); + psrc = psrc->advance(srcinc); + pdst = pdst->advance(dstinc); + } + while (--len); + } + } + + //-------------------------------------------------------------------- + // Blend from single color, using grayscale surface as alpha channel. + template + 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::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)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + blend_pix(pdst, color, + src_color_type::scale_cover(cover, psrc->c[0])); + psrc = psrc->next(); + pdst = pdst->next(); + } + 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, + const color_type* color_lut, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::pixel_type src_pixel_type; + + if (const src_pixel_type* psrc = from.pix_value_ptr(xsrc, ysrc)) + { + pixel_type* pdst = pix_value_ptr(xdst, ydst, len); + + do + { + blend_pix(pdst, color_lut[psrc->c[0]], cover); + psrc = psrc->next(); + pdst = pdst->next(); + } + while (--len); + } + } + + private: + rbuf_type* m_rbuf; + Blender m_blender; + unsigned m_comp_op; + }; + + + //----------------------------------------------------------------------- + typedef blender_rgba blender_rgba32; + typedef blender_rgba blender_argb32; + typedef blender_rgba blender_abgr32; + typedef blender_rgba blender_bgra32; + + typedef blender_rgba blender_srgba32; + typedef blender_rgba blender_sargb32; + typedef blender_rgba blender_sabgr32; + typedef blender_rgba blender_sbgra32; + + typedef blender_rgba_pre blender_rgba32_pre; + typedef blender_rgba_pre blender_argb32_pre; + typedef blender_rgba_pre blender_abgr32_pre; + typedef blender_rgba_pre blender_bgra32_pre; + + typedef blender_rgba_pre blender_srgba32_pre; + typedef blender_rgba_pre blender_sargb32_pre; + typedef blender_rgba_pre blender_sabgr32_pre; + typedef blender_rgba_pre blender_sbgra32_pre; + + typedef blender_rgba_plain blender_rgba32_plain; + typedef blender_rgba_plain blender_argb32_plain; + typedef blender_rgba_plain blender_abgr32_plain; + typedef blender_rgba_plain blender_bgra32_plain; + + typedef blender_rgba_plain blender_srgba32_plain; + typedef blender_rgba_plain blender_sargb32_plain; + typedef blender_rgba_plain blender_sabgr32_plain; + typedef blender_rgba_plain blender_sbgra32_plain; + + typedef blender_rgba blender_rgba64; + typedef blender_rgba blender_argb64; + typedef blender_rgba blender_abgr64; + typedef blender_rgba blender_bgra64; + + typedef blender_rgba_pre blender_rgba64_pre; + typedef blender_rgba_pre blender_argb64_pre; + typedef blender_rgba_pre blender_abgr64_pre; + typedef blender_rgba_pre blender_bgra64_pre; + + typedef blender_rgba_plain blender_rgba64_plain; + typedef blender_rgba_plain blender_argb64_plain; + typedef blender_rgba_plain blender_abgr64_plain; + typedef blender_rgba_plain blender_bgra64_plain; + + typedef blender_rgba blender_rgba128; + typedef blender_rgba blender_argb128; + typedef blender_rgba blender_abgr128; + typedef blender_rgba blender_bgra128; + + typedef blender_rgba_pre blender_rgba128_pre; + typedef blender_rgba_pre blender_argb128_pre; + typedef blender_rgba_pre blender_abgr128_pre; + typedef blender_rgba_pre blender_bgra128_pre; + + typedef blender_rgba_plain blender_rgba128_plain; + typedef blender_rgba_plain blender_argb128_plain; + typedef blender_rgba_plain blender_abgr128_plain; + typedef blender_rgba_plain blender_bgra128_plain; + + + //----------------------------------------------------------------------- + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_srgba32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sargb32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sabgr32_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_sbgra32_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_plain; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128_pre; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128_pre; + + typedef pixfmt_alpha_blend_rgba pixfmt_rgba128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_argb128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_abgr128_plain; + typedef pixfmt_alpha_blend_rgba pixfmt_bgra128_plain; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_transposer.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_transposer.h new file mode 100644 index 00000000000..64738b6c755 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_pixfmt_transposer.h @@ -0,0 +1,157 @@ +//---------------------------------------------------------------------------- +// 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_TRANSPOSER_INCLUDED +#define AGG_PIXFMT_TRANSPOSER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=======================================================pixfmt_transposer + template class pixfmt_transposer + { + public: + typedef PixFmt pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + pixfmt_transposer() : m_pixf(0) {} + explicit pixfmt_transposer(pixfmt_type& pixf) : m_pixf(&pixf) {} + void attach(pixfmt_type& pixf) { m_pixf = &pixf; } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_pixf->height(); } + AGG_INLINE unsigned height() const { return m_pixf->width(); } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + return m_pixf->pixel(y, x); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + m_pixf->copy_pixel(y, x, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, + const color_type& c, + int8u cover) + { + m_pixf->blend_pixel(y, x, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_vline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + m_pixf->copy_hline(y, x, len, c); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_vline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + m_pixf->blend_hline(y, x, len, c, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_vspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + m_pixf->blend_solid_hspan(y, x, len, c, covers); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_vspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + m_pixf->copy_color_hspan(y, x, len, colors); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_vspan(y, x, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + m_pixf->blend_color_hspan(y, x, len, colors, covers, cover); + } + + private: + pixfmt_type* m_pixf; + }; +} + +#endif + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_cells_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_cells_aa.h new file mode 100644 index 00000000000..d1cc705405d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_cells_aa.h @@ -0,0 +1,743 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_RASTERIZER_CELLS_AA_INCLUDED +#define AGG_RASTERIZER_CELLS_AA_INCLUDED + +#include +#include +#include +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------------rasterizer_cells_aa + // An internal class that implements the main rasterization algorithm. + // Used in the rasterizer. Should not be used direcly. + template class rasterizer_cells_aa + { + enum cell_block_scale_e + { + cell_block_shift = 12, + cell_block_size = 1 << cell_block_shift, + cell_block_mask = cell_block_size - 1, + cell_block_pool = 256 + }; + + struct sorted_y + { + unsigned start; + unsigned num; + }; + + public: + typedef Cell cell_type; + typedef rasterizer_cells_aa self_type; + + ~rasterizer_cells_aa(); + rasterizer_cells_aa(unsigned cell_block_limit=1024); + + void reset(); + void style(const cell_type& style_cell); + void line(int x1, int y1, int x2, int y2); + + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + void sort_cells(); + + unsigned total_cells() const + { + return m_num_cells; + } + + unsigned scanline_num_cells(unsigned y) const + { + return m_sorted_y[y - m_min_y].num; + } + + const cell_type* const* scanline_cells(unsigned y) const + { + return m_sorted_cells.data() + m_sorted_y[y - m_min_y].start; + } + + bool sorted() const { return m_sorted; } + + private: + rasterizer_cells_aa(const self_type&); + const self_type& operator = (const self_type&); + + void set_curr_cell(int x, int y); + void add_curr_cell(); + void render_hline(int ey, int x1, int y1, int x2, int y2); + void allocate_block(); + + private: + unsigned m_num_blocks; + unsigned m_max_blocks; + unsigned m_curr_block; + unsigned m_num_cells; + unsigned m_cell_block_limit; + cell_type** m_cells; + cell_type* m_curr_cell_ptr; + pod_vector m_sorted_cells; + pod_vector m_sorted_y; + cell_type m_curr_cell; + cell_type m_style_cell; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + bool m_sorted; + }; + + + + + //------------------------------------------------------------------------ + template + rasterizer_cells_aa::~rasterizer_cells_aa() + { + if(m_num_blocks) + { + cell_type** ptr = m_cells + m_num_blocks - 1; + while(m_num_blocks--) + { + pod_allocator::deallocate(*ptr, cell_block_size); + ptr--; + } + pod_allocator::deallocate(m_cells, m_max_blocks); + } + } + + //------------------------------------------------------------------------ + template + rasterizer_cells_aa::rasterizer_cells_aa(unsigned cell_block_limit) : + m_num_blocks(0), + m_max_blocks(0), + m_curr_block(0), + m_num_cells(0), + m_cell_block_limit(cell_block_limit), + m_cells(0), + m_curr_cell_ptr(0), + m_sorted_cells(), + m_sorted_y(), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_sorted(false) + { + m_style_cell.initial(); + m_curr_cell.initial(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::reset() + { + m_num_cells = 0; + m_curr_block = 0; + m_curr_cell.initial(); + m_style_cell.initial(); + m_sorted = false; + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::add_curr_cell() + { + if(m_curr_cell.area | m_curr_cell.cover) + { + if((m_num_cells & cell_block_mask) == 0) + { + if(m_num_blocks >= m_cell_block_limit) { + throw std::overflow_error("Exceeded cell block limit"); + } + allocate_block(); + } + *m_curr_cell_ptr++ = m_curr_cell; + ++m_num_cells; + } + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::set_curr_cell(int x, int y) + { + if(m_curr_cell.not_equal(x, y, m_style_cell)) + { + add_curr_cell(); + m_curr_cell.style(m_style_cell); + m_curr_cell.x = x; + m_curr_cell.y = y; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + } + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::render_hline(int ey, + int x1, int y1, + int x2, int y2) + { + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int fx1 = x1 & poly_subpixel_mask; + int fx2 = x2 & poly_subpixel_mask; + + int delta, p, first, dx; + int incr, lift, mod, rem; + + //trivial case. Happens often + if(y1 == y2) + { + set_curr_cell(ex2, ey); + return; + } + + //everything is located in a single cell. That is easy! + if(ex1 == ex2) + { + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + fx2) * delta; + return; + } + + //ok, we'll have to render a run of adjacent cells on the same + //hline... + p = (poly_subpixel_scale - fx1) * (y2 - y1); + first = poly_subpixel_scale; + incr = 1; + + dx = x2 - x1; + + if(dx < 0) + { + p = fx1 * (y2 - y1); + first = 0; + incr = -1; + dx = -dx; + } + + delta = p / dx; + mod = p % dx; + + if(mod < 0) + { + delta--; + mod += dx; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += (fx1 + first) * delta; + + ex1 += incr; + set_curr_cell(ex1, ey); + y1 += delta; + + if(ex1 != ex2) + { + p = poly_subpixel_scale * (y2 - y1 + delta); + lift = p / dx; + rem = p % dx; + + if (rem < 0) + { + lift--; + rem += dx; + } + + mod -= dx; + + while (ex1 != ex2) + { + delta = lift; + mod += rem; + if(mod >= 0) + { + mod -= dx; + delta++; + } + + m_curr_cell.cover += delta; + m_curr_cell.area += poly_subpixel_scale * delta; + y1 += delta; + ex1 += incr; + set_curr_cell(ex1, ey); + } + } + delta = y2 - y1; + m_curr_cell.cover += delta; + m_curr_cell.area += (fx2 + poly_subpixel_scale - first) * delta; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_cells_aa::style(const cell_type& style_cell) + { + m_style_cell.style(style_cell); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::line(int x1, int y1, int x2, int y2) + { + enum dx_limit_e { dx_limit = 16384 << poly_subpixel_shift }; + + int dx = x2 - x1; + + if(dx >= dx_limit || dx <= -dx_limit) + { + int cx = (x1 + x2) >> 1; + int cy = (y1 + y2) >> 1; + line(x1, y1, cx, cy); + line(cx, cy, x2, y2); + return; + } + + int dy = y2 - y1; + int ex1 = x1 >> poly_subpixel_shift; + int ex2 = x2 >> poly_subpixel_shift; + int ey1 = y1 >> poly_subpixel_shift; + int ey2 = y2 >> poly_subpixel_shift; + int fy1 = y1 & poly_subpixel_mask; + int fy2 = y2 & poly_subpixel_mask; + + int x_from, x_to; + int p, rem, mod, lift, delta, first, incr; + + if(ex1 < m_min_x) m_min_x = ex1; + if(ex1 > m_max_x) m_max_x = ex1; + if(ey1 < m_min_y) m_min_y = ey1; + if(ey1 > m_max_y) m_max_y = ey1; + if(ex2 < m_min_x) m_min_x = ex2; + if(ex2 > m_max_x) m_max_x = ex2; + if(ey2 < m_min_y) m_min_y = ey2; + if(ey2 > m_max_y) m_max_y = ey2; + + set_curr_cell(ex1, ey1); + + //everything is on a single hline + if(ey1 == ey2) + { + render_hline(ey1, x1, fy1, x2, fy2); + return; + } + + //Vertical line - we have to calculate start and end cells, + //and then - the common values of the area and coverage for + //all cells of the line. We know exactly there's only one + //cell, so, we don't have to call render_hline(). + incr = 1; + if(dx == 0) + { + int ex = x1 >> poly_subpixel_shift; + int two_fx = (x1 - (ex << poly_subpixel_shift)) << 1; + int area; + + first = poly_subpixel_scale; + if(dy < 0) + { + first = 0; + incr = -1; + } + + x_from = x1; + + //render_hline(ey1, x_from, fy1, x_from, first); + delta = first - fy1; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + + ey1 += incr; + set_curr_cell(ex, ey1); + + delta = first + first - poly_subpixel_scale; + area = two_fx * delta; + while(ey1 != ey2) + { + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, first); + m_curr_cell.cover = delta; + m_curr_cell.area = area; + ey1 += incr; + set_curr_cell(ex, ey1); + } + //render_hline(ey1, x_from, poly_subpixel_scale - first, x_from, fy2); + delta = fy2 - poly_subpixel_scale + first; + m_curr_cell.cover += delta; + m_curr_cell.area += two_fx * delta; + return; + } + + //ok, we have to render several hlines + p = (poly_subpixel_scale - fy1) * dx; + first = poly_subpixel_scale; + + if(dy < 0) + { + p = fy1 * dx; + first = 0; + incr = -1; + dy = -dy; + } + + delta = p / dy; + mod = p % dy; + + if(mod < 0) + { + delta--; + mod += dy; + } + + x_from = x1 + delta; + render_hline(ey1, x1, fy1, x_from, first); + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + + if(ey1 != ey2) + { + p = poly_subpixel_scale * dx; + lift = p / dy; + rem = p % dy; + + if(rem < 0) + { + lift--; + rem += dy; + } + mod -= dy; + + while(ey1 != ey2) + { + delta = lift; + mod += rem; + if (mod >= 0) + { + mod -= dy; + delta++; + } + + x_to = x_from + delta; + render_hline(ey1, x_from, poly_subpixel_scale - first, x_to, first); + x_from = x_to; + + ey1 += incr; + set_curr_cell(x_from >> poly_subpixel_shift, ey1); + } + } + render_hline(ey1, x_from, poly_subpixel_scale - first, x2, fy2); + } + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::allocate_block() + { + if(m_curr_block >= m_num_blocks) + { + if(m_num_blocks >= m_max_blocks) + { + cell_type** new_cells = + pod_allocator::allocate(m_max_blocks + + cell_block_pool); + + if(m_cells) + { + memcpy(new_cells, m_cells, m_max_blocks * sizeof(cell_type*)); + pod_allocator::deallocate(m_cells, m_max_blocks); + } + m_cells = new_cells; + m_max_blocks += cell_block_pool; + } + + m_cells[m_num_blocks++] = + pod_allocator::allocate(cell_block_size); + + } + m_curr_cell_ptr = m_cells[m_curr_block++]; + } + + + + //------------------------------------------------------------------------ + template static AGG_INLINE void swap_cells(T* a, T* b) + { + T temp = *a; + *a = *b; + *b = temp; + } + + + //------------------------------------------------------------------------ + enum + { + qsort_threshold = 9 + }; + + + //------------------------------------------------------------------------ + template + void qsort_cells(Cell** start, unsigned num) + { + Cell** stack[80]; + Cell*** top; + Cell** limit; + Cell** base; + + limit = start + num; + base = start; + top = stack; + + for (;;) + { + int len = int(limit - base); + + Cell** i; + Cell** j; + Cell** pivot; + + if(len > qsort_threshold) + { + // we use base + len/2 as the pivot + pivot = base + len / 2; + swap_cells(base, pivot); + + i = base + 1; + j = limit - 1; + + // now ensure that *i <= *base <= *j + if((*j)->x < (*i)->x) + { + swap_cells(i, j); + } + + if((*base)->x < (*i)->x) + { + swap_cells(base, i); + } + + if((*j)->x < (*base)->x) + { + swap_cells(base, j); + } + + for(;;) + { + int x = (*base)->x; + do i++; while( (*i)->x < x ); + do j--; while( x < (*j)->x ); + + if(i > j) + { + break; + } + + swap_cells(i, j); + } + + swap_cells(base, j); + + // now, push the largest sub-array + if(j - base > limit - i) + { + top[0] = base; + top[1] = j; + base = i; + } + else + { + top[0] = i; + top[1] = limit; + limit = j; + } + top += 2; + } + else + { + // the sub-array is small, perform insertion sort + j = base; + i = j + 1; + + for(; i < limit; j = i, i++) + { + for(; j[1]->x < (*j)->x; j--) + { + swap_cells(j + 1, j); + if (j == base) + { + break; + } + } + } + + if(top > stack) + { + top -= 2; + base = top[0]; + limit = top[1]; + } + else + { + break; + } + } + } + } + + + //------------------------------------------------------------------------ + template + void rasterizer_cells_aa::sort_cells() + { + if(m_sorted) return; //Perform sort only the first time. + + add_curr_cell(); + m_curr_cell.x = 0x7FFFFFFF; + m_curr_cell.y = 0x7FFFFFFF; + m_curr_cell.cover = 0; + m_curr_cell.area = 0; + + if(m_num_cells == 0) return; + +// DBG: Check to see if min/max works well. +//for(unsigned nc = 0; nc < m_num_cells; nc++) +//{ +// cell_type* cell = m_cells[nc >> cell_block_shift] + (nc & cell_block_mask); +// if(cell->x < m_min_x || +// cell->y < m_min_y || +// cell->x > m_max_x || +// cell->y > m_max_y) +// { +// cell = cell; // Breakpoint here +// } +//} + // Allocate the array of cell pointers + m_sorted_cells.allocate(m_num_cells, 16); + + // Allocate and zero the Y array + m_sorted_y.allocate(m_max_y - m_min_y + 1, 16); + m_sorted_y.zero(); + + // Create the Y-histogram (count the numbers of cells for each Y) + cell_type** block_ptr = m_cells; + cell_type* cell_ptr; + unsigned nb = m_num_cells; + unsigned i; + while(nb) + { + cell_ptr = *block_ptr++; + i = (nb > cell_block_size) ? cell_block_size : nb; + nb -= i; + while(i--) + { + m_sorted_y[cell_ptr->y - m_min_y].start++; + ++cell_ptr; + } + } + + // Convert the Y-histogram into the array of starting indexes + unsigned start = 0; + for(i = 0; i < m_sorted_y.size(); i++) + { + unsigned v = m_sorted_y[i].start; + m_sorted_y[i].start = start; + start += v; + } + + // Fill the cell pointer array sorted by Y + block_ptr = m_cells; + nb = m_num_cells; + while(nb) + { + cell_ptr = *block_ptr++; + i = (nb > cell_block_size) ? cell_block_size : nb; + nb -= i; + while(i--) + { + sorted_y& curr_y = m_sorted_y[cell_ptr->y - m_min_y]; + m_sorted_cells[curr_y.start + curr_y.num] = cell_ptr; + ++curr_y.num; + ++cell_ptr; + } + } + + // Finally arrange the X-arrays + for(i = 0; i < m_sorted_y.size(); i++) + { + const sorted_y& curr_y = m_sorted_y[i]; + if(curr_y.num) + { + qsort_cells(m_sorted_cells.data() + curr_y.start, curr_y.num); + } + } + m_sorted = true; + } + + + + //------------------------------------------------------scanline_hit_test + class scanline_hit_test + { + public: + scanline_hit_test(int x) : m_x(x), m_hit(false) {} + + void reset_spans() {} + void finalize(int) {} + void add_cell(int x, int) + { + if(m_x == x) m_hit = true; + } + void add_span(int x, int len, int) + { + if(m_x >= x && m_x < x+len) m_hit = true; + } + unsigned num_spans() const { return 1; } + bool hit() const { return m_hit; } + + private: + int m_x; + bool m_hit; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_compound_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_compound_aa.h new file mode 100644 index 00000000000..41d508010e8 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_compound_aa.h @@ -0,0 +1,663 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.3 +// 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. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_RASTERIZER_COMPOUND_AA_INCLUDED +#define AGG_RASTERIZER_COMPOUND_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + +namespace agg +{ + + //-----------------------------------------------------------cell_style_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_style_aa + { + int x; + int y; + int cover; + int area; + int16 left, right; + + void initial() + { + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + left = -1; + right = -1; + } + + void style(const cell_style_aa& c) + { + left = c.left; + right = c.right; + } + + int not_equal(int ex, int ey, const cell_style_aa& c) const + { + return (ex - x) | (ey - y) | (left - c.left) | (right - c.right); + } + }; + + + //===========================================================layer_order_e + enum layer_order_e + { + layer_unsorted, //------layer_unsorted + layer_direct, //------layer_direct + layer_inverse //------layer_inverse + }; + + + //==================================================rasterizer_compound_aa + template class rasterizer_compound_aa + { + struct style_info + { + unsigned start_cell; + unsigned num_cells; + int last_x; + }; + + struct cell_info + { + int x, area, cover; + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_compound_aa(unsigned cell_block_limit=1024) : + m_outline(cell_block_limit), + m_clipper(), + m_filling_rule(fill_non_zero), + m_layer_order(layer_direct), + m_styles(), // Active Styles + m_ast(), // Active Style Table (unique values) + m_asm(), // Active Style Mask + m_cells(), + m_cover_buf(), + m_min_style(0x7FFFFFFF), + m_max_style(-0x7FFFFFFF), + m_start_x(0), + m_start_y(0), + m_scan_y(0x7FFFFFFF), + m_sl_start(0), + m_sl_len(0) + {} + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void layer_order(layer_order_e order); + + //-------------------------------------------------------------------- + void styles(int left, int right); + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + int min_style() const { return m_min_style; } + int max_style() const { return m_max_style; } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + unsigned sweep_styles(); + int scanline_start() const { return m_sl_start; } + unsigned scanline_length() const { return m_sl_len; } + unsigned style(unsigned style_idx) const; + + cover_type* allocate_cover_buffer(unsigned len); + + //-------------------------------------------------------------------- + bool navigate_scanline(int y); + bool hit_test(int tx, int ty); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return cover; + } + + //-------------------------------------------------------------------- + // Sweeps one scanline with one style index. The style ID can be + // determined by calling style(). + template bool sweep_scanline(Scanline& sl, int style_idx) + { + int scan_y = m_scan_y - 1; + if(scan_y > m_outline.max_y()) return false; + + sl.reset_spans(); + + if(style_idx < 0) + { + style_idx = 0; + } + else + { + style_idx++; + } + + const style_info& st = m_styles[m_ast[style_idx]]; + + unsigned num_cells = st.num_cells; + cell_info* cell = &m_cells[st.start_cell]; + + int cover = 0; + while(num_cells--) + { + unsigned alpha; + int x = cell->x; + int area = cell->area; + + cover += cell->cover; + + ++cell; + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + sl.add_cell(x, alpha); + x++; + } + + if(num_cells && cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cell->x - x, alpha); + } + } + } + + if(sl.num_spans() == 0) return false; + sl.finalize(scan_y); + return true; + } + + private: + void add_style(int style_id); + + //-------------------------------------------------------------------- + // Disable copying + rasterizer_compound_aa(const rasterizer_compound_aa&); + const rasterizer_compound_aa& + operator = (const rasterizer_compound_aa&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + filling_rule_e m_filling_rule; + layer_order_e m_layer_order; + pod_vector m_styles; // Active Styles + pod_vector m_ast; // Active Style Table (unique values) + pod_vector m_asm; // Active Style Mask + pod_vector m_cells; + pod_vector m_cover_buf; + + int m_min_style; + int m_max_style; + coord_type m_start_x; + coord_type m_start_y; + int m_scan_y; + int m_sl_start; + unsigned m_sl_len; + }; + + + + + + + + + + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::reset() + { + m_outline.reset(); + m_min_style = 0x7FFFFFFF; + m_max_style = -0x7FFFFFFF; + m_scan_y = 0x7FFFFFFF; + m_sl_start = 0; + m_sl_len = 0; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::layer_order(layer_order_e order) + { + m_layer_order = order; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::styles(int left, int right) + { + cell_style_aa cell; + cell.initial(); + cell.left = (int16)left; + cell.right = (int16)right; + m_outline.style(cell); + if(left >= 0 && left < m_min_style) m_min_style = left; + if(left >= 0 && left > m_max_style) m_max_style = left; + if(right >= 0 && right < m_min_style) m_min_style = right; + if(right >= 0 && right > m_max_style) m_max_style = right; + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_compound_aa::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_compound_aa::sort() + { + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_compound_aa::rewind_scanlines() + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + m_scan_y = m_outline.min_y(); + m_styles.allocate(m_max_style - m_min_style + 2, 128); + return true; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE void rasterizer_compound_aa::add_style(int style_id) + { + if(style_id < 0) style_id = 0; + else style_id -= m_min_style - 1; + + unsigned nbyte = style_id >> 3; + unsigned mask = 1 << (style_id & 7); + + style_info* style = &m_styles[style_id]; + if((m_asm[nbyte] & mask) == 0) + { + m_ast.add(style_id); + m_asm[nbyte] |= mask; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + } + ++style->start_cell; + } + + //------------------------------------------------------------------------ + // Returns the number of styles + template + unsigned rasterizer_compound_aa::sweep_styles() + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return 0; + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_style_aa* const* cells = m_outline.scanline_cells(m_scan_y); + unsigned num_styles = m_max_style - m_min_style + 2; + const cell_style_aa* curr_cell; + unsigned style_id; + style_info* style; + cell_info* cell; + + m_cells.allocate(num_cells * 2, 256); // Each cell can have two styles + m_ast.capacity(num_styles, 64); + m_asm.allocate((num_styles + 7) >> 3, 8); + m_asm.zero(); + + if(num_cells) + { + // Pre-add zero (for no-fill style, that is, -1). + // We need that to ensure that the "-1 style" would go first. + m_asm[0] |= 1; + m_ast.add(0); + style = &m_styles[0]; + style->start_cell = 0; + style->num_cells = 0; + style->last_x = -0x7FFFFFFF; + + m_sl_start = cells[0]->x; + m_sl_len = cells[num_cells-1]->x - m_sl_start + 1; + while(num_cells--) + { + curr_cell = *cells++; + add_style(curr_cell->left); + add_style(curr_cell->right); + } + + // Convert the Y-histogram into the array of starting indexes + unsigned i; + unsigned start_cell = 0; + for(i = 0; i < m_ast.size(); i++) + { + style_info& st = m_styles[m_ast[i]]; + unsigned v = st.start_cell; + st.start_cell = start_cell; + start_cell += v; + } + + cells = m_outline.scanline_cells(m_scan_y); + num_cells = m_outline.scanline_num_cells(m_scan_y); + + while(num_cells--) + { + curr_cell = *cells++; + style_id = (curr_cell->left < 0) ? 0 : + curr_cell->left - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area += curr_cell->area; + cell->cover += curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = curr_cell->area; + cell->cover = curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + + style_id = (curr_cell->right < 0) ? 0 : + curr_cell->right - m_min_style + 1; + + style = &m_styles[style_id]; + if(curr_cell->x == style->last_x) + { + cell = &m_cells[style->start_cell + style->num_cells - 1]; + cell->area -= curr_cell->area; + cell->cover -= curr_cell->cover; + } + else + { + cell = &m_cells[style->start_cell + style->num_cells]; + cell->x = curr_cell->x; + cell->area = -curr_cell->area; + cell->cover = -curr_cell->cover; + style->last_x = curr_cell->x; + style->num_cells++; + } + } + } + if(m_ast.size() > 1) break; + ++m_scan_y; + } + ++m_scan_y; + + if(m_layer_order != layer_unsorted) + { + range_adaptor > ra(m_ast, 1, m_ast.size() - 1); + if(m_layer_order == layer_direct) quick_sort(ra, unsigned_greater); + else quick_sort(ra, unsigned_less); + } + + return m_ast.size() - 1; + } + + //------------------------------------------------------------------------ + // Returns style ID depending of the existing style index + template + AGG_INLINE + unsigned rasterizer_compound_aa::style(unsigned style_idx) const + { + return m_ast[style_idx + 1] + m_min_style - 1; + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_compound_aa::navigate_scanline(int y) + { + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + if(m_max_style < m_min_style) + { + return false; + } + if(y < m_outline.min_y() || y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + m_styles.allocate(m_max_style - m_min_style + 2, 128); + return true; + } + + //------------------------------------------------------------------------ + template + bool rasterizer_compound_aa::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) + { + return false; + } + + unsigned num_styles = sweep_styles(); + if(num_styles <= 0) + { + return false; + } + + scanline_hit_test sl(tx); + sweep_scanline(sl, -1); + return sl.hit(); + } + + //------------------------------------------------------------------------ + template + cover_type* rasterizer_compound_aa::allocate_cover_buffer(unsigned len) + { + m_cover_buf.allocate(len, 256); + return &m_cover_buf[0]; + } + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline.h new file mode 100644 index 00000000000..65203e34c5b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline.h @@ -0,0 +1,147 @@ +//---------------------------------------------------------------------------- +// 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_RASTERIZER_OUTLINE_INCLUDED +#define AGG_RASTERIZER_OUTLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //======================================================rasterizer_outline + template class rasterizer_outline + { + public: + explicit rasterizer_outline(Renderer& ren) : + m_ren(&ren), + m_start_x(0), + m_start_y(0), + m_vertices(0) + {} + void attach(Renderer& ren) { m_ren = &ren; } + + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_vertices = 1; + m_ren->move_to(m_start_x = x, m_start_y = y); + } + + //-------------------------------------------------------------------- + void line_to(int x, int y) + { + ++m_vertices; + m_ren->line_to(x, y); + } + + //-------------------------------------------------------------------- + void move_to_d(double x, double y) + { + move_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void line_to_d(double x, double y) + { + line_to(m_ren->coord(x), m_ren->coord(y)); + } + + //-------------------------------------------------------------------- + void close() + { + if(m_vertices > 2) + { + line_to(m_start_x, m_start_y); + } + m_vertices = 0; + } + + //-------------------------------------------------------------------- + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + if(is_closed(cmd)) close(); + } + else + { + line_to_d(x, y); + } + } + } + + + //-------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + + //-------------------------------------------------------------------- + template + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren->line_color(colors[i]); + add_path(vs, path_id[i]); + } + } + + + //-------------------------------------------------------------------- + template void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + m_ren->line_color(c.color(i)); + add_path(c, i); + } + } + + + private: + Renderer* m_ren; + int m_start_x; + int m_start_y; + unsigned m_vertices; + }; + + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline_aa.h new file mode 100644 index 00000000000..a06bd1e843e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_outline_aa.h @@ -0,0 +1,599 @@ +//---------------------------------------------------------------------------- +// 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_RASTERIZER_OUTLINE_AA_INCLUDED +#define AGG_RASTERIZER_OUTLINE_AA_INCLUDED + +#include "agg_basics.h" +#include "agg_line_aa_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //------------------------------------------------------------------------- + inline bool cmp_dist_start(int d) { return d > 0; } + inline bool cmp_dist_end(int d) { return d <= 0; } + + + + //-----------------------------------------------------------line_aa_vertex + // Vertex (x, y) with the distance to the next one. The last vertex has + // the distance between the last and the first points + struct line_aa_vertex + { + int x; + int y; + int len; + + line_aa_vertex() {} + line_aa_vertex(int x_, int y_) : + x(x_), + y(y_), + len(0) + { + } + + bool operator () (const line_aa_vertex& val) + { + double dx = val.x - x; + double dy = val.y - y; + return (len = uround(sqrt(dx * dx + dy * dy))) > + (line_subpixel_scale + line_subpixel_scale / 2); + } + }; + + + //----------------------------------------------------------outline_aa_join_e + enum outline_aa_join_e + { + outline_no_join, //-----outline_no_join + outline_miter_join, //-----outline_miter_join + outline_round_join, //-----outline_round_join + outline_miter_accurate_join //-----outline_accurate_join + }; + + //=======================================================rasterizer_outline_aa + template class rasterizer_outline_aa + { + private: + //------------------------------------------------------------------------ + struct draw_vars + { + unsigned idx; + int x1, y1, x2, y2; + line_parameters curr, next; + int lcurr, lnext; + int xb1, yb1, xb2, yb2; + unsigned flags; + }; + + void draw(draw_vars& dv, unsigned start, unsigned end); + + public: + typedef line_aa_vertex vertex_type; + typedef vertex_sequence vertex_storage_type; + + explicit rasterizer_outline_aa(Renderer& ren) : + m_ren(&ren), + m_line_join(ren.accurate_join_only() ? + outline_miter_accurate_join : + outline_round_join), + m_round_cap(false), + m_start_x(0), + m_start_y(0) + {} + void attach(Renderer& ren) { m_ren = &ren; } + + //------------------------------------------------------------------------ + void line_join(outline_aa_join_e join) + { + m_line_join = m_ren->accurate_join_only() ? + outline_miter_accurate_join : + join; + } + bool line_join() const { return m_line_join; } + + //------------------------------------------------------------------------ + void round_cap(bool v) { m_round_cap = v; } + bool round_cap() const { return m_round_cap; } + + //------------------------------------------------------------------------ + void move_to(int x, int y) + { + m_src_vertices.modify_last(vertex_type(m_start_x = x, m_start_y = y)); + } + + //------------------------------------------------------------------------ + void line_to(int x, int y) + { + m_src_vertices.add(vertex_type(x, y)); + } + + //------------------------------------------------------------------------ + void move_to_d(double x, double y) + { + move_to(Coord::conv(x), Coord::conv(y)); + } + + //------------------------------------------------------------------------ + void line_to_d(double x, double y) + { + line_to(Coord::conv(x), Coord::conv(y)); + } + + //------------------------------------------------------------------------ + void render(bool close_polygon); + + //------------------------------------------------------------------------ + void add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + render(false); + move_to_d(x, y); + } + else + { + if(is_end_poly(cmd)) + { + render(is_closed(cmd)); + if(is_closed(cmd)) + { + move_to(m_start_x, m_start_y); + } + } + else + { + line_to_d(x, y); + } + } + } + + //------------------------------------------------------------------------ + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + render(false); + } + + + //------------------------------------------------------------------------ + template + void render_all_paths(VertexSource& vs, + const ColorStorage& colors, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + m_ren->color(colors[i]); + add_path(vs, path_id[i]); + } + } + + + //------------------------------------------------------------------------ + template void render_ctrl(Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + m_ren->color(c.color(i)); + add_path(c, i); + } + } + + private: + rasterizer_outline_aa(const rasterizer_outline_aa&); + const rasterizer_outline_aa& operator = + (const rasterizer_outline_aa&); + + Renderer* m_ren; + vertex_storage_type m_src_vertices; + outline_aa_join_e m_line_join; + bool m_round_cap; + int m_start_x; + int m_start_y; + }; + + + + + + + + + //---------------------------------------------------------------------------- + template + void rasterizer_outline_aa::draw(draw_vars& dv, + unsigned start, + unsigned end) + { + unsigned i; + const vertex_storage_type::value_type* v; + + for(i = start; i < end; i++) + { + if(m_line_join == outline_round_join) + { + dv.xb1 = dv.curr.x1 + (dv.curr.y2 - dv.curr.y1); + dv.yb1 = dv.curr.y1 - (dv.curr.x2 - dv.curr.x1); + dv.xb2 = dv.curr.x2 + (dv.curr.y2 - dv.curr.y1); + dv.yb2 = dv.curr.y2 - (dv.curr.x2 - dv.curr.x1); + } + + switch(dv.flags) + { + case 0: m_ren->line3(dv.curr, dv.xb1, dv.yb1, dv.xb2, dv.yb2); break; + case 1: m_ren->line2(dv.curr, dv.xb2, dv.yb2); break; + case 2: m_ren->line1(dv.curr, dv.xb1, dv.yb1); break; + case 3: m_ren->line0(dv.curr); break; + } + + if(m_line_join == outline_round_join && (dv.flags & 2) == 0) + { + m_ren->pie(dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.next.y2 - dv.next.y1), + dv.curr.y2 - (dv.next.x2 - dv.next.x1)); + } + + dv.x1 = dv.x2; + dv.y1 = dv.y2; + dv.lcurr = dv.lnext; + dv.lnext = m_src_vertices[dv.idx].len; + + ++dv.idx; + if(dv.idx >= m_src_vertices.size()) dv.idx = 0; + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + + dv.curr = dv.next; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + dv.xb1 = dv.xb2; + dv.yb1 = dv.yb2; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + if((dv.flags & 2) == 0) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + break; + + case outline_round_join: + dv.flags >>= 1; + dv.flags |= ((dv.curr.diagonal_quadrant() == + dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + break; + } + } + } + + + + + //---------------------------------------------------------------------------- + template + void rasterizer_outline_aa::render(bool close_polygon) + { + m_src_vertices.close(close_polygon); + draw_vars dv; + const vertex_storage_type::value_type* v; + int x1; + int y1; + int x2; + int y2; + int lprev; + + if(close_polygon) + { + if(m_src_vertices.size() >= 3) + { + dv.idx = 2; + + v = &m_src_vertices[m_src_vertices.size() - 1]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[0]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[1]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; + } + + if((dv.flags & 1) == 0 && m_line_join != outline_round_join) + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + } + + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + draw(dv, 0, m_src_vertices.size()); + } + } + else + { + switch(m_src_vertices.size()) + { + case 0: + case 1: + break; + + case 2: + { + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + line_parameters lp(x1, y1, x2, y2, lprev); + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + m_ren->line3(lp, + x1 + (y2 - y1), + y1 - (x2 - x1), + x2 + (y2 - y1), + y2 - (x2 - x1)); + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, x2, y2, x2 + (y2 - y1), y2 - (x2 - x1)); + } + } + break; + + case 3: + { + int x3, y3; + int lnext; + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + lnext = v->len; + v = &m_src_vertices[2]; + x3 = v->x; + y3 = v->y; + line_parameters lp1(x1, y1, x2, y2, lprev); + line_parameters lp2(x2, y2, x3, y3, lnext); + + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + + if(m_line_join == outline_round_join) + { + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + + m_ren->pie(x2, y2, x2 + (y2 - y1), y2 - (x2 - x1), + x2 + (y3 - y2), y2 - (x3 - x2)); + + m_ren->line3(lp2, x2 + (y3 - y2), y2 - (x3 - x2), + x3 + (y3 - y2), y3 - (x3 - x2)); + } + else + { + bisectrix(lp1, lp2, &dv.xb1, &dv.yb1); + m_ren->line3(lp1, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + + m_ren->line3(lp2, dv.xb1, dv.yb1, + x3 + (y3 - y2), y3 - (x3 - x2)); + } + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, x3, y3, x3 + (y3 - y2), y3 - (x3 - x2)); + } + } + break; + + default: + { + dv.idx = 3; + + v = &m_src_vertices[0]; + x1 = v->x; + y1 = v->y; + lprev = v->len; + + v = &m_src_vertices[1]; + x2 = v->x; + y2 = v->y; + dv.lcurr = v->len; + line_parameters prev(x1, y1, x2, y2, lprev); + + v = &m_src_vertices[2]; + dv.x1 = v->x; + dv.y1 = v->y; + dv.lnext = v->len; + dv.curr = line_parameters(x2, y2, dv.x1, dv.y1, dv.lcurr); + + v = &m_src_vertices[dv.idx]; + dv.x2 = v->x; + dv.y2 = v->y; + dv.next = line_parameters(dv.x1, dv.y1, dv.x2, dv.y2, dv.lnext); + + dv.xb1 = 0; + dv.yb1 = 0; + dv.xb2 = 0; + dv.yb2 = 0; + + switch(m_line_join) + { + case outline_no_join: + dv.flags = 3; + break; + + case outline_miter_join: + case outline_round_join: + dv.flags = + (prev.diagonal_quadrant() == dv.curr.diagonal_quadrant()) | + ((dv.curr.diagonal_quadrant() == dv.next.diagonal_quadrant()) << 1); + break; + + case outline_miter_accurate_join: + dv.flags = 0; + break; + } + + if(m_round_cap) + { + m_ren->semidot(cmp_dist_start, x1, y1, x1 + (y2 - y1), y1 - (x2 - x1)); + } + if((dv.flags & 1) == 0) + { + if(m_line_join == outline_round_join) + { + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + x2 + (y2 - y1), y2 - (x2 - x1)); + m_ren->pie(prev.x2, prev.y2, + x2 + (y2 - y1), y2 - (x2 - x1), + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + bisectrix(prev, dv.curr, &dv.xb1, &dv.yb1); + m_ren->line3(prev, x1 + (y2 - y1), y1 - (x2 - x1), + dv.xb1, dv.yb1); + } + } + else + { + m_ren->line1(prev, + x1 + (y2 - y1), + y1 - (x2 - x1)); + } + if((dv.flags & 2) == 0 && m_line_join != outline_round_join) + { + bisectrix(dv.curr, dv.next, &dv.xb2, &dv.yb2); + } + + draw(dv, 1, m_src_vertices.size() - 2); + + if((dv.flags & 1) == 0) + { + if(m_line_join == outline_round_join) + { + m_ren->line3(dv.curr, + dv.curr.x1 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y1 - (dv.curr.x2 - dv.curr.x1), + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + else + { + m_ren->line3(dv.curr, dv.xb1, dv.yb1, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + } + else + { + m_ren->line2(dv.curr, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + if(m_round_cap) + { + m_ren->semidot(cmp_dist_end, dv.curr.x2, dv.curr.y2, + dv.curr.x2 + (dv.curr.y2 - dv.curr.y1), + dv.curr.y2 - (dv.curr.x2 - dv.curr.x1)); + } + + } + break; + } + } + m_src_vertices.remove_all(); + } + + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa.h new file mode 100644 index 00000000000..15832166462 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa.h @@ -0,0 +1,481 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_RASTERIZER_SCANLINE_AA_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" +#include "agg_rasterizer_scanline_aa_nogamma.h" +#include "agg_gamma_functions.h" + + +namespace agg +{ + //==================================================rasterizer_scanline_aa + // Polygon rasterizer that is used to render filled polygons with + // high-quality Anti-Aliasing. Internally, by default, the class uses + // integer coordinates in format 24.8, i.e. 24 bits for integer part + // and 8 bits for fractional - see poly_subpixel_shift. This class can be + // used in the following way: + // + // 1. filling_rule(filling_rule_e ft) - optional. + // + // 2. gamma() - optional. + // + // 3. reset() + // + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // more than one contour, but each contour must consist of at least 3 + // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); + // is the absolute minimum of vertices that define a triangle. + // The algorithm does not check either the number of vertices nor + // coincidence of their coordinates, but in the worst case it just + // won't draw anything. + // The orger of the vertices (clockwise or counterclockwise) + // is important when using the non-zero filling rule (fill_non_zero). + // In this case the vertex order of all the contours must be the same + // if you want your intersecting polygons to be without "holes". + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" + // while the intersecting contours with different orders will have "holes". + // + // filling_rule() and gamma() can be called anytime before "sweeping". + //------------------------------------------------------------------------ + template class rasterizer_scanline_aa + { + enum status + { + status_initial, + status_move_to, + status_line_to, + status_closed + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_scanline_aa(unsigned cell_block_limit=1024) : + m_outline(cell_block_limit), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = i; + } + + //-------------------------------------------------------------------- + template + rasterizer_scanline_aa(const GammaF& gamma_function, unsigned cell_block_limit) : + m_outline(cell_block_limit), + m_clipper(m_outline), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + gamma(gamma_function); + } + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } + + //-------------------------------------------------------------------- + template void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); + } + } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; + + cover += cur_cell->cover; + + //accumulate all cells with the same X + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + if(alpha) + { + sl.add_cell(x, alpha); + } + x++; + } + + if(num_cells && cur_cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cur_cell->x - x, alpha); + } + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa(const rasterizer_scanline_aa&); + const rasterizer_scanline_aa& + operator = (const rasterizer_scanline_aa&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + int m_gamma[aa_scale]; + filling_rule_e m_filling_rule; + bool m_auto_close; + coord_type m_start_x; + coord_type m_start_y; + unsigned m_status; + int m_scan_y; + }; + + + + + + + + + + + + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::close_polygon() + { + if(m_status == status_line_to) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + close_polygon(); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa::sort() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa::rewind_scanlines() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + m_scan_y = m_outline.min_y(); + return true; + } + + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa::navigate_scanline(int y) + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + return true; + } + + //------------------------------------------------------------------------ + template + bool rasterizer_scanline_aa::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa_nogamma.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa_nogamma.h new file mode 100644 index 00000000000..7729b3359a1 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_scanline_aa_nogamma.h @@ -0,0 +1,482 @@ +//---------------------------------------------------------------------------- +// 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. +// +//---------------------------------------------------------------------------- +// +// The author gratefully acknowleges the support of David Turner, +// Robert Wilhelm, and Werner Lemberg - the authors of the FreeType +// libray - in producing this work. See http://www.freetype.org for details. +// +//---------------------------------------------------------------------------- +// Contact: mcseem@antigrain.com +// mcseemagg@yahoo.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_NOGAMMA_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" + + +namespace agg +{ + + + //-----------------------------------------------------------------cell_aa + // A pixel cell. There're no constructors defined and it was done + // intentionally in order to avoid extra overhead when allocating an + // array of cells. + struct cell_aa + { + int x; + int y; + int cover; + int area; + + void initial() + { + x = 0x7FFFFFFF; + y = 0x7FFFFFFF; + cover = 0; + area = 0; + } + + void style(const cell_aa&) {} + + int not_equal(int ex, int ey, const cell_aa&) const + { + return ex != x || ey != y; + } + }; + + + //==================================================rasterizer_scanline_aa_nogamma + // Polygon rasterizer that is used to render filled polygons with + // high-quality Anti-Aliasing. Internally, by default, the class uses + // integer coordinates in format 24.8, i.e. 24 bits for integer part + // and 8 bits for fractional - see poly_subpixel_shift. This class can be + // used in the following way: + // + // 1. filling_rule(filling_rule_e ft) - optional. + // + // 2. gamma() - optional. + // + // 3. reset() + // + // 4. move_to(x, y) / line_to(x, y) - make the polygon. One can create + // more than one contour, but each contour must consist of at least 3 + // vertices, i.e. move_to(x1, y1); line_to(x2, y2); line_to(x3, y3); + // is the absolute minimum of vertices that define a triangle. + // The algorithm does not check either the number of vertices nor + // coincidence of their coordinates, but in the worst case it just + // won't draw anything. + // The orger of the vertices (clockwise or counterclockwise) + // is important when using the non-zero filling rule (fill_non_zero). + // In this case the vertex order of all the contours must be the same + // if you want your intersecting polygons to be without "holes". + // You actually can use different vertices order. If the contours do not + // intersect each other the order is not important anyway. If they do, + // contours with the same vertex order will be rendered without "holes" + // while the intersecting contours with different orders will have "holes". + // + // filling_rule() and gamma() can be called anytime before "sweeping". + //------------------------------------------------------------------------ + template class rasterizer_scanline_aa_nogamma + { + enum status + { + status_initial, + status_move_to, + status_line_to, + status_closed + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_scanline_aa_nogamma(unsigned cell_block_limit=1024) : + m_outline(cell_block_limit), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + } + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return cover; + } + + //-------------------------------------------------------------------- + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x(); } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x(); } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return cover; + } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area = cur_cell->area; + unsigned alpha; + + cover += cur_cell->cover; + + //accumulate all cells with the same X + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area += cur_cell->area; + cover += cur_cell->cover; + } + + if(area) + { + alpha = calculate_alpha((cover << (poly_subpixel_shift + 1)) - area); + if(alpha) + { + sl.add_cell(x, alpha); + } + x++; + } + + if(num_cells && cur_cell->x > x) + { + alpha = calculate_alpha(cover << (poly_subpixel_shift + 1)); + if(alpha) + { + sl.add_span(x, cur_cell->x - x, alpha); + } + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa_nogamma(const rasterizer_scanline_aa_nogamma&); + const rasterizer_scanline_aa_nogamma& + operator = (const rasterizer_scanline_aa_nogamma&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + filling_rule_e m_filling_rule; + bool m_auto_close; + coord_type m_start_x; + coord_type m_start_y; + unsigned m_status; + int m_scan_y; + }; + + + + + + + + + + + + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(conv_type::upscale(x1), conv_type::upscale(y1), + conv_type::upscale(x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::close_polygon() + { + if(m_status == status_line_to) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + close_polygon(); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_nogamma::sort() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa_nogamma::rewind_scanlines() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + m_scan_y = m_outline.min_y(); + return true; + } + + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa_nogamma::navigate_scanline(int y) + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + return true; + } + + //------------------------------------------------------------------------ + template + bool rasterizer_scanline_aa_nogamma::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_sl_clip.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_sl_clip.h new file mode 100644 index 00000000000..e7ba065acce --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rasterizer_sl_clip.h @@ -0,0 +1,351 @@ +//---------------------------------------------------------------------------- +// 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_RASTERIZER_SL_CLIP_INCLUDED +#define AGG_RASTERIZER_SL_CLIP_INCLUDED + +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //--------------------------------------------------------poly_max_coord_e + enum poly_max_coord_e + { + poly_max_coord = (1 << 30) - 1 //----poly_max_coord + }; + + //------------------------------------------------------------ras_conv_int + struct ras_conv_int + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //--------------------------------------------------------ras_conv_int_sat + struct ras_conv_int_sat + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return saturation::iround(a * b / c); + } + static int xi(int v) { return v; } + static int yi(int v) { return v; } + static int upscale(double v) + { + return saturation::iround(v * poly_subpixel_scale); + } + static int downscale(int v) { return v; } + }; + + //---------------------------------------------------------ras_conv_int_3x + struct ras_conv_int_3x + { + typedef int coord_type; + static AGG_INLINE int mul_div(double a, double b, double c) + { + return iround(a * b / c); + } + static int xi(int v) { return v * 3; } + static int yi(int v) { return v; } + static int upscale(double v) { return iround(v * poly_subpixel_scale); } + static int downscale(int v) { return v; } + }; + + //-----------------------------------------------------------ras_conv_dbl + struct ras_conv_dbl + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + //--------------------------------------------------------ras_conv_dbl_3x + struct ras_conv_dbl_3x + { + typedef double coord_type; + static AGG_INLINE double mul_div(double a, double b, double c) + { + return a * b / c; + } + static int xi(double v) { return iround(v * poly_subpixel_scale * 3); } + static int yi(double v) { return iround(v * poly_subpixel_scale); } + static double upscale(double v) { return v; } + static double downscale(int v) { return v / double(poly_subpixel_scale); } + }; + + + + + + //------------------------------------------------------rasterizer_sl_clip + template class rasterizer_sl_clip + { + public: + typedef Conv conv_type; + typedef typename Conv::coord_type coord_type; + typedef rect_base rect_type; + + //-------------------------------------------------------------------- + rasterizer_sl_clip() : + m_clip_box(0,0,0,0), + m_x1(0), + m_y1(0), + m_f1(0), + m_clipping(false) + {} + + //-------------------------------------------------------------------- + void reset_clipping() + { + m_clipping = false; + } + + //-------------------------------------------------------------------- + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) + { + m_clip_box = rect_type(x1, y1, x2, y2); + m_clip_box.normalize(); + m_clipping = true; + } + + //-------------------------------------------------------------------- + void move_to(coord_type x1, coord_type y1) + { + m_x1 = x1; + m_y1 = y1; + if(m_clipping) m_f1 = clipping_flags(x1, y1, m_clip_box); + } + + private: + //------------------------------------------------------------------------ + template + AGG_INLINE void line_clip_y(Rasterizer& ras, + coord_type x1, coord_type y1, + coord_type x2, coord_type y2, + unsigned f1, unsigned f2) const + { + f1 &= 10; + f2 &= 10; + if((f1 | f2) == 0) + { + // Fully visible + ras.line(Conv::xi(x1), Conv::yi(y1), Conv::xi(x2), Conv::yi(y2)); + } + else + { + if(f1 == f2) + { + // Invisible by Y + return; + } + + coord_type tx1 = x1; + coord_type ty1 = y1; + coord_type tx2 = x2; + coord_type ty2 = y2; + + if(f1 & 8) // y1 < clip.y1 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y1; + } + + if(f1 & 2) // y1 > clip.y2 + { + tx1 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty1 = m_clip_box.y2; + } + + if(f2 & 8) // y2 < clip.y1 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y1-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y1; + } + + if(f2 & 2) // y2 > clip.y2 + { + tx2 = x1 + Conv::mul_div(m_clip_box.y2-y1, x2-x1, y2-y1); + ty2 = m_clip_box.y2; + } + ras.line(Conv::xi(tx1), Conv::yi(ty1), + Conv::xi(tx2), Conv::yi(ty2)); + } + } + + + public: + //-------------------------------------------------------------------- + template + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + if(m_clipping) + { + unsigned f2 = clipping_flags(x2, y2, m_clip_box); + + if((m_f1 & 10) == (f2 & 10) && (m_f1 & 10) != 0) + { + // Invisible by Y + m_x1 = x2; + m_y1 = y2; + m_f1 = f2; + return; + } + + coord_type x1 = m_x1; + coord_type y1 = m_y1; + unsigned f1 = m_f1; + coord_type y3, y4; + unsigned f3, f4; + + switch(((f1 & 5) << 1) | (f2 & 5)) + { + case 0: // Visible by X + line_clip_y(ras, x1, y1, x2, y2, f1, f2); + break; + + case 1: // x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x2, y2, f3, f2); + break; + + case 2: // x1 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, x2, y2, f3, f2); + break; + + case 3: // x1 > clip.x2 && x2 > clip.x2 + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y2, f1, f2); + break; + + case 4: // x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x1, y2, f3, f2); + break; + + case 6: // x1 > clip.x2 && x2 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x2, y1, m_clip_box.x2, y3, f1, f3); + line_clip_y(ras, m_clip_box.x2, y3, m_clip_box.x1, y4, f3, f4); + line_clip_y(ras, m_clip_box.x1, y4, m_clip_box.x1, y2, f4, f2); + break; + + case 8: // x1 < clip.x1 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, x2, y2, f3, f2); + break; + + case 9: // x1 < clip.x1 && x2 > clip.x2 + y3 = y1 + Conv::mul_div(m_clip_box.x1-x1, y2-y1, x2-x1); + y4 = y1 + Conv::mul_div(m_clip_box.x2-x1, y2-y1, x2-x1); + f3 = clipping_flags_y(y3, m_clip_box); + f4 = clipping_flags_y(y4, m_clip_box); + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y3, f1, f3); + line_clip_y(ras, m_clip_box.x1, y3, m_clip_box.x2, y4, f3, f4); + line_clip_y(ras, m_clip_box.x2, y4, m_clip_box.x2, y2, f4, f2); + break; + + case 12: // x1 < clip.x1 && x2 < clip.x1 + line_clip_y(ras, m_clip_box.x1, y1, m_clip_box.x1, y2, f1, f2); + break; + } + m_f1 = f2; + } + else + { + ras.line(Conv::xi(m_x1), Conv::yi(m_y1), + Conv::xi(x2), Conv::yi(y2)); + } + m_x1 = x2; + m_y1 = y2; + } + + + private: + rect_type m_clip_box; + coord_type m_x1; + coord_type m_y1; + unsigned m_f1; + bool m_clipping; + }; + + + + + //---------------------------------------------------rasterizer_sl_no_clip + class rasterizer_sl_no_clip + { + public: + typedef ras_conv_int conv_type; + typedef int coord_type; + + rasterizer_sl_no_clip() : m_x1(0), m_y1(0) {} + + void reset_clipping() {} + void clip_box(coord_type x1, coord_type y1, coord_type x2, coord_type y2) {} + void move_to(coord_type x1, coord_type y1) { m_x1 = x1; m_y1 = y1; } + + template + void line_to(Rasterizer& ras, coord_type x2, coord_type y2) + { + ras.line(m_x1, m_y1, x2, y2); + m_x1 = x2; + m_y1 = y2; + } + + private: + int m_x1, m_y1; + }; + + + // -----rasterizer_sl_clip_int + // -----rasterizer_sl_clip_int_sat + // -----rasterizer_sl_clip_int_3x + // -----rasterizer_sl_clip_dbl + // -----rasterizer_sl_clip_dbl_3x + //------------------------------------------------------------------------ + typedef rasterizer_sl_clip rasterizer_sl_clip_int; + typedef rasterizer_sl_clip rasterizer_sl_clip_int_sat; + typedef rasterizer_sl_clip rasterizer_sl_clip_int_3x; + typedef rasterizer_sl_clip rasterizer_sl_clip_dbl; + typedef rasterizer_sl_clip rasterizer_sl_clip_dbl_3x; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_base.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_base.h new file mode 100644 index 00000000000..527c62f7891 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_base.h @@ -0,0 +1,731 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class renderer_base +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_BASE_INCLUDED +#define AGG_RENDERER_BASE_INCLUDED + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + +namespace agg +{ + + //-----------------------------------------------------------renderer_base + template class renderer_base + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + + //-------------------------------------------------------------------- + renderer_base() : m_ren(0), m_clip_box(1, 1, 0, 0) {} + explicit renderer_base(pixfmt_type& ren) : + m_ren(&ren), + m_clip_box(0, 0, ren.width() - 1, ren.height() - 1) + {} + void attach(pixfmt_type& ren) + { + m_ren = &ren; + m_clip_box = rect_i(0, 0, ren.width() - 1, ren.height() - 1); + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return *m_ren; } + pixfmt_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren->width(); } + unsigned height() const { return m_ren->height(); } + + //-------------------------------------------------------------------- + bool clip_box(int x1, int y1, int x2, int y2) + { + rect_i cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) + { + m_clip_box = cb; + return true; + } + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + if(visibility) + { + m_clip_box.x1 = 0; + m_clip_box.y1 = 0; + m_clip_box.x2 = width() - 1; + m_clip_box.y2 = height() - 1; + } + else + { + m_clip_box.x1 = 1; + m_clip_box.y1 = 1; + m_clip_box.x2 = 0; + m_clip_box.y2 = 0; + } + } + + //-------------------------------------------------------------------- + void clip_box_naked(int x1, int y1, int x2, int y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + } + + //-------------------------------------------------------------------- + bool inbox(int x, int y) const + { + return x >= m_clip_box.x1 && y >= m_clip_box.y1 && + x <= m_clip_box.x2 && y <= m_clip_box.y2; + } + + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_clip_box; } + int xmin() const { return m_clip_box.x1; } + int ymin() const { return m_clip_box.y1; } + int xmax() const { return m_clip_box.x2; } + int ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_clip_box; } + int bounding_xmin() const { return m_clip_box.x1; } + int bounding_ymin() const { return m_clip_box.y1; } + int bounding_xmax() const { return m_clip_box.x2; } + int bounding_ymax() const { return m_clip_box.y2; } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->copy_hline(0, y, width(), c); + } + } + } + + + //-------------------------------------------------------------------- + void fill(const color_type& c) + { + unsigned y; + if(width()) + { + for(y = 0; y < height(); y++) + { + m_ren->blend_hline(0, y, width(), c, cover_mask); + } + } + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + if(inbox(x, y)) + { + m_ren->copy_pixel(x, y, c); + } + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + if(inbox(x, y)) + { + m_ren->blend_pixel(x, y, c, cover); + } + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + return inbox(x, y) ? + m_ren->pixel(x, y) : + color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->copy_hline(x1, y, x2 - x1 + 1, c); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->copy_vline(x, y1, y2 - y1 + 1, c); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } + if(y > ymax()) return; + if(y < ymin()) return; + if(x1 > xmax()) return; + if(x2 < xmin()) return; + + if(x1 < xmin()) x1 = xmin(); + if(x2 > xmax()) x2 = xmax(); + + m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + if(y1 > y2) { int t = y2; y2 = y1; y1 = t; } + if(x > xmax()) return; + if(x < xmin()) return; + if(y1 > ymax()) return; + if(y2 < ymin()) return; + + if(y1 < ymin()) y1 = ymin(); + if(y2 > ymax()) y2 = ymax(); + + m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover); + } + + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c); + } + } + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + rect_i rc(x1, y1, x2, y2); + rc.normalize(); + if(rc.clip(clip_box())) + { + int y; + for(y = rc.y1; y <= rc.y2; y++) + { + m_ren->blend_hline(rc.x1, + y, + unsigned(rc.x2 - rc.x1 + 1), + c, + cover); + } + } + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + len -= xmin() - x; + if(len <= 0) return; + covers += xmin() - x; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_solid_hspan(x, y, len, c, covers); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + len -= ymin() - y; + if(len <= 0) return; + covers += ymin() - y; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_solid_vspan(x, y, len, c, covers); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->copy_color_hspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, int len, const color_type* colors) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->copy_color_vspan(x, y, len, colors); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(y > ymax()) return; + if(y < ymin()) return; + + if(x < xmin()) + { + int d = xmin() - x; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + x = xmin(); + } + if(x + len > xmax()) + { + len = xmax() - x + 1; + if(len <= 0) return; + } + m_ren->blend_color_hspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = agg::cover_full) + { + if(x > xmax()) return; + if(x < xmin()) return; + + if(y < ymin()) + { + int d = ymin() - y; + len -= d; + if(len <= 0) return; + if(covers) covers += d; + colors += d; + y = ymin(); + } + if(y + len > ymax()) + { + len = ymax() - y + 1; + if(len <= 0) return; + } + m_ren->blend_color_vspan(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + rect_i clip_rect_area(rect_i& dst, rect_i& src, int wsrc, int hsrc) const + { + rect_i rc(0,0,0,0); + rect_i cb = clip_box(); + ++cb.x2; + ++cb.y2; + + if(src.x1 < 0) + { + dst.x1 -= src.x1; + src.x1 = 0; + } + if(src.y1 < 0) + { + dst.y1 -= src.y1; + src.y1 = 0; + } + + if(src.x2 > wsrc) src.x2 = wsrc; + if(src.y2 > hsrc) src.y2 = hsrc; + + if(dst.x1 < cb.x1) + { + src.x1 += cb.x1 - dst.x1; + dst.x1 = cb.x1; + } + if(dst.y1 < cb.y1) + { + src.y1 += cb.y1 - dst.y1; + dst.y1 = cb.y1; + } + + if(dst.x2 > cb.x2) dst.x2 = cb.x2; + if(dst.y2 > cb.y2) dst.y2 = cb.y2; + + rc.x2 = dst.x2 - dst.x1; + rc.y2 = dst.y2 - dst.y1; + + if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1; + if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1; + return rc; + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + m_ren->copy_from(src, + rdst.x1, rdst.y1, + rsrc.x1, rsrc.y1, + rc.x2); + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from(src, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& src, + const color_type& color, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_color(src, + color, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& src, + const color_type* color_lut, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = agg::cover_full) + { + rect_i rsrc(0, 0, src.width(), src.height()); + if(rect_src_ptr) + { + rsrc.x1 = rect_src_ptr->x1; + rsrc.y1 = rect_src_ptr->y1; + rsrc.x2 = rect_src_ptr->x2 + 1; + rsrc.y2 = rect_src_ptr->y2 + 1; + } + + // Version with xdst, ydst (absolute positioning) + //rect_i rdst(xdst, ydst, xdst + rsrc.x2 - rsrc.x1, ydst + rsrc.y2 - rsrc.y1); + + // Version with dx, dy (relative positioning) + rect_i rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy); + rect_i rc = clip_rect_area(rdst, rsrc, src.width(), src.height()); + + if(rc.x2 > 0) + { + int incy = 1; + if(rdst.y1 > rsrc.y1) + { + rsrc.y1 += rc.y2 - 1; + rdst.y1 += rc.y2 - 1; + incy = -1; + } + while(rc.y2 > 0) + { + typename SrcPixelFormatRenderer::row_data rw = src.row(rsrc.y1); + if(rw.ptr) + { + int x1src = rsrc.x1; + int x1dst = rdst.x1; + int len = rc.x2; + if(rw.x1 > x1src) + { + x1dst += rw.x1 - x1src; + len -= rw.x1 - x1src; + x1src = rw.x1; + } + if(len > 0) + { + if(x1src + len-1 > rw.x2) + { + len -= x1src + len - rw.x2 - 1; + } + if(len > 0) + { + m_ren->blend_from_lut(src, + color_lut, + x1dst, rdst.y1, + x1src, rsrc.y1, + len, + cover); + } + } + } + rdst.y1 += incy; + rsrc.y1 += incy; + --rc.y2; + } + } + } + + private: + pixfmt_type* m_ren; + rect_i m_clip_box; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_markers.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_markers.h new file mode 100644 index 00000000000..820f7530793 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_markers.h @@ -0,0 +1,706 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class renderer_markers +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MARKERS_INCLUDED +#define AGG_RENDERER_MARKERS_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_primitives.h" + +namespace agg +{ + + //---------------------------------------------------------------marker_e + enum marker_e + { + marker_square, + marker_diamond, + marker_circle, + marker_crossed_circle, + marker_semiellipse_left, + marker_semiellipse_right, + marker_semiellipse_up, + marker_semiellipse_down, + marker_triangle_left, + marker_triangle_right, + marker_triangle_up, + marker_triangle_down, + marker_four_rays, + marker_cross, + marker_x, + marker_dash, + marker_dot, + marker_pixel, + + end_of_markers + }; + + + + //--------------------------------------------------------renderer_markers + template class renderer_markers : + public renderer_primitives + { + public: + typedef renderer_primitives base_type; + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_markers(base_ren_type& rbuf) : + base_type(rbuf) + {} + + //-------------------------------------------------------------------- + bool visible(int x, int y, int r) const + { + rect_i rc(x-r, y-r, x+y, y+r); + return rc.clip(base_type::ren().bounding_clip_box()); + } + + //-------------------------------------------------------------------- + void square(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_rectangle(x-r, y-r, x+r, y+r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void diamond(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + ++dx; + } + while(dy <= 0); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + //-------------------------------------------------------------------- + void circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::outlined_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + + //-------------------------------------------------------------------- + void crossed_circle(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::outlined_ellipse(x, y, r, r); + int r6 = r + (r >> 1); + if(r <= 2) r6++; + r >>= 1; + base_type::ren().blend_hline(x-r6, y, x-r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x+r, y, x+r6, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y-r6, y-r, base_type::line_color(), cover_full); + base_type::ren().blend_vline(x, y+r, y+r6, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //------------------------------------------------------------------------ + void semiellipse_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y-dy-1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void semiellipse_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int r8 = r * 4 / 5; + int dy = -r; + int dx = 0; + ellipse_bresenham_interpolator ei(r * 3 / 5, r+r8); + do + { + dx += ei.dx(); + dy += ei.dy(); + + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + + if(ei.dy() && dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++ei; + } + while(dy < r8); + base_type::ren().blend_hline(x-dx, y+dy+1, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_left(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x+dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_right(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_vline(x-dy, y-dx, y+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_up(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y-dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void triangle_down(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r6 = r * 3 / 5; + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy < r6); + base_type::ren().blend_hline(x-dx, y+dy, x+dx, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void four_rays(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r; + int dx = 0; + int flip = 0; + int r3 = -(r / 3); + do + { + base_type::ren().blend_pixel(x - dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dx, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y + dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dx, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dx, base_type::line_color(), cover_full); + + if(dx) + { + base_type::ren().blend_hline(x-dx+1, y+dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_hline(x-dx+1, y-dy, x+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x+dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + base_type::ren().blend_vline(x-dy, y-dx+1, y+dx-1, base_type::fill_color(), cover_full); + } + ++dy; + dx += flip; + flip ^= 1; + } + while(dy <= r3); + base_type::solid_rectangle(x+r3+1, y+r3+1, x-r3-1, y-r3-1); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void cross(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + base_type::ren().blend_vline(x, y-r, y+r, base_type::line_color(), cover_full); + base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + } + else + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + } + + + //-------------------------------------------------------------------- + void xing(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) + { + int dy = -r * 7 / 10; + do + { + base_type::ren().blend_pixel(x + dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y + dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x + dy, y - dy, base_type::line_color(), cover_full); + base_type::ren().blend_pixel(x - dy, y - dy, base_type::line_color(), cover_full); + ++dy; + } + while(dy < 0); + } + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dash(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::ren().blend_hline(x-r, y, x+r, base_type::line_color(), cover_full); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + + //-------------------------------------------------------------------- + void dot(int x, int y, int r) + { + if(visible(x, y, r)) + { + if(r) base_type::solid_ellipse(x, y, r, r); + else base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + } + + //-------------------------------------------------------------------- + void pixel(int x, int y, int) + { + base_type::ren().blend_pixel(x, y, base_type::fill_color(), cover_full); + } + + //-------------------------------------------------------------------- + void marker(int x, int y, int r, marker_e type) + { + switch(type) + { + case marker_square: square(x, y, r); break; + case marker_diamond: diamond(x, y, r); break; + case marker_circle: circle(x, y, r); break; + case marker_crossed_circle: crossed_circle(x, y, r); break; + case marker_semiellipse_left: semiellipse_left(x, y, r); break; + case marker_semiellipse_right: semiellipse_right(x, y, r); break; + case marker_semiellipse_up: semiellipse_up(x, y, r); break; + case marker_semiellipse_down: semiellipse_down(x, y, r); break; + case marker_triangle_left: triangle_left(x, y, r); break; + case marker_triangle_right: triangle_right(x, y, r); break; + case marker_triangle_up: triangle_up(x, y, r); break; + case marker_triangle_down: triangle_down(x, y, r); break; + case marker_four_rays: four_rays(x, y, r); break; + case marker_cross: cross(x, y, r); break; + case marker_x: xing(x, y, r); break; + case marker_dash: dash(x, y, r); break; + case marker_dot: dot(x, y, r); break; + case marker_pixel: pixel(x, y, r); break; + } + } + + + //-------------------------------------------------------------------- + template + void markers(int n, const T* x, const T* y, T r, marker_e type) + { + if(n <= 0) return; + if(r == 0) + { + do + { + base_type::ren().blend_pixel(int(*x), int(*y), base_type::fill_color(), cover_full); + ++x; + ++y; + } + while(--n); + return; + } + + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(r)); ++x; ++y; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template + void markers(int n, const T* x, const T* y, const T* r, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_diamond: do { diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_circle: do { circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_crossed_circle: do { crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_left: do { semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_right: do { semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_up: do { semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_semiellipse_down: do { semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_left: do { triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_right: do { triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_up: do { triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_triangle_down: do { triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_four_rays: do { four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_cross: do { cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_x: do { xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dash: do { dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_dot: do { dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + case marker_pixel: do { pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; } while(--n); break; + } + } + + //-------------------------------------------------------------------- + template + void markers(int n, const T* x, const T* y, const T* r, const color_type* fc, const color_type* lc, marker_e type) + { + if(n <= 0) return; + switch(type) + { + case marker_square: do { base_type::fill_color(*fc); base_type::line_color(*lc); square (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_diamond: do { base_type::fill_color(*fc); base_type::line_color(*lc); diamond (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_crossed_circle: do { base_type::fill_color(*fc); base_type::line_color(*lc); crossed_circle (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_right(int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_semiellipse_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); semiellipse_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_left: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_left (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_right: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_right (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_up: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_up (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_triangle_down: do { base_type::fill_color(*fc); base_type::line_color(*lc); triangle_down (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_four_rays: do { base_type::fill_color(*fc); base_type::line_color(*lc); four_rays (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_cross: do { base_type::fill_color(*fc); base_type::line_color(*lc); cross (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_x: do { base_type::fill_color(*fc); base_type::line_color(*lc); xing (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dash: do { base_type::fill_color(*fc); base_type::line_color(*lc); dash (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_dot: do { base_type::fill_color(*fc); base_type::line_color(*lc); dot (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + case marker_pixel: do { base_type::fill_color(*fc); base_type::line_color(*lc); pixel (int(*x), int(*y), int(*r)); ++x; ++y; ++r; ++fc; ++lc; } while(--n); break; + } + } + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_mclip.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_mclip.h new file mode 100644 index 00000000000..96a7d4e094e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_mclip.h @@ -0,0 +1,349 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class renderer_mclip +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_MCLIP_INCLUDED +#define AGG_RENDERER_MCLIP_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //----------------------------------------------------------renderer_mclip + template class renderer_mclip + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef typename pixfmt_type::row_data row_data; + typedef renderer_base base_ren_type; + + //-------------------------------------------------------------------- + explicit renderer_mclip(pixfmt_type& pixf) : + m_ren(pixf), + m_curr_cb(0), + m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + {} + void attach(pixfmt_type& pixf) + { + m_ren.attach(pixf); + reset_clipping(true); + } + + //-------------------------------------------------------------------- + const pixfmt_type& ren() const { return m_ren.ren(); } + pixfmt_type& ren() { return m_ren.ren(); } + + //-------------------------------------------------------------------- + unsigned width() const { return m_ren.width(); } + unsigned height() const { return m_ren.height(); } + + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_ren.clip_box(); } + int xmin() const { return m_ren.xmin(); } + int ymin() const { return m_ren.ymin(); } + int xmax() const { return m_ren.xmax(); } + int ymax() const { return m_ren.ymax(); } + + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_bounds; } + int bounding_xmin() const { return m_bounds.x1; } + int bounding_ymin() const { return m_bounds.y1; } + int bounding_xmax() const { return m_bounds.x2; } + int bounding_ymax() const { return m_bounds.y2; } + + //-------------------------------------------------------------------- + void first_clip_box() + { + m_curr_cb = 0; + if(m_clip.size()) + { + const rect_i& cb = m_clip[0]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + } + } + + //-------------------------------------------------------------------- + bool next_clip_box() + { + if(++m_curr_cb < m_clip.size()) + { + const rect_i& cb = m_clip[m_curr_cb]; + m_ren.clip_box_naked(cb.x1, cb.y1, cb.x2, cb.y2); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + m_ren.reset_clipping(visibility); + m_clip.remove_all(); + m_curr_cb = 0; + m_bounds = m_ren.clip_box(); + } + + //-------------------------------------------------------------------- + void add_clip_box(int x1, int y1, int x2, int y2) + { + rect_i cb(x1, y1, x2, y2); + cb.normalize(); + if(cb.clip(rect_i(0, 0, width() - 1, height() - 1))) + { + m_clip.add(cb); + if(cb.x1 < m_bounds.x1) m_bounds.x1 = cb.x1; + if(cb.y1 < m_bounds.y1) m_bounds.y1 = cb.y1; + if(cb.x2 > m_bounds.x2) m_bounds.x2 = cb.x2; + if(cb.y2 > m_bounds.y2) m_bounds.y2 = cb.y2; + } + } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + m_ren.clear(c); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().copy_pixel(x, y, c); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().blend_pixel(x, y, c, cover); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + return m_ren.ren().pixel(x, y); + } + } + while(next_clip_box()); + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_hline(x1, y, x2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_vline(x, y1, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_hline(x1, y, x2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_vline(x, y1, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_bar(x1, y1, x2, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_bar(x1, y1, x2, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_hspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_vspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, int len, const color_type* colors) + { + first_clip_box(); + do + { + m_ren.copy_color_hspan(x, y, len, colors); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_vspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + const rect_i* rc=0, + int x_to=0, + int y_to=0) + { + first_clip_box(); + do + { + m_ren.copy_from(from, rc, x_to, y_to); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& src, + const rect_i* rect_src_ptr = 0, + int dx = 0, + int dy = 0, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_from(src, rect_src_ptr, dx, dy, cover); + } + while(next_clip_box()); + } + + + private: + renderer_mclip(const renderer_mclip&); + const renderer_mclip& + operator = (const renderer_mclip&); + + base_ren_type m_ren; + pod_bvector m_clip; + unsigned m_curr_cb; + rect_i m_bounds; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_aa.h new file mode 100644 index 00000000000..ee564f04d50 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_aa.h @@ -0,0 +1,1837 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_OUTLINE_AA_INCLUDED +#define AGG_RENDERER_OUTLINE_AA_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" +#include "agg_line_aa_basics.h" +#include "agg_dda_line.h" +#include "agg_ellipse_bresenham.h" +#include "agg_renderer_base.h" +#include "agg_gamma_functions.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + + //===================================================distance_interpolator0 + class distance_interpolator0 + { + public: + //--------------------------------------------------------------------- + distance_interpolator0() {} + distance_interpolator0(int x1, int y1, int x2, int y2, int x, int y) : + m_dx(line_mr(x2) - line_mr(x1)), + m_dy(line_mr(y2) - line_mr(y1)), + m_dist((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx) + { + m_dx <<= line_mr_subpixel_shift; + m_dy <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; } + int dist() const { return m_dist; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + //==================================================distance_interpolator00 + class distance_interpolator00 + { + public: + //--------------------------------------------------------------------- + distance_interpolator00() {} + distance_interpolator00(int xc, int yc, + int x1, int y1, int x2, int y2, + int x, int y) : + m_dx1(line_mr(x1) - line_mr(xc)), + m_dy1(line_mr(y1) - line_mr(yc)), + m_dx2(line_mr(x2) - line_mr(xc)), + m_dy2(line_mr(y2) - line_mr(yc)), + m_dist1((line_mr(x + line_subpixel_scale/2) - line_mr(x1)) * m_dy1 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y1)) * m_dx1), + m_dist2((line_mr(x + line_subpixel_scale/2) - line_mr(x2)) * m_dy2 - + (line_mr(y + line_subpixel_scale/2) - line_mr(y2)) * m_dx2) + { + m_dx1 <<= line_mr_subpixel_shift; + m_dy1 <<= line_mr_subpixel_shift; + m_dx2 <<= line_mr_subpixel_shift; + m_dy2 <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist1 += m_dy1; m_dist2 += m_dy2; } + int dist1() const { return m_dist1; } + int dist2() const { return m_dist2; } + + private: + //--------------------------------------------------------------------- + int m_dx1; + int m_dy1; + int m_dx2; + int m_dy2; + int m_dist1; + int m_dist2; + }; + + //===================================================distance_interpolator1 + class distance_interpolator1 + { + public: + //--------------------------------------------------------------------- + distance_interpolator1() {} + distance_interpolator1(int x1, int y1, int x2, int y2, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; } + void dec_x() { m_dist -= m_dy; } + void inc_y() { m_dist -= m_dx; } + void dec_y() { m_dist += m_dx; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + if(dy > 0) m_dist -= m_dx; + if(dy < 0) m_dist += m_dx; + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; + } + + void dec_y(int dx) + //--------------------------------------------------------------------- + { + m_dist += m_dx; + if(dx > 0) m_dist += m_dy; + if(dx < 0) m_dist -= m_dy; + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dx() const { return m_dx; } + int dy() const { return m_dy; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dist; + }; + + + + + + //===================================================distance_interpolator2 + class distance_interpolator2 + { + public: + //--------------------------------------------------------------------- + distance_interpolator2() {} + distance_interpolator2(int x1, int y1, int x2, int y2, + int sx, int sy, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + distance_interpolator2(int x1, int y1, int x2, int y2, + int ex, int ey, int x, int y, int) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(ex) - line_mr(x2)), + m_dy_start(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_start) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + } + + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_start; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_start; } + int dy_end() const { return m_dy_start; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + + int m_dist; + int m_dist_start; + }; + + + + + + //===================================================distance_interpolator3 + class distance_interpolator3 + { + public: + //--------------------------------------------------------------------- + distance_interpolator3() {} + distance_interpolator3(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + m_dx_end(line_mr(ex) - line_mr(x2)), + m_dy_end(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), + + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end) + { + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() { m_dist += m_dy; m_dist_start += m_dy_start; m_dist_end += m_dy_end; } + void dec_x() { m_dist -= m_dy; m_dist_start -= m_dy_start; m_dist_end -= m_dy_end; } + void inc_y() { m_dist -= m_dx; m_dist_start -= m_dx_start; m_dist_end -= m_dx_end; } + void dec_y() { m_dist += m_dx; m_dist_start += m_dx_start; m_dist_end += m_dx_end; } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_end -= m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_end += m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_end; + }; + + + + + + //================================================line_interpolator_aa_base + template class line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum max_half_width_e + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_aa_base(renderer_type& ren, line_parameters& lp) : + m_lp(&lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_ren(ren), + m_len((lp.vertical == (lp.inc > 0)) ? -lp.len : lp.len), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : + abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_width(ren.subpixel_width()), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_mask) >> line_subpixel_shift), + m_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_scale * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist[i] = li.y(); + if(m_dist[i] >= stop) break; + ++li; + } + m_dist[i++] = 0x7FFF0000; + } + + //--------------------------------------------------------------------- + template int step_hor_base(DI& di) + { + ++m_li; + m_x += m_lp->inc; + m_y = (m_lp->y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_x(m_y - m_old_y); + else di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + template int step_ver_base(DI& di) + { + ++m_li; + m_y += m_lp->inc; + m_x = (m_lp->x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp->inc > 0) di.inc_y(m_x - m_old_x); + else di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + return di.dist() / m_len; + } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp->vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_aa_base(const line_interpolator_aa_base&); + const line_interpolator_aa_base& + operator = (const line_interpolator_aa_base&); + + protected: + line_parameters* m_lp; + dda2_line_interpolator m_li; + renderer_type& m_ren; + int m_len; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_step; + int m_dist[max_half_width + 1]; + cover_type m_covers[max_half_width * 2 + 4]; + }; + + + + + + + + //====================================================line_interpolator_aa0 + template class line_interpolator_aa0 : + public line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa0(renderer_type& ren, line_parameters& lp) : + line_interpolator_aa_base(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + + dy = 1; + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1++ = (cover_type)base_type::m_ren.cover(s1); + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + *p1++ = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + + dx = 1; + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + *--p0 = (cover_type)base_type::m_ren.cover(dist); + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa0(const line_interpolator_aa0&); + const line_interpolator_aa0& + operator = (const line_interpolator_aa0&); + + //--------------------------------------------------------------------- + distance_interpolator1 m_di; + }; + + + + + + + //====================================================line_interpolator_aa1 + template class line_interpolator_aa1 : + public line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa1(renderer_type& ren, line_parameters& lp, + int sx, int sy) : + line_interpolator_aa_base(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + + int npix = 1; + + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + --base_type::m_step; + if(npix == 0) break; + npix = 0; + } + while(base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + + dist_start = m_di.dist_start(); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dy; + } + + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + *p1 = 0; + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + *--p0 = 0; + if(dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa1(const line_interpolator_aa1&); + const line_interpolator_aa1& + operator = (const line_interpolator_aa1&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + + + //====================================================line_interpolator_aa2 + template class line_interpolator_aa2 : + public line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa2(renderer_type& ren, line_parameters& lp, + int ex, int ey) : + line_interpolator_aa_base(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask, + 0) + { + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa2(const line_interpolator_aa2&); + const line_interpolator_aa2& + operator = (const line_interpolator_aa2&); + + //--------------------------------------------------------------------- + distance_interpolator2 m_di; + }; + + + + + + + + + + + //====================================================line_interpolator_aa3 + template class line_interpolator_aa3 : + public line_interpolator_aa_base + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + typedef line_interpolator_aa_base base_type; + + //--------------------------------------------------------------------- + line_interpolator_aa3(renderer_type& ren, line_parameters& lp, + int sx, int sy, int ex, int ey) : + line_interpolator_aa_base(ren, lp), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask) + { + int dist1_start; + int dist2_start; + int npix = 1; + if(lp.vertical) + { + do + { + --base_type::m_li; + base_type::m_y -= lp.inc; + base_type::m_x = (base_type::m_lp->x1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(base_type::m_x - base_type::m_old_x); + else m_di.inc_y(base_type::m_x - base_type::m_old_x); + + base_type::m_old_x = base_type::m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(base_type::m_dist[dx] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + else + { + do + { + --base_type::m_li; + base_type::m_x -= lp.inc; + base_type::m_y = (base_type::m_lp->y1 + base_type::m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(base_type::m_y - base_type::m_old_y); + else m_di.inc_x(base_type::m_y - base_type::m_old_y); + + base_type::m_old_y = base_type::m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(base_type::m_dist[dy] <= base_type::m_width); + if(npix == 0) break; + npix = 0; + } + while(--base_type::m_step >= -base_type::m_max_extent); + } + base_type::m_li.adjust_forward(); + base_type::m_step -= base_type::m_max_extent; + } + + + //--------------------------------------------------------------------- + bool step_hor() + { + int dist_start; + int dist_end; + int dist; + int dy; + int s1 = base_type::step_hor_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = base_type::m_dist[dy] - s1) <= base_type::m_width) + { + dist_start -= m_di.dx_start(); + dist_end -= m_di.dx_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dy] + s1) <= base_type::m_width) + { + dist_start += m_di.dx_start(); + dist_end += m_di.dx_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dy; + } + base_type::m_ren.blend_solid_vspan(base_type::m_x, + base_type::m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + //--------------------------------------------------------------------- + bool step_ver() + { + int dist_start; + int dist_end; + int dist; + int dx; + int s1 = base_type::step_ver_base(m_di); + cover_type* p0 = base_type::m_covers + base_type::max_half_width + 2; + cover_type* p1 = p0; + + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + + int npix = 0; + *p1 = 0; + if(dist_end > 0) + { + if(dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(s1); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = base_type::m_dist[dx] - s1) <= base_type::m_width) + { + dist_start += m_di.dy_start(); + dist_end += m_di.dy_end(); + *p1 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p1 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_end = m_di.dist_end(); + while((dist = base_type::m_dist[dx] + s1) <= base_type::m_width) + { + dist_start -= m_di.dy_start(); + dist_end -= m_di.dy_end(); + *--p0 = 0; + if(dist_end > 0 && dist_start <= 0) + { + *p0 = (cover_type)base_type::m_ren.cover(dist); + ++npix; + } + ++dx; + } + base_type::m_ren.blend_solid_hspan(base_type::m_x - dx + 1, + base_type::m_y, + unsigned(p1 - p0), + p0); + return npix && ++base_type::m_step < base_type::m_count; + } + + private: + line_interpolator_aa3(const line_interpolator_aa3&); + const line_interpolator_aa3& + operator = (const line_interpolator_aa3&); + + //--------------------------------------------------------------------- + distance_interpolator3 m_di; + }; + + + + + //==========================================================line_profile_aa + // + // See Implementation agg_line_profile_aa.cpp + // + class line_profile_aa + { + public: + //--------------------------------------------------------------------- + typedef int8u value_type; + enum subpixel_scale_e + { + subpixel_shift = line_subpixel_shift, + subpixel_scale = 1 << subpixel_shift, + subpixel_mask = subpixel_scale - 1 + }; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1 + }; + + //--------------------------------------------------------------------- + line_profile_aa() : + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = (value_type)i; + } + + //--------------------------------------------------------------------- + template + line_profile_aa(double w, const GammaF& gamma_function) : + m_subpixel_width(0), + m_min_width(1.0), + m_smoother_width(1.0) + { + gamma(gamma_function); + width(w); + } + + //--------------------------------------------------------------------- + void min_width(double w) { m_min_width = w; } + void smoother_width(double w) { m_smoother_width = w; } + + //--------------------------------------------------------------------- + template void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = value_type( + uround(gamma_function(double(i) / aa_mask) * aa_mask)); + } + } + + void width(double w); + + unsigned profile_size() const { return m_profile.size(); } + int subpixel_width() const { return m_subpixel_width; } + + //--------------------------------------------------------------------- + double min_width() const { return m_min_width; } + double smoother_width() const { return m_smoother_width; } + + //--------------------------------------------------------------------- + value_type value(int dist) const + { + return m_profile[dist + subpixel_scale*2]; + } + + private: + line_profile_aa(const line_profile_aa&); + const line_profile_aa& operator = (const line_profile_aa&); + + value_type* profile(double w); + void set(double center_width, double smoother_width); + + //--------------------------------------------------------------------- + pod_array m_profile; + value_type m_gamma[aa_scale]; + int m_subpixel_width; + double m_min_width; + double m_smoother_width; + }; + + + //======================================================renderer_outline_aa + template class renderer_outline_aa + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_aa self_type; + typedef typename base_ren_type::color_type color_type; + + //--------------------------------------------------------------------- + renderer_outline_aa(base_ren_type& ren, line_profile_aa& prof) : + m_ren(&ren), + m_profile(&prof), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //--------------------------------------------------------------------- + void profile(line_profile_aa& prof) { m_profile = &prof; } + line_profile_aa& profile() const { return *m_profile; } + line_profile_aa& profile() { return *m_profile; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_profile->subpixel_width(); } + + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- + int cover(int d) const + { + return m_profile->value(d); + } + + //------------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_hspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, const cover_type* covers) + { + m_ren->blend_solid_vspan(x, y, len, m_color, covers); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return false; } + + //------------------------------------------------------------------------- + template + void semidot_hline(Cmp cmp, + int xc1, int yc1, int xc2, int yc2, + int x1, int y1, int x2) + { + cover_type covers[line_interpolator_aa_base::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = x1 << line_subpixel_shift; + int y = y1 << line_subpixel_shift; + int w = subpixel_width(); + distance_interpolator0 di(xc1, yc1, xc2, yc2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int x0 = x1; + int dx = x - xc1; + int dy = y - yc1; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(cmp(di.dist()) && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++x1 <= x2); + m_ren->blend_solid_hspan(x0, y1, + unsigned(p1 - p0), + color(), + p0); + } + + //------------------------------------------------------------------------- + template + void semidot(Cmp cmp, int xc1, int yc1, int xc2, int yc2) + { + if(m_clipping && clipping_flags(xc1, yc1, m_clip_box)) return; + + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc1 >> line_subpixel_shift; + int y = yc1 >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + semidot_hline(cmp, xc1, yc1, xc2, yc2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void pie_hline(int xc, int yc, int xp1, int yp1, int xp2, int yp2, + int xh1, int yh1, int xh2) + { + if(m_clipping && clipping_flags(xc, yc, m_clip_box)) return; + + cover_type covers[line_interpolator_aa_base::max_half_width * 2 + 4]; + cover_type* p0 = covers; + cover_type* p1 = covers; + int x = xh1 << line_subpixel_shift; + int y = yh1 << line_subpixel_shift; + int w = subpixel_width(); + + distance_interpolator00 di(xc, yc, xp1, yp1, xp2, yp2, x, y); + x += line_subpixel_scale/2; + y += line_subpixel_scale/2; + + int xh0 = xh1; + int dx = x - xc; + int dy = y - yc; + do + { + int d = int(fast_sqrt(dx*dx + dy*dy)); + *p1 = 0; + if(di.dist1() <= 0 && di.dist2() > 0 && d <= w) + { + *p1 = (cover_type)cover(d); + } + ++p1; + dx += line_subpixel_scale; + di.inc_x(); + } + while(++xh1 <= xh2); + m_ren->blend_solid_hspan(xh0, yh1, + unsigned(p1 - p0), + color(), + p0); + } + + + //------------------------------------------------------------------------- + void pie(int xc, int yc, int x1, int y1, int x2, int y2) + { + int r = ((subpixel_width() + line_subpixel_mask) >> line_subpixel_shift); + if(r < 1) r = 1; + ellipse_bresenham_interpolator ei(r, r); + int dx = 0; + int dy = -r; + int dy0 = dy; + int dx0 = dx; + int x = xc >> line_subpixel_shift; + int y = yc >> line_subpixel_shift; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y-dy0, x+dx0); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + pie_hline(xc, yc, x1, y1, x2, y2, x-dx0, y+dy0, x+dx0); + } + + //------------------------------------------------------------------------- + void line0_no_clip(line_parameters& lp) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line0_no_clip(lp1); + line0_no_clip(lp2); + return; + } + + line_interpolator_aa0 li(*this, lp); + if(li.count()) + { + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + } + + //------------------------------------------------------------------------- + void line0(line_parameters& lp) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + line0_no_clip(lp2); + } + else + { + line0_no_clip(lp); + } + } + } + else + { + line0_no_clip(lp); + } + } + + //------------------------------------------------------------------------- + void line1_no_clip(line_parameters& lp, int sx, int sy) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line1_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1); + line1_no_clip(lp2, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + line_interpolator_aa1 li(*this, lp, sx, sy); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + + //------------------------------------------------------------------------- + void line1(line_parameters& lp, int sx, int sy) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + line1_no_clip(lp2, sx, sy); + } + else + { + line1_no_clip(lp, sx, sy); + } + } + } + else + { + line1_no_clip(lp, sx, sy); + } + } + + //------------------------------------------------------------------------- + void line2_no_clip(line_parameters& lp, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + line2_no_clip(lp1, lp1.x2 + (lp1.y2 - lp1.y1), lp1.y2 - (lp1.x2 - lp1.x1)); + line2_no_clip(lp2, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_aa2 li(*this, lp, ex, ey); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + //------------------------------------------------------------------------- + void line2(line_parameters& lp, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line2_no_clip(lp2, ex, ey); + } + else + { + line2_no_clip(lp, ex, ey); + } + } + } + else + { + line2_no_clip(lp, ex, ey); + } + } + + //------------------------------------------------------------------------- + void line3_no_clip(line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_aa3 li(*this, lp, sx, sy, ex, ey); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + } + + //------------------------------------------------------------------------- + void line3(line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + + private: + base_ren_type* m_ren; + line_profile_aa* m_profile; + color_type m_color; + rect_i m_clip_box; + bool m_clipping; + }; + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_image.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_image.h new file mode 100644 index 00000000000..8abb9fa0bdd --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_outline_image.h @@ -0,0 +1,1036 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_OUTLINE_IMAGE_INCLUDED +#define AGG_RENDERER_OUTLINE_IMAGE_INCLUDED + +#include "agg_array.h" +#include "agg_math.h" +#include "agg_line_aa_basics.h" +#include "agg_dda_line.h" +#include "agg_rendering_buffer.h" +#include "agg_clip_liang_barsky.h" + + +namespace agg +{ + //========================================================line_image_scale + template class line_image_scale + { + public: + typedef typename Source::color_type color_type; + + line_image_scale(const Source& src, double height) : + m_source(src), + m_height(height), + m_scale(src.height() / height), + m_scale_inv(height / src.height()) + { + } + + double width() const { return m_source.width(); } + double height() const { return m_height; } + + color_type pixel(int x, int y) const + { + if (m_scale < 1.0) + { + // Interpolate between nearest source pixels. + double src_y = (y + 0.5) * m_scale - 0.5; + int h = m_source.height() - 1; + int y1 = ifloor(src_y); + int y2 = y1 + 1; + rgba pix1 = (y1 < 0) ? rgba::no_color() : m_source.pixel(x, y1); + rgba pix2 = (y2 > h) ? rgba::no_color() : m_source.pixel(x, y2); + return pix1.gradient(pix2, src_y - y1); + } + else + { + // Average source pixels between y and y+1. + double src_y1 = (y + 0.5) * m_scale - 0.5; + double src_y2 = src_y1 + m_scale; + int h = m_source.height() - 1; + int y1 = ifloor(src_y1); + int y2 = ifloor(src_y2); + rgba c = rgba::no_color(); + if (y1 >= 0) c += rgba(m_source.pixel(x, y1)) *= y1 + 1 - src_y1; + while (++y1 < y2) + { + if (y1 <= h) c += m_source.pixel(x, y1); + } + if (y2 <= h) c += rgba(m_source.pixel(x, y2)) *= src_y2 - y2; + return c *= m_scale_inv; + } + } + + private: + line_image_scale(const line_image_scale&); + const line_image_scale& operator = (const line_image_scale&); + + const Source& m_source; + double m_height; + double m_scale; + double m_scale_inv; + }; + + + + //======================================================line_image_pattern + template class line_image_pattern + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + + //-------------------------------------------------------------------- + line_image_pattern(Filter& filter) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + } + + // Create + //-------------------------------------------------------------------- + template + line_image_pattern(Filter& filter, const Source& src) : + m_filter(&filter), + m_dilation(filter.dilation() + 1), + m_dilation_hr(m_dilation << line_subpixel_shift), + m_data(), + m_width(0), + m_height(0), + m_width_hr(0), + m_half_height_hr(0), + m_offset_y_hr(0) + { + create(src); + } + + // Create + //-------------------------------------------------------------------- + template void create(const Source& src) + { + m_height = uceil(src.height()); + m_width = uceil(src.width()); + m_width_hr = uround(src.width() * line_subpixel_scale); + m_half_height_hr = uround(src.height() * line_subpixel_scale/2); + m_offset_y_hr = m_dilation_hr + m_half_height_hr - line_subpixel_scale/2; + m_half_height_hr += line_subpixel_scale/2; + + m_data.resize((m_width + m_dilation * 2) * (m_height + m_dilation * 2)); + + m_buf.attach(&m_data[0], m_width + m_dilation * 2, + m_height + m_dilation * 2, + m_width + m_dilation * 2); + unsigned x, y; + color_type* d1; + color_type* d2; + for(y = 0; y < m_height; y++) + { + d1 = m_buf.row_ptr(y + m_dilation) + m_dilation; + for(x = 0; x < m_width; x++) + { + *d1++ = src.pixel(x, y); + } + } + + const color_type* s1; + const color_type* s2; + for(y = 0; y < m_dilation; y++) + { + //s1 = m_buf.row_ptr(m_height + m_dilation - 1) + m_dilation; + //s2 = m_buf.row_ptr(m_dilation) + m_dilation; + d1 = m_buf.row_ptr(m_dilation + m_height + y) + m_dilation; + d2 = m_buf.row_ptr(m_dilation - y - 1) + m_dilation; + for(x = 0; x < m_width; x++) + { + //*d1++ = color_type(*s1++, 0); + //*d2++ = color_type(*s2++, 0); + *d1++ = color_type::no_color(); + *d2++ = color_type::no_color(); + } + } + + unsigned h = m_height + m_dilation * 2; + for(y = 0; y < h; y++) + { + s1 = m_buf.row_ptr(y) + m_dilation; + s2 = m_buf.row_ptr(y) + m_dilation + m_width; + d1 = m_buf.row_ptr(y) + m_dilation + m_width; + d2 = m_buf.row_ptr(y) + m_dilation; + + for(x = 0; x < m_dilation; x++) + { + *d1++ = *s1++; + *--d2 = *--s2; + } + } + } + + //-------------------------------------------------------------------- + int pattern_width() const { return m_width_hr; } + int line_width() const { return m_half_height_hr; } + double width() const { return m_height; } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_filter->pixel_high_res(m_buf.rows(), + p, + x % m_width_hr + m_dilation_hr, + y + m_offset_y_hr); + } + + //-------------------------------------------------------------------- + const filter_type& filter() const { return *m_filter; } + + private: + line_image_pattern(const line_image_pattern&); + const line_image_pattern& + operator = (const line_image_pattern&); + + protected: + row_ptr_cache m_buf; + const filter_type* m_filter; + unsigned m_dilation; + int m_dilation_hr; + pod_array m_data; + unsigned m_width; + unsigned m_height; + int m_width_hr; + int m_half_height_hr; + int m_offset_y_hr; + }; + + + + + + + //=================================================line_image_pattern_pow2 + template class line_image_pattern_pow2 : + public line_image_pattern + { + public: + typedef Filter filter_type; + typedef typename filter_type::color_type color_type; + typedef line_image_pattern base_type; + + //-------------------------------------------------------------------- + line_image_pattern_pow2(Filter& filter) : + line_image_pattern(filter), m_mask(line_subpixel_mask) {} + + //-------------------------------------------------------------------- + template + line_image_pattern_pow2(Filter& filter, const Source& src) : + line_image_pattern(filter), m_mask(line_subpixel_mask) + { + create(src); + } + + //-------------------------------------------------------------------- + template void create(const Source& src) + { + line_image_pattern::create(src); + m_mask = 1; + while(m_mask < base_type::m_width) + { + m_mask <<= 1; + m_mask |= 1; + } + m_mask <<= line_subpixel_shift - 1; + m_mask |= line_subpixel_mask; + base_type::m_width_hr = m_mask + 1; + } + + //-------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + base_type::m_filter->pixel_high_res( + base_type::m_buf.rows(), + p, + (x & m_mask) + base_type::m_dilation_hr, + y + base_type::m_offset_y_hr); + } + private: + unsigned m_mask; + }; + + + + + + + + //===================================================distance_interpolator4 + class distance_interpolator4 + { + public: + //--------------------------------------------------------------------- + distance_interpolator4() {} + distance_interpolator4(int x1, int y1, int x2, int y2, + int sx, int sy, int ex, int ey, + int len, double scale, int x, int y) : + m_dx(x2 - x1), + m_dy(y2 - y1), + m_dx_start(line_mr(sx) - line_mr(x1)), + m_dy_start(line_mr(sy) - line_mr(y1)), + m_dx_end(line_mr(ex) - line_mr(x2)), + m_dy_end(line_mr(ey) - line_mr(y2)), + + m_dist(iround(double(x + line_subpixel_scale/2 - x2) * double(m_dy) - + double(y + line_subpixel_scale/2 - y2) * double(m_dx))), + + m_dist_start((line_mr(x + line_subpixel_scale/2) - line_mr(sx)) * m_dy_start - + (line_mr(y + line_subpixel_scale/2) - line_mr(sy)) * m_dx_start), + + m_dist_end((line_mr(x + line_subpixel_scale/2) - line_mr(ex)) * m_dy_end - + (line_mr(y + line_subpixel_scale/2) - line_mr(ey)) * m_dx_end), + m_len(uround(len / scale)) + { + double d = len * scale; + int dx = iround(((x2 - x1) << line_subpixel_shift) / d); + int dy = iround(((y2 - y1) << line_subpixel_shift) / d); + m_dx_pict = -dy; + m_dy_pict = dx; + m_dist_pict = ((x + line_subpixel_scale/2 - (x1 - dy)) * m_dy_pict - + (y + line_subpixel_scale/2 - (y1 + dx)) * m_dx_pict) >> + line_subpixel_shift; + + m_dx <<= line_subpixel_shift; + m_dy <<= line_subpixel_shift; + m_dx_start <<= line_mr_subpixel_shift; + m_dy_start <<= line_mr_subpixel_shift; + m_dx_end <<= line_mr_subpixel_shift; + m_dy_end <<= line_mr_subpixel_shift; + } + + //--------------------------------------------------------------------- + void inc_x() + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + + //--------------------------------------------------------------------- + void dec_x() + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + + //--------------------------------------------------------------------- + void inc_y() + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + + //--------------------------------------------------------------------- + void dec_y() + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + + //--------------------------------------------------------------------- + void inc_x(int dy) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void dec_x(int dy) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + if(dy > 0) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + } + if(dy < 0) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + } + } + + //--------------------------------------------------------------------- + void inc_y(int dx) + { + m_dist -= m_dx; + m_dist_start -= m_dx_start; + m_dist_pict -= m_dx_pict; + m_dist_end -= m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + void dec_y(int dx) + { + m_dist += m_dx; + m_dist_start += m_dx_start; + m_dist_pict += m_dx_pict; + m_dist_end += m_dx_end; + if(dx > 0) + { + m_dist += m_dy; + m_dist_start += m_dy_start; + m_dist_pict += m_dy_pict; + m_dist_end += m_dy_end; + } + if(dx < 0) + { + m_dist -= m_dy; + m_dist_start -= m_dy_start; + m_dist_pict -= m_dy_pict; + m_dist_end -= m_dy_end; + } + } + + //--------------------------------------------------------------------- + int dist() const { return m_dist; } + int dist_start() const { return m_dist_start; } + int dist_pict() const { return m_dist_pict; } + int dist_end() const { return m_dist_end; } + + //--------------------------------------------------------------------- + int dx() const { return m_dx; } + int dy() const { return m_dy; } + int dx_start() const { return m_dx_start; } + int dy_start() const { return m_dy_start; } + int dx_pict() const { return m_dx_pict; } + int dy_pict() const { return m_dy_pict; } + int dx_end() const { return m_dx_end; } + int dy_end() const { return m_dy_end; } + int len() const { return m_len; } + + private: + //--------------------------------------------------------------------- + int m_dx; + int m_dy; + int m_dx_start; + int m_dy_start; + int m_dx_pict; + int m_dy_pict; + int m_dx_end; + int m_dy_end; + + int m_dist; + int m_dist_start; + int m_dist_pict; + int m_dist_end; + int m_len; + }; + + + + + + //==================================================line_interpolator_image + template class line_interpolator_image + { + public: + typedef Renderer renderer_type; + typedef typename Renderer::color_type color_type; + + //--------------------------------------------------------------------- + enum max_half_width_e + { + max_half_width = 64 + }; + + //--------------------------------------------------------------------- + line_interpolator_image(renderer_type& ren, const line_parameters& lp, + int sx, int sy, int ex, int ey, + int pattern_start, + double scale_x) : + m_lp(lp), + m_li(lp.vertical ? line_dbl_hr(lp.x2 - lp.x1) : + line_dbl_hr(lp.y2 - lp.y1), + lp.vertical ? abs(lp.y2 - lp.y1) : + abs(lp.x2 - lp.x1) + 1), + m_di(lp.x1, lp.y1, lp.x2, lp.y2, sx, sy, ex, ey, lp.len, scale_x, + lp.x1 & ~line_subpixel_mask, lp.y1 & ~line_subpixel_mask), + m_ren(ren), + m_x(lp.x1 >> line_subpixel_shift), + m_y(lp.y1 >> line_subpixel_shift), + m_old_x(m_x), + m_old_y(m_y), + m_count((lp.vertical ? abs((lp.y2 >> line_subpixel_shift) - m_y) : + abs((lp.x2 >> line_subpixel_shift) - m_x))), + m_width(ren.subpixel_width()), + //m_max_extent(m_width >> (line_subpixel_shift - 2)), + m_max_extent((m_width + line_subpixel_scale) >> line_subpixel_shift), + m_start(pattern_start + (m_max_extent + 2) * ren.pattern_width()), + m_step(0) + { + agg::dda2_line_interpolator li(0, lp.vertical ? + (lp.dy << agg::line_subpixel_shift) : + (lp.dx << agg::line_subpixel_shift), + lp.len); + + unsigned i; + int stop = m_width + line_subpixel_scale * 2; + for(i = 0; i < max_half_width; ++i) + { + m_dist_pos[i] = li.y(); + if(m_dist_pos[i] >= stop) break; + ++li; + } + m_dist_pos[i] = 0x7FFF0000; + + int dist1_start; + int dist2_start; + int npix = 1; + + if(lp.vertical) + { + do + { + --m_li; + m_y -= lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_y(m_x - m_old_x); + else m_di.inc_y(m_x - m_old_x); + + m_old_x = m_x; + + dist1_start = dist2_start = m_di.dist_start(); + + int dx = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start += m_di.dy_start(); + dist2_start -= m_di.dy_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dx; + } + while(m_dist_pos[dx] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + else + { + do + { + --m_li; + + m_x -= lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(lp.inc > 0) m_di.dec_x(m_y - m_old_y); + else m_di.inc_x(m_y - m_old_y); + + m_old_y = m_y; + + dist1_start = dist2_start = m_di.dist_start(); + + int dy = 0; + if(dist1_start < 0) ++npix; + do + { + dist1_start -= m_di.dx_start(); + dist2_start += m_di.dx_start(); + if(dist1_start < 0) ++npix; + if(dist2_start < 0) ++npix; + ++dy; + } + while(m_dist_pos[dy] <= m_width); + if(npix == 0) break; + + npix = 0; + } + while(--m_step >= -m_max_extent); + } + m_li.adjust_forward(); + m_step -= m_max_extent; + } + + //--------------------------------------------------------------------- + bool step_hor() + { + ++m_li; + m_x += m_lp.inc; + m_y = (m_lp.y1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_x(m_y - m_old_y); + else m_di.dec_x(m_y - m_old_y); + + m_old_y = m_y; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc < 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dy; + int dist; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dy = 1; + while((dist = m_dist_pos[dy]) - s1 <= m_width) + { + dist_start -= m_di.dx_start(); + dist_pict -= m_di.dx_pict(); + dist_end -= m_di.dx_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 - dist); + ++npix; + } + ++p1; + ++dy; + } + + dy = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dy]) + s1 <= m_width) + { + dist_start += m_di.dx_start(); + dist_pict += m_di.dx_pict(); + dist_end += m_di.dx_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 + dist); + ++npix; + } + ++dy; + } + m_ren.blend_color_vspan(m_x, + m_y - dy + 1, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + + //--------------------------------------------------------------------- + bool step_ver() + { + ++m_li; + m_y += m_lp.inc; + m_x = (m_lp.x1 + m_li.y()) >> line_subpixel_shift; + + if(m_lp.inc > 0) m_di.inc_y(m_x - m_old_x); + else m_di.dec_y(m_x - m_old_x); + + m_old_x = m_x; + + int s1 = m_di.dist() / m_lp.len; + int s2 = -s1; + + if(m_lp.inc > 0) s1 = -s1; + + int dist_start; + int dist_pict; + int dist_end; + int dist; + int dx; + + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + color_type* p0 = m_colors + max_half_width + 2; + color_type* p1 = p0; + + int npix = 0; + p1->clear(); + if(dist_end > 0) + { + if(dist_start <= 0) + { + m_ren.pixel(p1, dist_pict, s2); + } + ++npix; + } + ++p1; + + dx = 1; + while((dist = m_dist_pos[dx]) - s1 <= m_width) + { + dist_start += m_di.dy_start(); + dist_pict += m_di.dy_pict(); + dist_end += m_di.dy_end(); + p1->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p1, dist_pict, s2 + dist); + ++npix; + } + ++p1; + ++dx; + } + + dx = 1; + dist_start = m_di.dist_start(); + dist_pict = m_di.dist_pict() + m_start; + dist_end = m_di.dist_end(); + while((dist = m_dist_pos[dx]) + s1 <= m_width) + { + dist_start -= m_di.dy_start(); + dist_pict -= m_di.dy_pict(); + dist_end -= m_di.dy_end(); + --p0; + p0->clear(); + if(dist_end > 0 && dist_start <= 0) + { + if(m_lp.inc > 0) dist = -dist; + m_ren.pixel(p0, dist_pict, s2 - dist); + ++npix; + } + ++dx; + } + m_ren.blend_color_hspan(m_x - dx + 1, + m_y, + unsigned(p1 - p0), + p0); + return npix && ++m_step < m_count; + } + + + //--------------------------------------------------------------------- + int pattern_end() const { return m_start + m_di.len(); } + + //--------------------------------------------------------------------- + bool vertical() const { return m_lp.vertical; } + int width() const { return m_width; } + int count() const { return m_count; } + + private: + line_interpolator_image(const line_interpolator_image&); + const line_interpolator_image& + operator = (const line_interpolator_image&); + + protected: + const line_parameters& m_lp; + dda2_line_interpolator m_li; + distance_interpolator4 m_di; + renderer_type& m_ren; + int m_plen; + int m_x; + int m_y; + int m_old_x; + int m_old_y; + int m_count; + int m_width; + int m_max_extent; + int m_start; + int m_step; + int m_dist_pos[max_half_width + 1]; + color_type m_colors[max_half_width * 2 + 4]; + }; + + + + + + + + + //===================================================renderer_outline_image + template + class renderer_outline_image + { + public: + //--------------------------------------------------------------------- + typedef BaseRenderer base_ren_type; + typedef renderer_outline_image self_type; + typedef typename base_ren_type::color_type color_type; + typedef ImagePattern pattern_type; + + + //--------------------------------------------------------------------- + renderer_outline_image(base_ren_type& ren, pattern_type& patt) : + m_ren(&ren), + m_pattern(&patt), + m_start(0), + m_scale_x(1.0), + m_clip_box(0,0,0,0), + m_clipping(false) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //--------------------------------------------------------------------- + void pattern(pattern_type& p) { m_pattern = &p; } + pattern_type& pattern() const { return *m_pattern; } + + //--------------------------------------------------------------------- + void reset_clipping() { m_clipping = false; } + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = line_coord_sat::conv(x1); + m_clip_box.y1 = line_coord_sat::conv(y1); + m_clip_box.x2 = line_coord_sat::conv(x2); + m_clip_box.y2 = line_coord_sat::conv(y2); + m_clipping = true; + } + + //--------------------------------------------------------------------- + void scale_x(double s) { m_scale_x = s; } + double scale_x() const { return m_scale_x; } + + //--------------------------------------------------------------------- + void start_x(double s) { m_start = iround(s * line_subpixel_scale); } + double start_x() const { return double(m_start) / line_subpixel_scale; } + + //--------------------------------------------------------------------- + int subpixel_width() const { return m_pattern->line_width(); } + int pattern_width() const { return m_pattern->pattern_width(); } + double width() const { return double(subpixel_width()) / line_subpixel_scale; } + + //------------------------------------------------------------------------- + void pixel(color_type* p, int x, int y) const + { + m_pattern->pixel(p, x, y); + } + + //------------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_hspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, const color_type* colors) + { + m_ren->blend_color_vspan(x, y, len, colors, 0); + } + + //------------------------------------------------------------------------- + static bool accurate_join_only() { return true; } + + //------------------------------------------------------------------------- + template + void semidot(Cmp, int, int, int, int) + { + } + + //------------------------------------------------------------------------- + void pie(int, int, int, int, int, int) + { + } + + //------------------------------------------------------------------------- + void line0(const line_parameters&) + { + } + + //------------------------------------------------------------------------- + void line1(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line2(const line_parameters&, int, int) + { + } + + //------------------------------------------------------------------------- + void line3_no_clip(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(lp.len > line_max_length) + { + line_parameters lp1, lp2; + lp.divide(lp1, lp2); + int mx = lp1.x2 + (lp1.y2 - lp1.y1); + int my = lp1.y2 - (lp1.x2 - lp1.x1); + line3_no_clip(lp1, (lp.x1 + sx) >> 1, (lp.y1 + sy) >> 1, mx, my); + line3_no_clip(lp2, mx, my, (lp.x2 + ex) >> 1, (lp.y2 + ey) >> 1); + return; + } + + fix_degenerate_bisectrix_start(lp, &sx, &sy); + fix_degenerate_bisectrix_end(lp, &ex, &ey); + line_interpolator_image li(*this, lp, + sx, sy, + ex, ey, + m_start, m_scale_x); + if(li.vertical()) + { + while(li.step_ver()); + } + else + { + while(li.step_hor()); + } + m_start += uround(lp.len / m_scale_x); + } + + //------------------------------------------------------------------------- + void line3(const line_parameters& lp, + int sx, int sy, int ex, int ey) + { + if(m_clipping) + { + int x1 = lp.x1; + int y1 = lp.y1; + int x2 = lp.x2; + int y2 = lp.y2; + unsigned flags = clip_line_segment(&x1, &y1, &x2, &y2, m_clip_box); + int start = m_start; + if((flags & 4) == 0) + { + if(flags) + { + line_parameters lp2(x1, y1, x2, y2, + uround(calc_distance(x1, y1, x2, y2))); + if(flags & 1) + { + m_start += uround(calc_distance(lp.x1, lp.y1, x1, y1) / m_scale_x); + sx = x1 + (y2 - y1); + sy = y1 - (x2 - x1); + } + else + { + while(abs(sx - lp.x1) + abs(sy - lp.y1) > lp2.len) + { + sx = (lp.x1 + sx) >> 1; + sy = (lp.y1 + sy) >> 1; + } + } + if(flags & 2) + { + ex = x2 + (y2 - y1); + ey = y2 - (x2 - x1); + } + else + { + while(abs(ex - lp.x2) + abs(ey - lp.y2) > lp2.len) + { + ex = (lp.x2 + ex) >> 1; + ey = (lp.y2 + ey) >> 1; + } + } + line3_no_clip(lp2, sx, sy, ex, ey); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + m_start = start + uround(lp.len / m_scale_x); + } + else + { + line3_no_clip(lp, sx, sy, ex, ey); + } + } + + private: + base_ren_type* m_ren; + pattern_type* m_pattern; + int m_start; + double m_scale_x; + rect_i m_clip_box; + bool m_clipping; + }; + + + + + +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_primitives.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_primitives.h new file mode 100644 index 00000000000..f008db7c947 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_primitives.h @@ -0,0 +1,224 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class renderer_primitives +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERER_PRIMITIVES_INCLUDED +#define AGG_RENDERER_PRIMITIVES_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_base.h" +#include "agg_dda_line.h" +#include "agg_ellipse_bresenham.h" + +namespace agg +{ + //-----------------------------------------------------renderer_primitives + template class renderer_primitives + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + explicit renderer_primitives(base_ren_type& ren) : + m_ren(&ren), + m_fill_color(), + m_line_color(), + m_curr_x(0), + m_curr_y(0) + {} + void attach(base_ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + static int coord(double c) + { + return iround(c * line_bresenham_interpolator::subpixel_scale); + } + + //-------------------------------------------------------------------- + void fill_color(const color_type& c) { m_fill_color = c; } + void line_color(const color_type& c) { m_line_color = c; } + const color_type& fill_color() const { return m_fill_color; } + const color_type& line_color() const { return m_line_color; } + + //-------------------------------------------------------------------- + void rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_hline(x1, y1, x2-1, m_line_color, cover_full); + m_ren->blend_vline(x2, y1, y2-1, m_line_color, cover_full); + m_ren->blend_hline(x1+1, y2, x2, m_line_color, cover_full); + m_ren->blend_vline(x1, y1+1, y2, m_line_color, cover_full); + } + + //-------------------------------------------------------------------- + void solid_rectangle(int x1, int y1, int x2, int y2) + { + m_ren->blend_bar(x1, y1, x2, y2, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_rectangle(int x1, int y1, int x2, int y2) + { + rectangle(x1, y1, x2, y2); + m_ren->blend_bar(x1+1, y1+1, x2-1, y2-1, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + do + { + dx += ei.dx(); + dy += ei.dy(); + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void solid_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + int dy0 = dy; + int dx0 = dx; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + if(dy != dy0) + { + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + m_ren->blend_hline(x-dx0, y-dy0, x+dx0, m_fill_color, cover_full); + } + dx0 = dx; + dy0 = dy; + ++ei; + } + while(dy < 0); + m_ren->blend_hline(x-dx0, y+dy0, x+dx0, m_fill_color, cover_full); + } + + //-------------------------------------------------------------------- + void outlined_ellipse(int x, int y, int rx, int ry) + { + ellipse_bresenham_interpolator ei(rx, ry); + int dx = 0; + int dy = -ry; + + do + { + dx += ei.dx(); + dy += ei.dy(); + + m_ren->blend_pixel(x + dx, y + dy, m_line_color, cover_full); + m_ren->blend_pixel(x + dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y - dy, m_line_color, cover_full); + m_ren->blend_pixel(x - dx, y + dy, m_line_color, cover_full); + + if(ei.dy() && dx) + { + m_ren->blend_hline(x-dx+1, y+dy, x+dx-1, m_fill_color, cover_full); + m_ren->blend_hline(x-dx+1, y-dy, x+dx-1, m_fill_color, cover_full); + } + ++ei; + } + while(dy < 0); + } + + //-------------------------------------------------------------------- + void line(int x1, int y1, int x2, int y2, bool last=false) + { + line_bresenham_interpolator li(x1, y1, x2, y2); + + unsigned len = li.len(); + if(len == 0) + { + if(last) + { + m_ren->blend_pixel(li.line_lr(x1), li.line_lr(y1), m_line_color, cover_full); + } + return; + } + + if(last) ++len; + + if(li.is_ver()) + { + do + { + m_ren->blend_pixel(li.x2(), li.y1(), m_line_color, cover_full); + li.vstep(); + } + while(--len); + } + else + { + do + { + m_ren->blend_pixel(li.x1(), li.y2(), m_line_color, cover_full); + li.hstep(); + } + while(--len); + } + } + + //-------------------------------------------------------------------- + void move_to(int x, int y) + { + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + void line_to(int x, int y, bool last=false) + { + line(m_curr_x, m_curr_y, x, y, last); + m_curr_x = x; + m_curr_y = y; + } + + //-------------------------------------------------------------------- + const base_ren_type& ren() const { return *m_ren; } + base_ren_type& ren() { return *m_ren; } + + //-------------------------------------------------------------------- + const rendering_buffer& rbuf() const { return m_ren->rbuf(); } + rendering_buffer& rbuf() { return m_ren->rbuf(); } + + private: + base_ren_type* m_ren; + color_type m_fill_color; + color_type m_line_color; + int m_curr_x; + int m_curr_y; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_raster_text.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_raster_text.h new file mode 100644 index 00000000000..87b43f96005 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_raster_text.h @@ -0,0 +1,264 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_RASTER_TEXT_INCLUDED +#define AGG_RENDERER_RASTER_TEXT_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //==============================================renderer_raster_htext_solid + template + class renderer_raster_htext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_htext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + {} + void attach(ren_type& ren) { m_ren = &ren; } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_hspan(r.x1, i, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + //=============================================renderer_raster_vtext_solid + template + class renderer_raster_vtext_solid + { + public: + typedef BaseRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + typedef typename ren_type::color_type color_type; + + renderer_raster_vtext_solid(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + template + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, !flip); + if(r.x2 >= r.x1) + { + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(i - r.y1)); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->blend_solid_vspan(i, r.x1, (r.x2 - r.x1 + 1), + m_color, + m_glyph->span(r.y2 - i)); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + color_type m_color; + }; + + + + + + + //===================================================renderer_raster_htext + template + class renderer_raster_htext + { + public: + typedef ScanlineRenderer ren_type; + typedef GlyphGenerator glyph_gen_type; + typedef typename glyph_gen_type::glyph_rect glyph_rect; + + class scanline_single_span + { + public: + typedef agg::cover_type cover_type; + + //---------------------------------------------------------------- + struct const_span + { + int x; + unsigned len; + const cover_type* covers; + + const_span() {} + const_span(int x_, unsigned len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) + {} + }; + + typedef const const_span* const_iterator; + + //---------------------------------------------------------------- + scanline_single_span(int x, int y, unsigned len, + const cover_type* covers) : + m_y(y), + m_span(x, len, covers) + {} + + //---------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return 1; } + const_iterator begin() const { return &m_span; } + + private: + //---------------------------------------------------------------- + int m_y; + const_span m_span; + }; + + + + //-------------------------------------------------------------------- + renderer_raster_htext(ren_type& ren, glyph_gen_type& glyph) : + m_ren(&ren), + m_glyph(&glyph) + { + } + + + //-------------------------------------------------------------------- + template + void render_text(double x, double y, const CharT* str, bool flip=false) + { + glyph_rect r; + while(*str) + { + m_glyph->prepare(&r, x, y, *str, flip); + if(r.x2 >= r.x1) + { + m_ren->prepare(); + int i; + if(flip) + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(r.y2 - i))); + } + } + else + { + for(i = r.y1; i <= r.y2; i++) + { + m_ren->render( + scanline_single_span(r.x1, + i, + (r.x2 - r.x1 + 1), + m_glyph->span(i - r.y1))); + } + } + } + x += r.dx; + y += r.dy; + ++str; + } + } + + private: + ren_type* m_ren; + glyph_gen_type* m_glyph; + }; + + + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_scanline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_scanline.h new file mode 100644 index 00000000000..6d65056c537 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_renderer_scanline.h @@ -0,0 +1,852 @@ +//---------------------------------------------------------------------------- +// 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_RENDERER_SCANLINE_INCLUDED +#define AGG_RENDERER_SCANLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_renderer_base.h" + +namespace agg +{ + + //================================================render_scanline_aa_solid + template + void render_scanline_aa_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + + //===============================================render_scanlines_aa_solid + template + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_aa_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan(x, y, (unsigned)span->len, + ren_color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - span->len - 1), + ren_color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //==============================================renderer_scanline_aa_solid + template class renderer_scanline_aa_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa_solid() : m_ren(0) {} + explicit renderer_scanline_aa_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_aa_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + + + + + + //======================================================render_scanline_aa + template + void render_scanline_aa(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + const typename Scanline::cover_type* covers = span->covers; + + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, + (span->len < 0) ? 0 : covers, *covers); + + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_aa + template + void render_scanlines_aa(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_aa(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_aa + template + class renderer_scanline_aa + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_aa() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_aa(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_aa(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + //===============================================render_scanline_bin_solid + template + void render_scanline_bin_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //==============================================render_scanlines_bin_solid + template + void render_scanlines_bin_solid(Rasterizer& ras, Scanline& sl, + BaseRenderer& ren, const ColorT& color) + { + if(ras.rewind_scanlines()) + { + // Explicitly convert "color" to the BaseRenderer color type. + // For example, it can be called with color type "rgba", while + // "rgba8" is needed. Otherwise it will be implicitly + // converted in the loop many times. + //---------------------- + typename BaseRenderer::color_type ren_color(color); + + sl.reset(ras.min_x(), ras.max_x()); + while(ras.sweep_scanline(sl)) + { + //render_scanline_bin_solid(sl, ren, ren_color); + + // This code is equivalent to the above call (copy/paste). + // It's just a "manual" optimization for old compilers, + // like Microsoft Visual C++ v6.0 + //------------------------------- + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + ren.blend_hline(span->x, + sl.y(), + span->x - 1 + ((span->len < 0) ? + -span->len : + span->len), + ren_color, + cover_full); + if(--num_spans == 0) break; + ++span; + } + } + } + } + + //=============================================renderer_scanline_bin_solid + template class renderer_scanline_bin_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin_solid() : m_ren(0) {} + explicit renderer_scanline_bin_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_bin_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + + + + + + + + + //======================================================render_scanline_bin + template + void render_scanline_bin(const Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + int y = sl.y(); + + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); + for(;;) + { + int x = span->x; + int len = span->len; + if(len < 0) len = -len; + typename BaseRenderer::color_type* colors = alloc.allocate(len); + span_gen.generate(colors, x, y, len); + ren.blend_color_hspan(x, y, len, colors, 0, cover_full); + if(--num_spans == 0) break; + ++span; + } + } + + //=====================================================render_scanlines_bin + template + void render_scanlines_bin(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, + SpanAllocator& alloc, SpanGenerator& span_gen) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + span_gen.prepare(); + while(ras.sweep_scanline(sl)) + { + render_scanline_bin(sl, ren, alloc, span_gen); + } + } + } + + //====================================================renderer_scanline_bin + template + class renderer_scanline_bin + { + public: + typedef BaseRenderer base_ren_type; + typedef SpanAllocator alloc_type; + typedef SpanGenerator span_gen_type; + + //-------------------------------------------------------------------- + renderer_scanline_bin() : m_ren(0), m_alloc(0), m_span_gen(0) {} + renderer_scanline_bin(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) : + m_ren(&ren), + m_alloc(&alloc), + m_span_gen(&span_gen) + {} + void attach(base_ren_type& ren, + alloc_type& alloc, + span_gen_type& span_gen) + { + m_ren = &ren; + m_alloc = &alloc; + m_span_gen = &span_gen; + } + + //-------------------------------------------------------------------- + void prepare() { m_span_gen->prepare(); } + + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_bin(sl, *m_ren, *m_alloc, *m_span_gen); + } + + private: + base_ren_type* m_ren; + alloc_type* m_alloc; + span_gen_type* m_span_gen; + }; + + + + + + + + + + + //========================================================render_scanlines + template + void render_scanlines(Rasterizer& ras, Scanline& sl, Renderer& ren) + { + if(ras.rewind_scanlines()) + { + sl.reset(ras.min_x(), ras.max_x()); + ren.prepare(); + while(ras.sweep_scanline(sl)) + { + ren.render(sl); + } + } + } + + //========================================================render_all_paths + template + void render_all_paths(Rasterizer& ras, + Scanline& sl, + Renderer& r, + VertexSource& vs, + const ColorStorage& as, + const PathId& path_id, + unsigned num_paths) + { + for(unsigned i = 0; i < num_paths; i++) + { + ras.reset(); + ras.add_path(vs, path_id[i]); + r.color(as[i]); + render_scanlines(ras, sl, r); + } + } + + + + + + + //=============================================render_scanlines_compound + template + void render_scanlines_compound(Rasterizer& ras, + ScanlineAA& sl_aa, + ScanlineBin& sl_bin, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + sl_bin.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + if(ras.sweep_scanline(sl_bin, -1)) + { + // Clear the spans of the mix_buffer + //-------------------- + typename ScanlineBin::const_iterator span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + memset(mix_buffer + span_bin->x - min_x, + 0, + span_bin->len * sizeof(color_type)); + + if(--num_spans == 0) break; + ++span_bin; + } + + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + color_type* colors; + color_type* cspan; + typename ScanlineAA::cover_type* covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = c; + } + else + { + colors->add(c, *covers); + } + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + covers = span_aa->covers; + do + { + if(*covers == cover_full) + { + *colors = *cspan; + } + else + { + colors->add(*cspan, *covers); + } + ++cspan; + ++colors; + ++covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + + // Emit the blended result as a color hspan + //------------------------- + span_bin = sl_bin.begin(); + num_spans = sl_bin.num_spans(); + for(;;) + { + ren.blend_color_hspan(span_bin->x, + sl_bin.y(), + span_bin->len, + mix_buffer + span_bin->x - min_x, + 0, + cover_full); + if(--num_spans == 0) break; + ++span_bin; + } + } // if(ras.sweep_scanline(sl_bin, -1)) + } // if(num_styles == 1) ... else + } // while((num_styles = ras.sweep_styles()) > 0) + } // if(ras.rewind_scanlines()) + } + + //=======================================render_scanlines_compound_layered + template + void render_scanlines_compound_layered(Rasterizer& ras, + ScanlineAA& sl_aa, + BaseRenderer& ren, + SpanAllocator& alloc, + StyleHandler& sh) + { + if(ras.rewind_scanlines()) + { + int min_x = ras.min_x(); + int len = ras.max_x() - min_x + 2; + sl_aa.reset(min_x, ras.max_x()); + + typedef typename BaseRenderer::color_type color_type; + color_type* color_span = alloc.allocate(len * 2); + color_type* mix_buffer = color_span + len; + cover_type* cover_buffer = ras.allocate_cover_buffer(len); + unsigned num_spans; + + unsigned num_styles; + unsigned style; + bool solid; + while((num_styles = ras.sweep_styles()) > 0) + { + typename ScanlineAA::const_iterator span_aa; + if(num_styles == 1) + { + // Optimization for a single style. Happens often + //------------------------- + if(ras.sweep_scanline(sl_aa, 0)) + { + style = ras.style(0); + if(sh.is_solid(style)) + { + // Just solid fill + //----------------------- + render_scanline_aa_solid(sl_aa, ren, sh.color(style)); + } + else + { + // Arbitrary span generator + //----------------------- + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + for(;;) + { + len = span_aa->len; + sh.generate_span(color_span, + span_aa->x, + sl_aa.y(), + len, + style); + + ren.blend_color_hspan(span_aa->x, + sl_aa.y(), + span_aa->len, + color_span, + span_aa->covers); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + else + { + int sl_start = ras.scanline_start(); + unsigned sl_len = ras.scanline_length(); + + if(sl_len) + { + memset(mix_buffer + sl_start - min_x, + 0, + sl_len * sizeof(color_type)); + + memset(cover_buffer + sl_start - min_x, + 0, + sl_len * sizeof(cover_type)); + + int sl_y = 0x7FFFFFFF; + unsigned i; + for(i = 0; i < num_styles; i++) + { + style = ras.style(i); + solid = sh.is_solid(style); + + if(ras.sweep_scanline(sl_aa, i)) + { + unsigned cover; + color_type* colors; + color_type* cspan; + cover_type* src_covers; + cover_type* dst_covers; + span_aa = sl_aa.begin(); + num_spans = sl_aa.num_spans(); + sl_y = sl_aa.y(); + if(solid) + { + // Just solid fill + //----------------------- + for(;;) + { + color_type c = sh.color(style); + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(c, cover); + *dst_covers += cover; + } + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + else + { + // Arbitrary span generator + //----------------------- + for(;;) + { + len = span_aa->len; + colors = mix_buffer + span_aa->x - min_x; + cspan = color_span; + sh.generate_span(cspan, + span_aa->x, + sl_aa.y(), + len, + style); + src_covers = span_aa->covers; + dst_covers = cover_buffer + span_aa->x - min_x; + do + { + cover = *src_covers; + if(*dst_covers + cover > cover_full) + { + cover = cover_full - *dst_covers; + } + if(cover) + { + colors->add(*cspan, cover); + *dst_covers += cover; + } + ++cspan; + ++colors; + ++src_covers; + ++dst_covers; + } + while(--len); + if(--num_spans == 0) break; + ++span_aa; + } + } + } + } + ren.blend_color_hspan(sl_start, + sl_y, + sl_len, + mix_buffer + sl_start - min_x, + 0, + cover_full); + } //if(sl_len) + } //if(num_styles == 1) ... else + } //while((num_styles = ras.sweep_styles()) > 0) + } //if(ras.rewind_scanlines()) + } + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer.h new file mode 100644 index 00000000000..191347f63e2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer.h @@ -0,0 +1,300 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class rendering_buffer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_INCLUDED +#define AGG_RENDERING_BUFFER_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //===========================================================row_accessor + template class row_accessor + { + public: + typedef const_row_info row_data; + + //------------------------------------------------------------------- + row_accessor() : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_accessor(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_start(0), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = m_start = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(stride < 0) + { + m_start = m_buf - (AGG_INT64)(height - 1) * stride; + } + } + + //-------------------------------------------------------------------- + AGG_INLINE T* buf() { return m_buf; } + AGG_INLINE const T* buf() const { return m_buf; } + AGG_INLINE unsigned width() const { return m_width; } + AGG_INLINE unsigned height() const { return m_height; } + AGG_INLINE int stride() const { return m_stride; } + AGG_INLINE unsigned stride_abs() const + { + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); + } + + //-------------------------------------------------------------------- + AGG_INLINE T* row_ptr(int, int y, unsigned) + { + return m_start + y * (AGG_INT64)m_stride; + } + AGG_INLINE T* row_ptr(int y) { return m_start + y * (AGG_INT64)m_stride; } + AGG_INLINE const T* row_ptr(int y) const { return m_start + y * (AGG_INT64)m_stride; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, row_ptr(y)); + } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf& src) + { + unsigned h = height(); + if(src.height() < h) h = src.height(); + + unsigned l = stride_abs(); + if(src.stride_abs() < l) l = src.stride_abs(); + + l *= sizeof(T); + + unsigned y; + unsigned w = width(); + for (y = 0; y < h; y++) + { + memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + T* m_start; // Pointer to first pixel depending on stride + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //==========================================================row_ptr_cache + template class row_ptr_cache + { + public: + typedef const_row_info row_data; + + //------------------------------------------------------------------- + row_ptr_cache() : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + } + + //-------------------------------------------------------------------- + row_ptr_cache(T* buf, unsigned width, unsigned height, int stride) : + m_buf(0), + m_rows(), + m_width(0), + m_height(0), + m_stride(0) + { + attach(buf, width, height, stride); + } + + //-------------------------------------------------------------------- + void attach(T* buf, unsigned width, unsigned height, int stride) + { + m_buf = buf; + m_width = width; + m_height = height; + m_stride = stride; + if(height > m_rows.size()) + { + m_rows.resize(height); + } + + T* row_ptr = m_buf; + + if(stride < 0) + { + row_ptr = m_buf - (AGG_INT64)(height - 1) * stride; + } + + T** rows = &m_rows[0]; + + while(height--) + { + *rows++ = row_ptr; + row_ptr += stride; + } + } + + //-------------------------------------------------------------------- + AGG_INLINE T* buf() { return m_buf; } + AGG_INLINE const T* buf() const { return m_buf; } + AGG_INLINE unsigned width() const { return m_width; } + AGG_INLINE unsigned height() const { return m_height; } + AGG_INLINE int stride() const { return m_stride; } + AGG_INLINE unsigned stride_abs() const + { + return (m_stride < 0) ? unsigned(-m_stride) : unsigned(m_stride); + } + + //-------------------------------------------------------------------- + AGG_INLINE T* row_ptr(int, int y, unsigned) + { + return m_rows[y]; + } + AGG_INLINE T* row_ptr(int y) { return m_rows[y]; } + AGG_INLINE const T* row_ptr(int y) const { return m_rows[y]; } + AGG_INLINE row_data row (int y) const + { + return row_data(0, m_width-1, m_rows[y]); + } + + //-------------------------------------------------------------------- + T const* const* rows() const { return &m_rows[0]; } + + //-------------------------------------------------------------------- + template + void copy_from(const RenBuf& src) + { + unsigned h = height(); + if(src.height() < h) h = src.height(); + + unsigned l = stride_abs(); + if(src.stride_abs() < l) l = src.stride_abs(); + + l *= sizeof(T); + + unsigned y; + unsigned w = width(); + for (y = 0; y < h; y++) + { + memcpy(row_ptr(0, y, w), src.row_ptr(y), l); + } + } + + //-------------------------------------------------------------------- + void clear(T value) + { + unsigned y; + unsigned w = width(); + unsigned stride = stride_abs(); + for(y = 0; y < height(); y++) + { + T* p = row_ptr(0, y, w); + unsigned x; + for(x = 0; x < stride; x++) + { + *p++ = value; + } + } + } + + private: + //-------------------------------------------------------------------- + T* m_buf; // Pointer to renrdering buffer + pod_array m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + int m_stride; // Number of bytes per row. Can be < 0 + }; + + + + + //========================================================rendering_buffer + // + // The definition of the main type for accessing the rows in the frame + // buffer. It provides functionality to navigate to the rows in a + // rectangular matrix, from top to bottom or from bottom to top depending + // on stride. + // + // row_accessor is cheap to create/destroy, but performs one multiplication + // when calling row_ptr(). + // + // row_ptr_cache creates an array of pointers to rows, so, the access + // via row_ptr() may be faster. But it requires memory allocation + // when creating. For example, on typical Intel Pentium hardware + // row_ptr_cache speeds span_image_filter_rgb_nn up to 10% + // + // It's used only in short hand typedefs like pixfmt_rgba32 and can be + // redefined in agg_config.h + // In real applications you can use both, depending on your needs + //------------------------------------------------------------------------ +#ifdef AGG_RENDERING_BUFFER + typedef AGG_RENDERING_BUFFER rendering_buffer; +#else +// typedef row_ptr_cache rendering_buffer; + typedef row_accessor rendering_buffer; +#endif + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer_dynarow.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer_dynarow.h new file mode 100644 index 00000000000..188746f3d39 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rendering_buffer_dynarow.h @@ -0,0 +1,137 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class rendering_buffer_dynarow +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RENDERING_BUFFER_DYNAROW_INCLUDED +#define AGG_RENDERING_BUFFER_DYNAROW_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //===============================================rendering_buffer_dynarow + // Rendering buffer class with dynamic allocation of the rows. + // The rows are allocated as needed when requesting for span_ptr(). + // The class automatically calculates min_x and max_x for each row. + // Generally it's more efficient to use this class as a temporary buffer + // for rendering a few lines and then to blend it with another buffer. + // + class rendering_buffer_dynarow + { + public: + typedef row_info row_data; + + //------------------------------------------------------------------- + ~rendering_buffer_dynarow() + { + init(0,0,0); + } + + //------------------------------------------------------------------- + rendering_buffer_dynarow() : + m_rows(), + m_width(0), + m_height(0), + m_byte_width(0) + { + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + rendering_buffer_dynarow(unsigned width, unsigned height, + unsigned byte_width) : + m_rows(height), + m_width(width), + m_height(height), + m_byte_width(byte_width) + { + memset(&m_rows[0], 0, sizeof(row_data) * height); + } + + // Allocate and clear the buffer + //-------------------------------------------------------------------- + void init(unsigned width, unsigned height, unsigned byte_width) + { + unsigned i; + for(i = 0; i < m_height; ++i) + { + pod_allocator::deallocate((int8u*)m_rows[i].ptr, m_byte_width); + } + if(width && height) + { + m_width = width; + m_height = height; + m_byte_width = byte_width; + m_rows.resize(height); + memset(&m_rows[0], 0, sizeof(row_data) * height); + } + } + + //-------------------------------------------------------------------- + unsigned width() const { return m_width; } + unsigned height() const { return m_height; } + unsigned byte_width() const { return m_byte_width; } + + // The main function used for rendering. Returns pointer to the + // pre-allocated span. Memory for the row is allocated as needed. + //-------------------------------------------------------------------- + int8u* row_ptr(int x, int y, unsigned len) + { + row_data* r = &m_rows[y]; + int x2 = x + len - 1; + if(r->ptr) + { + if(x < r->x1) { r->x1 = x; } + if(x2 > r->x2) { r->x2 = x2; } + } + else + { + int8u* p = pod_allocator::allocate(m_byte_width); + r->ptr = p; + r->x1 = x; + r->x2 = x2; + memset(p, 0, m_byte_width); + } + return (int8u*)r->ptr; + } + + //-------------------------------------------------------------------- + const int8u* row_ptr(int y) const { return m_rows[y].ptr; } + int8u* row_ptr(int y) { return row_ptr(0, y, m_width); } + row_data row (int y) const { return m_rows[y]; } + + private: + //-------------------------------------------------------------------- + // Prohibit copying + rendering_buffer_dynarow(const rendering_buffer_dynarow&); + const rendering_buffer_dynarow& operator = (const rendering_buffer_dynarow&); + + private: + //-------------------------------------------------------------------- + pod_array m_rows; // Pointers to each row of the buffer + unsigned m_width; // Width in pixels + unsigned m_height; // Height in pixels + unsigned m_byte_width; // Width in bytes + }; + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rounded_rect.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rounded_rect.h new file mode 100644 index 00000000000..fe8d26f71b6 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_rounded_rect.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Rounded rectangle vertex generator +// +//---------------------------------------------------------------------------- + +#ifndef AGG_ROUNDED_RECT_INCLUDED +#define AGG_ROUNDED_RECT_INCLUDED + +#include "agg_basics.h" +#include "agg_arc.h" + +namespace agg +{ + //------------------------------------------------------------rounded_rect + // + // See Implemantation agg_rounded_rect.cpp + // + class rounded_rect + { + public: + rounded_rect() {} + rounded_rect(double x1, double y1, double x2, double y2, double r); + + void rect(double x1, double y1, double x2, double y2); + void radius(double r); + void radius(double rx, double ry); + void radius(double rx_bottom, double ry_bottom, double rx_top, double ry_top); + void radius(double rx1, double ry1, double rx2, double ry2, + double rx3, double ry3, double rx4, double ry4); + void normalize_radius(); + + void approximation_scale(double s) { m_arc.approximation_scale(s); } + double approximation_scale() const { return m_arc.approximation_scale(); } + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_rx1; + double m_ry1; + double m_rx2; + double m_ry2; + double m_rx3; + double m_ry3; + double m_rx4; + double m_ry4; + unsigned m_status; + arc m_arc; + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_bin.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_bin.h new file mode 100644 index 00000000000..660292b6136 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_bin.h @@ -0,0 +1,264 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Class scanline_bin - binary scanline. +// +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_bin) 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_SCANLINE_BIN_INCLUDED +#define AGG_SCANLINE_BIN_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_bin + // + // This is binary scaline container which supports the interface + // used in the rasterizer::render(). See description of agg_scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_bin + { + public: + typedef int32 coord_type; + + struct span + { + int16 x; + int16 len; + }; + + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_bin() : + m_last_x(0x7FFFFFF0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_cur_span->len = (int16)(m_cur_span->len + len); + } + else + { + ++m_cur_span; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_bin(const scanline_bin&); + const scanline_bin operator = (const scanline_bin&); + + int m_last_x; + int m_y; + pod_array m_spans; + span* m_cur_span; + }; + + + + + + + //===========================================================scanline32_bin + class scanline32_bin + { + public: + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span + { + span() {} + span(coord_type x_, coord_type len_) : x(x_), len(len_) {} + + coord_type x; + coord_type len; + }; + typedef pod_bvector span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + + //-------------------------------------------------------------------- + scanline32_bin() : m_max_len(0), m_last_x(0x7FFFFFF0) {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned) + { + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1)); + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned) + { + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len))); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const void*) + { + add_span(x, len, 0); + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_bin(const scanline32_bin&); + const scanline32_bin operator = (const scanline32_bin&); + + unsigned m_max_len; + int m_last_x; + int m_y; + span_array_type m_spans; + }; + + + + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_boolean_algebra.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_boolean_algebra.h new file mode 100644 index 00000000000..bc2e9c9d51f --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_boolean_algebra.h @@ -0,0 +1,1567 @@ +//---------------------------------------------------------------------------- +// 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_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED +#define AGG_SCANLINE_BOOLEAN_ALGEBRA_INCLUDED + +#include +#include +#include "agg_basics.h" + + +namespace agg +{ + + //-----------------------------------------------sbool_combine_spans_bin + // Functor. + // Combine two binary encoded spans, i.e., when we don't have any + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template + struct sbool_combine_spans_bin + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + //---------------------------------------------sbool_combine_spans_empty + // Functor. + // Combine two spans as empty ones. The functor does nothing + // and is used to XOR binary spans. + //---------------- + template + struct sbool_combine_spans_empty + { + void operator () (const typename Scanline1::const_iterator&, + const typename Scanline2::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + + //--------------------------------------------------sbool_add_span_empty + // Functor. + // Add nothing. Used in conbine_shapes_sub + //---------------- + template + struct sbool_add_span_empty + { + void operator () (const typename Scanline1::const_iterator&, + int, unsigned, + Scanline&) const + {} + }; + + + //----------------------------------------------------sbool_add_span_bin + // Functor. + // Add a binary span + //---------------- + template + struct sbool_add_span_bin + { + void operator () (const typename Scanline1::const_iterator&, + int x, unsigned len, + Scanline& sl) const + { + sl.add_span(x, len, cover_full); + } + }; + + + + + //-----------------------------------------------------sbool_add_span_aa + // Functor. + // Add an anti-aliased span + // anti-aliasing information, but only X and Length. The function + // is compatible with any type of scanlines. + //---------------- + template + struct sbool_add_span_aa + { + void operator () (const typename Scanline1::const_iterator& span, + int x, unsigned len, + Scanline& sl) const + { + if(span->len < 0) + { + sl.add_span(x, len, *span->covers); + } + else + if(span->len > 0) + { + const typename Scanline1::cover_type* covers = span->covers; + if(span->x < x) covers += x - span->x; + sl.add_cells(x, len, covers); + } + } + }; + + + + + //----------------------------------------------sbool_intersect_spans_aa + // Functor. + // Intersect two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template + struct sbool_intersect_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_cells(x, len, covers2); + } + else + { + do + { + cover = *(span1->covers) * *covers2++; + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_cells(x, len, covers1); + } + else + { + do + { + cover = *covers1++ * *(span2->covers); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * *(span2->covers); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + + + + + //--------------------------------------------------sbool_unite_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template + struct sbool_unite_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + if(*(span1->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *covers2++); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) == cover_full) + { + sl.add_span(x, len, cover_full); + } + else + { + do + { + cover = cover_mask * cover_mask - + (cover_mask - *covers1++) * + (cover_mask - *(span2->covers)); + sl.add_cell(x++, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = cover_mask * cover_mask - + (cover_mask - *(span1->covers)) * + (cover_mask - *(span2->covers)); + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + break; + } + } + }; + + + //---------------------------------------------sbool_xor_formula_linear + template + struct sbool_xor_formula_linear + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned cover = a + b; + if(cover > cover_mask) cover = cover_mask + cover_mask - cover; + return cover; + } + }; + + + //---------------------------------------------sbool_xor_formula_saddle + template + struct sbool_xor_formula_saddle + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1 + }; + + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + unsigned k = a * b; + if(k == cover_mask * cover_mask) return 0; + + a = (cover_mask * cover_mask - (a << cover_shift) + k) >> cover_shift; + b = (cover_mask * cover_mask - (b << cover_shift) + k) >> cover_shift; + return cover_mask - ((a * b) >> cover_shift); + } + }; + + + //-------------------------------------------sbool_xor_formula_abs_diff + struct sbool_xor_formula_abs_diff + { + static AGG_INLINE unsigned calculate(unsigned a, unsigned b) + { + return unsigned(abs(int(a) - int(b))); + } + }; + + + + //----------------------------------------------------sbool_xor_spans_aa + // Functor. + // XOR two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template + struct sbool_xor_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*covers1++, *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = XorFormula::calculate(*(span1->covers), *covers2++); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + do + { + cover = XorFormula::calculate(*covers1++, *(span2->covers)); + if(cover) sl.add_cell(x, cover); + ++x; + } + while(--len); + break; + + case 3: // Both are solid spans + cover = XorFormula::calculate(*(span1->covers), *(span2->covers)); + if(cover) sl.add_span(x, len, cover); + break; + + } + } + }; + + + + + + //-----------------------------------------------sbool_subtract_spans_aa + // Functor. + // Unite two spans preserving the anti-aliasing information. + // The result is added to the "sl" scanline. + //------------------ + template + struct sbool_subtract_spans_aa + { + enum cover_scale_e + { + cover_shift = CoverShift, + cover_size = 1 << cover_shift, + cover_mask = cover_size - 1, + cover_full = cover_mask + }; + + + void operator () (const typename Scanline1::const_iterator& span1, + const typename Scanline2::const_iterator& span2, + int x, unsigned len, + Scanline& sl) const + { + unsigned cover; + const typename Scanline1::cover_type* covers1; + const typename Scanline2::cover_type* covers2; + + // Calculate the operation code and choose the + // proper combination algorithm. + // 0 = Both spans are of AA type + // 1 = span1 is solid, span2 is AA + // 2 = span1 is AA, span2 is solid + // 3 = Both spans are of solid type + //----------------- + switch((span1->len < 0) | ((span2->len < 0) << 1)) + { + case 0: // Both are AA spans + covers1 = span1->covers; + covers2 = span2->covers; + if(span1->x < x) covers1 += x - span1->x; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *covers1++ * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 1: // span1 is solid, span2 is AA + covers2 = span2->covers; + if(span2->x < x) covers2 += x - span2->x; + do + { + cover = *(span1->covers) * (cover_mask - *covers2++); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + break; + + case 2: // span1 is AA, span2 is solid + covers1 = span1->covers; + if(span1->x < x) covers1 += x - span1->x; + if(*(span2->covers) != cover_full) + { + do + { + cover = *covers1++ * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_cell(x, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + ++x; + } + while(--len); + } + break; + + case 3: // Both are solid spans + cover = *(span1->covers) * (cover_mask - *(span2->covers)); + if(cover) + { + sl.add_span(x, len, + (cover == cover_full * cover_full) ? + cover_full : + (cover >> cover_shift)); + } + break; + } + } + }; + + + + + + + //--------------------------------------------sbool_add_spans_and_render + template + void sbool_add_spans_and_render(const Scanline1& sl1, + Scanline& sl, + Renderer& ren, + AddSpanFunctor add_span) + { + sl.reset_spans(); + typename Scanline1::const_iterator span = sl1.begin(); + unsigned num_spans = sl1.num_spans(); + for(;;) + { + add_span(span, span->x, abs((int)span->len), sl); + if(--num_spans == 0) break; + ++span; + } + sl.finalize(sl1.y()); + ren.render(sl); + } + + + + + + + + //---------------------------------------------sbool_intersect_scanlines + // Intersect two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template + void sbool_intersect_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + if(num1 == 0) return; + + unsigned num2 = sl2.num_spans(); + if(num2 == 0) return; + + typename Scanline1::const_iterator span1 = sl1.begin(); + typename Scanline2::const_iterator span2 = sl2.begin(); + + while(num1 && num2) + { + int xb1 = span1->x; + int xb2 = span2->x; + int xe1 = xb1 + abs((int)span1->len) - 1; + int xe2 = xb2 + abs((int)span2->len) - 1; + + // Determine what spans we should advance in the next step + // The span with the least ending X should be advanced + // advance_both is just an optimization when we ending + // coordinates are the same and we can advance both + //-------------- + bool advance_span1 = xe1 < xe2; + bool advance_both = xe1 == xe2; + + // Find the intersection of the spans + // and check if they intersect + //-------------- + if(xb1 < xb2) xb1 = xb2; + if(xe1 > xe2) xe1 = xe2; + if(xb1 <= xe1) + { + combine_spans(span1, span2, xb1, xe1 - xb1 + 1, sl); + } + + // Advance the spans + //-------------- + if(advance_both) + { + --num1; + --num2; + if(num1) ++span1; + if(num2) ++span2; + } + else + { + if(advance_span1) + { + --num1; + if(num1) ++span1; + } + else + { + --num2; + if(num2) ++span2; + } + } + } + } + + + + + + + + + //------------------------------------------------sbool_intersect_shapes + // Intersect the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See sbool_intersect_scanlines for details. + //---------- + template + void sbool_intersect_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + if(!sg1.rewind_scanlines()) return; + if(!sg2.rewind_scanlines()) return; + + // Get the bounding boxes + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + + // Calculate the intersection of the bounding + // boxes and return if they don't intersect. + //----------------- + rect_i ir = intersect_rectangles(r1, r2); + if(!ir.is_valid()) return; + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ir.x1, ir.x2); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + + ren.prepare(); + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + for(;;) + { + while(sl1.y() < sl2.y()) + { + if(!sg1.sweep_scanline(sl1)) return; + } + while(sl2.y() < sl1.y()) + { + if(!sg2.sweep_scanline(sl2)) return; + } + + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_intersect_scanlines(sl1, sl2, sl, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + if(!sg1.sweep_scanline(sl1)) return; + if(!sg2.sweep_scanline(sl2)) return; + } + } + } + + + + + + + + //-------------------------------------------------sbool_unite_scanlines + // Unite two scanlines, "sl1" and "sl2" and generate a new "sl" one. + // The combine_spans functor can be of type sbool_combine_spans_bin or + // sbool_intersect_spans_aa. First is a general functor to combine + // two spans without Anti-Aliasing, the second preserves the AA + // information, but works slower + // + template + void sbool_unite_scanlines(const Scanline1& sl1, + const Scanline2& sl2, + Scanline& sl, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + sl.reset_spans(); + + unsigned num1 = sl1.num_spans(); + unsigned num2 = sl2.num_spans(); + + typename Scanline1::const_iterator span1;// = sl1.begin(); + typename Scanline2::const_iterator span2;// = sl2.begin(); + + enum invalidation_e + { + invalid_b = 0xFFFFFFF, + invalid_e = invalid_b - 1 + }; + + // Initialize the spans as invalid + //--------------- + int xb1 = invalid_b; + int xb2 = invalid_b; + int xe1 = invalid_e; + int xe2 = invalid_e; + + // Initialize span1 if there are spans + //--------------- + if(num1) + { + span1 = sl1.begin(); + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + --num1; + } + + // Initialize span2 if there are spans + //--------------- + if(num2) + { + span2 = sl2.begin(); + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + --num2; + } + + + for(;;) + { + // Retrieve a new span1 if it's invalid + //---------------- + if(num1 && xb1 > xe1) + { + --num1; + ++span1; + xb1 = span1->x; + xe1 = xb1 + abs((int)span1->len) - 1; + } + + // Retrieve a new span2 if it's invalid + //---------------- + if(num2 && xb2 > xe2) + { + --num2; + ++span2; + xb2 = span2->x; + xe2 = xb2 + abs((int)span2->len) - 1; + } + + if(xb1 > xe1 && xb2 > xe2) break; + + // Calculate the intersection + //---------------- + int xb = xb1; + int xe = xe1; + if(xb < xb2) xb = xb2; + if(xe > xe2) xe = xe2; + int len = xe - xb + 1; // The length of the intersection + if(len > 0) + { + // The spans intersect, + // add the beginning of the span + //---------------- + if(xb1 < xb2) + { + add_span1(span1, xb1, xb2 - xb1, sl); + xb1 = xb2; + } + else + if(xb2 < xb1) + { + add_span2(span2, xb2, xb1 - xb2, sl); + xb2 = xb1; + } + + // Add the combination part of the spans + //---------------- + combine_spans(span1, span2, xb, len, sl); + + + // Invalidate the fully processed span or both + //---------------- + if(xe1 < xe2) + { + // Invalidate span1 and eat + // the processed part of span2 + //-------------- + xb1 = invalid_b; + xe1 = invalid_e; + xb2 += len; + } + else + if(xe2 < xe1) + { + // Invalidate span2 and eat + // the processed part of span1 + //-------------- + xb2 = invalid_b; + xe2 = invalid_e; + xb1 += len; + } + else + { + xb1 = invalid_b; // Invalidate both + xb2 = invalid_b; + xe1 = invalid_e; + xe2 = invalid_e; + } + } + else + { + // The spans do not intersect + //-------------- + if(xb1 < xb2) + { + // Advance span1 + //--------------- + if(xb1 <= xe1) + { + add_span1(span1, xb1, xe1 - xb1 + 1, sl); + } + xb1 = invalid_b; // Invalidate + xe1 = invalid_e; + } + else + { + // Advance span2 + //--------------- + if(xb2 <= xe2) + { + add_span2(span2, xb2, xe2 - xb2 + 1, sl); + } + xb2 = invalid_b; // Invalidate + xe2 = invalid_e; + } + } + } + } + + + + + //----------------------------------------------------sbool_unite_shapes + // Unite the scanline shapes. Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be + // of different type. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_unite_scanlines with CombineSpansFunctor + // as the last argument. See sbool_unite_scanlines for details. + //---------- + template + void sbool_unite_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + AddSpanFunctor2 add_span2, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // If anyone of them doesn't contain + // any scanlines, then return. + //----------------- + bool flag1 = sg1.rewind_scanlines(); + bool flag2 = sg2.rewind_scanlines(); + if(!flag1 && !flag2) return; + + // Get the bounding boxes + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + rect_i r2(sg2.min_x(), sg2.min_y(), sg2.max_x(), sg2.max_y()); + + // Calculate the union of the bounding boxes + //----------------- + rect_i ur(1,1,0,0); + if(flag1 && flag2) ur = unite_rectangles(r1, r2); + else if(flag1) ur = r1; + else if(flag2) ur = r2; + + if(!ur.is_valid()) return; + + ren.prepare(); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(ur.x1, ur.x2); + if(flag1) + { + sl1.reset(sg1.min_x(), sg1.max_x()); + flag1 = sg1.sweep_scanline(sl1); + } + + if(flag2) + { + sl2.reset(sg2.min_x(), sg2.max_x()); + flag2 = sg2.sweep_scanline(sl2); + } + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate. + //----------------- + while(flag1 || flag2) + { + if(flag1 && flag2) + { + if(sl1.y() == sl2.y()) + { + // The Y coordinates are the same. + // Combine the scanlines, render if they contain any spans, + // and advance both generators to the next scanlines + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, + add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + flag1 = sg1.sweep_scanline(sl1); + flag2 = sg2.sweep_scanline(sl2); + } + else + { + if(sl1.y() < sl2.y()) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + else + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + else + { + if(flag1) + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + flag1 = sg1.sweep_scanline(sl1); + } + if(flag2) + { + sbool_add_spans_and_render(sl2, sl, ren, add_span2); + flag2 = sg2.sweep_scanline(sl2); + } + } + } + } + + + + + + + + + //-------------------------------------------------sbool_subtract_shapes + // Subtract the scanline shapes, "sg1-sg2". Here the "Scanline Generator" + // abstraction is used. ScanlineGen1 and ScanlineGen2 are + // the generators, and can be of type rasterizer_scanline_aa<>. + // There function requires three scanline containers that can be of + // different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + // the function calls sbool_intersect_scanlines with CombineSpansFunctor + // as the last argument. See combine_scanlines_sub for details. + //---------- + template + void sbool_subtract_shapes(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren, + AddSpanFunctor1 add_span1, + CombineSpansFunctor combine_spans) + { + // Prepare the scanline generators. + // Here "sg1" is master, "sg2" is slave. + //----------------- + if(!sg1.rewind_scanlines()) return; + bool flag2 = sg2.rewind_scanlines(); + + // Get the bounding box + //---------------- + rect_i r1(sg1.min_x(), sg1.min_y(), sg1.max_x(), sg1.max_y()); + + // Reset the scanlines and get two first ones + //----------------- + sl.reset(sg1.min_x(), sg1.max_x()); + sl1.reset(sg1.min_x(), sg1.max_x()); + sl2.reset(sg2.min_x(), sg2.max_x()); + if(!sg1.sweep_scanline(sl1)) return; + + if(flag2) flag2 = sg2.sweep_scanline(sl2); + + ren.prepare(); + + // A fake span2 processor + sbool_add_span_empty add_span2; + + // The main loop + // Here we synchronize the scanlines with + // the same Y coordinate, ignoring all other ones. + // Only scanlines having the same Y-coordinate + // are to be combined. + //----------------- + bool flag1 = true; + do + { + // Synchronize "slave" with "master" + //----------------- + while(flag2 && sl2.y() < sl1.y()) + { + flag2 = sg2.sweep_scanline(sl2); + } + + + if(flag2 && sl2.y() == sl1.y()) + { + // The Y coordinates are the same. + // Combine the scanlines and render if they contain any spans. + //---------------------- + sbool_unite_scanlines(sl1, sl2, sl, add_span1, add_span2, combine_spans); + if(sl.num_spans()) + { + sl.finalize(sl1.y()); + ren.render(sl); + } + } + else + { + sbool_add_spans_and_render(sl1, sl, ren, add_span1); + } + + // Advance the "master" + flag1 = sg1.sweep_scanline(sl1); + } + while(flag1); + } + + + + + + + + //---------------------------------------------sbool_intersect_shapes_aa + // Intersect two anti-aliased scanline shapes. + // Here the "Scanline Generator" abstraction is used. + // ScanlineGen1 and ScanlineGen2 are the generators, and can be of + // type rasterizer_scanline_aa<>. There function requires three + // scanline containers that can be of different types. + // "sl1" and "sl2" are used to retrieve scanlines from the generators, + // "sl" is ised as the resulting scanline to render it. + // The external "sl1" and "sl2" are used only for the sake of + // optimization and reusing of the scanline objects. + //---------- + template + void sbool_intersect_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_intersect_spans_aa combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //--------------------------------------------sbool_intersect_shapes_bin + // Intersect two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_intersect_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_combine_spans_bin combine_functor; + sbool_intersect_shapes(sg1, sg2, sl1, sl2, sl, ren, combine_functor); + } + + + + + + //-------------------------------------------------sbool_unite_shapes_aa + // Unite two anti-aliased scanline shapes + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_unite_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor1; + sbool_add_span_aa add_functor2; + sbool_unite_spans_aa combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + //------------------------------------------------sbool_unite_shapes_bin + // Unite two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_unite_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin add_functor1; + sbool_add_span_bin add_functor2; + sbool_combine_spans_bin combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + + + + //---------------------------------------------------sbool_xor_shapes_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. There's + // a modified "Linear" XOR used instead of classical "Saddle" one. + // The reason is to have the result absolutely conststent with what + // the scanline rasterizer produces. + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_xor_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor1; + sbool_add_span_aa add_functor2; + sbool_xor_spans_aa > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //------------------------------------------sbool_xor_shapes_saddle_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the classical "Saddle" used to calculate the + // Anti-Aliasing values, that is: + // a XOR b : 1-((1-a+a*b)*(1-b+a*b)) + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_xor_shapes_saddle_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor1; + sbool_add_span_aa add_functor2; + sbool_xor_spans_aa > combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + //--------------------------------------sbool_xor_shapes_abs_diff_aa + // Apply eXclusive OR to two anti-aliased scanline shapes. + // There's the absolute difference used to calculate + // Anti-Aliasing values, that is: + // a XOR b : abs(a-b) + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_xor_shapes_abs_diff_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor1; + sbool_add_span_aa add_functor2; + sbool_xor_spans_aa combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + //--------------------------------------------------sbool_xor_shapes_bin + // Apply eXclusive OR to two binary scanline shapes (without anti-aliasing). + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_xor_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin add_functor1; + sbool_add_span_bin add_functor2; + sbool_combine_spans_empty combine_functor; + sbool_unite_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor1, add_functor2, combine_functor); + } + + + + + + + //----------------------------------------------sbool_subtract_shapes_aa + // Subtract shapes "sg1-sg2" with anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_subtract_shapes_aa(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_aa add_functor; + sbool_subtract_spans_aa combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + //---------------------------------------------sbool_subtract_shapes_bin + // Subtract binary shapes "sg1-sg2" without anti-aliasing + // See intersect_shapes_aa for more comments + //---------- + template + void sbool_subtract_shapes_bin(ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + sbool_add_span_bin add_functor; + sbool_combine_spans_empty combine_functor; + sbool_subtract_shapes(sg1, sg2, sl1, sl2, sl, ren, + add_functor, combine_functor); + } + + + + + + + //------------------------------------------------------------sbool_op_e + enum sbool_op_e + { + sbool_or, //----sbool_or + sbool_and, //----sbool_and + sbool_xor, //----sbool_xor + sbool_xor_saddle, //----sbool_xor_saddle + sbool_xor_abs_diff, //----sbool_xor_abs_diff + sbool_a_minus_b, //----sbool_a_minus_b + sbool_b_minus_a //----sbool_b_minus_a + }; + + + + + + + //----------------------------------------------sbool_combine_shapes_bin + template + void sbool_combine_shapes_bin(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_bin(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : + case sbool_xor_saddle : + case sbool_xor_abs_diff: sbool_xor_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_bin (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_bin (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + + + + + //-----------------------------------------------sbool_combine_shapes_aa + template + void sbool_combine_shapes_aa(sbool_op_e op, + ScanlineGen1& sg1, ScanlineGen2& sg2, + Scanline1& sl1, Scanline2& sl2, + Scanline& sl, Renderer& ren) + { + switch(op) + { + case sbool_or : sbool_unite_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_and : sbool_intersect_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor : sbool_xor_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_saddle : sbool_xor_shapes_saddle_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_xor_abs_diff: sbool_xor_shapes_abs_diff_aa(sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_a_minus_b : sbool_subtract_shapes_aa (sg1, sg2, sl1, sl2, sl, ren); break; + case sbool_b_minus_a : sbool_subtract_shapes_aa (sg2, sg1, sl2, sl1, sl, ren); break; + } + } + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_p.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_p.h new file mode 100644 index 00000000000..1d1cbe72f1e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_p.h @@ -0,0 +1,329 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Class scanline_p - a general purpose scanline container with packed spans. +// +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_p) 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_SCANLINE_P_INCLUDED +#define AGG_SCANLINE_P_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //=============================================================scanline_p8 + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_p8 + { + public: + typedef scanline_p8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + scanline_p8() : + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = (cover_type)cover; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 1; + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)len; + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr++; + m_cur_span->x = (int16)x; + m_cur_span->len = (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + pod_array m_spans; + span* m_cur_span; + }; + + + + + + + + + //==========================================================scanline32_p8 + class scanline32_p8 + { + public: + typedef scanline32_p8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + struct span + { + span() {} + span(coord_type x_, coord_type len_, const cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + typedef pod_bvector span_array_type; + + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + scanline32_p8() : + m_max_len(0), + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 3; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + *m_cover_ptr = cover_type(cover); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x), 1, m_cover_ptr)); + } + m_last_x = x; + m_cover_ptr++; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, len * sizeof(cover_type)); + if(x == m_last_x+1 && m_spans.size() && m_spans.last().len > 0) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x), coord_type(len), m_cover_ptr)); + } + m_cover_ptr += len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_spans.size() && + m_spans.last().len < 0 && + cover == *m_spans.last().covers) + { + m_spans.last().len -= coord_type(len); + } + else + { + *m_cover_ptr = cover_type(cover); + m_spans.add(span(coord_type(x), -coord_type(len), m_cover_ptr++)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + + private: + scanline32_p8(const self_type&); + const self_type& operator = (const self_type&); + + unsigned m_max_len; + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + span_array_type m_spans; + }; + + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_aa.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_aa.h new file mode 100644 index 00000000000..b3471fce768 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_aa.h @@ -0,0 +1,815 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_SCANLINE_STORAGE_AA_INCLUDED +#define AGG_SCANLINE_STORAGE_AA_INCLUDED + +#include +#include +#include +#include "agg_array.h" + + +namespace agg +{ + + //----------------------------------------------scanline_cell_storage + template class scanline_cell_storage + { + struct extra_span + { + unsigned len; + T* ptr; + }; + + public: + typedef T value_type; + + //--------------------------------------------------------------- + ~scanline_cell_storage() + { + remove_all(); + } + + //--------------------------------------------------------------- + scanline_cell_storage() : + m_cells(128-2), + m_extra_storage() + {} + + + // Copying + //--------------------------------------------------------------- + scanline_cell_storage(const scanline_cell_storage& v) : + m_cells(v.m_cells), + m_extra_storage() + { + copy_extra_storage(v); + } + + //--------------------------------------------------------------- + const scanline_cell_storage& + operator = (const scanline_cell_storage& v) + { + remove_all(); + m_cells = v.m_cells; + copy_extra_storage(v); + return *this; + } + + //--------------------------------------------------------------- + void remove_all() + { + int i; + for(i = m_extra_storage.size()-1; i >= 0; --i) + { + pod_allocator::deallocate(m_extra_storage[i].ptr, + m_extra_storage[i].len); + } + m_extra_storage.remove_all(); + m_cells.remove_all(); + } + + //--------------------------------------------------------------- + int add_cells(const T* cells, unsigned num_cells) + { + int idx = m_cells.allocate_continuous_block(num_cells); + if(idx >= 0) + { + T* ptr = &m_cells[idx]; + memcpy(ptr, cells, sizeof(T) * num_cells); + return idx; + } + extra_span s; + s.len = num_cells; + s.ptr = pod_allocator::allocate(num_cells); + memcpy(s.ptr, cells, sizeof(T) * num_cells); + m_extra_storage.add(s); + return -int(m_extra_storage.size()); + } + + //--------------------------------------------------------------- + const T* operator [] (int idx) const + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + //--------------------------------------------------------------- + T* operator [] (int idx) + { + if(idx >= 0) + { + if((unsigned)idx >= m_cells.size()) return 0; + return &m_cells[(unsigned)idx]; + } + unsigned i = unsigned(-idx - 1); + if(i >= m_extra_storage.size()) return 0; + return m_extra_storage[i].ptr; + } + + private: + void copy_extra_storage(const scanline_cell_storage& v) + { + unsigned i; + for(i = 0; i < v.m_extra_storage.size(); ++i) + { + const extra_span& src = v.m_extra_storage[i]; + extra_span dst; + dst.len = src.len; + dst.ptr = pod_allocator::allocate(dst.len); + memcpy(dst.ptr, src.ptr, dst.len * sizeof(T)); + m_extra_storage.add(dst); + } + } + + pod_bvector m_cells; + pod_bvector m_extra_storage; + }; + + + + + + + //-----------------------------------------------scanline_storage_aa + template class scanline_storage_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------- + struct span_data + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + int covers_id; // The index of the cells in the scanline_cell_storage + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + const T* covers; + }; + + const_iterator() : m_storage(0) {} + const_iterator(embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + init_span(); + } + + private: + void init_span() + { + const span_data& s = m_storage->span_by_index(m_span_idx); + m_span.x = s.x; + m_span.len = s.len; + m_span.covers = m_storage->covers_by_index(s.covers_id); + } + + scanline_storage_aa* m_storage; + unsigned m_span_idx; + span m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_aa& storage) : + m_storage(&storage) + { + init(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void init(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_aa* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_aa() : + m_covers(), + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + m_fake_span.covers_id = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare() + { + m_covers.remove_all(); + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + for(;;) + { + span_data sp; + + sp.x = span_iterator->x; + sp.len = span_iterator->len; + int len = abs(int(sp.len)); + sp.covers_id = + m_covers.add_cells(span_iterator->covers, + unsigned(len)); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + len - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; + ++span_iterator; + } + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + if(sp.len < 0) + { + sl.add_span(sp.x, unsigned(-sp.len), *covers); + } + else + { + sl.add_cells(sp.x, sp.len, covers); + } + } + while(--num_spans); + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.init(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y + + for(i = 0; i < m_scanlines.size(); ++i) + { + size += sizeof(int32) * 3; // scanline size in bytes, Y, num_spans + + const scanline_data& sl_this = m_scanlines[i]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + size += sizeof(int32) * 2; // X, span_len + if(sp.len < 0) + { + size += sizeof(T); // cover + } + else + { + size += sizeof(T) * unsigned(sp.len); // covers + } + } + while(--num_spans); + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int32(int8u* dst, int32 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + unsigned i; + + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); + + for(i = 0; i < m_scanlines.size(); ++i) + { + const scanline_data& sl_this = m_scanlines[i]; + + int8u* size_ptr = data; + data += sizeof(int32); // Reserve space for scanline size in bytes + + write_int32(data, sl_this.y); // Y + data += sizeof(int32); + + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + + write_int32(data, sp.x); // X + data += sizeof(int32); + + write_int32(data, sp.len); // span_len + data += sizeof(int32); + + if(sp.len < 0) + { + memcpy(data, covers, sizeof(T)); + data += sizeof(T); + } + else + { + memcpy(data, covers, unsigned(sp.len) * sizeof(T)); + data += sizeof(T) * unsigned(sp.len); + } + } + while(--num_spans); + write_int32(size_ptr, int32(unsigned(data - size_ptr))); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + //--------------------------------------------------------------- + const T* covers_by_index(int i) const + { + return m_covers[i]; + } + + private: + scanline_cell_storage m_covers; + pod_bvector m_spans; + pod_bvector m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + typedef scanline_storage_aa scanline_storage_aa8; //--------scanline_storage_aa8 + typedef scanline_storage_aa scanline_storage_aa16; //--------scanline_storage_aa16 + typedef scanline_storage_aa scanline_storage_aa32; //--------scanline_storage_aa32 + + + + + //------------------------------------------serialized_scanlines_adaptor_aa + template class serialized_scanlines_adaptor_aa + { + public: + typedef T cover_type; + + //--------------------------------------------------------------------- + class embedded_scanline + { + public: + typedef T cover_type; + + //----------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, "covers" is valid + const T* covers; + }; + + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline* sl) : + m_ptr(sl->m_ptr), + m_dx(sl->m_dx) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + if(m_span.len < 0) + { + m_ptr += sizeof(T); + } + else + { + m_ptr += m_span.len * sizeof(T); + } + init_span(); + } + + private: + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + void init_span() + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + m_span.covers = m_ptr; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //----------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //----------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(this); } + + + private: + //----------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + //----------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_aa(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + //-------------------------------------------------------------------- + unsigned read_int32u() + { + int32u val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + m_ptr = m_data; + if(m_ptr < m_end) + { + m_min_x = read_int32u() + m_dx; + m_min_y = read_int32u() + m_dy; + m_max_x = read_int32u() + m_dx; + m_max_y = read_int32u() + m_dy; + } + return m_ptr < m_end; + } + + //-------------------------------------------------------------------- + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + read_int32(); // Skip scanline size in bytes + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); + + do + { + int x = read_int32() + m_dx; + int len = read_int32(); + + if(len < 0) + { + sl.add_span(x, unsigned(-len), *m_ptr); + m_ptr += sizeof(T); + } + else + { + sl.add_cells(x, len, m_ptr); + m_ptr += len * sizeof(T); + } + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + unsigned byte_size = read_int32u(); + sl.init(m_ptr, m_dx, m_dy); + m_ptr += byte_size - sizeof(int32); + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + + typedef serialized_scanlines_adaptor_aa serialized_scanlines_adaptor_aa8; //----serialized_scanlines_adaptor_aa8 + typedef serialized_scanlines_adaptor_aa serialized_scanlines_adaptor_aa16; //----serialized_scanlines_adaptor_aa16 + typedef serialized_scanlines_adaptor_aa serialized_scanlines_adaptor_aa32; //----serialized_scanlines_adaptor_aa32 + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_bin.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_bin.h new file mode 100644 index 00000000000..3ab1adca516 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_storage_bin.h @@ -0,0 +1,586 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates 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_SCANLINE_STORAGE_BIN_INCLUDED +#define AGG_SCANLINE_STORAGE_BIN_INCLUDED + +#include +#include +#include +#include "agg_array.h" + + +namespace agg +{ + + //-----------------------------------------------scanline_storage_bin + class scanline_storage_bin + { + public: + //--------------------------------------------------------------- + struct span_data + { + int32 x; + int32 len; + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline* sl) : + m_storage(sl->m_storage), + m_span_idx(sl->m_scanline.start_span) + { + m_span = m_storage->span_by_index(m_span_idx); + } + + const span_data& operator*() const { return m_span; } + const span_data* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + m_span = m_storage->span_by_index(m_span_idx); + } + + private: + const scanline_storage_bin* m_storage; + unsigned m_span_idx; + span_data m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(scanline_storage_bin& storage) : + m_storage(&storage) + { + setup(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(this); } + + //----------------------------------------------------------- + void setup(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + scanline_storage_bin* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_bin() : + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare() + { + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + for(;;) + { + span_data sp; + sp.x = span_iterator->x; + sp.len = (int32)abs((int)(span_iterator->len)); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + sp.len - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; + ++span_iterator; + } + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + sl.add_span(sp.x, sp.len, cover_full); + } + while(--num_spans); + + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.setup(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y + + for(i = 0; i < m_scanlines.size(); ++i) + { + size += sizeof(int32) * 2 + // Y, num_spans + unsigned(m_scanlines[i].num_spans) * sizeof(int32) * 2; // X, span_len + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int32(int8u* dst, int32 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + unsigned i; + + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); + + for(i = 0; i < m_scanlines.size(); ++i) + { + const scanline_data& sl_this = m_scanlines[i]; + + write_int32(data, sl_this.y); // Y + data += sizeof(int32); + + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + write_int32(data, sp.x); // X + data += sizeof(int32); + + write_int32(data, sp.len); // len + data += sizeof(int32); + } + while(--num_spans); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + + private: + pod_bvector m_spans; + pod_bvector m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + + + + + + + + + + + + //---------------------------------------serialized_scanlines_adaptor_bin + class serialized_scanlines_adaptor_bin + { + public: + typedef bool cover_type; + + //-------------------------------------------------------------------- + class embedded_scanline + { + public: + + //---------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; + }; + + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline* sl) : + m_ptr(sl->m_ptr), + m_dx(sl->m_dx) + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + } + + private: + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //---------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //---------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(this); } + + + private: + //---------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + //---------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_bin(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + m_ptr = m_data; + if(m_ptr < m_end) + { + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; + } + return m_ptr < m_end; + } + + //-------------------------------------------------------------------- + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); + + do + { + int x = read_int32() + m_dx; + int len = read_int32(); + + if(len < 0) len = -len; + sl.add_span(x, unsigned(len), cover_full); + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + sl.init(m_ptr, m_dx, m_dy); + + // Jump to the next scanline + //-------------------------- + read_int32(); // Y + int num_spans = read_int32(); // num_spans + m_ptr += num_spans * sizeof(int32) * 2; + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_u.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_u.h new file mode 100644 index 00000000000..2628f55f47b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_scanline_u.h @@ -0,0 +1,499 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Adaptation for 32-bit screen coordinates (scanline32_u) 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_SCANLINE_U_INCLUDED +#define AGG_SCANLINE_U_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //=============================================================scanline_u8 + // + // Unpacked scanline container class + // + // This class is used to transfer data from a scanline rasterizer + // to the rendering buffer. It's organized very simple. The class stores + // information of horizontal spans to render it into a pixel-map buffer. + // Each span has staring X, length, and an array of bytes that determine the + // cover-values for each pixel. + // Before using this class you should know the minimal and maximal pixel + // coordinates of your scanline. The protocol of using is: + // 1. reset(min_x, max_x) + // 2. add_cell() / add_span() - accumulate scanline. + // When forming one scanline the next X coordinate must be always greater + // than the last stored one, i.e. it works only with ordered coordinates. + // 3. Call finalize(y) and render the scanline. + // 3. Call reset_spans() to prepare for the new scanline. + // + // 4. Rendering: + // + // Scanline provides an iterator class that allows you to extract + // the spans and the cover values for each pixel. Be aware that clipping + // has not been done yet, so you should perform it yourself. + // Use scanline_u8::iterator to render spans: + //------------------------------------------------------------------------- + // + // int y = sl.y(); // Y-coordinate of the scanline + // + // ************************************ + // ...Perform vertical clipping here... + // ************************************ + // + // scanline_u8::const_iterator span = sl.begin(); + // + // unsigned char* row = m_rbuf->row(y); // The address of the beginning + // // of the current row + // + // unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that + // // num_spans is always greater than 0. + // + // do + // { + // const scanline_u8::cover_type* covers = + // span->covers; // The array of the cover values + // + // int num_pix = span->len; // Number of pixels of the span. + // // Always greater than 0, still it's + // // better to use "int" instead of + // // "unsigned" because it's more + // // convenient for clipping + // int x = span->x; + // + // ************************************** + // ...Perform horizontal clipping here... + // ...you have x, covers, and pix_count.. + // ************************************** + // + // unsigned char* dst = row + x; // Calculate the start address of the row. + // // In this case we assume a simple + // // grayscale image 1-byte per pixel. + // do + // { + // *dst++ = *covers++; // Hypotetical rendering. + // } + // while(--num_pix); + // + // ++span; + // } + // while(--num_spans); // num_spans cannot be 0, so this loop is quite safe + //------------------------------------------------------------------------ + // + // The question is: why should we accumulate the whole scanline when we + // could render just separate spans when they're ready? + // That's because using the scanline is generally faster. When is consists + // of more than one span the conditions for the processor cash system + // are better, because switching between two different areas of memory + // (that can be very large) occurs less frequently. + //------------------------------------------------------------------------ + class scanline_u8 + { + public: + typedef scanline_u8 self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = (cover_type)cover; + if(x == m_last_x+1) + { + m_cur_span->len++; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 1; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_cur_span->len += (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = (coord_type)len; + m_cur_span->covers = &m_covers[x]; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + iterator begin() { return &m_spans[1]; } + + private: + scanline_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + pod_array m_spans; + span* m_cur_span; + }; + + + + + //==========================================================scanline_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template + class scanline_u8_am : public scanline_u8 + { + public: + typedef scanline_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + + scanline_u8_am() : base_type(), m_alpha_mask(0) {} + scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) + { + base_type::finalize(span_y); + if(m_alpha_mask) + { + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + base_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } + } + + private: + AlphaMask* m_alpha_mask; + }; + + + + + //===========================================================scanline32_u8 + class scanline32_u8 + { + public: + typedef scanline32_u8 self_type; + typedef int8u cover_type; + typedef int32 coord_type; + + //-------------------------------------------------------------------- + struct span + { + span() {} + span(coord_type x_, coord_type len_, cover_type* covers_) : + x(x_), len(len_), covers(covers_) {} + + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef pod_bvector span_array_type; + + //-------------------------------------------------------------------- + class const_iterator + { + public: + const_iterator(const span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + const span& operator*() const { return m_spans[m_span_idx]; } + const span* operator->() const { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + const span_array_type& m_spans; + unsigned m_span_idx; + }; + + //-------------------------------------------------------------------- + class iterator + { + public: + iterator(span_array_type& spans) : + m_spans(spans), + m_span_idx(0) + {} + + span& operator*() { return m_spans[m_span_idx]; } + span* operator->() { return &m_spans[m_span_idx]; } + + void operator ++ () { ++m_span_idx; } + + private: + span_array_type& m_spans; + unsigned m_span_idx; + }; + + + + //-------------------------------------------------------------------- + scanline32_u8() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_covers() + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = max_x - min_x + 2; + if(max_len > m_covers.size()) + { + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover) + { + x -= m_min_x; + m_covers[x] = cover_type(cover); + if(x == m_last_x+1) + { + m_spans.last().len++; + } + else + { + m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x])); + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + x -= m_min_x; + memcpy(&m_covers[x], covers, len * sizeof(cover_type)); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x + m_min_x), + coord_type(len), + &m_covers[x])); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[x], cover, len); + if(x == m_last_x+1) + { + m_spans.last().len += coord_type(len); + } + else + { + m_spans.add(span(coord_type(x + m_min_x), + coord_type(len), + &m_covers[x])); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_spans.remove_all(); + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return m_spans.size(); } + const_iterator begin() const { return const_iterator(m_spans); } + iterator begin() { return iterator(m_spans); } + + private: + scanline32_u8(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + span_array_type m_spans; + }; + + + + + //========================================================scanline32_u8_am + // + // The scanline container with alpha-masking + // + //------------------------------------------------------------------------ + template + class scanline32_u8_am : public scanline32_u8 + { + public: + typedef scanline32_u8 base_type; + typedef AlphaMask alpha_mask_type; + typedef base_type::cover_type cover_type; + typedef base_type::coord_type coord_type; + + + scanline32_u8_am() : base_type(), m_alpha_mask(0) {} + scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {} + + //-------------------------------------------------------------------- + void finalize(int span_y) + { + base_type::finalize(span_y); + if(m_alpha_mask) + { + typename base_type::iterator span = base_type::begin(); + unsigned count = base_type::num_spans(); + do + { + m_alpha_mask->combine_hspan(span->x, + base_type::y(), + span->covers, + span->len); + ++span; + } + while(--count); + } + } + + private: + AlphaMask* m_alpha_mask; + }; + + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_shorten_path.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_shorten_path.h new file mode 100644 index 00000000000..dd9929ff974 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_shorten_path.h @@ -0,0 +1,66 @@ +//---------------------------------------------------------------------------- +// 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_SHORTEN_PATH_INCLUDED +#define AGG_SHORTEN_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //===========================================================shorten_path + template + void shorten_path(VertexSequence& vs, double s, unsigned closed = 0) + { + typedef typename VertexSequence::value_type vertex_type; + + if(s > 0.0 && vs.size() > 1) + { + double d; + int n = int(vs.size() - 2); + while(n) + { + d = vs[n].dist; + if(d > s) break; + vs.remove_last(); + s -= d; + --n; + } + if(vs.size() < 2) + { + vs.remove_all(); + } + else + { + n = vs.size() - 1; + vertex_type& prev = vs[n-1]; + vertex_type& last = vs[n]; + d = (prev.dist - s) / prev.dist; + double x = prev.x + (last.x - prev.x) * d; + double y = prev.y + (last.y - prev.y) * d; + last.x = x; + last.y = y; + if(!prev(last)) vs.remove_last(); + vs.close(closed != 0); + } + } + } + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_simul_eq.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_simul_eq.h new file mode 100644 index 00000000000..3d0dce4b447 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_simul_eq.h @@ -0,0 +1,147 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Solving simultaneous equations +// +//---------------------------------------------------------------------------- +#ifndef AGG_SIMUL_EQ_INCLUDED +#define AGG_SIMUL_EQ_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //=============================================================swap_arrays + template void swap_arrays(T* a1, T* a2, unsigned n) + { + unsigned i; + for(i = 0; i < n; i++) + { + T tmp = *a1; + *a1++ = *a2; + *a2++ = tmp; + } + } + + + //============================================================matrix_pivot + template + struct matrix_pivot + { + static int pivot(double m[Rows][Cols], unsigned row) + { + int k = int(row); + double max_val, tmp; + + max_val = -1.0; + unsigned i; + for(i = row; i < Rows; i++) + { + if((tmp = fabs(m[i][row])) > max_val && tmp != 0.0) + { + max_val = tmp; + k = i; + } + } + + if(m[k][row] == 0.0) + { + return -1; + } + + if(k != int(row)) + { + swap_arrays(m[k], m[row], Cols); + return k; + } + return 0; + } + }; + + + + //===============================================================simul_eq + template + struct simul_eq + { + static bool solve(const double left[Size][Size], + const double right[Size][RightCols], + double result[Size][RightCols]) + { + unsigned i, j, k; + double a1; + + double tmp[Size][Size + RightCols]; + + for(i = 0; i < Size; i++) + { + for(j = 0; j < Size; j++) + { + tmp[i][j] = left[i][j]; + } + for(j = 0; j < RightCols; j++) + { + tmp[i][Size + j] = right[i][j]; + } + } + + for(k = 0; k < Size; k++) + { + if(matrix_pivot::pivot(tmp, k) < 0) + { + return false; // Singularity.... + } + + a1 = tmp[k][k]; + + for(j = k; j < Size + RightCols; j++) + { + tmp[k][j] /= a1; + } + + for(i = k + 1; i < Size; i++) + { + a1 = tmp[i][k]; + for (j = k; j < Size + RightCols; j++) + { + tmp[i][j] -= a1 * tmp[k][j]; + } + } + } + + + for(k = 0; k < RightCols; k++) + { + int m; + for(m = int(Size - 1); m >= 0; m--) + { + result[m][k] = tmp[m][Size + k]; + for(j = m + 1; j < Size; j++) + { + result[m][k] -= tmp[m][j] * result[j][k]; + } + } + } + return true; + } + + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_allocator.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_allocator.h new file mode 100644 index 00000000000..201b69bb01e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_allocator.h @@ -0,0 +1,54 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_ALLOCATOR_INCLUDED +#define AGG_SPAN_ALLOCATOR_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + //----------------------------------------------------------span_allocator + template class span_allocator + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + AGG_INLINE color_type* allocate(unsigned span_len) + { + if(span_len > m_span.size()) + { + // To reduce the number of reallocs we align the + // span_len to 256 color elements. + // Well, I just like this number and it looks reasonable. + //----------------------- + m_span.resize(((span_len + 255) >> 8) << 8); + } + return &m_span[0]; + } + + AGG_INLINE color_type* span() { return &m_span[0]; } + AGG_INLINE unsigned max_span_len() const { return m_span.size(); } + + private: + pod_array m_span; + }; +} + + +#endif + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_converter.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_converter.h new file mode 100644 index 00000000000..91d0f87c256 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_converter.h @@ -0,0 +1,56 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_CONVERTER_INCLUDED +#define AGG_SPAN_CONVERTER_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //----------------------------------------------------------span_converter + template class span_converter + { + public: + typedef typename SpanGenerator::color_type color_type; + + span_converter(SpanGenerator& span_gen, SpanConverter& span_cnv) : + m_span_gen(&span_gen), m_span_cnv(&span_cnv) {} + + void attach_generator(SpanGenerator& span_gen) { m_span_gen = &span_gen; } + void attach_converter(SpanConverter& span_cnv) { m_span_cnv = &span_cnv; } + + //-------------------------------------------------------------------- + void prepare() + { + m_span_gen->prepare(); + m_span_cnv->prepare(); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_span_gen->generate(span, x, y, len); + m_span_cnv->generate(span, x, y, len); + } + + private: + SpanGenerator* m_span_gen; + SpanConverter* m_span_cnv; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud.h new file mode 100644 index 00000000000..2986c88feec --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud.h @@ -0,0 +1,172 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_GOURAUD_INCLUDED +#define AGG_SPAN_GOURAUD_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" + +namespace agg +{ + + //============================================================span_gouraud + template class span_gouraud + { + public: + typedef ColorT color_type; + + struct coord_type + { + double x; + double y; + color_type color; + }; + + //-------------------------------------------------------------------- + span_gouraud() : + m_vertex(0) + { + m_cmd[0] = path_cmd_stop; + } + + //-------------------------------------------------------------------- + span_gouraud(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d) : + m_vertex(0) + { + colors(c1, c2, c3); + triangle(x1, y1, x2, y2, x3, y3, d); + } + + //-------------------------------------------------------------------- + void colors(ColorT c1, ColorT c2, ColorT c3) + { + m_coord[0].color = c1; + m_coord[1].color = c2; + m_coord[2].color = c3; + } + + //-------------------------------------------------------------------- + // Sets the triangle and dilates it if needed. + // The trick here is to calculate beveled joins in the vertices of the + // triangle and render it as a 6-vertex polygon. + // It's necessary to achieve numerical stability. + // However, the coordinates to interpolate colors are calculated + // as miter joins (calc_intersection). + void triangle(double x1, double y1, + double x2, double y2, + double x3, double y3, + double d) + { + m_coord[0].x = m_x[0] = x1; + m_coord[0].y = m_y[0] = y1; + m_coord[1].x = m_x[1] = x2; + m_coord[1].y = m_y[1] = y2; + m_coord[2].x = m_x[2] = x3; + m_coord[2].y = m_y[2] = y3; + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_stop; + + if(d != 0.0) + { + dilate_triangle(m_coord[0].x, m_coord[0].y, + m_coord[1].x, m_coord[1].y, + m_coord[2].x, m_coord[2].y, + m_x, m_y, d); + + calc_intersection(m_x[4], m_y[4], m_x[5], m_y[5], + m_x[0], m_y[0], m_x[1], m_y[1], + &m_coord[0].x, &m_coord[0].y); + + calc_intersection(m_x[0], m_y[0], m_x[1], m_y[1], + m_x[2], m_y[2], m_x[3], m_y[3], + &m_coord[1].x, &m_coord[1].y); + + calc_intersection(m_x[2], m_y[2], m_x[3], m_y[3], + m_x[4], m_y[4], m_x[5], m_y[5], + &m_coord[2].x, &m_coord[2].y); + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_line_to; + m_cmd[5] = path_cmd_line_to; + m_cmd[6] = path_cmd_stop; + } + } + + //-------------------------------------------------------------------- + // Vertex Source Interface to feed the coordinates to the rasterizer + void rewind(unsigned) + { + m_vertex = 0; + } + + //-------------------------------------------------------------------- + unsigned vertex(double* x, double* y) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + + protected: + //-------------------------------------------------------------------- + void arrange_vertices(coord_type* coord) const + { + coord[0] = m_coord[0]; + coord[1] = m_coord[1]; + coord[2] = m_coord[2]; + + if(m_coord[0].y > m_coord[2].y) + { + coord[0] = m_coord[2]; + coord[2] = m_coord[0]; + } + + coord_type tmp; + if(coord[0].y > coord[1].y) + { + tmp = coord[1]; + coord[1] = coord[0]; + coord[0] = tmp; + } + + if(coord[1].y > coord[2].y) + { + tmp = coord[2]; + coord[2] = coord[1]; + coord[1] = tmp; + } + } + + private: + //-------------------------------------------------------------------- + coord_type m_coord[3]; + double m_x[8]; + double m_y[8]; + unsigned m_cmd[8]; + unsigned m_vertex; + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_gray.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_gray.h new file mode 100644 index 00000000000..d5fc39d1023 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_gray.h @@ -0,0 +1,241 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_GOURAUD_GRAY_INCLUDED +#define AGG_SPAN_GOURAUD_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_gray + template class span_gouraud_gray : public span_gouraud + { + public: + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + typedef span_gouraud base_type; + typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; + + private: + //-------------------------------------------------------------------- + struct gray_calc + { + void init(const coord_type& c1, const coord_type& c2) + { + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (fabs(dy) < 1e-10) ? 1e10 : 1.0 / dy; + m_v1 = c1.color.v; + m_a1 = c1.color.a; + m_dv = c2.color.v - m_v1; + m_da = c2.color.a - m_a1; + } + + void calc(double y) + { + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_v = m_v1 + iround(m_dv * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); + } + + double m_x1; + double m_y1; + double m_dx; + double m_1dy; + int m_v1; + int m_a1; + int m_dv; + int m_da; + int m_v; + int m_a; + int m_x; + }; + + + public: + //-------------------------------------------------------------------- + span_gouraud_gray() {} + span_gouraud_gray(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d = 0) : + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + {} + + //-------------------------------------------------------------------- + void prepare() + { + coord_type coord[3]; + base_type::arrange_vertices(coord); + + m_y2 = int(coord[1].y); + + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; + + m_c1.init(coord[0], coord[2]); + m_c2.init(coord[0], coord[1]); + m_c3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_c1.calc(y); + const gray_calc* pc1 = &m_c1; + const gray_calc* pc2 = &m_c2; + + if(y < m_y2) + { + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_c2.calc(y + m_c2.m_1dy); + } + else + { + // Upper part (second subtriangle) + //------------------------- + m_c3.calc(y - m_c3.m_1dy); + pc2 = &m_c3; + } + + if(m_swap) + { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- + const gray_calc* t = pc2; + pc2 = pc1; + pc1 = t; + } + + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; + + dda_line_interpolator<14> v(pc1->m_v, pc2->m_v, nlen); + dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); + + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + v -= start; + a -= start; + nlen += start; + + int vv, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) + { + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; + } + + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) + { + span->v = (value_type)v.y(); + span->a = (value_type)a.y(); + v += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + ++span; + --len; + } + + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vv = v.y(); + va = a.y(); + if(vv < 0) vv = 0; if(vv > lim) vv = lim; + if(va < 0) va = 0; if(va > lim) va = lim; + span->v = (value_type)vv; + span->a = (value_type)va; + v += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } + + + private: + bool m_swap; + int m_y2; + gray_calc m_c1; + gray_calc m_c2; + gray_calc m_c3; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_rgba.h new file mode 100644 index 00000000000..1b285720297 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gouraud_rgba.h @@ -0,0 +1,277 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_GOURAUD_RGBA_INCLUDED +#define AGG_SPAN_GOURAUD_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_dda_line.h" +#include "agg_span_gouraud.h" + +namespace agg +{ + + //=======================================================span_gouraud_rgba + template class span_gouraud_rgba : public span_gouraud + { + public: + typedef ColorT color_type; + typedef typename ColorT::value_type value_type; + typedef span_gouraud base_type; + typedef typename base_type::coord_type coord_type; + enum subpixel_scale_e + { + subpixel_shift = 4, + subpixel_scale = 1 << subpixel_shift + }; + + private: + //-------------------------------------------------------------------- + struct rgba_calc + { + void init(const coord_type& c1, const coord_type& c2) + { + m_x1 = c1.x - 0.5; + m_y1 = c1.y - 0.5; + m_dx = c2.x - c1.x; + double dy = c2.y - c1.y; + m_1dy = (dy < 1e-5) ? 1e5 : 1.0 / dy; + m_r1 = c1.color.r; + m_g1 = c1.color.g; + m_b1 = c1.color.b; + m_a1 = c1.color.a; + m_dr = c2.color.r - m_r1; + m_dg = c2.color.g - m_g1; + m_db = c2.color.b - m_b1; + m_da = c2.color.a - m_a1; + } + + void calc(double y) + { + double k = (y - m_y1) * m_1dy; + if(k < 0.0) k = 0.0; + if(k > 1.0) k = 1.0; + m_r = m_r1 + iround(m_dr * k); + m_g = m_g1 + iround(m_dg * k); + m_b = m_b1 + iround(m_db * k); + m_a = m_a1 + iround(m_da * k); + m_x = iround((m_x1 + m_dx * k) * subpixel_scale); + } + + double m_x1; + double m_y1; + double m_dx; + double m_1dy; + int m_r1; + int m_g1; + int m_b1; + int m_a1; + int m_dr; + int m_dg; + int m_db; + int m_da; + int m_r; + int m_g; + int m_b; + int m_a; + int m_x; + }; + + public: + + //-------------------------------------------------------------------- + span_gouraud_rgba() {} + span_gouraud_rgba(const color_type& c1, + const color_type& c2, + const color_type& c3, + double x1, double y1, + double x2, double y2, + double x3, double y3, + double d = 0) : + base_type(c1, c2, c3, x1, y1, x2, y2, x3, y3, d) + {} + + //-------------------------------------------------------------------- + void prepare() + { + coord_type coord[3]; + base_type::arrange_vertices(coord); + + m_y2 = int(coord[1].y); + + m_swap = cross_product(coord[0].x, coord[0].y, + coord[2].x, coord[2].y, + coord[1].x, coord[1].y) < 0.0; + + m_rgba1.init(coord[0], coord[2]); + m_rgba2.init(coord[0], coord[1]); + m_rgba3.init(coord[1], coord[2]); + } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + m_rgba1.calc(y);//(m_rgba1.m_1dy > 2) ? m_rgba1.m_y1 : y); + const rgba_calc* pc1 = &m_rgba1; + const rgba_calc* pc2 = &m_rgba2; + + if(y <= m_y2) + { + // Bottom part of the triangle (first subtriangle) + //------------------------- + m_rgba2.calc(y + m_rgba2.m_1dy); + } + else + { + // Upper part (second subtriangle) + m_rgba3.calc(y - m_rgba3.m_1dy); + //------------------------- + pc2 = &m_rgba3; + } + + if(m_swap) + { + // It means that the triangle is oriented clockwise, + // so that we need to swap the controlling structures + //------------------------- + const rgba_calc* t = pc2; + pc2 = pc1; + pc1 = t; + } + + // Get the horizontal length with subpixel accuracy + // and protect it from division by zero + //------------------------- + int nlen = abs(pc2->m_x - pc1->m_x); + if(nlen <= 0) nlen = 1; + + dda_line_interpolator<14> r(pc1->m_r, pc2->m_r, nlen); + dda_line_interpolator<14> g(pc1->m_g, pc2->m_g, nlen); + dda_line_interpolator<14> b(pc1->m_b, pc2->m_b, nlen); + dda_line_interpolator<14> a(pc1->m_a, pc2->m_a, nlen); + + // Calculate the starting point of the gradient with subpixel + // accuracy and correct (roll back) the interpolators. + // This operation will also clip the beginning of the span + // if necessary. + //------------------------- + int start = pc1->m_x - (x << subpixel_shift); + r -= start; + g -= start; + b -= start; + a -= start; + nlen += start; + + int vr, vg, vb, va; + enum lim_e { lim = color_type::base_mask }; + + // Beginning part of the span. Since we rolled back the + // interpolators, the color values may have overflow. + // So that, we render the beginning part with checking + // for overflow. It lasts until "start" is positive; + // typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len && start > 0) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) { vr = 0; }; if(vr > lim) { vr = lim; }; + if(vg < 0) { vg = 0; }; if(vg > lim) { vg = lim; }; + if(vb < 0) { vb = 0; }; if(vb > lim) { vb = lim; }; + if(va < 0) { va = 0; }; if(va > lim) { va = lim; }; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + start -= subpixel_scale; + ++span; + --len; + } + + // Middle part, no checking for overflow. + // Actual spans can be longer than the calculated length + // because of anti-aliasing, thus, the interpolators can + // overflow. But while "nlen" is positive we are safe. + //------------------------- + while(len && nlen > 0) + { + span->r = (value_type)r.y(); + span->g = (value_type)g.y(); + span->b = (value_type)b.y(); + span->a = (value_type)a.y(); + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + nlen -= subpixel_scale; + ++span; + --len; + } + + // Ending part; checking for overflow. + // Typically it's 1-2 pixels, but may be more in some cases. + //------------------------- + while(len) + { + vr = r.y(); + vg = g.y(); + vb = b.y(); + va = a.y(); + if(vr < 0) { vr = 0; }; if(vr > lim) { vr = lim; }; + if(vg < 0) { vg = 0; }; if(vg > lim) { vg = lim; }; + if(vb < 0) { vb = 0; }; if(vb > lim) { vb = lim; }; + if(va < 0) { va = 0; }; if(va > lim) { va = lim; }; + span->r = (value_type)vr; + span->g = (value_type)vg; + span->b = (value_type)vb; + span->a = (value_type)va; + r += subpixel_scale; + g += subpixel_scale; + b += subpixel_scale; + a += subpixel_scale; + ++span; + --len; + } + } + + private: + bool m_swap; + int m_y2; + rgba_calc m_rgba1; + rgba_calc m_rgba2; + rgba_calc m_rgba3; + }; + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient.h new file mode 100644 index 00000000000..58b506dcfe6 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient.h @@ -0,0 +1,377 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_GRADIENT_INCLUDED +#define AGG_SPAN_GRADIENT_INCLUDED + +#include +#include +#include +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_array.h" + + +namespace agg +{ + + enum gradient_subpixel_scale_e + { + gradient_subpixel_shift = 4, //-----gradient_subpixel_shift + gradient_subpixel_scale = 1 << gradient_subpixel_shift, //-----gradient_subpixel_scale + gradient_subpixel_mask = gradient_subpixel_scale - 1 //-----gradient_subpixel_mask + }; + + + + //==========================================================span_gradient + template + class span_gradient + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - + gradient_subpixel_shift + }; + + //-------------------------------------------------------------------- + span_gradient() {} + + //-------------------------------------------------------------------- + span_gradient(interpolator_type& inter, + GradientF& gradient_function, + ColorF& color_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_color_function(&color_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const ColorF& color_function() const { return *m_color_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(GradientF& gf) { m_gradient_function = &gf; } + void color_function(ColorF& cf) { m_color_function = &cf; } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_color_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_color_function->size()) d = m_color_function->size() - 1; + *span++ = (*m_color_function)[d]; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + GradientF* m_gradient_function; + ColorF* m_color_function; + int m_d1; + int m_d2; + }; + + + + + //=====================================================gradient_linear_color + template + struct gradient_linear_color + { + typedef ColorT color_type; + + gradient_linear_color() {} + gradient_linear_color(const color_type& c1, const color_type& c2, + unsigned size = 256) : + m_c1(c1), m_c2(c2), m_size(size) + // VFALCO 4/28/09 + ,m_mult(1/(double(size)-1)) + // VFALCO + {} + + unsigned size() const { return m_size; } + color_type operator [] (unsigned v) const + { + // VFALCO 4/28/09 + //return m_c1.gradient(m_c2, double(v) / double(m_size - 1)); + return m_c1.gradient(m_c2, double(v) * m_mult ); + // VFALCO + } + + void colors(const color_type& c1, const color_type& c2, unsigned size = 256) + { + m_c1 = c1; + m_c2 = c2; + m_size = size; + // VFALCO 4/28/09 + m_mult=1/(double(size)-1); + // VFALCO + } + + color_type m_c1; + color_type m_c2; + unsigned m_size; + // VFALCO 4/28/09 + double m_mult; + // VFALCO + }; + + + + + + + //==========================================================gradient_circle + class gradient_circle + { + // Actually the same as radial. Just for compatibility + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + + //==========================================================gradient_radial + class gradient_radial + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return int(fast_sqrt(x*x + y*y)); + } + }; + + //========================================================gradient_radial_d + class gradient_radial_d + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return uround(sqrt(double(x)*double(x) + double(y)*double(y))); + } + }; + + //====================================================gradient_radial_focus + class gradient_radial_focus + { + public: + //--------------------------------------------------------------------- + gradient_radial_focus() : + m_r(100 * gradient_subpixel_scale), + m_fx(0), + m_fy(0) + { + update_values(); + } + + //--------------------------------------------------------------------- + gradient_radial_focus(double r, double fx, double fy) : + m_r (iround(r * gradient_subpixel_scale)), + m_fx(iround(fx * gradient_subpixel_scale)), + m_fy(iround(fy * gradient_subpixel_scale)) + { + update_values(); + } + + //--------------------------------------------------------------------- + void init(double r, double fx, double fy) + { + m_r = iround(r * gradient_subpixel_scale); + m_fx = iround(fx * gradient_subpixel_scale); + m_fy = iround(fy * gradient_subpixel_scale); + update_values(); + } + + //--------------------------------------------------------------------- + double radius() const { return double(m_r) / gradient_subpixel_scale; } + double focus_x() const { return double(m_fx) / gradient_subpixel_scale; } + double focus_y() const { return double(m_fy) / gradient_subpixel_scale; } + + //--------------------------------------------------------------------- + int calculate(int x, int y, int) const + { + double dx = x - m_fx; + double dy = y - m_fy; + double d2 = dx * m_fy - dy * m_fx; + double d3 = m_r2 * (dx * dx + dy * dy) - d2 * d2; + return iround((dx * m_fx + dy * m_fy + sqrt(fabs(d3))) * m_mul); + } + + private: + //--------------------------------------------------------------------- + void update_values() + { + // Calculate the invariant values. In case the focal center + // lies exactly on the gradient circle the divisor degenerates + // into zero. In this case we just move the focal center by + // one subpixel unit possibly in the direction to the origin (0,0) + // and calculate the values again. + //------------------------- + m_r2 = double(m_r) * double(m_r); + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + double d = (m_r2 - (m_fx2 + m_fy2)); + if(d == 0) + { + if(m_fx) { if(m_fx < 0) ++m_fx; else --m_fx; } + if(m_fy) { if(m_fy < 0) ++m_fy; else --m_fy; } + m_fx2 = double(m_fx) * double(m_fx); + m_fy2 = double(m_fy) * double(m_fy); + d = (m_r2 - (m_fx2 + m_fy2)); + } + m_mul = m_r / d; + } + + int m_r; + int m_fx; + int m_fy; + double m_r2; + double m_fx2; + double m_fy2; + double m_mul; + }; + + + //==============================================================gradient_x + class gradient_x + { + public: + static int calculate(int x, int, int) { return x; } + }; + + + //==============================================================gradient_y + class gradient_y + { + public: + static int calculate(int, int y, int) { return y; } + }; + + //========================================================gradient_diamond + class gradient_diamond + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + int ax = abs(x); + int ay = abs(y); + return ax > ay ? ax : ay; + } + }; + + //=============================================================gradient_xy + class gradient_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return abs(x) * abs(y) / d; + } + }; + + //========================================================gradient_sqrt_xy + class gradient_sqrt_xy + { + public: + static AGG_INLINE int calculate(int x, int y, int) + { + return fast_sqrt(abs(x) * abs(y)); + } + }; + + //==========================================================gradient_conic + class gradient_conic + { + public: + static AGG_INLINE int calculate(int x, int y, int d) + { + return uround(fabs(atan2(double(y), double(x))) * double(d) / pi); + } + }; + + //=================================================gradient_repeat_adaptor + template class gradient_repeat_adaptor + { + public: + gradient_repeat_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int ret = m_gradient->calculate(x, y, d) % d; + if(ret < 0) ret += d; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + //================================================gradient_reflect_adaptor + template class gradient_reflect_adaptor + { + public: + gradient_reflect_adaptor(const GradientF& gradient) : + m_gradient(&gradient) {} + + AGG_INLINE int calculate(int x, int y, int d) const + { + int d2 = d << 1; + int ret = m_gradient->calculate(x, y, d) % d2; + if(ret < 0) ret += d2; + if(ret >= d) ret = d2 - ret; + return ret; + } + + private: + const GradientF* m_gradient; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_alpha.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_alpha.h new file mode 100644 index 00000000000..2ec040e3b93 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_alpha.h @@ -0,0 +1,126 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_GRADIENT_ALPHA_INCLUDED +#define AGG_SPAN_GRADIENT_ALPHA_INCLUDED + +#include "agg_span_gradient.h" + +namespace agg +{ + //======================================================span_gradient_alpha + template + class span_gradient_alpha + { + public: + typedef Interpolator interpolator_type; + typedef ColorT color_type; + typedef typename color_type::value_type alpha_type; + + enum downscale_shift_e + { + downscale_shift = interpolator_type::subpixel_shift - gradient_subpixel_shift + }; + + + //-------------------------------------------------------------------- + span_gradient_alpha() {} + + //-------------------------------------------------------------------- + span_gradient_alpha(interpolator_type& inter, + GradientF& gradient_function, + AlphaF& alpha_function, + double d1, double d2) : + m_interpolator(&inter), + m_gradient_function(&gradient_function), + m_alpha_function(&alpha_function), + m_d1(iround(d1 * gradient_subpixel_scale)), + m_d2(iround(d2 * gradient_subpixel_scale)) + {} + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + const GradientF& gradient_function() const { return *m_gradient_function; } + const AlphaF& alpha_function() const { return *m_alpha_function; } + double d1() const { return double(m_d1) / gradient_subpixel_scale; } + double d2() const { return double(m_d2) / gradient_subpixel_scale; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& i) { m_interpolator = &i; } + void gradient_function(const GradientF& gf) { m_gradient_function = &gf; } + void alpha_function(const AlphaF& af) { m_alpha_function = ⁡ } + void d1(double v) { m_d1 = iround(v * gradient_subpixel_scale); } + void d2(double v) { m_d2 = iround(v * gradient_subpixel_scale); } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + int dd = m_d2 - m_d1; + if(dd < 1) dd = 1; + m_interpolator->begin(x+0.5, y+0.5, len); + do + { + m_interpolator->coordinates(&x, &y); + int d = m_gradient_function->calculate(x >> downscale_shift, + y >> downscale_shift, m_d2); + d = ((d - m_d1) * (int)m_alpha_function->size()) / dd; + if(d < 0) d = 0; + if(d >= (int)m_alpha_function->size()) d = m_alpha_function->size() - 1; + span->a = (*m_alpha_function)[d]; + ++span; + ++(*m_interpolator); + } + while(--len); + } + + private: + interpolator_type* m_interpolator; + GradientF* m_gradient_function; + AlphaF* m_alpha_function; + int m_d1; + int m_d2; + }; + + + //=======================================================gradient_alpha_x + template struct gradient_alpha_x + { + typedef typename ColorT::value_type alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //====================================================gradient_alpha_x_u8 + struct gradient_alpha_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return x; } + }; + + //==========================================gradient_alpha_one_munus_x_u8 + struct gradient_alpha_one_munus_x_u8 + { + typedef int8u alpha_type; + alpha_type operator [] (alpha_type x) const { return 255-x; } + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_contour.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_contour.h new file mode 100644 index 00000000000..899bb799b6c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_contour.h @@ -0,0 +1,362 @@ +//---------------------------------------------------------------------------- +// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1) +// http://milan.marusinec.sk/aggcp +// +// For Anti-Grain Geometry - Version 2.4 +// http://www.antigrain.org +// +// Contribution Created By: +// Milan Marusinec alias Milano +// milan@marusinec.sk +// Copyright (c) 2007-2008 +// +// 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. +// +// [History] ----------------------------------------------------------------- +// +// 02.02.2008-Milano: Ported from Object Pascal code of AggPas +// +#ifndef AGG_SPAN_GRADIENT_CONTOUR_INCLUDED +#define AGG_SPAN_GRADIENT_CONTOUR_INCLUDED + +#include "agg_basics.h" +#include "agg_trans_affine.h" +#include "agg_path_storage.h" +#include "agg_pixfmt_gray.h" +#include "agg_conv_transform.h" +#include "agg_conv_curve.h" +#include "agg_bounding_rect.h" +#include "agg_renderer_base.h" +#include "agg_renderer_primitives.h" +#include "agg_rasterizer_outline.h" +#include "agg_span_gradient.h" + +#define infinity 1E20 + +namespace agg +{ + + //==========================================================gradient_contour + class gradient_contour + { + private: + int8u* m_buffer; + int m_width; + int m_height; + int m_frame; + + double m_d1; + double m_d2; + + public: + gradient_contour() : + m_buffer(NULL), + m_width(0), + m_height(0), + m_frame(10), + m_d1(0), + m_d2(100) + { + } + + gradient_contour(double d1, double d2) : + m_buffer(NULL), + m_width(0), + m_height(0), + m_frame(10), + m_d1(d1), + m_d2(d2) + { + } + + ~gradient_contour() + { + if (m_buffer) + { + delete [] m_buffer; + } + } + + int8u* contour_create(path_storage* ps ); + + int contour_width() { return m_width; } + int contour_height() { return m_height; } + + void d1(double d ) { m_d1 = d; } + void d2(double d ) { m_d2 = d; } + + void frame(int f ) { m_frame = f; } + int frame() { return m_frame; } + + int calculate(int x, int y, int d) const + { + if (m_buffer) + { + int px = x >> agg::gradient_subpixel_shift; + int py = y >> agg::gradient_subpixel_shift; + + px %= m_width; + + if (px < 0) + { + px += m_width; + } + + py %= m_height; + + if (py < 0 ) + { + py += m_height; + } + + return iround(m_buffer[py * m_width + px ] * (m_d2 / 256 ) + m_d1 ) << gradient_subpixel_shift; + + } + else + { + return 0; + } + } + + }; + + static AGG_INLINE int square(int x ) { return x * x; } + + // DT algorithm by: Pedro Felzenszwalb + void dt(float* spanf, float* spang, float* spanr, int* spann ,int length ) + { + int k = 0; + float s; + + spann[0 ] = 0; + spang[0 ] = float(-infinity ); + spang[1 ] = float(+infinity ); + + for (int q = 1; q <= length - 1; q++) + { + s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] ); + + while (s <= spang[k ]) + { + k--; + s = ((spanf[q ] + square(q ) ) - (spanf[spann[k ] ] + square(spann[k ] ) ) ) / (2 * q - 2 * spann[k ] ); + } + + k++; + spann[k ] = q; + spang[k ] = s; + spang[k + 1 ] = float(+infinity); + + } + + k = 0; + + for (int q = 0; q <= length - 1; q++) + { + while (spang[k + 1 ] < q ) + { + k++; + } + + spanr[q ] = square(q - spann[k ] ) + spanf[spann[k ] ]; + } + } + + // DT algorithm by: Pedro Felzenszwalb + int8u* gradient_contour::contour_create(path_storage* ps ) + { + int8u* result = NULL; + + if (ps) + { + // I. Render Black And White NonAA Stroke of the Path + // Path Bounding Box + Some Frame Space Around [configurable] + agg::conv_curve conv(*ps); + + double x1, y1, x2, y2; + + if (agg::bounding_rect_single(conv ,0 ,&x1 ,&y1 ,&x2 ,&y2 )) + { + // Create BW Rendering Surface + int width = int(ceil(x2 - x1 ) ) + m_frame * 2 + 1; + int height = int(ceil(y2 - y1 ) ) + m_frame * 2 + 1; + + int8u* buffer = new int8u[width * height]; + + if (buffer) + { + memset(buffer ,255 ,width * height ); + + // Setup VG Engine & Render + agg::rendering_buffer rb; + rb.attach(buffer ,width ,height ,width ); + + agg::pixfmt_gray8 pf(rb); + agg::renderer_base renb(pf ); + + agg::renderer_primitives > prim(renb ); + agg::rasterizer_outline > > ras(prim ); + + agg::trans_affine mtx; + mtx *= agg::trans_affine_translation(-x1 + m_frame, -y1 + m_frame ); + + agg::conv_transform > trans(conv ,mtx ); + + prim.line_color(agg::rgba8(0 ,0 ,0 ,255 ) ); + ras.add_path(trans ); + + // II. Distance Transform + // Create Float Buffer + 0 vs. infinity (1e20) assignment + float* image = new float[width * height]; + + if (image) + { + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++, l++ ) + { + if (buffer[l ] == 0) + { + image[l ] = 0.0; + } + else + { + image[l ] = float(infinity ); + } + } + + } + + // DT of 2d + // SubBuff max width,height + int length = width; + + if (height > length) + { + length = height; + } + + float* spanf = new float[length]; + float* spang = new float[length + 1]; + float* spanr = new float[length]; + int* spann = new int[length]; + + if ((spanf) && (spang) && (spanr) && (spann)) + { + // Transform along columns + for (int x = 0; x < width; x++ ) + { + for (int y = 0; y < height; y++ ) + { + spanf[y] = image[y * width + x]; + } + + // DT of 1d + dt(spanf ,spang ,spanr ,spann ,height ); + + for (int y = 0; y < height; y++ ) + { + image[y * width + x] = spanr[y]; + } + } + + // Transform along rows + for (int y = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++ ) + { + spanf[x] = image[y * width + x]; + } + + // DT of 1d + dt(spanf ,spang ,spanr ,spann ,width ); + + for (int x = 0; x < width; x++ ) + { + image[y * width + x] = spanr[x]; + } + } + + // Take Square Roots, Min & Max + float min = sqrt(image[0] ); + float max = min; + + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++, l++ ) + { + image[l] = sqrt(image[l]); + + if (min > image[l]) + { + min = image[l]; + } + + if (max < image[l]) + { + max = image[l]; + } + + } + } + + // III. Convert To Grayscale + if (min == max) + { + memset(buffer ,0 ,width * height ); + } + else + { + float scale = 255 / (max - min ); + + for (int y = 0, l = 0; y < height; y++ ) + { + for (int x = 0; x < width; x++ ,l++ ) + { + buffer[l] = int8u(int((image[l] - min ) * scale )); + } + } + } + + // OK + if (m_buffer) + { + delete [] m_buffer; + } + + m_buffer = buffer; + m_width = width; + m_height = height; + + buffer = NULL; + result = m_buffer; + + } + + if (spanf) { delete [] spanf; } + if (spang) { delete [] spang; } + if (spanr) { delete [] spanr; } + if (spann) { delete [] spann; } + + delete [] image; + + } + } + + if (buffer) + { + delete [] buffer; + } + + } + + } + return result; + } + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_image.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_image.h new file mode 100644 index 00000000000..c99eaca166b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_gradient_image.h @@ -0,0 +1,188 @@ +//---------------------------------------------------------------------------- +// AGG Contribution Pack - Gradients 1 (AGG CP - Gradients 1) +// http://milan.marusinec.sk/aggcp +// +// For Anti-Grain Geometry - Version 2.4 +// http://www.antigrain.org +// +// Contribution Created By: +// Milan Marusinec alias Milano +// milan@marusinec.sk +// Copyright (c) 2007-2008 +// +// 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. +// +// [History] ----------------------------------------------------------------- +// +// 03.02.2008-Milano: Ported from Object Pascal code of AggPas +// +#ifndef AGG_SPAN_GRADIENT_IMAGE_INCLUDED +#define AGG_SPAN_GRADIENT_IMAGE_INCLUDED + +#include "agg_basics.h" +#include "agg_span_gradient.h" +#include "agg_color_rgba.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" + +namespace agg +{ + + //==========================================================one_color_function + template class one_color_function + { + public: + typedef ColorT color_type; + + color_type m_color; + + one_color_function() : + m_color() + { + } + + static unsigned size() { return 1; } + + const color_type& operator [] (unsigned i) const + { + return m_color; + } + + color_type* operator [] (unsigned i) + { + return &m_color; + } + }; + + //==========================================================gradient_image + template class gradient_image + { + private: + //------------ fields + typedef ColorT color_type; + typedef agg::pixfmt_rgba32 pixfmt_type; + + agg::rgba8* m_buffer; + + int m_alocdx; + int m_alocdy; + int m_width; + int m_height; + + color_type* m_color; + + one_color_function m_color_function; + + public: + gradient_image() : + m_color_function(), + m_buffer(NULL), + m_alocdx(0), + m_alocdy(0), + m_width(0), + m_height(0) + { + m_color = m_color_function[0 ]; + } + + ~gradient_image() + { + if (m_buffer) { delete [] m_buffer; } + } + + void* image_create(int width, int height ) + { + void* result = NULL; + + if (width > m_alocdx || height > m_alocdy) + { + if (m_buffer) { delete [] m_buffer; } + + m_buffer = NULL; + m_buffer = new agg::rgba8[width * height]; + + if (m_buffer) + { + m_alocdx = width; + m_alocdy = height; + } + else + { + m_alocdx = 0; + m_alocdy = 0; + }; + }; + + if (m_buffer) + { + m_width = width; + m_height = height; + + for (int rows = 0; rows < height; rows++) + { + agg::rgba8* row = &m_buffer[rows * m_alocdx ]; + memset(row ,0 ,m_width * 4 ); + }; + + result = m_buffer; + }; + return result; + } + + void* image_buffer() { return m_buffer; } + int image_width() { return m_width; } + int image_height() { return m_height; } + int image_stride() { return m_alocdx * 4; } + + int calculate(int x, int y, int d) const + { + if (m_buffer) + { + int px = x >> agg::gradient_subpixel_shift; + int py = y >> agg::gradient_subpixel_shift; + + px %= m_width; + + if (px < 0) + { + px += m_width; + } + + py %= m_height; + + if (py < 0 ) + { + py += m_height; + } + + rgba8* pixel = &m_buffer[py * m_alocdx + px ]; + + m_color->r = pixel->r; + m_color->g = pixel->g; + m_color->b = pixel->b; + m_color->a = pixel->a; + + } + else + { + m_color->r = 0; + m_color->g = 0; + m_color->b = 0; + m_color->a = 0; + } + return 0; + } + + const one_color_function& color_function() const + { + return m_color_function; + } + + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter.h new file mode 100644 index 00000000000..2f613e5d86c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter.h @@ -0,0 +1,246 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Image transformations with filtering. Span generator base class +// +//---------------------------------------------------------------------------- +#ifndef AGG_SPAN_IMAGE_FILTER_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_INCLUDED + +#include "agg_basics.h" +#include "agg_image_filters.h" +#include "agg_span_interpolator_linear.h" + +namespace agg +{ + + //-------------------------------------------------------span_image_filter + template class span_image_filter + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + + //-------------------------------------------------------------------- + span_image_filter() {} + span_image_filter(source_type& src, + interpolator_type& interpolator, + image_filter_lut* filter) : + m_src(&src), + m_interpolator(&interpolator), + m_filter(filter), + m_dx_dbl(0.5), + m_dy_dbl(0.5), + m_dx_int(image_subpixel_scale / 2), + m_dy_int(image_subpixel_scale / 2) + {} + void attach(source_type& v) { m_src = &v; } + + //-------------------------------------------------------------------- + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + const image_filter_lut& filter() const { return *m_filter; } + int filter_dx_int() const { return m_dx_int; } + int filter_dy_int() const { return m_dy_int; } + double filter_dx_dbl() const { return m_dx_dbl; } + double filter_dy_dbl() const { return m_dy_dbl; } + + //-------------------------------------------------------------------- + void interpolator(interpolator_type& v) { m_interpolator = &v; } + void filter(image_filter_lut& v) { m_filter = &v; } + void filter_offset(double dx, double dy) + { + m_dx_dbl = dx; + m_dy_dbl = dy; + m_dx_int = iround(dx * image_subpixel_scale); + m_dy_int = iround(dy * image_subpixel_scale); + } + void filter_offset(double d) { filter_offset(d, d); } + + //-------------------------------------------------------------------- + interpolator_type& interpolator() { return *m_interpolator; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + private: + source_type* m_src; + interpolator_type* m_interpolator; + image_filter_lut* m_filter; + double m_dx_dbl; + double m_dy_dbl; + unsigned m_dx_int; + unsigned m_dy_int; + }; + + + + + //==============================================span_image_resample_affine + template + class span_image_resample_affine : + public span_image_filter > + { + public: + typedef Source source_type; + typedef span_interpolator_linear interpolator_type; + typedef span_image_filter base_type; + + //-------------------------------------------------------------------- + span_image_resample_affine() : + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + //-------------------------------------------------------------------- + span_image_resample_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(200.0), + m_blur_x(1.0), + m_blur_y(1.0) + {} + + + //-------------------------------------------------------------------- + int scale_limit() const { return uround(m_scale_limit); } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return m_blur_x; } + double blur_y() const { return m_blur_y; } + void blur_x(double v) { m_blur_x = v; } + void blur_y(double v) { m_blur_y = v; } + void blur(double v) { m_blur_x = m_blur_y = v; } + + //-------------------------------------------------------------------- + void prepare() + { + double scale_x; + double scale_y; + + base_type::interpolator().transformer().scaling_abs(&scale_x, &scale_y); + + if(scale_x * scale_y > m_scale_limit) + { + scale_x = scale_x * m_scale_limit / (scale_x * scale_y); + scale_y = scale_y * m_scale_limit / (scale_x * scale_y); + } + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + if(scale_x > m_scale_limit) scale_x = m_scale_limit; + if(scale_y > m_scale_limit) scale_y = m_scale_limit; + + scale_x *= m_blur_x; + scale_y *= m_blur_y; + + if(scale_x < 1) scale_x = 1; + if(scale_y < 1) scale_y = 1; + + m_rx = uround( scale_x * double(image_subpixel_scale)); + m_rx_inv = uround(1.0/scale_x * double(image_subpixel_scale)); + + m_ry = uround( scale_y * double(image_subpixel_scale)); + m_ry_inv = uround(1.0/scale_y * double(image_subpixel_scale)); + } + + protected: + int m_rx; + int m_ry; + int m_rx_inv; + int m_ry_inv; + + private: + double m_scale_limit; + double m_blur_x; + double m_blur_y; + }; + + + + //=====================================================span_image_resample + template + class span_image_resample : + public span_image_filter + { + public: + typedef Source source_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + + //-------------------------------------------------------------------- + span_image_resample() : + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + span_image_resample(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter), + m_scale_limit(20), + m_blur_x(image_subpixel_scale), + m_blur_y(image_subpixel_scale) + {} + + //-------------------------------------------------------------------- + int scale_limit() const { return m_scale_limit; } + void scale_limit(int v) { m_scale_limit = v; } + + //-------------------------------------------------------------------- + double blur_x() const { return double(m_blur_x) / double(image_subpixel_scale); } + double blur_y() const { return double(m_blur_y) / double(image_subpixel_scale); } + void blur_x(double v) { m_blur_x = uround(v * double(image_subpixel_scale)); } + void blur_y(double v) { m_blur_y = uround(v * double(image_subpixel_scale)); } + void blur(double v) { m_blur_x = + m_blur_y = uround(v * double(image_subpixel_scale)); } + + protected: + AGG_INLINE void adjust_scale(int* rx, int* ry) + { + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + if(*rx > image_subpixel_scale * m_scale_limit) + { + *rx = image_subpixel_scale * m_scale_limit; + } + if(*ry > image_subpixel_scale * m_scale_limit) + { + *ry = image_subpixel_scale * m_scale_limit; + } + *rx = (*rx * m_blur_x) >> image_subpixel_shift; + *ry = (*ry * m_blur_y) >> image_subpixel_shift; + if(*rx < image_subpixel_scale) *rx = image_subpixel_scale; + if(*ry < image_subpixel_scale) *ry = image_subpixel_scale; + } + + int m_scale_limit; + int m_blur_x; + int m_blur_y; + }; + + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_gray.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_gray.h new file mode 100644 index 00000000000..e2c688e004c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_gray.h @@ -0,0 +1,723 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_IMAGE_FILTER_GRAY_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_GRAY_INCLUDED + +#include "agg_basics.h" +#include "agg_color_gray.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_gray_nn + template + class span_image_filter_gray_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_nn() {} + span_image_filter_gray_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + span->v = *(const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=========================================span_image_filter_gray_bilinear + template + class span_image_filter_gray_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear() {} + span_image_filter_gray_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * (image_subpixel_scale - y_hr); + + fg_ptr = (const value_type*)base_type::source().next_y(); + fg += *fg_ptr * (image_subpixel_scale - x_hr) * y_hr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + fg += *fg_ptr * x_hr * y_hr; + + span->v = color_type::downshift(fg, image_subpixel_shift * 2); + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_gray_bilinear_clip + template + class span_image_filter_gray_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_bilinear_clip() {} + span_image_filter_gray_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + long_type src_alpha; + value_type back_v = m_back_color.v; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * (image_subpixel_scale - y_hr); + fg += *fg_ptr++ * (image_subpixel_scale - y_hr) * x_hr; + + ++y_lr; + fg_ptr = (const value_type*)base_type::source().row_ptr(y_lr) + x_lr; + + fg += *fg_ptr++ * (image_subpixel_scale - x_hr) * y_hr; + fg += *fg_ptr++ * x_hr * y_hr; + + fg = color_type::downshift(fg, image_subpixel_shift * 2); + src_alpha = color_type::full_value(); + } + else + { + unsigned weight; + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg = back_v; + src_alpha = back_a; + } + else + { + fg = src_alpha = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg += weight * + *((const value_type*)base_type::source().row_ptr(y_lr) + x_lr); + src_alpha += weight * color_type::full_value(); + } + else + { + fg += back_v * weight; + src_alpha += back_a * weight; + } + + fg = color_type::downshift(fg, image_subpixel_shift * 2); + src_alpha = color_type::downshift(src_alpha, image_subpixel_shift * 2); + } + } + + span->v = (value_type)fg; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //==============================================span_image_filter_gray_2x2 + template + class span_image_filter_gray_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray_2x2() {} + span_image_filter_gray_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg += weight * *fg_ptr; + + fg >>= image_filter_shift; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==================================================span_image_filter_gray + template + class span_image_filter_gray : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_gray() {} + span_image_filter_gray(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + fg += *fg_ptr * + ((weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift); + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg = color_type::downshift(fg, image_filter_shift); + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_resample_gray_affine + template + class span_image_resample_gray_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray_affine() {} + span_image_resample_gray_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //================================================span_image_resample_gray + template + class span_image_resample_gray : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_gray() {} + span_image_resample_gray(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg /= total_weight; + if(fg < 0) fg = 0; + if(fg > color_type::full_value()) fg = color_type::full_value(); + + span->v = (value_type)fg; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgb.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgb.h new file mode 100644 index 00000000000..f78ae19c1b4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgb.h @@ -0,0 +1,861 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_IMAGE_FILTER_RGB_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGB_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //===============================================span_image_filter_rgb_nn + template + class span_image_filter_rgb_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_nn() {} + span_image_filter_rgb_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = color_type::full_value(); + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_filter_rgb_bilinear + template + class span_image_filter_rgb_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear() {} + span_image_filter_rgb_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + const value_type *fg_ptr; + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + span->r = color_type::downshift(fg[order_type::R], image_subpixel_shift * 2); + span->g = color_type::downshift(fg[order_type::G], image_subpixel_shift * 2); + span->b = color_type::downshift(fg[order_type::B], image_subpixel_shift * 2); + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=====================================span_image_filter_rgb_bilinear_clip + template + class span_image_filter_rgb_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_bilinear_clip() {} + span_image_filter_rgb_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + long_type src_alpha; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + src_alpha = color_type::full_value(); + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + src_alpha = back_a; + } + else + { + fg[0] = fg[1] = fg[2] = src_alpha = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + x_lr + x_lr + x_lr; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + src_alpha += weight * color_type::full_value(); + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + src_alpha += back_a * weight; + } + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + src_alpha = color_type::downshift(src_alpha, image_subpixel_shift * 2); + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)src_alpha; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + + //===============================================span_image_filter_rgb_2x2 + template + class span_image_filter_rgb_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb_2x2() {} + span_image_filter_rgb_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //===================================================span_image_filter_rgb + template + class span_image_filter_rgb : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgb() {} + span_image_filter_rgb(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==========================================span_image_resample_rgb_affine + template + class span_image_resample_rgb_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb_affine() {} + span_image_resample_rgb_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //=================================================span_image_resample_rgb + template + class span_image_resample_rgb : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgb() {} + span_image_resample_rgb(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[3]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + + if(fg[order_type::R] > color_type::full_value()) fg[order_type::R] = color_type::full_value(); + if(fg[order_type::G] > color_type::full_value()) fg[order_type::G] = color_type::full_value(); + if(fg[order_type::B] > color_type::full_value()) fg[order_type::B] = color_type::full_value(); + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = color_type::full_value(); + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgba.h new file mode 100644 index 00000000000..af7a1a2ef0d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_image_filter_rgba.h @@ -0,0 +1,890 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_IMAGE_FILTER_RGBA_INCLUDED +#define AGG_SPAN_IMAGE_FILTER_RGBA_INCLUDED + +#include "agg_basics.h" +#include "agg_color_rgba.h" +#include "agg_span_image_filter.h" + + +namespace agg +{ + + //==============================================span_image_filter_rgba_nn + template + class span_image_filter_rgba_nn : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_nn() {} + span_image_filter_rgba_nn(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + do + { + base_type::interpolator().coordinates(&x, &y); + const value_type* fg_ptr = (const value_type*) + base_type::source().span(x >> image_subpixel_shift, + y >> image_subpixel_shift, + 1); + span->r = fg_ptr[order_type::R]; + span->g = fg_ptr[order_type::G]; + span->b = fg_ptr[order_type::B]; + span->a = fg_ptr[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //=========================================span_image_filter_rgba_bilinear + template + class span_image_filter_rgba_bilinear : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear() {} + span_image_filter_rgba_bilinear(source_type& src, + interpolator_type& inter) : + base_type(src, inter, 0) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + const value_type *fg_ptr; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + fg[0] = + fg[1] = + fg[2] = + fg[3] = image_subpixel_scale * image_subpixel_scale / 2; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + span->r = value_type(color_type::downshift(fg[order_type::R], image_subpixel_shift * 2)); + span->g = value_type(color_type::downshift(fg[order_type::G], image_subpixel_shift * 2)); + span->b = value_type(color_type::downshift(fg[order_type::B], image_subpixel_shift * 2)); + span->a = value_type(color_type::downshift(fg[order_type::A], image_subpixel_shift * 2)); + + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + //====================================span_image_filter_rgba_bilinear_clip + template + class span_image_filter_rgba_bilinear_clip : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_bilinear_clip() {} + span_image_filter_rgba_bilinear_clip(source_type& src, + const color_type& back_color, + interpolator_type& inter) : + base_type(src, inter, 0), + m_back_color(back_color) + {} + const color_type& background_color() const { return m_back_color; } + void background_color(const color_type& v) { m_back_color = v; } + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + value_type back_r = m_back_color.r; + value_type back_g = m_back_color.g; + value_type back_b = m_back_color.b; + value_type back_a = m_back_color.a; + + const value_type *fg_ptr; + int maxx = base_type::source().width() - 1; + int maxy = base_type::source().height() - 1; + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + + if(x_lr >= 0 && y_lr >= 0 && + x_lr < maxx && y_lr < maxy) + { + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + ++y_lr; + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + weight = (image_subpixel_scale - x_hr) * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + weight = x_hr * y_hr; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + fg[3] = color_type::downshift(fg[3], image_subpixel_shift * 2); + } + else + { + if(x_lr < -1 || y_lr < -1 || + x_lr > maxx || y_lr > maxy) + { + fg[order_type::R] = back_r; + fg[order_type::G] = back_g; + fg[order_type::B] = back_b; + fg[order_type::A] = back_a; + } + else + { + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + weight = (image_subpixel_scale - x_hr) * + (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * (image_subpixel_scale - y_hr); + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr--; + y_lr++; + + weight = (image_subpixel_scale - x_hr) * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + x_lr++; + + weight = x_hr * y_hr; + if(x_lr >= 0 && y_lr >= 0 && + x_lr <= maxx && y_lr <= maxy) + { + fg_ptr = (const value_type*) + base_type::source().row_ptr(y_lr) + (x_lr << 2); + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr++; + } + else + { + fg[order_type::R] += back_r * weight; + fg[order_type::G] += back_g * weight; + fg[order_type::B] += back_b * weight; + fg[order_type::A] += back_a * weight; + } + + fg[0] = color_type::downshift(fg[0], image_subpixel_shift * 2); + fg[1] = color_type::downshift(fg[1], image_subpixel_shift * 2); + fg[2] = color_type::downshift(fg[2], image_subpixel_shift * 2); + fg[3] = color_type::downshift(fg[3], image_subpixel_shift * 2); + } + } + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + private: + color_type m_back_color; + }; + + + //==============================================span_image_filter_rgba_2x2 + template + class span_image_filter_rgba_2x2 : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba_2x2() {} + span_image_filter_rgba_2x2(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + const value_type *fg_ptr; + const int16* weight_array = base_type::filter().weight_array() + + ((base_type::filter().diameter()/2 - 1) << + image_subpixel_shift); + + do + { + int x_hr; + int y_hr; + + base_type::interpolator().coordinates(&x_hr, &y_hr); + + x_hr -= base_type::filter_dx_int(); + y_hr -= base_type::filter_dy_int(); + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + unsigned weight; + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + x_hr &= image_subpixel_mask; + y_hr &= image_subpixel_mask; + + fg_ptr = (const value_type*)base_type::source().span(x_lr, y_lr, 2); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr + image_subpixel_scale] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_y(); + weight = (weight_array[x_hr + image_subpixel_scale] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg_ptr = (const value_type*)base_type::source().next_x(); + weight = (weight_array[x_hr] * + weight_array[y_hr] + + image_filter_scale / 2) >> + image_filter_shift; + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + fg[3] = color_type::downshift(fg[3], image_filter_shift); + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //==================================================span_image_filter_rgba + template + class span_image_filter_rgba : + public span_image_filter + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_filter base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + + //-------------------------------------------------------------------- + span_image_filter_rgba() {} + span_image_filter_rgba(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, &filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + const value_type *fg_ptr; + + unsigned diameter = base_type::filter().diameter(); + int start = base_type::filter().start(); + const int16* weight_array = base_type::filter().weight_array(); + + int x_count; + int weight_y; + + do + { + base_type::interpolator().coordinates(&x, &y); + + x -= base_type::filter_dx_int(); + y -= base_type::filter_dy_int(); + + int x_hr = x; + int y_hr = y; + + int x_lr = x_hr >> image_subpixel_shift; + int y_lr = y_hr >> image_subpixel_shift; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int x_fract = x_hr & image_subpixel_mask; + unsigned y_count = diameter; + + y_hr = image_subpixel_mask - (y_hr & image_subpixel_mask); + fg_ptr = (const value_type*)base_type::source().span(x_lr + start, + y_lr + start, + diameter); + for(;;) + { + x_count = diameter; + weight_y = weight_array[y_hr]; + x_hr = image_subpixel_mask - x_fract; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + image_filter_shift; + + fg[0] += weight * *fg_ptr++; + fg[1] += weight * *fg_ptr++; + fg[2] += weight * *fg_ptr++; + fg[3] += weight * *fg_ptr; + + if(--x_count == 0) break; + x_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + + if(--y_count == 0) break; + y_hr += image_subpixel_scale; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] = color_type::downshift(fg[0], image_filter_shift); + fg[1] = color_type::downshift(fg[1], image_filter_shift); + fg[2] = color_type::downshift(fg[2], image_filter_shift); + fg[3] = color_type::downshift(fg[3], image_filter_shift); + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + ++span; + ++base_type::interpolator(); + + } while(--len); + } + }; + + + + //========================================span_image_resample_rgba_affine + template + class span_image_resample_rgba_affine : + public span_image_resample_affine + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef span_image_resample_affine base_type; + typedef typename base_type::interpolator_type interpolator_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba_affine() {} + span_image_resample_rgba_affine(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + int radius_x = (diameter * base_type::m_rx) >> 1; + int radius_y = (diameter * base_type::m_ry) >> 1; + int len_x_lr = + (diameter * base_type::m_rx + image_subpixel_mask) >> + image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + + do + { + base_type::interpolator().coordinates(&x, &y); + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + base_type::m_ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + base_type::m_rx_inv) >> + image_subpixel_shift; + + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += base_type::m_rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += base_type::m_ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::A]) fg[order_type::R] = fg[order_type::A]; + if(fg[order_type::G] > fg[order_type::A]) fg[order_type::G] = fg[order_type::A]; + if(fg[order_type::B] > fg[order_type::A]) fg[order_type::B] = fg[order_type::A]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + + + //==============================================span_image_resample_rgba + template + class span_image_resample_rgba : + public span_image_resample + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef Interpolator interpolator_type; + typedef span_image_resample base_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + downscale_shift = image_filter_shift + }; + + //-------------------------------------------------------------------- + span_image_resample_rgba() {} + span_image_resample_rgba(source_type& src, + interpolator_type& inter, + image_filter_lut& filter) : + base_type(src, inter, filter) + {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + base_type::interpolator().begin(x + base_type::filter_dx_dbl(), + y + base_type::filter_dy_dbl(), len); + long_type fg[4]; + + int diameter = base_type::filter().diameter(); + int filter_scale = diameter << image_subpixel_shift; + + const int16* weight_array = base_type::filter().weight_array(); + do + { + int rx; + int ry; + int rx_inv = image_subpixel_scale; + int ry_inv = image_subpixel_scale; + base_type::interpolator().coordinates(&x, &y); + base_type::interpolator().local_scale(&rx, &ry); + base_type::adjust_scale(&rx, &ry); + + rx_inv = image_subpixel_scale * image_subpixel_scale / rx; + ry_inv = image_subpixel_scale * image_subpixel_scale / ry; + + int radius_x = (diameter * rx) >> 1; + int radius_y = (diameter * ry) >> 1; + int len_x_lr = + (diameter * rx + image_subpixel_mask) >> + image_subpixel_shift; + + x += base_type::filter_dx_int() - radius_x; + y += base_type::filter_dy_int() - radius_y; + + fg[0] = fg[1] = fg[2] = fg[3] = 0; + + int y_lr = y >> image_subpixel_shift; + int y_hr = ((image_subpixel_mask - (y & image_subpixel_mask)) * + ry_inv) >> + image_subpixel_shift; + int total_weight = 0; + int x_lr = x >> image_subpixel_shift; + int x_hr = ((image_subpixel_mask - (x & image_subpixel_mask)) * + rx_inv) >> + image_subpixel_shift; + int x_hr2 = x_hr; + const value_type* fg_ptr = + (const value_type*)base_type::source().span(x_lr, y_lr, len_x_lr); + + for(;;) + { + int weight_y = weight_array[y_hr]; + x_hr = x_hr2; + for(;;) + { + int weight = (weight_y * weight_array[x_hr] + + image_filter_scale / 2) >> + downscale_shift; + fg[0] += *fg_ptr++ * weight; + fg[1] += *fg_ptr++ * weight; + fg[2] += *fg_ptr++ * weight; + fg[3] += *fg_ptr++ * weight; + total_weight += weight; + x_hr += rx_inv; + if(x_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_x(); + } + y_hr += ry_inv; + if(y_hr >= filter_scale) break; + fg_ptr = (const value_type*)base_type::source().next_y(); + } + + fg[0] /= total_weight; + fg[1] /= total_weight; + fg[2] /= total_weight; + fg[3] /= total_weight; + + if(fg[0] < 0) fg[0] = 0; + if(fg[1] < 0) fg[1] = 0; + if(fg[2] < 0) fg[2] = 0; + if(fg[3] < 0) fg[3] = 0; + + if(fg[order_type::A] > color_type::full_value()) fg[order_type::A] = color_type::full_value(); + if(fg[order_type::R] > fg[order_type::R]) fg[order_type::R] = fg[order_type::R]; + if(fg[order_type::G] > fg[order_type::G]) fg[order_type::G] = fg[order_type::G]; + if(fg[order_type::B] > fg[order_type::B]) fg[order_type::B] = fg[order_type::B]; + + span->r = (value_type)fg[order_type::R]; + span->g = (value_type)fg[order_type::G]; + span->b = (value_type)fg[order_type::B]; + span->a = (value_type)fg[order_type::A]; + + ++span; + ++base_type::interpolator(); + } while(--len); + } + }; + + +} + + +#endif + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_adaptor.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_adaptor.h new file mode 100644 index 00000000000..0fdfa774796 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_adaptor.h @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //===============================================span_interpolator_adaptor + template + class span_interpolator_adaptor : public Interpolator + { + public: + typedef Interpolator base_type; + typedef typename base_type::trans_type trans_type; + typedef Distortion distortion_type; + + //-------------------------------------------------------------------- + span_interpolator_adaptor() {} + span_interpolator_adaptor(trans_type& trans, + distortion_type& dist) : + base_type(trans), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + span_interpolator_adaptor(trans_type& trans, + distortion_type& dist, + double x, double y, unsigned len) : + base_type(trans, x, y, len), + m_distortion(&dist) + { + } + + //-------------------------------------------------------------------- + distortion_type& distortion() const + { + return *m_distortion; + } + + //-------------------------------------------------------------------- + void distortion(distortion_type& dist) + { + m_distortion = dist; + } + + //-------------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + base_type::coordinates(x, y); + m_distortion->calculate(x, y); + } + + private: + //-------------------------------------------------------------------- + distortion_type* m_distortion; + }; +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_linear.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_linear.h new file mode 100644 index 00000000000..ef10505ce11 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_linear.h @@ -0,0 +1,232 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_INTERPOLATOR_LINEAR_INCLUDED +#define AGG_SPAN_INTERPOLATOR_LINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_dda_line.h" +#include "agg_trans_affine.h" + +namespace agg +{ + + //================================================span_interpolator_linear + template + class span_interpolator_linear + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_linear() {} + span_interpolator_linear(trans_type& trans) : m_trans(&trans) {} + span_interpolator_linear(trans_type& trans, + double x, double y, unsigned len) : + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + int x2 = iround(tx * subpixel_scale); + int y2 = iround(ty * subpixel_scale); + + m_li_x = dda2_line_interpolator(x1, x2, len); + m_li_y = dda2_line_interpolator(y1, y2, len); + } + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + m_trans->transform(&xe, &ye); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(xe * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ye * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + }; + + + + + + + //=====================================span_interpolator_linear_subdiv + template + class span_interpolator_linear_subdiv + { + public: + typedef Transformer trans_type; + + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_interpolator_linear_subdiv() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_interpolator_linear_subdiv(trans_type& trans, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) {} + + span_interpolator_linear_subdiv(trans_type& trans, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_trans(&trans) + { + begin(x, y, len); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + double tx; + double ty; + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + + if(len > m_subdiv_size) len = m_subdiv_size; + tx = x; + ty = y; + m_trans->transform(&tx, &ty); + int x1 = iround(tx * subpixel_scale); + int y1 = iround(ty * subpixel_scale); + + tx = x + len; + ty = y; + m_trans->transform(&tx, &ty); + + m_li_x = dda2_line_interpolator(x1, iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(y1, iround(ty * subpixel_scale), len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++m_li_x; + ++m_li_y; + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + double tx = double(m_src_x) / double(subpixel_scale) + len; + double ty = m_src_y; + m_trans->transform(&tx, &ty); + m_li_x = dda2_line_interpolator(m_li_x.y(), iround(tx * subpixel_scale), len); + m_li_y = dda2_line_interpolator(m_li_y.y(), iround(ty * subpixel_scale), len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_li_x.y(); + *y = m_li_y.y(); + } + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + trans_type* m_trans; + dda2_line_interpolator m_li_x; + dda2_line_interpolator m_li_y; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + + +} + + + +#endif + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_persp.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_persp.h new file mode 100644 index 00000000000..cad437e04f5 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_persp.h @@ -0,0 +1,462 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_INTERPOLATOR_PERSP_INCLUDED +#define AGG_SPAN_INTERPOLATOR_PERSP_INCLUDED + +#include "agg_trans_perspective.h" +#include "agg_dda_line.h" + +namespace agg +{ + + + + //===========================================span_interpolator_persp_exact + template + class span_interpolator_persp_exact + { + public: + typedef trans_perspective trans_type; + typedef trans_perspective::iterator_x iterator_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_exact() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_exact(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_exact(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_exact(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_iterator = m_trans_dir.begin(x, y, 1.0); + double xt = m_iterator.x; + double yt = m_iterator.y; + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + + //---------------------------------------------------------------- + void operator++() + { + ++m_iterator; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = iround(m_iterator.x * subpixel_scale); + *y = iround(m_iterator.y * subpixel_scale); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + iterator_type m_iterator; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + + + + + + + + + + + + //============================================span_interpolator_persp_lerp + template + class span_interpolator_persp_lerp + { + public: + typedef trans_perspective trans_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_persp_lerp() {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + span_interpolator_persp_lerp(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + //-------------------------------------------------------------------- + // Direct transformations + span_interpolator_persp_lerp(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //-------------------------------------------------------------------- + // Reverse transformations + span_interpolator_persp_lerp(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + m_trans_dir.quad_to_quad(src, dst); + m_trans_inv.quad_to_quad(dst, src); + } + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_trans_dir.is_valid(); } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + // Calculate transformed coordinates at x1,y1 + double xt = x; + double yt = y; + m_trans_dir.transform(&xt, &yt); + int x1 = iround(xt * subpixel_scale); + int y1 = iround(yt * subpixel_scale); + + double dx; + double dy; + const double delta = 1/double(subpixel_scale); + + // Calculate scale by X at x1,y1 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x1,y1 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy1 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate transformed coordinates at x2,y2 + x += len; + xt = x; + yt = y; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= x; + dy -= y; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void resynchronize(double xe, double ye, unsigned len) + { + // Assume x1,y1 are equal to the ones at the previous end point + int x1 = m_coord_x.y(); + int y1 = m_coord_y.y(); + int sx1 = m_scale_x.y(); + int sy1 = m_scale_y.y(); + + // Calculate transformed coordinates at x2,y2 + double xt = xe; + double yt = ye; + m_trans_dir.transform(&xt, &yt); + int x2 = iround(xt * subpixel_scale); + int y2 = iround(yt * subpixel_scale); + + const double delta = 1/double(subpixel_scale); + double dx; + double dy; + + // Calculate scale by X at x2,y2 + dx = xt + delta; + dy = yt; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sx2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Calculate scale by Y at x2,y2 + dx = xt; + dy = yt + delta; + m_trans_inv.transform(&dx, &dy); + dx -= xe; + dy -= ye; + int sy2 = uround(subpixel_scale/sqrt(dx*dx + dy*dy)) >> subpixel_shift; + + // Initialize the interpolators + m_coord_x = dda2_line_interpolator(x1, x2, len); + m_coord_y = dda2_line_interpolator(y1, y2, len); + m_scale_x = dda2_line_interpolator(sx1, sx2, len); + m_scale_y = dda2_line_interpolator(sy1, sy2, len); + } + + + //---------------------------------------------------------------- + void operator++() + { + ++m_coord_x; + ++m_coord_y; + ++m_scale_x; + ++m_scale_y; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_coord_x.y(); + *y = m_coord_y.y(); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) + { + *x = m_scale_x.y(); + *y = m_scale_y.y(); + } + + //---------------------------------------------------------------- + void transform(double* x, double* y) const + { + m_trans_dir.transform(x, y); + } + + private: + trans_type m_trans_dir; + trans_type m_trans_inv; + dda2_line_interpolator m_coord_x; + dda2_line_interpolator m_coord_y; + dda2_line_interpolator m_scale_x; + dda2_line_interpolator m_scale_y; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_trans.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_trans.h new file mode 100644 index 00000000000..32bc678a8e4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_interpolator_trans.h @@ -0,0 +1,92 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Horizontal span interpolator for use with an arbitrary transformer +// The efficiency highly depends on the operations done in the transformer +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED +#define AGG_SPAN_INTERPOLATOR_TRANS_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //=================================================span_interpolator_trans + template + class span_interpolator_trans + { + public: + typedef Transformer trans_type; + enum subpixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + //-------------------------------------------------------------------- + span_interpolator_trans() {} + span_interpolator_trans(trans_type& trans) : m_trans(&trans) {} + span_interpolator_trans(trans_type& trans, + double x, double y, unsigned) : + m_trans(&trans) + { + begin(x, y, 0); + } + + //---------------------------------------------------------------- + const trans_type& transformer() const { return *m_trans; } + void transformer(const trans_type& trans) { m_trans = &trans; } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned) + { + m_x = x; + m_y = y; + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); + } + + //---------------------------------------------------------------- + void operator++() + { + m_x += 1.0; + double x = m_x; + double y = m_y; + m_trans->transform(&x, &y); + m_ix = iround(x * subpixel_scale); + m_iy = iround(y * subpixel_scale); + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + *x = m_ix; + *y = m_iy; + } + + private: + trans_type* m_trans; + double m_x; + double m_y; + int m_ix; + int m_iy; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_gray.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_gray.h new file mode 100644 index 00000000000..ae1a49f879e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_gray.h @@ -0,0 +1,93 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_PATTERN_GRAY_INCLUDED +#define AGG_SPAN_PATTERN_GRAY_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================span_pattern_gray + template class span_pattern_gray + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_gray() {} + span_pattern_gray(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->v = *p; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgb.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgb.h new file mode 100644 index 00000000000..4850508af1e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgb.h @@ -0,0 +1,96 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_PATTERN_RGB_INCLUDED +#define AGG_SPAN_PATTERN_RGB_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //========================================================span_pattern_rgb + template class span_pattern_rgb + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgb() {} + span_pattern_rgb(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y), + m_alpha(color_type::base_mask) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type v) { m_alpha = v; } + value_type alpha() const { return m_alpha; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = m_alpha; + p = m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + value_type m_alpha; + + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgba.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgba.h new file mode 100644 index 00000000000..d47d2a6c022 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_pattern_rgba.h @@ -0,0 +1,94 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// 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_SPAN_PATTERN_RGBA_INCLUDED +#define AGG_SPAN_PATTERN_RGBA_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================span_pattern_rgba + template class span_pattern_rgba + { + public: + typedef Source source_type; + typedef typename source_type::color_type color_type; + typedef typename source_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + //-------------------------------------------------------------------- + span_pattern_rgba() {} + span_pattern_rgba(source_type& src, + unsigned offset_x, unsigned offset_y) : + m_src(&src), + m_offset_x(offset_x), + m_offset_y(offset_y) + {} + + //-------------------------------------------------------------------- + void attach(source_type& v) { m_src = &v; } + source_type& source() { return *m_src; } + const source_type& source() const { return *m_src; } + + //-------------------------------------------------------------------- + void offset_x(unsigned v) { m_offset_x = v; } + void offset_y(unsigned v) { m_offset_y = v; } + unsigned offset_x() const { return m_offset_x; } + unsigned offset_y() const { return m_offset_y; } + void alpha(value_type) {} + value_type alpha() const { return 0; } + + //-------------------------------------------------------------------- + void prepare() {} + void generate(color_type* span, int x, int y, unsigned len) + { + x += m_offset_x; + y += m_offset_y; + const value_type* p = (const value_type*)m_src->span(x, y, len); + do + { + span->r = p[order_type::R]; + span->g = p[order_type::G]; + span->b = p[order_type::B]; + span->a = p[order_type::A]; + p = (const value_type*)m_src->next_x(); + ++span; + } + while(--len); + } + + private: + source_type* m_src; + unsigned m_offset_x; + unsigned m_offset_y; + + }; + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_solid.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_solid.h new file mode 100644 index 00000000000..ee46df99913 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_solid.h @@ -0,0 +1,53 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// span_solid_rgba8 +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPAN_SOLID_INCLUDED +#define AGG_SPAN_SOLID_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + //--------------------------------------------------------------span_solid + template class span_solid + { + public: + typedef ColorT color_type; + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + void generate(color_type* span, int x, int y, unsigned len) + { + do { *span++ = m_color; } while(--len); + } + + private: + color_type m_color; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_subdiv_adaptor.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_subdiv_adaptor.h new file mode 100644 index 00000000000..b5b855ec977 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_span_subdiv_adaptor.h @@ -0,0 +1,141 @@ +//---------------------------------------------------------------------------- +// 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_SPAN_SUBDIV_ADAPTOR_INCLUDED +#define AGG_SPAN_SUBDIV_ADAPTOR_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //=================================================span_subdiv_adaptor + template + class span_subdiv_adaptor + { + public: + typedef Interpolator interpolator_type; + typedef typename interpolator_type::trans_type trans_type; + + enum sublixel_scale_e + { + subpixel_shift = SubpixelShift, + subpixel_scale = 1 << subpixel_shift + }; + + + //---------------------------------------------------------------- + span_subdiv_adaptor() : + m_subdiv_shift(4), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) {} + + span_subdiv_adaptor(interpolator_type& interpolator, + double x, double y, unsigned len, + unsigned subdiv_shift = 4) : + m_subdiv_shift(subdiv_shift), + m_subdiv_size(1 << m_subdiv_shift), + m_subdiv_mask(m_subdiv_size - 1), + m_interpolator(&interpolator) + { + begin(x, y, len); + } + + + //---------------------------------------------------------------- + const interpolator_type& interpolator() const { return *m_interpolator; } + void interpolator(interpolator_type& intr) { m_interpolator = &intr; } + + //---------------------------------------------------------------- + const trans_type& transformer() const + { + return *m_interpolator->transformer(); + } + void transformer(const trans_type& trans) + { + m_interpolator->transformer(trans); + } + + //---------------------------------------------------------------- + unsigned subdiv_shift() const { return m_subdiv_shift; } + void subdiv_shift(unsigned shift) + { + m_subdiv_shift = shift; + m_subdiv_size = 1 << m_subdiv_shift; + m_subdiv_mask = m_subdiv_size - 1; + } + + //---------------------------------------------------------------- + void begin(double x, double y, unsigned len) + { + m_pos = 1; + m_src_x = iround(x * subpixel_scale) + subpixel_scale; + m_src_y = y; + m_len = len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->begin(x, y, len); + } + + //---------------------------------------------------------------- + void operator++() + { + ++(*m_interpolator); + if(m_pos >= m_subdiv_size) + { + unsigned len = m_len; + if(len > m_subdiv_size) len = m_subdiv_size; + m_interpolator->resynchronize(double(m_src_x) / double(subpixel_scale) + len, + m_src_y, + len); + m_pos = 0; + } + m_src_x += subpixel_scale; + ++m_pos; + --m_len; + } + + //---------------------------------------------------------------- + void coordinates(int* x, int* y) const + { + m_interpolator->coordinates(x, y); + } + + //---------------------------------------------------------------- + void local_scale(int* x, int* y) const + { + m_interpolator->local_scale(x, y); + } + + + private: + unsigned m_subdiv_shift; + unsigned m_subdiv_size; + unsigned m_subdiv_mask; + interpolator_type* m_interpolator; + int m_src_x; + double m_src_y; + unsigned m_pos; + unsigned m_len; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_affine.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_affine.h new file mode 100644 index 00000000000..1a611638833 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_affine.h @@ -0,0 +1,518 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Affine transformation classes. +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_AFFINE_INCLUDED +#define AGG_TRANS_AFFINE_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + const double affine_epsilon = 1e-14; + + //============================================================trans_affine + // + // See Implementation agg_trans_affine.cpp + // + // Affine transformation are linear transformations in Cartesian coordinates + // (strictly speaking not only in Cartesian, but for the beginning we will + // think so). They are rotation, scaling, translation and skewing. + // After any affine transformation a line segment remains a line segment + // and it will never become a curve. + // + // There will be no math about matrix calculations, since it has been + // described many times. Ask yourself a very simple question: + // "why do we need to understand and use some matrix stuff instead of just + // rotating, scaling and so on". The answers are: + // + // 1. Any combination of transformations can be done by only 4 multiplications + // and 4 additions in floating point. + // 2. One matrix transformation is equivalent to the number of consecutive + // discrete transformations, i.e. the matrix "accumulates" all transformations + // in the order of their settings. Suppose we have 4 transformations: + // * rotate by 30 degrees, + // * scale X to 2.0, + // * scale Y to 1.5, + // * move to (100, 100). + // The result will depend on the order of these transformations, + // and the advantage of matrix is that the sequence of discret calls: + // rotate(30), scaleX(2.0), scaleY(1.5), move(100,100) + // will have exactly the same result as the following matrix transformations: + // + // affine_matrix m; + // m *= rotate_matrix(30); + // m *= scaleX_matrix(2.0); + // m *= scaleY_matrix(1.5); + // m *= move_matrix(100,100); + // + // m.transform_my_point_at_last(x, y); + // + // What is the good of it? In real life we will set-up the matrix only once + // and then transform many points, let alone the convenience to set any + // combination of transformations. + // + // So, how to use it? Very easy - literally as it's shown above. Not quite, + // let us write a correct example: + // + // agg::trans_affine m; + // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); + // m *= agg::trans_affine_scaling(2.0, 1.5); + // m *= agg::trans_affine_translation(100.0, 100.0); + // m.transform(&x, &y); + // + // The affine matrix is all you need to perform any linear transformation, + // but all transformations have origin point (0,0). It means that we need to + // use 2 translations if we want to rotate someting around (100,100): + // + // m *= agg::trans_affine_translation(-100.0, -100.0); // move to (0,0) + // m *= agg::trans_affine_rotation(30.0 * 3.1415926 / 180.0); // rotate + // m *= agg::trans_affine_translation(100.0, 100.0); // move back to (100,100) + //---------------------------------------------------------------------- + struct trans_affine + { + double sx, shy, shx, sy, tx, ty; + + //------------------------------------------ Construction + // Identity matrix + trans_affine() : + sx(1.0), shy(0.0), shx(0.0), sy(1.0), tx(0.0), ty(0.0) + {} + + // Custom matrix. Usually used in derived classes + trans_affine(double v0, double v1, double v2, + double v3, double v4, double v5) : + sx(v0), shy(v1), shx(v2), sy(v3), tx(v4), ty(v5) + {} + + // Custom matrix from m[6] + explicit trans_affine(const double* m) : + sx(m[0]), shy(m[1]), shx(m[2]), sy(m[3]), tx(m[4]), ty(m[5]) + {} + + // Rectangle to a parallelogram. + trans_affine(double x1, double y1, double x2, double y2, + const double* parl) + { + rect_to_parl(x1, y1, x2, y2, parl); + } + + // Parallelogram to a rectangle. + trans_affine(const double* parl, + double x1, double y1, double x2, double y2) + { + parl_to_rect(parl, x1, y1, x2, y2); + } + + // Arbitrary parallelogram transformation. + trans_affine(const double* src, const double* dst) + { + parl_to_parl(src, dst); + } + + //---------------------------------- Parellelogram transformations + // transform a parallelogram to another one. Src and dst are + // pointers to arrays of three points (double[6], x1,y1,...) that + // identify three corners of the parallelograms assuming implicit + // fourth point. The arguments are arrays of double[6] mapped + // to x1,y1, x2,y2, x3,y3 where the coordinates are: + // *-----------------* + // / (x3,y3)/ + // / / + // /(x1,y1) (x2,y2)/ + // *-----------------* + const trans_affine& parl_to_parl(const double* src, + const double* dst); + + const trans_affine& rect_to_parl(double x1, double y1, + double x2, double y2, + const double* parl); + + const trans_affine& parl_to_rect(const double* parl, + double x1, double y1, + double x2, double y2); + + + //------------------------------------------ Operations + // Reset - load an identity matrix + const trans_affine& reset(); + + // Direct transformations operations + const trans_affine& translate(double x, double y); + const trans_affine& rotate(double a); + const trans_affine& scale(double s); + const trans_affine& scale(double x, double y); + + // Multiply matrix to another one + const trans_affine& multiply(const trans_affine& m); + + // Multiply "m" to "this" and assign the result to "this" + const trans_affine& premultiply(const trans_affine& m); + + // Multiply matrix to inverse of another one + const trans_affine& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" to "this" and assign the result to "this" + const trans_affine& premultiply_inv(const trans_affine& m); + + // Invert matrix. Do not try to invert degenerate matrices, + // there's no check for validity. If you set scale to 0 and + // then try to invert matrix, expect unpredictable result. + const trans_affine& invert(); + + // Mirroring around X + const trans_affine& flip_x(); + + // Mirroring around Y + const trans_affine& flip_y(); + + //------------------------------------------- Load/Store + // Store matrix to an array [6] of double + void store_to(double* m) const + { + *m++ = sx; *m++ = shy; *m++ = shx; *m++ = sy; *m++ = tx; *m++ = ty; + } + + // Load matrix from an array [6] of double + const trans_affine& load_from(const double* m) + { + sx = *m++; shy = *m++; shx = *m++; sy = *m++; tx = *m++; ty = *m++; + return *this; + } + + //------------------------------------------- Operators + + // Multiply the matrix by another one + const trans_affine& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply the matrix by inverse of another one + const trans_affine& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_affine operator * (const trans_affine& m) const + { + return trans_affine(*this).multiply(m); + } + + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_affine operator / (const trans_affine& m) const + { + return trans_affine(*this).multiply_inv(m); + } + + // Calculate and return the inverse matrix + trans_affine operator ~ () const + { + trans_affine ret = *this; + return ret.invert(); + } + + // Equal operator with default epsilon + bool operator == (const trans_affine& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_affine& m) const + { + return !is_equal(m, affine_epsilon); + } + + //-------------------------------------------- Transformations + // Direct transformation of x and y + void transform(double* x, double* y) const; + + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slower than the + // direct transformation. For massive operations it's better to + // invert() the matrix and then use direct transformations. + void inverse_transform(double* x, double* y) const; + + //-------------------------------------------- Auxiliary + // Calculate the determinant of matrix + double determinant() const + { + return sx * sy - shy * shx; + } + + // Calculate the reciprocal of the determinant + double determinant_reciprocal() const + { + return 1.0 / (sx * sy - shy * shx); + } + + // Get the average scale (by X and Y). + // Basically used to calculate the approximation_scale when + // decomposinting curves into line segments. + double scale() const; + + // Check to see if the matrix is not degenerate + bool is_valid(double epsilon = affine_epsilon) const; + + // Check to see if it's an identity matrix + bool is_identity(double epsilon = affine_epsilon) const; + + // Check to see if two matrices are equal + bool is_equal(const trans_affine& m, double epsilon = affine_epsilon) const; + + // Determine the major parameters. Use with caution considering + // possible degenerate cases. + double rotation() const; + void translation(double* dx, double* dy) const; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; + }; + + //------------------------------------------------------------------------ + inline void trans_affine::transform(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_affine::transform_2x2(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; + } + + //------------------------------------------------------------------------ + inline void trans_affine::inverse_transform(double* x, double* y) const + { + double d = determinant_reciprocal(); + double a = (*x - tx) * d; + double b = (*y - ty) * d; + *x = a * sy - b * shx; + *y = b * sx - a * shy; + } + + //------------------------------------------------------------------------ + inline double trans_affine::scale() const + { + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::rotate(double a) + { + double ca = cos(a); + double sa = sin(a); + double t0 = sx * ca - shy * sa; + double t2 = shx * ca - sy * sa; + double t4 = tx * ca - ty * sa; + shy = sx * sa + shy * ca; + sy = shx * sa + sy * ca; + ty = tx * sa + ty * ca; + sx = t0; + shx = t2; + tx = t4; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double x, double y) + { + double mm0 = x; // Possible hint for the optimizer + double mm3 = y; + sx *= mm0; + shx *= mm0; + tx *= mm0; + shy *= mm3; + sy *= mm3; + ty *= mm3; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::scale(double s) + { + double m = s; // Possible hint for the optimizer + sx *= m; + shx *= m; + tx *= m; + shy *= m; + sy *= m; + ty *= m; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply(const trans_affine& m) + { + trans_affine t = m; + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + inline const trans_affine& trans_affine::premultiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline void trans_affine::scaling_abs(double* x, double* y) const + { + // Used to calculate scaling coefficients in image resampling. + // When there is considerable shear this method gives us much + // better estimation than just sx, sy. + *x = sqrt(sx * sx + shx * shx); + *y = sqrt(shy * shy + sy * sy); + } + + //====================================================trans_affine_rotation + // Rotation matrix. sin() and cos() are calculated twice for the same angle. + // There's no harm because the performance of sin()/cos() is very good on all + // modern processors. Besides, this operation is not going to be invoked too + // often. + class trans_affine_rotation : public trans_affine + { + public: + trans_affine_rotation(double a) : + trans_affine(cos(a), sin(a), -sin(a), cos(a), 0.0, 0.0) + {} + }; + + //====================================================trans_affine_scaling + // Scaling matrix. x, y - scale coefficients by X and Y respectively + class trans_affine_scaling : public trans_affine + { + public: + trans_affine_scaling(double x, double y) : + trans_affine(x, 0.0, 0.0, y, 0.0, 0.0) + {} + + trans_affine_scaling(double s) : + trans_affine(s, 0.0, 0.0, s, 0.0, 0.0) + {} + }; + + //================================================trans_affine_translation + // Translation matrix + class trans_affine_translation : public trans_affine + { + public: + trans_affine_translation(double x, double y) : + trans_affine(1.0, 0.0, 0.0, 1.0, x, y) + {} + }; + + //====================================================trans_affine_skewing + // Sckewing (shear) matrix + class trans_affine_skewing : public trans_affine + { + public: + trans_affine_skewing(double x, double y) : + trans_affine(1.0, tan(y), tan(x), 1.0, 0.0, 0.0) + {} + }; + + + //===============================================trans_affine_line_segment + // Rotate, Scale and Translate, associating 0...dist with line segment + // x1,y1,x2,y2 + class trans_affine_line_segment : public trans_affine + { + public: + trans_affine_line_segment(double x1, double y1, double x2, double y2, + double dist) + { + double dx = x2 - x1; + double dy = y2 - y1; + if(dist > 0.0) + { + multiply(trans_affine_scaling(sqrt(dx * dx + dy * dy) / dist)); + } + multiply(trans_affine_rotation(atan2(dy, dx))); + multiply(trans_affine_translation(x1, y1)); + } + }; + + + //============================================trans_affine_reflection_unit + // Reflection matrix. Reflect coordinates across the line through + // the origin containing the unit vector (ux, uy). + // Contributed by John Horigan + class trans_affine_reflection_unit : public trans_affine + { + public: + trans_affine_reflection_unit(double ux, double uy) : + trans_affine(2.0 * ux * ux - 1.0, + 2.0 * ux * uy, + 2.0 * ux * uy, + 2.0 * uy * uy - 1.0, + 0.0, 0.0) + {} + }; + + + //=================================================trans_affine_reflection + // Reflection matrix. Reflect coordinates across the line through + // the origin at the angle a or containing the non-unit vector (x, y). + // Contributed by John Horigan + class trans_affine_reflection : public trans_affine_reflection_unit + { + public: + trans_affine_reflection(double a) : + trans_affine_reflection_unit(cos(a), sin(a)) + {} + + + trans_affine_reflection(double x, double y) : + trans_affine_reflection_unit(x / sqrt(x * x + y * y), y / sqrt(x * x + y * y)) + {} + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_bilinear.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_bilinear.h new file mode 100644 index 00000000000..f3ab5964725 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_bilinear.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Bilinear 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_BILINEAR_INCLUDED +#define AGG_TRANS_BILINEAR_INCLUDED + +#include "agg_basics.h" +#include "agg_simul_eq.h" + +namespace agg +{ + + //==========================================================trans_bilinear + class trans_bilinear + { + public: + //-------------------------------------------------------------------- + trans_bilinear() : m_valid(false) {} + + //-------------------------------------------------------------------- + // Arbitrary quadrangle transformations + trans_bilinear(const double* src, const double* dst) + { + quad_to_quad(src, dst); + } + + + //-------------------------------------------------------------------- + // Direct transformations + trans_bilinear(double x1, double y1, double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + + //-------------------------------------------------------------------- + // Reverse transformations + trans_bilinear(const double* quad, + double x1, double y1, double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + + //-------------------------------------------------------------------- + // Set the transformations using two arbitrary quadrangles. + void quad_to_quad(const double* src, const double* dst) + { + double left[4][4]; + double right[4][2]; + + unsigned i; + for(i = 0; i < 4; i++) + { + unsigned ix = i * 2; + unsigned iy = ix + 1; + left[i][0] = 1.0; + left[i][1] = src[ix] * src[iy]; + left[i][2] = src[ix]; + left[i][3] = src[iy]; + + right[i][0] = dst[ix]; + right[i][1] = dst[iy]; + } + m_valid = simul_eq<4, 2>::solve(left, right, m_mtx); + } + + + //-------------------------------------------------------------------- + // Set the direct transformations, i.e., rectangle -> quadrangle + void rect_to_quad(double x1, double y1, double x2, double y2, + const double* quad) + { + double src[8]; + src[0] = src[6] = x1; + src[2] = src[4] = x2; + src[1] = src[3] = y1; + src[5] = src[7] = y2; + quad_to_quad(src, quad); + } + + + //-------------------------------------------------------------------- + // Set the reverse transformations, i.e., quadrangle -> rectangle + void quad_to_rect(const double* quad, + double x1, double y1, double x2, double y2) + { + double dst[8]; + dst[0] = dst[6] = x1; + dst[2] = dst[4] = x2; + dst[1] = dst[3] = y1; + dst[5] = dst[7] = y2; + quad_to_quad(quad, dst); + } + + //-------------------------------------------------------------------- + // Check if the equations were solved successfully + bool is_valid() const { return m_valid; } + + //-------------------------------------------------------------------- + // Transform a point (x, y) + void transform(double* x, double* y) const + { + double tx = *x; + double ty = *y; + double xy = tx * ty; + *x = m_mtx[0][0] + m_mtx[1][0] * xy + m_mtx[2][0] * tx + m_mtx[3][0] * ty; + *y = m_mtx[0][1] + m_mtx[1][1] * xy + m_mtx[2][1] * tx + m_mtx[3][1] * ty; + } + + + //-------------------------------------------------------------------- + class iterator_x + { + double inc_x; + double inc_y; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double tx, double ty, double step, const double m[4][2]) : + inc_x(m[1][0] * step * ty + m[2][0] * step), + inc_y(m[1][1] * step * ty + m[2][1] * step), + x(m[0][0] + m[1][0] * tx * ty + m[2][0] * tx + m[3][0] * ty), + y(m[0][1] + m[1][1] * tx * ty + m[2][1] * tx + m[3][1] * ty) + { + } + + void operator ++ () + { + x += inc_x; + y += inc_y; + } + }; + + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, m_mtx); + } + + private: + double m_mtx[4][2]; + bool m_valid; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_double_path.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_double_path.h new file mode 100644 index 00000000000..c645a7f8690 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_double_path.h @@ -0,0 +1,131 @@ +//---------------------------------------------------------------------------- +// 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_TRANS_DOUBLE_PATH_INCLUDED +#define AGG_TRANS_DOUBLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_double_path.cpp + // + //-------------------------------------------------------trans_double_path + class trans_double_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence vertex_storage; + + trans_double_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void base_height(double v) { m_base_height = v; } + double base_height() const { return m_base_height; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to1(double x, double y); + void line_to1(double x, double y); + void move_to2(double x, double y); + void line_to2(double x, double y); + void finalize_paths(); + + //-------------------------------------------------------------------- + template + void add_paths(VertexSource1& vs1, VertexSource2& vs2, + unsigned path1_id=0, unsigned path2_id=0) + { + double x; + double y; + + unsigned cmd; + + vs1.rewind(path1_id); + while(!is_stop(cmd = vs1.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to1(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to1(x, y); + } + } + } + + vs2.rewind(path2_id); + while(!is_stop(cmd = vs2.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to2(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to2(x, y); + } + } + } + finalize_paths(); + } + + //-------------------------------------------------------------------- + double total_length1() const; + double total_length2() const; + void transform(double *x, double *y) const; + + private: + double finalize_path(vertex_storage& vertices); + void transform1(const vertex_storage& vertices, + double kindex, double kx, + double *x, double* y) const; + + vertex_storage m_src_vertices1; + vertex_storage m_src_vertices2; + double m_base_length; + double m_base_height; + double m_kindex1; + double m_kindex2; + status_e m_status1; + status_e m_status2; + bool m_preserve_x_scale; + }; + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_perspective.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_perspective.h new file mode 100644 index 00000000000..7d4aa26c798 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_perspective.h @@ -0,0 +1,731 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Perspective 2D transformations +// +//---------------------------------------------------------------------------- +#ifndef AGG_TRANS_PERSPECTIVE_INCLUDED +#define AGG_TRANS_PERSPECTIVE_INCLUDED + +#include "agg_trans_affine.h" + +namespace agg +{ + //=======================================================trans_perspective + struct trans_perspective + { + double sx, shy, w0, shx, sy, w1, tx, ty, w2; + + //------------------------------------------------------- Construction + // Identity matrix + trans_perspective() : + sx (1), shy(0), w0(0), + shx(0), sy (1), w1(0), + tx (0), ty (0), w2(1) {} + + // Custom matrix + trans_perspective(double v0, double v1, double v2, + double v3, double v4, double v5, + double v6, double v7, double v8) : + sx (v0), shy(v1), w0(v2), + shx(v3), sy (v4), w1(v5), + tx (v6), ty (v7), w2(v8) {} + + // Custom matrix from m[9] + explicit trans_perspective(const double* m) : + sx (m[0]), shy(m[1]), w0(m[2]), + shx(m[3]), sy (m[4]), w1(m[5]), + tx (m[6]), ty (m[7]), w2(m[8]) {} + + // From affine + explicit trans_perspective(const trans_affine& a) : + sx (a.sx ), shy(a.shy), w0(0), + shx(a.shx), sy (a.sy ), w1(0), + tx (a.tx ), ty (a.ty ), w2(1) {} + + // Rectangle to quadrilateral + trans_perspective(double x1, double y1, double x2, double y2, + const double* quad); + + // Quadrilateral to rectangle + trans_perspective(const double* quad, + double x1, double y1, double x2, double y2); + + // Arbitrary quadrilateral transformations + trans_perspective(const double* src, const double* dst); + + //-------------------------------------- Quadrilateral transformations + // The arguments are double[8] that are mapped to quadrilaterals: + // x1,y1, x2,y2, x3,y3, x4,y4 + bool quad_to_quad(const double* qs, const double* qd); + + bool rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q); + + bool quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2); + + // Map square (0,0,1,1) to the quadrilateral and vice versa + bool square_to_quad(const double* q); + bool quad_to_square(const double* q); + + + //--------------------------------------------------------- Operations + // Reset - load an identity matrix + const trans_perspective& reset(); + + // Invert matrix. Returns false in degenerate case + bool invert(); + + // Direct transformations operations + const trans_perspective& translate(double x, double y); + const trans_perspective& rotate(double a); + const trans_perspective& scale(double s); + const trans_perspective& scale(double x, double y); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_perspective& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_perspective& m); + + // Multiply matrix to inverse of another one + const trans_perspective& multiply_inv(const trans_perspective& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_perspective& m); + + // Multiply the matrix by another one + const trans_perspective& multiply(const trans_affine& m); + + // Multiply "m" by "this" and assign the result to "this" + const trans_perspective& premultiply(const trans_affine& m); + + // Multiply the matrix by inverse of another one + const trans_perspective& multiply_inv(const trans_affine& m); + + // Multiply inverse of "m" by "this" and assign the result to "this" + const trans_perspective& premultiply_inv(const trans_affine& m); + + //--------------------------------------------------------- Load/Store + void store_to(double* m) const; + const trans_perspective& load_from(const double* m); + + //---------------------------------------------------------- Operators + // Multiply the matrix by another one + const trans_perspective& operator *= (const trans_perspective& m) + { + return multiply(m); + } + const trans_perspective& operator *= (const trans_affine& m) + { + return multiply(m); + } + + // Multiply the matrix by inverse of another one + const trans_perspective& operator /= (const trans_perspective& m) + { + return multiply_inv(m); + } + const trans_perspective& operator /= (const trans_affine& m) + { + return multiply_inv(m); + } + + // Multiply the matrix by another one and return + // the result in a separete matrix. + trans_perspective operator * (const trans_perspective& m) const + { + return trans_perspective(*this).multiply(m); + } + trans_perspective operator * (const trans_affine& m) const + { + return trans_perspective(*this).multiply(m); + } + + // Multiply the matrix by inverse of another one + // and return the result in a separete matrix. + trans_perspective operator / (const trans_perspective& m) const + { + return trans_perspective(*this).multiply_inv(m); + } + trans_perspective operator / (const trans_affine& m) const + { + return trans_perspective(*this).multiply_inv(m); + } + + // Calculate and return the inverse matrix + trans_perspective operator ~ () const + { + trans_perspective ret = *this; + ret.invert(); + return ret; + } + + // Equal operator with default epsilon + bool operator == (const trans_perspective& m) const + { + return is_equal(m, affine_epsilon); + } + + // Not Equal operator with default epsilon + bool operator != (const trans_perspective& m) const + { + return !is_equal(m, affine_epsilon); + } + + //---------------------------------------------------- Transformations + // Direct transformation of x and y + void transform(double* x, double* y) const; + + // Direct transformation of x and y, affine part only + void transform_affine(double* x, double* y) const; + + // Direct transformation of x and y, 2x2 matrix only, no translation + void transform_2x2(double* x, double* y) const; + + // Inverse transformation of x and y. It works slow because + // it explicitly inverts the matrix on every call. For massive + // operations it's better to invert() the matrix and then use + // direct transformations. + void inverse_transform(double* x, double* y) const; + + + //---------------------------------------------------------- Auxiliary + const trans_perspective& from_affine(const trans_affine& a); + double determinant() const; + double determinant_reciprocal() const; + + bool is_valid(double epsilon = affine_epsilon) const; + bool is_identity(double epsilon = affine_epsilon) const; + bool is_equal(const trans_perspective& m, + double epsilon = affine_epsilon) const; + + // Determine the major affine parameters. Use with caution + // considering possible degenerate cases. + double scale() const; + double rotation() const; + void translation(double* dx, double* dy) const; + void scaling(double* x, double* y) const; + void scaling_abs(double* x, double* y) const; + + + + //-------------------------------------------------------------------- + class iterator_x + { + double den; + double den_step; + double nom_x; + double nom_x_step; + double nom_y; + double nom_y_step; + + public: + double x; + double y; + + iterator_x() {} + iterator_x(double px, double py, double step, const trans_perspective& m) : + den(px * m.w0 + py * m.w1 + m.w2), + den_step(m.w0 * step), + nom_x(px * m.sx + py * m.shx + m.tx), + nom_x_step(step * m.sx), + nom_y(px * m.shy + py * m.sy + m.ty), + nom_y_step(step * m.shy), + x(nom_x / den), + y(nom_y / den) + {} + + void operator ++ () + { + den += den_step; + nom_x += nom_x_step; + nom_y += nom_y_step; + double d = 1.0 / den; + x = nom_x * d; + y = nom_y * d; + } + }; + + //-------------------------------------------------------------------- + iterator_x begin(double x, double y, double step) const + { + return iterator_x(x, y, step, *this); + } + }; + + + + + + + + + + + + + + + //------------------------------------------------------------------------ + inline bool trans_perspective::square_to_quad(const double* q) + { + double dx = q[0] - q[2] + q[4] - q[6]; + double dy = q[1] - q[3] + q[5] - q[7]; + if(dx == 0.0 && dy == 0.0) + { + // Affine case (parallelogram) + //--------------- + sx = q[2] - q[0]; + shy = q[3] - q[1]; + w0 = 0.0; + shx = q[4] - q[2]; + sy = q[5] - q[3]; + w1 = 0.0; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + else + { + double dx1 = q[2] - q[4]; + double dy1 = q[3] - q[5]; + double dx2 = q[6] - q[4]; + double dy2 = q[7] - q[5]; + double den = dx1 * dy2 - dx2 * dy1; + if(den == 0.0) + { + // Singular case + //--------------- + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + // General case + //--------------- + double u = (dx * dy2 - dy * dx2) / den; + double v = (dy * dx1 - dx * dy1) / den; + sx = q[2] - q[0] + u * q[2]; + shy = q[3] - q[1] + u * q[3]; + w0 = u; + shx = q[6] - q[0] + v * q[6]; + sy = q[7] - q[1] + v * q[7]; + w1 = v; + tx = q[0]; + ty = q[1]; + w2 = 1.0; + } + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::invert() + { + double d0 = sy * w2 - w1 * ty; + double d1 = w0 * ty - shy * w2; + double d2 = shy * w1 - w0 * sy; + double d = sx * d0 + shx * d1 + tx * d2; + if(d == 0.0) + { + sx = shy = w0 = shx = sy = w1 = tx = ty = w2 = 0.0; + return false; + } + d = 1.0 / d; + trans_perspective a = *this; + sx = d * d0; + shy = d * d1; + w0 = d * d2; + shx = d * (a.w1 *a.tx - a.shx*a.w2); + sy = d * (a.sx *a.w2 - a.w0 *a.tx); + w1 = d * (a.w0 *a.shx - a.sx *a.w1); + tx = d * (a.shx*a.ty - a.sy *a.tx); + ty = d * (a.shy*a.tx - a.sx *a.ty); + w2 = d * (a.sx *a.sy - a.shy*a.shx); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_square(const double* q) + { + if(!square_to_quad(q)) return false; + invert(); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_quad(const double* qs, + const double* qd) + { + trans_perspective p; + if(! quad_to_square(qs)) return false; + if(!p.square_to_quad(qd)) return false; + multiply(p); + return true; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::rect_to_quad(double x1, double y1, + double x2, double y2, + const double* q) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(r, q); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::quad_to_rect(const double* q, + double x1, double y1, + double x2, double y2) + { + double r[8]; + r[0] = r[6] = x1; + r[2] = r[4] = x2; + r[1] = r[3] = y1; + r[5] = r[7] = y2; + return quad_to_quad(q, r); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(double x1, double y1, + double x2, double y2, + const double* quad) + { + rect_to_quad(x1, y1, x2, y2, quad); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* quad, + double x1, double y1, + double x2, double y2) + { + quad_to_rect(quad, x1, y1, x2, y2); + } + + //------------------------------------------------------------------------ + inline trans_perspective::trans_perspective(const double* src, + const double* dst) + { + quad_to_quad(src, dst); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::reset() + { + sx = 1; shy = 0; w0 = 0; + shx = 0; sy = 1; w1 = 0; + tx = 0; ty = 0; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_perspective& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::multiply(const trans_affine& a) + { + trans_perspective b = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_perspective& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy + a.tx*b.w0; + shx = a.sx *b.shx + a.shx*b.sy + a.tx*b.w1; + tx = a.sx *b.tx + a.shx*b.ty + a.tx*b.w2; + shy = a.shy*b.sx + a.sy *b.shy + a.ty*b.w0; + sy = a.shy*b.shx + a.sy *b.sy + a.ty*b.w1; + ty = a.shy*b.tx + a.sy *b.ty + a.ty*b.w2; + w0 = a.w0 *b.sx + a.w1 *b.shy + a.w2*b.w0; + w1 = a.w0 *b.shx + a.w1 *b.sy + a.w2*b.w1; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2*b.w2; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::premultiply(const trans_affine& b) + { + trans_perspective a = *this; + sx = a.sx *b.sx + a.shx*b.shy; + shx = a.sx *b.shx + a.shx*b.sy; + tx = a.sx *b.tx + a.shx*b.ty + a.tx; + shy = a.shy*b.sx + a.sy *b.shy; + sy = a.shy*b.shx + a.sy *b.sy; + ty = a.shy*b.tx + a.sy *b.ty + a.ty; + w0 = a.w0 *b.sx + a.w1 *b.shy; + w1 = a.w0 *b.shx + a.w1 *b.sy; + w2 = a.w0 *b.tx + a.w1 *b.ty + a.w2; + return *this; + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::multiply_inv(const trans_affine& m) + { + trans_affine t = m; + t.invert(); + return multiply(t); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_perspective& m) + { + trans_perspective t = m; + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + const trans_perspective& + trans_perspective::premultiply_inv(const trans_affine& m) + { + trans_perspective t(m); + t.invert(); + return *this = t.multiply(*this); + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::translate(double x, double y) + { + tx += x; + ty += y; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::rotate(double a) + { + multiply(trans_affine_rotation(a)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double s) + { + multiply(trans_affine_scaling(s)); + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::scale(double x, double y) + { + multiply(trans_affine_scaling(x, y)); + return *this; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform(double* px, double* py) const + { + double x = *px; + double y = *py; + double m = 1.0 / (x*w0 + y*w1 + w2); + *px = m * (x*sx + y*shx + tx); + *py = m * (x*shy + y*sy + ty); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_affine(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx + tx; + *y = tmp * shy + *y * sy + ty; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::transform_2x2(double* x, double* y) const + { + double tmp = *x; + *x = tmp * sx + *y * shx; + *y = tmp * shy + *y * sy; + } + + //------------------------------------------------------------------------ + inline void trans_perspective::inverse_transform(double* x, double* y) const + { + trans_perspective t(*this); + if(t.invert()) t.transform(x, y); + } + + //------------------------------------------------------------------------ + inline void trans_perspective::store_to(double* m) const + { + *m++ = sx; *m++ = shy; *m++ = w0; + *m++ = shx; *m++ = sy; *m++ = w1; + *m++ = tx; *m++ = ty; *m++ = w2; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& trans_perspective::load_from(const double* m) + { + sx = *m++; shy = *m++; w0 = *m++; + shx = *m++; sy = *m++; w1 = *m++; + tx = *m++; ty = *m++; w2 = *m++; + return *this; + } + + //------------------------------------------------------------------------ + inline const trans_perspective& + trans_perspective::from_affine(const trans_affine& a) + { + sx = a.sx; shy = a.shy; w0 = 0; + shx = a.shx; sy = a.sy; w1 = 0; + tx = a.tx; ty = a.ty; w2 = 1; + return *this; + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant() const + { + return sx * (sy * w2 - ty * w1) + + shx * (ty * w0 - shy * w2) + + tx * (shy * w1 - sy * w0); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::determinant_reciprocal() const + { + return 1.0 / determinant(); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_valid(double epsilon) const + { + return fabs(sx) > epsilon && fabs(sy) > epsilon && fabs(w2) > epsilon; + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_identity(double epsilon) const + { + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(w0, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(w1, 0.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon) && + is_equal_eps(w2, 1.0, epsilon); + } + + //------------------------------------------------------------------------ + inline bool trans_perspective::is_equal(const trans_perspective& m, + double epsilon) const + { + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(w0, m.w0, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(w1, m.w1, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon) && + is_equal_eps(w2, m.w2, epsilon); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::scale() const + { + double x = 0.707106781 * sx + 0.707106781 * shx; + double y = 0.707106781 * shy + 0.707106781 * sy; + return sqrt(x*x + y*y); + } + + //------------------------------------------------------------------------ + inline double trans_perspective::rotation() const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 0.0; + transform(&x1, &y1); + transform(&x2, &y2); + return atan2(y2-y1, x2-x1); + } + + //------------------------------------------------------------------------ + void trans_perspective::translation(double* dx, double* dy) const + { + *dx = tx; + *dy = ty; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling(double* x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 1.0; + trans_perspective t(*this); + t *= trans_affine_rotation(-rotation()); + t.transform(&x1, &y1); + t.transform(&x2, &y2); + *x = x2 - x1; + *y = y2 - y1; + } + + //------------------------------------------------------------------------ + void trans_perspective::scaling_abs(double* x, double* y) const + { + *x = sqrt(sx * sx + shx * shx); + *y = sqrt(shy * shy + sy * sy); + } + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_single_path.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_single_path.h new file mode 100644 index 00000000000..9f4bf53bdbc --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_single_path.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_TRANS_SINGLE_PATH_INCLUDED +#define AGG_TRANS_SINGLE_PATH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + // See also: agg_trans_single_path.cpp + // + //-------------------------------------------------------trans_single_path + class trans_single_path + { + enum status_e + { + initial, + making_path, + ready + }; + + public: + typedef vertex_sequence vertex_storage; + + trans_single_path(); + + //-------------------------------------------------------------------- + void base_length(double v) { m_base_length = v; } + double base_length() const { return m_base_length; } + + //-------------------------------------------------------------------- + void preserve_x_scale(bool f) { m_preserve_x_scale = f; } + bool preserve_x_scale() const { return m_preserve_x_scale; } + + //-------------------------------------------------------------------- + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + void finalize_path(); + + //-------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if(is_move_to(cmd)) + { + move_to(x, y); + } + else + { + if(is_vertex(cmd)) + { + line_to(x, y); + } + } + } + finalize_path(); + } + + //-------------------------------------------------------------------- + double total_length() const; + void transform(double *x, double *y) const; + + private: + vertex_storage m_src_vertices; + double m_base_length; + double m_kindex; + status_e m_status; + bool m_preserve_x_scale; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_viewport.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_viewport.h new file mode 100644 index 00000000000..7088f990780 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_viewport.h @@ -0,0 +1,303 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Viewport transformer - simple orthogonal conversions from world coordinates +// to screen (device) ones. +// +//---------------------------------------------------------------------------- + +#ifndef AGG_TRANS_VIEWPORT_INCLUDED +#define AGG_TRANS_VIEWPORT_INCLUDED + +#include +#include "agg_trans_affine.h" + + +namespace agg +{ + + enum aspect_ratio_e + { + aspect_ratio_stretch, + aspect_ratio_meet, + aspect_ratio_slice + }; + + + //----------------------------------------------------------trans_viewport + class trans_viewport + { + public: + //------------------------------------------------------------------- + trans_viewport() : + m_world_x1(0.0), + m_world_y1(0.0), + m_world_x2(1.0), + m_world_y2(1.0), + m_device_x1(0.0), + m_device_y1(0.0), + m_device_x2(1.0), + m_device_y2(1.0), + m_aspect(aspect_ratio_stretch), + m_is_valid(true), + m_align_x(0.5), + m_align_y(0.5), + m_wx1(0.0), + m_wy1(0.0), + m_wx2(1.0), + m_wy2(1.0), + m_dx1(0.0), + m_dy1(0.0), + m_kx(1.0), + m_ky(1.0) + {} + + //------------------------------------------------------------------- + void preserve_aspect_ratio(double alignx, + double aligny, + aspect_ratio_e aspect) + { + m_align_x = alignx; + m_align_y = aligny; + m_aspect = aspect; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double x1, double y1, double x2, double y2) + { + m_device_x1 = x1; + m_device_y1 = y1; + m_device_x2 = x2; + m_device_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void world_viewport(double x1, double y1, double x2, double y2) + { + m_world_x1 = x1; + m_world_y1 = y1; + m_world_x2 = x2; + m_world_y2 = y2; + update(); + } + + //------------------------------------------------------------------- + void device_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_device_x1; + *y1 = m_device_y1; + *x2 = m_device_x2; + *y2 = m_device_y2; + } + + //------------------------------------------------------------------- + void world_viewport(double* x1, double* y1, double* x2, double* y2) const + { + *x1 = m_world_x1; + *y1 = m_world_y1; + *x2 = m_world_x2; + *y2 = m_world_y2; + } + + //------------------------------------------------------------------- + void world_viewport_actual(double* x1, double* y1, + double* x2, double* y2) const + { + *x1 = m_wx1; + *y1 = m_wy1; + *x2 = m_wx2; + *y2 = m_wy2; + } + + //------------------------------------------------------------------- + bool is_valid() const { return m_is_valid; } + double align_x() const { return m_align_x; } + double align_y() const { return m_align_y; } + aspect_ratio_e aspect_ratio() const { return m_aspect; } + + //------------------------------------------------------------------- + void transform(double* x, double* y) const + { + *x = (*x - m_wx1) * m_kx + m_dx1; + *y = (*y - m_wy1) * m_ky + m_dy1; + } + + //------------------------------------------------------------------- + void transform_scale_only(double* x, double* y) const + { + *x *= m_kx; + *y *= m_ky; + } + + //------------------------------------------------------------------- + void inverse_transform(double* x, double* y) const + { + *x = (*x - m_dx1) / m_kx + m_wx1; + *y = (*y - m_dy1) / m_ky + m_wy1; + } + + //------------------------------------------------------------------- + void inverse_transform_scale_only(double* x, double* y) const + { + *x /= m_kx; + *y /= m_ky; + } + + //------------------------------------------------------------------- + double device_dx() const { return m_dx1 - m_wx1 * m_kx; } + double device_dy() const { return m_dy1 - m_wy1 * m_ky; } + + //------------------------------------------------------------------- + double scale_x() const + { + return m_kx; + } + + //------------------------------------------------------------------- + double scale_y() const + { + return m_ky; + } + + //------------------------------------------------------------------- + double scale() const + { + return (m_kx + m_ky) * 0.5; + } + + //------------------------------------------------------------------- + trans_affine to_affine() const + { + trans_affine mtx = trans_affine_translation(-m_wx1, -m_wy1); + mtx *= trans_affine_scaling(m_kx, m_ky); + mtx *= trans_affine_translation(m_dx1, m_dy1); + return mtx; + } + + //------------------------------------------------------------------- + trans_affine to_affine_scale_only() const + { + return trans_affine_scaling(m_kx, m_ky); + } + + //------------------------------------------------------------------- + unsigned byte_size() const + { + return sizeof(*this); + } + + void serialize(int8u* ptr) const + { + memcpy(ptr, this, sizeof(*this)); + } + + void deserialize(const int8u* ptr) + { + memcpy(this, ptr, sizeof(*this)); + } + + private: + void update(); + + double m_world_x1; + double m_world_y1; + double m_world_x2; + double m_world_y2; + double m_device_x1; + double m_device_y1; + double m_device_x2; + double m_device_y2; + aspect_ratio_e m_aspect; + bool m_is_valid; + double m_align_x; + double m_align_y; + double m_wx1; + double m_wy1; + double m_wx2; + double m_wy2; + double m_dx1; + double m_dy1; + double m_kx; + double m_ky; + }; + + + + //----------------------------------------------------------------------- + inline void trans_viewport::update() + { + const double epsilon = 1e-30; + if(fabs(m_world_x1 - m_world_x2) < epsilon || + fabs(m_world_y1 - m_world_y2) < epsilon || + fabs(m_device_x1 - m_device_x2) < epsilon || + fabs(m_device_y1 - m_device_y2) < epsilon) + { + m_wx1 = m_world_x1; + m_wy1 = m_world_y1; + m_wx2 = m_world_x1 + 1.0; + m_wy2 = m_world_y2 + 1.0; + m_dx1 = m_device_x1; + m_dy1 = m_device_y1; + m_kx = 1.0; + m_ky = 1.0; + m_is_valid = false; + return; + } + + double world_x1 = m_world_x1; + double world_y1 = m_world_y1; + double world_x2 = m_world_x2; + double world_y2 = m_world_y2; + double device_x1 = m_device_x1; + double device_y1 = m_device_y1; + double device_x2 = m_device_x2; + double device_y2 = m_device_y2; + if(m_aspect != aspect_ratio_stretch) + { + double d; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + + if((m_aspect == aspect_ratio_meet) == (m_kx < m_ky)) + { + d = (world_y2 - world_y1) * m_ky / m_kx; + world_y1 += (world_y2 - world_y1 - d) * m_align_y; + world_y2 = world_y1 + d; + } + else + { + d = (world_x2 - world_x1) * m_kx / m_ky; + world_x1 += (world_x2 - world_x1 - d) * m_align_x; + world_x2 = world_x1 + d; + } + } + m_wx1 = world_x1; + m_wy1 = world_y1; + m_wx2 = world_x2; + m_wy2 = world_y2; + m_dx1 = device_x1; + m_dy1 = device_y1; + m_kx = (device_x2 - device_x1) / (world_x2 - world_x1); + m_ky = (device_y2 - device_y1) / (world_y2 - world_y1); + m_is_valid = true; + } + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_warp_magnifier.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_warp_magnifier.h new file mode 100644 index 00000000000..38a92dbec8d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_trans_warp_magnifier.h @@ -0,0 +1,56 @@ +//---------------------------------------------------------------------------- +// 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_WARP_MAGNIFIER_INCLUDED +#define AGG_WARP_MAGNIFIER_INCLUDED + + +namespace agg +{ + + //----------------------------------------------------trans_warp_magnifier + // + // See Inmplementation agg_trans_warp_magnifier.cpp + // + class trans_warp_magnifier + { + public: + trans_warp_magnifier() : m_xc(0.0), m_yc(0.0), m_magn(1.0), m_radius(1.0) {} + + void center(double x, double y) { m_xc = x; m_yc = y; } + void magnification(double m) { m_magn = m; } + void radius(double r) { m_radius = r; } + + double xc() const { return m_xc; } + double yc() const { return m_yc; } + double magnification() const { return m_magn; } + double radius() const { return m_radius; } + + void transform(double* x, double* y) const; + void inverse_transform(double* x, double* y) const; + + private: + double m_xc; + double m_yc; + double m_magn; + double m_radius; + }; + + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_bspline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_bspline.h new file mode 100644 index 00000000000..a2944548c02 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_bspline.h @@ -0,0 +1,74 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_BSPLINE_INCLUDED +#define AGG_VCGEN_BSPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_bspline.h" + + +namespace agg +{ + + //==========================================================vcgen_bspline + class vcgen_bspline + { + enum status_e + { + initial, + ready, + polygon, + end_poly, + stop + }; + + public: + typedef pod_bvector vertex_storage; + + vcgen_bspline(); + + void interpolation_step(double v) { m_interpolation_step = v; } + double interpolation_step() const { return m_interpolation_step; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_bspline(const vcgen_bspline&); + const vcgen_bspline& operator = (const vcgen_bspline&); + + vertex_storage m_src_vertices; + bspline m_spline_x; + bspline m_spline_y; + double m_interpolation_step; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_cur_abscissa; + double m_max_abscissa; + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_contour.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_contour.h new file mode 100644 index 00000000000..8c25da13f5a --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_contour.h @@ -0,0 +1,94 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_CONTOUR_INCLUDED +#define AGG_VCGEN_CONTOUR_INCLUDED + +#include "agg_math_stroke.h" + +namespace agg +{ + + //----------------------------------------------------------vcgen_contour + // + // See Implementation agg_vcgen_contour.cpp + // + class vcgen_contour + { + enum status_e + { + initial, + ready, + outline, + out_vertices, + end_poly, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + typedef pod_bvector coord_storage; + + vcgen_contour(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(m_width = w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_width; } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void auto_detect_orientation(bool v) { m_auto_detect = v; } + bool auto_detect_orientation() const { return m_auto_detect; } + + // Generator interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_contour(const vcgen_contour&); + const vcgen_contour& operator = (const vcgen_contour&); + + math_stroke m_stroker; + double m_width; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + status_e m_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + unsigned m_closed; + unsigned m_orientation; + bool m_auto_detect; + }; + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_dash.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_dash.h new file mode 100644 index 00000000000..c87dce4c815 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_dash.h @@ -0,0 +1,93 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Line dash generator +// +//---------------------------------------------------------------------------- +#ifndef AGG_VCGEN_DASH_INCLUDED +#define AGG_VCGEN_DASH_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //---------------------------------------------------------------vcgen_dash + // + // See Implementation agg_vcgen_dash.cpp + // + class vcgen_dash + { + enum max_dashes_e + { + max_dashes = 32 + }; + + enum status_e + { + initial, + ready, + polyline, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + + vcgen_dash(); + + void remove_all_dashes(); + void add_dash(double dash_len, double gap_len); + void dash_start(double ds); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_dash(const vcgen_dash&); + const vcgen_dash& operator = (const vcgen_dash&); + + void calc_dash_start(double ds); + + double m_dashes[max_dashes]; + double m_total_dash_len; + unsigned m_num_dashes; + double m_dash_start; + double m_shorten; + double m_curr_dash_start; + unsigned m_curr_dash; + double m_curr_rest; + const vertex_dist* m_v1; + const vertex_dist* m_v2; + + vertex_storage m_src_vertices; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_markers_term.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_markers_term.h new file mode 100644 index 00000000000..ee1e74e3eb4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_markers_term.h @@ -0,0 +1,66 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_MARKERS_TERM_INCLUDED +#define AGG_VCGEN_MARKERS_TERM_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + +namespace agg +{ + + //======================================================vcgen_markers_term + // + // See Implemantation agg_vcgen_markers_term.cpp + // Terminal markers generator (arrowhead/arrowtail) + // + //------------------------------------------------------------------------ + class vcgen_markers_term + { + public: + vcgen_markers_term() : m_curr_id(0), m_curr_idx(0) {} + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_markers_term(const vcgen_markers_term&); + const vcgen_markers_term& operator = (const vcgen_markers_term&); + + struct coord_type + { + double x, y; + + coord_type() {} + coord_type(double x_, double y_) : x(x_), y(y_) {} + }; + + typedef pod_bvector coord_storage; + + coord_storage m_markers; + unsigned m_curr_id; + unsigned m_curr_idx; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_smooth_poly1.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_smooth_poly1.h new file mode 100644 index 00000000000..80fc0fb7969 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_smooth_poly1.h @@ -0,0 +1,87 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_SMOOTH_POLY1_INCLUDED +#define AGG_VCGEN_SMOOTH_POLY1_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" + + +namespace agg +{ + + //======================================================vcgen_smooth_poly1 + // + // See Implementation agg_vcgen_smooth_poly1.cpp + // Smooth polygon generator + // + //------------------------------------------------------------------------ + class vcgen_smooth_poly1 + { + enum status_e + { + initial, + ready, + polygon, + ctrl_b, + ctrl_e, + ctrl1, + ctrl2, + end_poly, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + + vcgen_smooth_poly1(); + + void smooth_value(double v) { m_smooth_value = v * 0.5; } + double smooth_value() const { return m_smooth_value * 2.0; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_smooth_poly1(const vcgen_smooth_poly1&); + const vcgen_smooth_poly1& operator = (const vcgen_smooth_poly1&); + + void calculate(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3); + + vertex_storage m_src_vertices; + double m_smooth_value; + unsigned m_closed; + status_e m_status; + unsigned m_src_vertex; + double m_ctrl1_x; + double m_ctrl1_y; + double m_ctrl2_x; + double m_ctrl2_y; + }; + +} + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_stroke.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_stroke.h new file mode 100644 index 00000000000..778223fe40e --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_stroke.h @@ -0,0 +1,102 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_STROKE_INCLUDED +#define AGG_VCGEN_STROKE_INCLUDED + +#include "agg_math_stroke.h" + + +namespace agg +{ + + //============================================================vcgen_stroke + // + // See Implementation agg_vcgen_stroke.cpp + // Stroke generator + // + //------------------------------------------------------------------------ + class vcgen_stroke + { + enum status_e + { + initial, + ready, + cap1, + cap2, + outline1, + close_first, + outline2, + out_vertices, + end_poly1, + end_poly2, + stop + }; + + public: + typedef vertex_sequence vertex_storage; + typedef pod_bvector coord_storage; + + vcgen_stroke(); + + void line_cap(line_cap_e lc) { m_stroker.line_cap(lc); } + void line_join(line_join_e lj) { m_stroker.line_join(lj); } + void inner_join(inner_join_e ij) { m_stroker.inner_join(ij); } + + line_cap_e line_cap() const { return m_stroker.line_cap(); } + line_join_e line_join() const { return m_stroker.line_join(); } + inner_join_e inner_join() const { return m_stroker.inner_join(); } + + void width(double w) { m_stroker.width(w); } + void miter_limit(double ml) { m_stroker.miter_limit(ml); } + void miter_limit_theta(double t) { m_stroker.miter_limit_theta(t); } + void inner_miter_limit(double ml) { m_stroker.inner_miter_limit(ml); } + void approximation_scale(double as) { m_stroker.approximation_scale(as); } + + double width() const { return m_stroker.width(); } + double miter_limit() const { return m_stroker.miter_limit(); } + double inner_miter_limit() const { return m_stroker.inner_miter_limit(); } + double approximation_scale() const { return m_stroker.approximation_scale(); } + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + vcgen_stroke(const vcgen_stroke&); + const vcgen_stroke& operator = (const vcgen_stroke&); + + math_stroke m_stroker; + vertex_storage m_src_vertices; + coord_storage m_out_vertices; + double m_shorten; + unsigned m_closed; + status_e m_status; + status_e m_prev_status; + unsigned m_src_vertex; + unsigned m_out_vertex; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_vertex_sequence.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_vertex_sequence.h new file mode 100644 index 00000000000..5adc6715970 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vcgen_vertex_sequence.h @@ -0,0 +1,135 @@ +//---------------------------------------------------------------------------- +// 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_VCGEN_VERTEX_SEQUENCE_INCLUDED +#define AGG_VCGEN_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_vertex_sequence.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //===================================================vcgen_vertex_sequence + class vcgen_vertex_sequence + { + public: + typedef vertex_dist_cmd vertex_type; + typedef vertex_sequence vertex_storage; + + vcgen_vertex_sequence() : + m_flags(0), + m_cur_vertex(0), + m_shorten(0.0), + m_ready(false) + { + } + + // Vertex Generator Interface + void remove_all(); + void add_vertex(double x, double y, unsigned cmd); + + // Vertex Source Interface + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + void shorten(double s) { m_shorten = s; } + double shorten() const { return m_shorten; } + + private: + vcgen_vertex_sequence(const vcgen_vertex_sequence&); + const vcgen_vertex_sequence& operator = (const vcgen_vertex_sequence&); + + vertex_storage m_src_vertices; + unsigned m_flags; + unsigned m_cur_vertex; + double m_shorten; + bool m_ready; + }; + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::remove_all() + { + m_ready = false; + m_src_vertices.remove_all(); + m_cur_vertex = 0; + m_flags = 0; + } + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::add_vertex(double x, double y, unsigned cmd) + { + m_ready = false; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist_cmd(x, y, cmd)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist_cmd(x, y, cmd)); + } + else + { + m_flags = cmd & path_flags_mask; + } + } + } + + + //------------------------------------------------------------------------ + inline void vcgen_vertex_sequence::rewind(unsigned) + { + if(!m_ready) + { + m_src_vertices.close(is_closed(m_flags)); + shorten_path(m_src_vertices, m_shorten, get_close_flag(m_flags)); + } + m_ready = true; + m_cur_vertex = 0; + } + + //------------------------------------------------------------------------ + inline unsigned vcgen_vertex_sequence::vertex(double* x, double* y) + { + if(!m_ready) + { + rewind(0); + } + + if(m_cur_vertex == m_src_vertices.size()) + { + ++m_cur_vertex; + return path_cmd_end_poly | m_flags; + } + + if(m_cur_vertex > m_src_vertices.size()) + { + return path_cmd_stop; + } + + vertex_type& v = m_src_vertices[m_cur_vertex++]; + *x = v.x; + *y = v.y; + return v.cmd; + } + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vertex_sequence.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vertex_sequence.h new file mode 100644 index 00000000000..2ad0701b37a --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vertex_sequence.h @@ -0,0 +1,172 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// vertex_sequence container and vertex_dist struct +// +//---------------------------------------------------------------------------- +#ifndef AGG_VERTEX_SEQUENCE_INCLUDED +#define AGG_VERTEX_SEQUENCE_INCLUDED + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_math.h" + +namespace agg +{ + + //----------------------------------------------------------vertex_sequence + // Modified agg::pod_bvector. The data is interpreted as a sequence + // of vertices. It means that the type T must expose: + // + // bool T::operator() (const T& val) + // + // that is called every time new vertex is being added. The main purpose + // of this operator is the possibility to calculate some values during + // adding and to return true if the vertex fits some criteria or false if + // it doesn't. In the last case the new vertex is not added. + // + // The simple example is filtering coinciding vertices with calculation + // of the distance between the current and previous ones: + // + // struct vertex_dist + // { + // double x; + // double y; + // double dist; + // + // vertex_dist() {} + // vertex_dist(double x_, double y_) : + // x(x_), + // y(y_), + // dist(0.0) + // { + // } + // + // bool operator () (const vertex_dist& val) + // { + // return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; + // } + // }; + // + // Function close() calls this operator and removes the last vertex if + // necessary. + //------------------------------------------------------------------------ + template + class vertex_sequence : public pod_bvector + { + public: + typedef pod_bvector base_type; + + void add(const T& val); + void modify_last(const T& val); + void close(bool remove_flag); + }; + + + + //------------------------------------------------------------------------ + template + void vertex_sequence::add(const T& val) + { + if(base_type::size() > 1) + { + if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) + { + base_type::remove_last(); + } + } + base_type::add(val); + } + + + //------------------------------------------------------------------------ + template + void vertex_sequence::modify_last(const T& val) + { + base_type::remove_last(); + add(val); + } + + + + //------------------------------------------------------------------------ + template + void vertex_sequence::close(bool closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; + T t = (*this)[base_type::size() - 1]; + base_type::remove_last(); + modify_last(t); + } + + if(closed) + { + while(base_type::size() > 1) + { + if((*this)[base_type::size() - 1]((*this)[0])) break; + base_type::remove_last(); + } + } + } + + + //-------------------------------------------------------------vertex_dist + // Vertex (x, y) with the distance to the next one. The last vertex has + // distance between the last and the first points if the polygon is closed + // and 0.0 if it's a polyline. + struct vertex_dist + { + double x; + double y; + double dist; + + vertex_dist() {} + vertex_dist(double x_, double y_) : + x(x_), + y(y_), + dist(0.0) + { + } + + bool operator () (const vertex_dist& val) + { + bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; + if(!ret) dist = 1.0 / vertex_dist_epsilon; + return ret; + } + }; + + + + //--------------------------------------------------------vertex_dist_cmd + // Save as the above but with additional "command" value + struct vertex_dist_cmd : public vertex_dist + { + unsigned cmd; + + vertex_dist_cmd() {} + vertex_dist_cmd(double x_, double y_, unsigned cmd_) : + vertex_dist(x_, y_), + cmd(cmd_) + { + } + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polygon.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polygon.h new file mode 100644 index 00000000000..ded754e2114 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polygon.h @@ -0,0 +1,83 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_CLIP_POLYGON_INCLUDED +#define AGG_VPGEN_CLIP_POLYGON_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polygon + // + // See Implementation agg_vpgen_clip_polygon.cpp + // + class vpgen_clip_polygon + { + public: + vpgen_clip_polygon() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_clip_flags(0), + m_num_vertices(0), + m_vertex(0), + m_cmd(path_cmd_move_to) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return true; } + static bool auto_unclose() { return false; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + unsigned clipping_flags(double x, double y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + unsigned m_clip_flags; + double m_x[4]; + double m_y[4]; + unsigned m_num_vertices; + unsigned m_vertex; + unsigned m_cmd; + }; + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polyline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polyline.h new file mode 100644 index 00000000000..b070a7759e5 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_clip_polyline.h @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_CLIP_POLYLINE_INCLUDED +#define AGG_VPGEN_CLIP_POLYLINE_INCLUDED + +#include "agg_basics.h" + +namespace agg +{ + + //======================================================vpgen_clip_polyline + // + // See Implementation agg_vpgen_clip_polyline.cpp + // + class vpgen_clip_polyline + { + public: + vpgen_clip_polyline() : + m_clip_box(0, 0, 1, 1), + m_x1(0), + m_y1(0), + m_num_vertices(0), + m_vertex(0), + m_move_to(false) + { + } + + void clip_box(double x1, double y1, double x2, double y2) + { + m_clip_box.x1 = x1; + m_clip_box.y1 = y1; + m_clip_box.x2 = x2; + m_clip_box.y2 = y2; + m_clip_box.normalize(); + } + + double x1() const { return m_clip_box.x1; } + double y1() const { return m_clip_box.y1; } + double x2() const { return m_clip_box.x2; } + double y2() const { return m_clip_box.y2; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return true; } + + void reset(); + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + rect_d m_clip_box; + double m_x1; + double m_y1; + double m_x[2]; + double m_y[2]; + unsigned m_cmd[2]; + unsigned m_num_vertices; + unsigned m_vertex; + bool m_move_to; + }; + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_segmentator.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_segmentator.h new file mode 100644 index 00000000000..29b3c9fa6f0 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/agg_vpgen_segmentator.h @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------- +// 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_VPGEN_SEGMENTATOR_INCLUDED +#define AGG_VPGEN_SEGMENTATOR_INCLUDED + +#include +#include "agg_basics.h" + +namespace agg +{ + + //=======================================================vpgen_segmentator + // + // See Implementation agg_vpgen_segmentator.cpp + // + class vpgen_segmentator + { + public: + vpgen_segmentator() : m_approximation_scale(1.0) {} + + void approximation_scale(double s) { m_approximation_scale = s; } + double approximation_scale() const { return m_approximation_scale; } + + static bool auto_close() { return false; } + static bool auto_unclose() { return false; } + + void reset() { m_cmd = path_cmd_stop; } + void move_to(double x, double y); + void line_to(double x, double y); + unsigned vertex(double* x, double* y); + + private: + double m_approximation_scale; + double m_x1; + double m_y1; + double m_dx; + double m_dy; + double m_dl; + double m_ddl; + unsigned m_cmd; + }; + + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_bezier_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_bezier_ctrl.h new file mode 100644 index 00000000000..01851eb3e18 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_bezier_ctrl.h @@ -0,0 +1,196 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes bezier_ctrl_impl, bezier_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_BEZIER_CTRL_INCLUDED +#define AGG_BEZIER_CTRL_INCLUDED + +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_conv_stroke.h" +#include "agg_conv_curve.h" +#include "agg_polygon_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------bezier_ctrl_impl + class bezier_ctrl_impl : public ctrl + { + public: + bezier_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4); + curve4& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + double x4() const { return m_poly.xn(3); } + double y4() const { return m_poly.yn(3); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + void x4(double x) { m_poly.xn(3) = x; } + void y4(double y) { m_poly.yn(3) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 7; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve4 m_curve; + ellipse m_ellipse; + conv_stroke m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------bezier_ctrl + template class bezier_ctrl : public bezier_ctrl_impl + { + public: + bezier_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + bezier_ctrl(const bezier_ctrl&); + const bezier_ctrl& operator = (const bezier_ctrl&); + + ColorT m_color; + }; + + + + + + //--------------------------------------------------------curve3_ctrl_impl + class curve3_ctrl_impl : public ctrl + { + public: + curve3_ctrl_impl(); + + void curve(double x1, double y1, + double x2, double y2, + double x3, double y3); + curve3& curve(); + + double x1() const { return m_poly.xn(0); } + double y1() const { return m_poly.yn(0); } + double x2() const { return m_poly.xn(1); } + double y2() const { return m_poly.yn(1); } + double x3() const { return m_poly.xn(2); } + double y3() const { return m_poly.yn(2); } + + void x1(double x) { m_poly.xn(0) = x; } + void y1(double y) { m_poly.yn(0) = y; } + void x2(double x) { m_poly.xn(1) = x; } + void y2(double y) { m_poly.yn(1) = y; } + void x3(double x) { m_poly.xn(2) = x; } + void y3(double y) { m_poly.yn(2) = y; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_poly.point_radius(r); } + double point_radius() const { return m_poly.point_radius(); } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 6; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + + private: + curve3 m_curve; + ellipse m_ellipse; + conv_stroke m_stroke; + polygon_ctrl_impl m_poly; + unsigned m_idx; + }; + + + + //----------------------------------------------------------curve3_ctrl + template class curve3_ctrl : public curve3_ctrl_impl + { + public: + curve3_ctrl() : + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + curve3_ctrl(const curve3_ctrl&); + const curve3_ctrl& operator = (const curve3_ctrl&); + + ColorT m_color; + }; + + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_cbox_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_cbox_ctrl.h new file mode 100644 index 00000000000..7ecbce27f42 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_cbox_ctrl.h @@ -0,0 +1,112 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes cbox_ctrl_impl, cbox_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CBOX_CTRL_INCLUDED +#define AGG_CBOX_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + + +namespace agg +{ + + //----------------------------------------------------------cbox_ctrl_impl + class cbox_ctrl_impl : public ctrl + { + public: + cbox_ctrl_impl(double x, double y, const char* label, bool flip_y=false); + + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + + const char* label() { return m_label; } + void label(const char* l); + + bool status() const { return m_status; } + void status(bool st) { m_status = st; } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 3; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + double m_text_thickness; + double m_text_height; + double m_text_width; + char m_label[128]; + bool m_status; + double m_vx[32]; + double m_vy[32]; + + gsv_text m_text; + conv_stroke m_text_poly; + + unsigned m_idx; + unsigned m_vertex; + }; + + + //----------------------------------------------------------cbox_ctrl_impl + template class cbox_ctrl : public cbox_ctrl_impl + { + public: + cbox_ctrl(double x, double y, const char* label, bool flip_y=false) : + cbox_ctrl_impl(x, y, label, flip_y), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_inactive_color(rgba(0.0, 0.0, 0.0)), + m_active_color(rgba(0.4, 0.0, 0.0)) + { + m_colors[0] = &m_inactive_color; + m_colors[1] = &m_text_color; + m_colors[2] = &m_active_color; + } + + void text_color(const ColorT& c) { m_text_color = c; } + void inactive_color(const ColorT& c) { m_inactive_color = c; } + void active_color(const ColorT& c) { m_active_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + cbox_ctrl(const cbox_ctrl&); + const cbox_ctrl& operator = (const cbox_ctrl&); + + ColorT m_text_color; + ColorT m_inactive_color; + ColorT m_active_color; + ColorT* m_colors[3]; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_ctrl.h new file mode 100644 index 00000000000..7e811c63e17 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_ctrl.h @@ -0,0 +1,118 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Function render_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_CTRL_INCLUDED +#define AGG_CTRL_INCLUDED + +#include "agg_trans_affine.h" +#include "agg_renderer_scanline.h" + +namespace agg +{ + + //--------------------------------------------------------------------ctrl + class ctrl + { + public: + //-------------------------------------------------------------------- + virtual ~ctrl() {} + ctrl(double x1, double y1, double x2, double y2, bool flip_y) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), + m_flip_y(flip_y), + m_mtx(0) + { + } + + //-------------------------------------------------------------------- + virtual bool in_rect(double x, double y) const = 0; + virtual bool on_mouse_button_down(double x, double y) = 0; + virtual bool on_mouse_button_up(double x, double y) = 0; + virtual bool on_mouse_move(double x, double y, bool button_flag) = 0; + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up) = 0; + + //-------------------------------------------------------------------- + void transform(const trans_affine& mtx) { m_mtx = &mtx; } + void no_transform() { m_mtx = 0; } + + //-------------------------------------------------------------------- + void transform_xy(double* x, double* y) const + { + if(m_flip_y) *y = m_y1 + m_y2 - *y; + if(m_mtx) m_mtx->transform(x, y); + } + + //-------------------------------------------------------------------- + void inverse_transform_xy(double* x, double* y) const + { + if(m_mtx) m_mtx->inverse_transform(x, y); + if(m_flip_y) *y = m_y1 + m_y2 - *y; + } + + //-------------------------------------------------------------------- + double scale() const { return m_mtx ? m_mtx->scale() : 1.0; } + + private: + ctrl(const ctrl&); + const ctrl& operator = (const ctrl&); + + protected: + double m_x1; + double m_y1; + double m_x2; + double m_y2; + + private: + bool m_flip_y; + const trans_affine* m_mtx; + }; + + + //-------------------------------------------------------------------- + template + void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + ras.reset(); + ras.add_path(c, i); + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + } + + + //-------------------------------------------------------------------- + template + void render_ctrl_rs(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + for(i = 0; i < c.num_paths(); i++) + { + ras.reset(); + ras.add_path(c, i); + r.color(c.color(i)); + render_scanlines(ras, sl, r); + } + } + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_ctrl.h new file mode 100644 index 00000000000..0a645a71468 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_ctrl.h @@ -0,0 +1,170 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class gamma_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_CTRL_INCLUDED +#define AGG_GAMMA_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_gamma_spline.h" +#include "agg_ellipse.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + //------------------------------------------------------------------------ + // Class that can be used to create an interactive control to set up + // gamma arrays. + //------------------------------------------------------------------------ + class gamma_ctrl_impl : public ctrl + { + public: + gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + // Set other parameters + void border_width(double t, double extra=0.0); + void curve_width(double t) { m_curve_width = t; } + void grid_width(double t) { m_grid_width = t; } + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + void point_size(double s) { m_point_size = s; } + + // Event handlers. Just call them if the respective events + // in your system occure. The functions return true if redrawing + // is required. + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + void change_active_point(); + + // A copy of agg::gamma_spline interface + void values(double kx1, double ky1, double kx2, double ky2); + void values(double* kx1, double* ky1, double* kx2, double* ky2) const; + const unsigned char* gamma() const { return m_gamma_spline.gamma(); } + double y(double x) const { return m_gamma_spline.y(x); } + double operator() (double x) const { return m_gamma_spline.y(x); } + const gamma_spline& get_gamma_spline() const { return m_gamma_spline; } + + // Vertex soutce interface + unsigned num_paths() { return 7; } + void rewind(unsigned idx); + unsigned vertex(double* x, double* y); + + private: + void calc_spline_box(); + void calc_points(); + void calc_values(); + + gamma_spline m_gamma_spline; + double m_border_width; + double m_border_extra; + double m_curve_width; + double m_grid_width; + double m_text_thickness; + double m_point_size; + double m_text_height; + double m_text_width; + double m_xc1; + double m_yc1; + double m_xc2; + double m_yc2; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_xt1; + double m_yt1; + double m_xt2; + double m_yt2; + conv_stroke m_curve_poly; + ellipse m_ellipse; + gsv_text m_text; + conv_stroke m_text_poly; + unsigned m_idx; + unsigned m_vertex; + double m_vx[32]; + double m_vy[32]; + double m_xp1; + double m_yp1; + double m_xp2; + double m_yp2; + bool m_p1_active; + unsigned m_mouse_point; + double m_pdx; + double m_pdy; + }; + + + + template class gamma_ctrl : public gamma_ctrl_impl + { + public: + gamma_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + gamma_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_curve_color(rgba(0.0, 0.0, 0.0)), + m_grid_color(rgba(0.2, 0.2, 0.0)), + m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)), + m_active_pnt_color(rgba(1.0, 0.0, 0.0)), + m_text_color(rgba(0.0, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_curve_color; + m_colors[3] = &m_grid_color; + m_colors[4] = &m_inactive_pnt_color; + m_colors[5] = &m_active_pnt_color; + m_colors[6] = &m_text_color; + } + + // Set colors + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void curve_color(const ColorT& c) { m_curve_color = c; } + void grid_color(const ColorT& c) { m_grid_color = c; } + void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; } + void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; } + void text_color(const ColorT& c) { m_text_color = c; } + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + gamma_ctrl(const gamma_ctrl&); + const gamma_ctrl& operator = (const gamma_ctrl&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_curve_color; + ColorT m_grid_color; + ColorT m_inactive_pnt_color; + ColorT m_active_pnt_color; + ColorT m_text_color; + ColorT* m_colors[7]; + }; + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_spline.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_spline.h new file mode 100644 index 00000000000..4f21710d9f2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_gamma_spline.h @@ -0,0 +1,95 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class gamma_spline +// +//---------------------------------------------------------------------------- + +#ifndef AGG_GAMMA_SPLINE_INCLUDED +#define AGG_GAMMA_SPLINE_INCLUDED + +#include "agg_basics.h" +#include "agg_bspline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Class-helper for calculation gamma-correction arrays. A gamma-correction + // array is an array of 256 unsigned chars that determine the actual values + // of Anti-Aliasing for each pixel coverage value from 0 to 255. If all the + // values in the array are equal to its index, i.e. 0,1,2,3,... there's + // no gamma-correction. Class agg::polyfill allows you to use custom + // gamma-correction arrays. You can calculate it using any approach, and + // class gamma_spline allows you to calculate almost any reasonable shape + // of the gamma-curve with using only 4 values - kx1, ky1, kx2, ky2. + // + // kx2 + // +----------------------------------+ + // | | | . | + // | | | . | ky2 + // | | . ------| + // | | . | + // | | . | + // |----------------.|----------------| + // | . | | + // | . | | + // |-------. | | + // ky1 | . | | | + // | . | | | + // +----------------------------------+ + // kx1 + // + // Each value can be in range [0...2]. Value 1.0 means one quarter of the + // bounding rectangle. Function values() calculates the curve by these + // 4 values. After calling it one can get the gamma-array with call gamma(). + // Class also supports the vertex source interface, i.e rewind() and + // vertex(). It's made for convinience and used in class gamma_ctrl. + // Before calling rewind/vertex one must set the bounding box + // box() using pixel coordinates. + //------------------------------------------------------------------------ + + class gamma_spline + { + public: + gamma_spline(); + + void values(double kx1, double ky1, double kx2, double ky2); + const unsigned char* gamma() const { return m_gamma; } + double y(double x) const; + void values(double* kx1, double* ky1, double* kx2, double* ky2) const; + void box(double x1, double y1, double x2, double y2); + + void rewind(unsigned); + unsigned vertex(double* x, double* y); + + private: + unsigned char m_gamma[256]; + double m_x[4]; + double m_y[4]; + bspline m_spline; + double m_x1; + double m_y1; + double m_x2; + double m_y2; + double m_cur_x; + }; + + + + +} + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_polygon_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_polygon_ctrl.h new file mode 100644 index 00000000000..6f465d96b81 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_polygon_ctrl.h @@ -0,0 +1,166 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes polygon_ctrl_impl, polygon_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef POLYGON_CTRL_INCLUDED +#define POLYGON_CTRL_INCLUDED + +#include "agg_array.h" +#include "agg_conv_stroke.h" +#include "agg_ellipse.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + class simple_polygon_vertex_source + { + public: + simple_polygon_vertex_source(const double* polygon, unsigned np, + bool roundoff = false, + bool close = true) : + m_polygon(polygon), + m_num_points(np), + m_vertex(0), + m_roundoff(roundoff), + m_close(close) + { + } + + void close(bool f) { m_close = f; } + bool close() const { return m_close; } + + void rewind(unsigned) + { + m_vertex = 0; + } + + unsigned vertex(double* x, double* y) + { + if(m_vertex > m_num_points) return path_cmd_stop; + if(m_vertex == m_num_points) + { + ++m_vertex; + return path_cmd_end_poly | (m_close ? path_flags_close : 0); + } + *x = m_polygon[m_vertex * 2]; + *y = m_polygon[m_vertex * 2 + 1]; + if(m_roundoff) + { + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + } + ++m_vertex; + return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + } + + private: + const double* m_polygon; + unsigned m_num_points; + unsigned m_vertex; + bool m_roundoff; + bool m_close; + }; + + + + + class polygon_ctrl_impl : public ctrl + { + public: + polygon_ctrl_impl(unsigned np, double point_radius=5); + + unsigned num_points() const { return m_num_points; } + double xn(unsigned n) const { return m_polygon[n * 2]; } + double yn(unsigned n) const { return m_polygon[n * 2 + 1]; } + double& xn(unsigned n) { return m_polygon[n * 2]; } + double& yn(unsigned n) { return m_polygon[n * 2 + 1]; } + + const double* polygon() const { return &m_polygon[0]; } + + void line_width(double w) { m_stroke.width(w); } + double line_width() const { return m_stroke.width(); } + + void point_radius(double r) { m_point_radius = r; } + double point_radius() const { return m_point_radius; } + + void in_polygon_check(bool f) { m_in_polygon_check = f; } + bool in_polygon_check() const { return m_in_polygon_check; } + + void close(bool f) { m_vs.close(f); } + bool close() const { return m_vs.close(); } + + // Vertex source interface + unsigned num_paths() { return 1; } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + + private: + bool check_edge(unsigned i, double x, double y) const; + bool point_in_polygon(double x, double y) const; + + pod_array m_polygon; + unsigned m_num_points; + int m_node; + int m_edge; + simple_polygon_vertex_source m_vs; + conv_stroke m_stroke; + ellipse m_ellipse; + double m_point_radius; + unsigned m_status; + double m_dx; + double m_dy; + bool m_in_polygon_check; + }; + + + + //----------------------------------------------------------polygon_ctrl + template class polygon_ctrl : public polygon_ctrl_impl + { + public: + polygon_ctrl(unsigned np, double point_radius=5) : + polygon_ctrl_impl(np, point_radius), + m_color(rgba(0.0, 0.0, 0.0)) + { + } + + void line_color(const ColorT& c) { m_color = c; } + const ColorT& color(unsigned i) const { return m_color; } + + private: + polygon_ctrl(const polygon_ctrl&); + const polygon_ctrl& operator = (const polygon_ctrl&); + + ColorT m_color; + }; + + + + +} + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_rbox_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_rbox_ctrl.h new file mode 100644 index 00000000000..4d47bccdbb3 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_rbox_ctrl.h @@ -0,0 +1,141 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes rbox_ctrl_impl, rbox_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_RBOX_CTRL_INCLUDED +#define AGG_RBOX_CTRL_INCLUDED + +#include "agg_array.h" +#include "agg_ellipse.h" +#include "agg_conv_stroke.h" +#include "agg_gsv_text.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + + +namespace agg +{ + + //------------------------------------------------------------------------ + class rbox_ctrl_impl : public ctrl + { + public: + rbox_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_width(double t, double extra=0.0); + void text_thickness(double t) { m_text_thickness = t; } + void text_size(double h, double w=0.0); + + void add_item(const char* text); + int cur_item() const { return m_cur_item; } + void cur_item(int i) { m_cur_item = i; } + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 5; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_rbox(); + + double m_border_width; + double m_border_extra; + double m_text_thickness; + double m_text_height; + double m_text_width; + pod_array m_items[32]; + unsigned m_num_items; + int m_cur_item; + + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + + double m_vx[32]; + double m_vy[32]; + unsigned m_draw_item; + double m_dy; + + ellipse m_ellipse; + conv_stroke m_ellipse_poly; + gsv_text m_text; + conv_stroke m_text_poly; + + unsigned m_idx; + unsigned m_vertex; + }; + + + + //------------------------------------------------------------------------ + template class rbox_ctrl : public rbox_ctrl_impl + { + public: + rbox_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + rbox_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_inactive_color(rgba(0.0, 0.0, 0.0)), + m_active_color(rgba(0.4, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_text_color; + m_colors[3] = &m_inactive_color; + m_colors[4] = &m_active_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void text_color(const ColorT& c) { m_text_color = c; } + void inactive_color(const ColorT& c) { m_inactive_color = c; } + void active_color(const ColorT& c) { m_active_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + rbox_ctrl(const rbox_ctrl&); + const rbox_ctrl& operator = (const rbox_ctrl&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_text_color; + ColorT m_inactive_color; + ColorT m_active_color; + ColorT* m_colors[5]; + }; + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_scale_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_scale_ctrl.h new file mode 100644 index 00000000000..b1e32c20372 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_scale_ctrl.h @@ -0,0 +1,146 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes scale_ctrl_impl, scale_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SCALE_CTRL_INCLUDED +#define AGG_SCALE_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + class scale_ctrl_impl : public ctrl + { + enum move_e + { + move_nothing, + move_value1, + move_value2, + move_slider + }; + + public: + scale_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_thickness(double t, double extra=0.0); + void resize(double x1, double y1, double x2, double y2); + + double min_delta() const { return m_min_d; } + void min_delta(double d) { m_min_d = d; } + + double value1() const { return m_value1; } + void value1(double value); + + double value2() const { return m_value2; } + void value2(double value); + + void move(double d); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex soutce interface + unsigned num_paths() { return 5; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_box(); + + double m_border_thickness; + double m_border_extra; + double m_value1; + double m_value2; + double m_min_d; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_pdx; + double m_pdy; + move_e m_move_what; + double m_vx[32]; + double m_vy[32]; + + ellipse m_ellipse; + + unsigned m_idx; + unsigned m_vertex; + + }; + + + + //------------------------------------------------------------------------ + template class scale_ctrl : public scale_ctrl_impl + { + public: + scale_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + scale_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 0.9, 0.8)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_pointers_color(rgba(0.8, 0.0, 0.0, 0.8)), + m_slider_color(rgba(0.2, 0.1, 0.0, 0.6)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_pointers_color; + m_colors[3] = &m_pointers_color; + m_colors[4] = &m_slider_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void pointers_color(const ColorT& c) { m_pointers_color = c; } + void slider_color(const ColorT& c) { m_slider_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + scale_ctrl(const scale_ctrl&); + const scale_ctrl& operator = (const scale_ctrl&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_pointers_color; + ColorT m_slider_color; + ColorT* m_colors[5]; + }; + + + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_slider_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_slider_ctrl.h new file mode 100644 index 00000000000..b50a95c59d4 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_slider_ctrl.h @@ -0,0 +1,150 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes slider_ctrl_impl, slider_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SLIDER_CTRL_INCLUDED +#define AGG_SLIDER_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_math.h" +#include "agg_ellipse.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_gsv_text.h" +#include "agg_conv_stroke.h" +#include "agg_path_storage.h" +#include "agg_ctrl.h" + + +namespace agg +{ + + //--------------------------------------------------------slider_ctrl_impl + class slider_ctrl_impl : public ctrl + { + public: + slider_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y=false); + + void border_width(double t, double extra=0.0); + + void range(double min, double max) { m_min = min; m_max = max; } + void num_steps(unsigned num) { m_num_steps = num; } + void label(const char* fmt); + void text_thickness(double t) { m_text_thickness = t; } + + bool descending() const { return m_descending; } + void descending(bool v) { m_descending = v; } + + double value() const { return m_value * (m_max - m_min) + m_min; } + void value(double value); + + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + // Vertex source interface + unsigned num_paths() { return 6; }; + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_box(); + bool normalize_value(bool preview_value_flag); + + double m_border_width; + double m_border_extra; + double m_text_thickness; + double m_value; + double m_preview_value; + double m_min; + double m_max; + unsigned m_num_steps; + bool m_descending; + char m_label[64]; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + double m_pdx; + bool m_mouse_move; + double m_vx[32]; + double m_vy[32]; + + ellipse m_ellipse; + + unsigned m_idx; + unsigned m_vertex; + + gsv_text m_text; + conv_stroke m_text_poly; + path_storage m_storage; + + }; + + + + //----------------------------------------------------------slider_ctrl + template class slider_ctrl : public slider_ctrl_impl + { + public: + slider_ctrl(double x1, double y1, double x2, double y2, bool flip_y=false) : + slider_ctrl_impl(x1, y1, x2, y2, flip_y), + m_background_color(rgba(1.0, 0.9, 0.8)), + m_triangle_color(rgba(0.7, 0.6, 0.6)), + m_text_color(rgba(0.0, 0.0, 0.0)), + m_pointer_preview_color(rgba(0.6, 0.4, 0.4, 0.4)), + m_pointer_color(rgba(0.8, 0.0, 0.0, 0.6)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_triangle_color; + m_colors[2] = &m_text_color; + m_colors[3] = &m_pointer_preview_color; + m_colors[4] = &m_pointer_color; + m_colors[5] = &m_text_color; + } + + + void background_color(const ColorT& c) { m_background_color = c; } + void pointer_color(const ColorT& c) { m_pointer_color = c; } + + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + slider_ctrl(const slider_ctrl&); + const slider_ctrl& operator = (const slider_ctrl&); + + ColorT m_background_color; + ColorT m_triangle_color; + ColorT m_text_color; + ColorT m_pointer_preview_color; + ColorT m_pointer_color; + ColorT* m_colors[6]; + }; + + + + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_spline_ctrl.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_spline_ctrl.h new file mode 100644 index 00000000000..8477f27d782 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/ctrl/agg_spline_ctrl.h @@ -0,0 +1,159 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes spline_ctrl_impl, spline_ctrl +// +//---------------------------------------------------------------------------- + +#ifndef AGG_SPLINE_CTRL_INCLUDED +#define AGG_SPLINE_CTRL_INCLUDED + +#include "agg_basics.h" +#include "agg_ellipse.h" +#include "agg_bspline.h" +#include "agg_conv_stroke.h" +#include "agg_path_storage.h" +#include "agg_trans_affine.h" +#include "agg_color_rgba.h" +#include "agg_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Class that can be used to create an interactive control to set up + // gamma arrays. + //------------------------------------------------------------------------ + class spline_ctrl_impl : public ctrl + { + public: + spline_ctrl_impl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y=false); + + // Set other parameters + void border_width(double t, double extra=0.0); + void curve_width(double t) { m_curve_width = t; } + void point_size(double s) { m_point_size = s; } + + // Event handlers. Just call them if the respective events + // in your system occure. The functions return true if redrawing + // is required. + virtual bool in_rect(double x, double y) const; + virtual bool on_mouse_button_down(double x, double y); + virtual bool on_mouse_button_up(double x, double y); + virtual bool on_mouse_move(double x, double y, bool button_flag); + virtual bool on_arrow_keys(bool left, bool right, bool down, bool up); + + void active_point(int i); + + const double* spline() const { return m_spline_values; } + const int8u* spline8() const { return m_spline_values8; } + double value(double x) const; + void value(unsigned idx, double y); + void point(unsigned idx, double x, double y); + void x(unsigned idx, double x) { m_xp[idx] = x; } + void y(unsigned idx, double y) { m_yp[idx] = y; } + double x(unsigned idx) const { return m_xp[idx]; } + double y(unsigned idx) const { return m_yp[idx]; } + void update_spline(); + + // Vertex soutce interface + unsigned num_paths() { return 5; } + void rewind(unsigned path_id); + unsigned vertex(double* x, double* y); + + private: + void calc_spline_box(); + void calc_curve(); + double calc_xp(unsigned idx); + double calc_yp(unsigned idx); + void set_xp(unsigned idx, double val); + void set_yp(unsigned idx, double val); + + unsigned m_num_pnt; + double m_xp[32]; + double m_yp[32]; + bspline m_spline; + double m_spline_values[256]; + int8u m_spline_values8[256]; + double m_border_width; + double m_border_extra; + double m_curve_width; + double m_point_size; + double m_xs1; + double m_ys1; + double m_xs2; + double m_ys2; + path_storage m_curve_pnt; + conv_stroke m_curve_poly; + ellipse m_ellipse; + unsigned m_idx; + unsigned m_vertex; + double m_vx[32]; + double m_vy[32]; + int m_active_pnt; + int m_move_pnt; + double m_pdx; + double m_pdy; + const trans_affine* m_mtx; + }; + + + template class spline_ctrl : public spline_ctrl_impl + { + public: + spline_ctrl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y=false) : + spline_ctrl_impl(x1, y1, x2, y2, num_pnt, flip_y), + m_background_color(rgba(1.0, 1.0, 0.9)), + m_border_color(rgba(0.0, 0.0, 0.0)), + m_curve_color(rgba(0.0, 0.0, 0.0)), + m_inactive_pnt_color(rgba(0.0, 0.0, 0.0)), + m_active_pnt_color(rgba(1.0, 0.0, 0.0)) + { + m_colors[0] = &m_background_color; + m_colors[1] = &m_border_color; + m_colors[2] = &m_curve_color; + m_colors[3] = &m_inactive_pnt_color; + m_colors[4] = &m_active_pnt_color; + } + + // Set colors + void background_color(const ColorT& c) { m_background_color = c; } + void border_color(const ColorT& c) { m_border_color = c; } + void curve_color(const ColorT& c) { m_curve_color = c; } + void inactive_pnt_color(const ColorT& c) { m_inactive_pnt_color = c; } + void active_pnt_color(const ColorT& c) { m_active_pnt_color = c; } + const ColorT& color(unsigned i) const { return *m_colors[i]; } + + private: + spline_ctrl(const spline_ctrl&); + const spline_ctrl& operator = (const spline_ctrl&); + + ColorT m_background_color; + ColorT m_border_color; + ColorT m_curve_color; + ColorT m_inactive_pnt_color; + ColorT m_active_pnt_color; + ColorT* m_colors[5]; + }; + + + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/agg_platform_support.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/agg_platform_support.h new file mode 100644 index 00000000000..9a63411e508 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/agg_platform_support.h @@ -0,0 +1,686 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class platform_support +// +// It's not a part of the AGG library, it's just a helper class to create +// interactive demo examples. Since the examples should not be too complex +// this class is provided to support some very basic interactive graphical +// functionality, such as putting the rendered image to the window, simple +// keyboard and mouse input, window resizing, setting the window title, +// and catching the "idle" events. +// +// The idea is to have a single header file that does not depend on any +// platform (I hate these endless #ifdef/#elif/#elif.../#endif) and a number +// of different implementations depending on the concrete platform. +// The most popular platforms are: +// +// Windows-32 API +// X-Window API +// SDL library (see http://www.libsdl.org/) +// MacOS C/C++ API +// +// This file does not include any system dependent .h files such as +// windows.h or X11.h, so, your demo applications do not depend on the +// platform. The only file that can #include system dependend headers +// is the implementation file agg_platform_support.cpp. Different +// implementations are placed in different directories, such as +// ~/agg/src/platform/win32 +// ~/agg/src/platform/sdl +// ~/agg/src/platform/X11 +// and so on. +// +// All the system dependent stuff sits in the platform_specific +// class which is forward-declared here but not defined. +// The platform_support class has just a pointer to it and it's +// the responsibility of the implementation to create/delete it. +// This class being defined in the implementation file can have +// any platform dependent stuff such as HWND, X11 Window and so on. +// +//---------------------------------------------------------------------------- + + +#ifndef AGG_PLATFORM_SUPPORT_INCLUDED +#define AGG_PLATFORM_SUPPORT_INCLUDED + + +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_trans_viewport.h" +#include "ctrl/agg_ctrl.h" + +namespace agg +{ + + //----------------------------------------------------------window_flag_e + // These are flags used in method init(). Not all of them are + // applicable on different platforms, for example the win32_api + // cannot use a hardware buffer (window_hw_buffer). + // The implementation should simply ignore unsupported flags. + enum window_flag_e + { + window_resize = 1, + window_hw_buffer = 2, + window_keep_aspect_ratio = 4, + window_process_all_keys = 8 + }; + + //-----------------------------------------------------------pix_format_e + // Possible formats of the rendering buffer. Initially I thought that it's + // reasonable to create the buffer and the rendering functions in + // accordance with the native pixel format of the system because it + // would have no overhead for pixel format conersion. + // But eventually I came to a conclusion that having a possibility to + // convert pixel formats on demand is a good idea. First, it was X11 where + // there lots of different formats and visuals and it would be great to + // render everything in, say, RGB-24 and display it automatically without + // any additional efforts. The second reason is to have a possibility to + // debug renderers for different pixel formats and colorspaces having only + // one computer and one system. + // + // This stuff is not included into the basic AGG functionality because the + // number of supported pixel formats (and/or colorspaces) can be great and + // if one needs to add new format it would be good only to add new + // rendering files without having to modify any existing ones (a general + // principle of incapsulation and isolation). + // + // Using a particular pixel format doesn't obligatory mean the necessity + // of software conversion. For example, win32 API can natively display + // gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats. + // This list can be (and will be!) extended in future. + enum pix_format_e + { + pix_format_undefined = 0, // By default. No conversions are applied + pix_format_bw, // 1 bit per color B/W + pix_format_gray8, // Simple 256 level grayscale + pix_format_sgray8, // Simple 256 level grayscale (sRGB) + pix_format_gray16, // Simple 65535 level grayscale + pix_format_gray32, // Grayscale, one 32-bit float per pixel + pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering! + pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering! + pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering! + pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering! + pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering! + pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering! + pix_format_rgb24, // R-G-B, one byte per color component + pix_format_srgb24, // R-G-B, one byte per color component (sRGB) + pix_format_bgr24, // B-G-R, one byte per color component + pix_format_sbgr24, // B-G-R, native win32 BMP format (sRGB) + pix_format_rgba32, // R-G-B-A, one byte per color component + pix_format_srgba32, // R-G-B-A, one byte per color component (sRGB) + pix_format_argb32, // A-R-G-B, native MAC format + pix_format_sargb32, // A-R-G-B, native MAC format (sRGB) + pix_format_abgr32, // A-B-G-R, one byte per color component + pix_format_sabgr32, // A-B-G-R, one byte per color component (sRGB) + pix_format_bgra32, // B-G-R-A, native win32 BMP format + pix_format_sbgra32, // B-G-R-A, native win32 BMP format (sRGB) + pix_format_rgb48, // R-G-B, 16 bits per color component + pix_format_bgr48, // B-G-R, native win32 BMP format. + pix_format_rgb96, // R-G-B, one 32-bit float per color component + pix_format_bgr96, // B-G-R, one 32-bit float per color component + pix_format_rgba64, // R-G-B-A, 16 bits byte per color component + pix_format_argb64, // A-R-G-B, native MAC format + pix_format_abgr64, // A-B-G-R, one byte per color component + pix_format_bgra64, // B-G-R-A, native win32 BMP format + pix_format_rgba128, // R-G-B-A, one 32-bit float per color component + pix_format_argb128, // A-R-G-B, one 32-bit float per color component + pix_format_abgr128, // A-B-G-R, one 32-bit float per color component + pix_format_bgra128, // B-G-R-A, one 32-bit float per color component + + end_of_pix_formats + }; + + //-------------------------------------------------------------input_flag_e + // Mouse and keyboard flags. They can be different on different platforms + // and the ways they are obtained are also different. But in any case + // the system dependent flags should be mapped into these ones. The meaning + // of that is as follows. For example, if kbd_ctrl is set it means that the + // ctrl key is pressed and being held at the moment. They are also used in + // the overridden methods such as on_mouse_move(), on_mouse_button_down(), + // on_mouse_button_dbl_click(), on_mouse_button_up(), on_key(). + // In the method on_mouse_button_up() the mouse flags have different + // meaning. They mean that the respective button is being released, but + // the meaning of the keyboard flags remains the same. + // There's absolut minimal set of flags is used because they'll be most + // probably supported on different platforms. Even the mouse_right flag + // is restricted because Mac's mice have only one button, but AFAIK + // it can be simulated with holding a special key on the keydoard. + enum input_flag_e + { + mouse_left = 1, + mouse_right = 2, + kbd_shift = 4, + kbd_ctrl = 8 + }; + + //--------------------------------------------------------------key_code_e + // Keyboard codes. There's also a restricted set of codes that are most + // probably supported on different platforms. Any platform dependent codes + // should be converted into these ones. There're only those codes are + // defined that cannot be represented as printable ASCII-characters. + // All printable ASCII-set can be used in a regular C/C++ manner: + // ' ', 'A', '0' '+' and so on. + // Since the class is used for creating very simple demo-applications + // we don't need very rich possibilities here, just basic ones. + // Actually the numeric key codes are taken from the SDL library, so, + // the implementation of the SDL support does not require any mapping. + enum key_code_e + { + // ASCII set. Should be supported everywhere + key_backspace = 8, + key_tab = 9, + key_clear = 12, + key_return = 13, + key_pause = 19, + key_escape = 27, + + // Keypad + key_delete = 127, + key_kp0 = 256, + key_kp1 = 257, + key_kp2 = 258, + key_kp3 = 259, + key_kp4 = 260, + key_kp5 = 261, + key_kp6 = 262, + key_kp7 = 263, + key_kp8 = 264, + key_kp9 = 265, + key_kp_period = 266, + key_kp_divide = 267, + key_kp_multiply = 268, + key_kp_minus = 269, + key_kp_plus = 270, + key_kp_enter = 271, + key_kp_equals = 272, + + // Arrow-keys and stuff + key_up = 273, + key_down = 274, + key_right = 275, + key_left = 276, + key_insert = 277, + key_home = 278, + key_end = 279, + key_page_up = 280, + key_page_down = 281, + + // Functional keys. You'd better avoid using + // f11...f15 in your applications if you want + // the applications to be portable + key_f1 = 282, + key_f2 = 283, + key_f3 = 284, + key_f4 = 285, + key_f5 = 286, + key_f6 = 287, + key_f7 = 288, + key_f8 = 289, + key_f9 = 290, + key_f10 = 291, + key_f11 = 292, + key_f12 = 293, + key_f13 = 294, + key_f14 = 295, + key_f15 = 296, + + // The possibility of using these keys is + // very restricted. Actually it's guaranteed + // only in win32_api and win32_sdl implementations + key_numlock = 300, + key_capslock = 301, + key_scrollock = 302, + + // Phew! + end_of_key_codes + }; + + + //------------------------------------------------------------------------ + // A predeclaration of the platform dependent class. Since we do not + // know anything here the only we can have is just a pointer to this + // class as a data member. It should be created and destroyed explicitly + // in the constructor/destructor of the platform_support class. + // Although the pointer to platform_specific is public the application + // cannot have access to its members or methods since it does not know + // anything about them and it's a perfect incapsulation :-) + class platform_specific; + + + //----------------------------------------------------------ctrl_container + // A helper class that contains pointers to a number of controls. + // This class is used to ease the event handling with controls. + // The implementation should simply call the appropriate methods + // of this class when appropriate events occur. + class ctrl_container + { + enum max_ctrl_e { max_ctrl = 64 }; + + public: + //-------------------------------------------------------------------- + ctrl_container() : m_num_ctrl(0), m_cur_ctrl(-1) {} + + //-------------------------------------------------------------------- + void add(ctrl& c) + { + if(m_num_ctrl < max_ctrl) + { + m_ctrl[m_num_ctrl++] = &c; + } + } + + //-------------------------------------------------------------------- + bool in_rect(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->in_rect(x, y)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_mouse_button_down(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_button_down(x, y)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_mouse_button_up(double x, double y) + { + unsigned i; + bool flag = false; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_button_up(x, y)) flag = true; + } + return flag; + } + + //-------------------------------------------------------------------- + bool on_mouse_move(double x, double y, bool button_flag) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->on_mouse_move(x, y, button_flag)) return true; + } + return false; + } + + //-------------------------------------------------------------------- + bool on_arrow_keys(bool left, bool right, bool down, bool up) + { + if(m_cur_ctrl >= 0) + { + return m_ctrl[m_cur_ctrl]->on_arrow_keys(left, right, down, up); + } + return false; + } + + //-------------------------------------------------------------------- + bool set_cur(double x, double y) + { + unsigned i; + for(i = 0; i < m_num_ctrl; i++) + { + if(m_ctrl[i]->in_rect(x, y)) + { + if(m_cur_ctrl != int(i)) + { + m_cur_ctrl = i; + return true; + } + return false; + } + } + if(m_cur_ctrl != -1) + { + m_cur_ctrl = -1; + return true; + } + return false; + } + + private: + ctrl* m_ctrl[max_ctrl]; + unsigned m_num_ctrl; + int m_cur_ctrl; + }; + + + + //---------------------------------------------------------platform_support + // This class is a base one to the apllication classes. It can be used + // as follows: + // + // class the_application : public agg::platform_support + // { + // public: + // the_application(unsigned bpp, bool flip_y) : + // platform_support(bpp, flip_y) + // . . . + // + // //override stuff . . . + // virtual void on_init() + // { + // . . . + // } + // + // virtual void on_draw() + // { + // . . . + // } + // + // virtual void on_resize(int sx, int sy) + // { + // . . . + // } + // // . . . and so on, see virtual functions + // + // + // //any your own stuff . . . + // }; + // + // + // int agg_main(int argc, char* argv[]) + // { + // the_application app(pix_format_rgb24, true); + // app.caption("AGG Example. Lion"); + // + // if(app.init(500, 400, agg::window_resize)) + // { + // return app.run(); + // } + // return 1; + // } + // + // The reason to have agg_main() instead of just main() is that SDL + // for Windows requires including SDL.h if you define main(). Since + // the demo applications cannot rely on any platform/library specific + // stuff it's impossible to include SDL.h into the application files. + // The demo applications are simple and their use is restricted, so, + // this approach is quite reasonable. + // + class platform_support + { + public: + enum max_images_e { max_images = 16 }; + + // format - see enum pix_format_e {}; + // flip_y - true if you want to have the Y-axis flipped vertically. + platform_support(pix_format_e format, bool flip_y); + virtual ~platform_support(); + + // Setting the windows caption (title). Should be able + // to be called at least before calling init(). + // It's perfect if they can be called anytime. + void caption(const char* cap); + const char* caption() const { return m_caption; } + + //-------------------------------------------------------------------- + // These 3 methods handle working with images. The image + // formats are the simplest ones, such as .BMP in Windows or + // .ppm in Linux. In the applications the names of the files + // should not have any file extensions. Method load_img() can + // be called before init(), so, the application could be able + // to determine the initial size of the window depending on + // the size of the loaded image. + // The argument "idx" is the number of the image 0...max_images-1 + bool load_img(unsigned idx, const char* file); + bool save_img(unsigned idx, const char* file); + bool create_img(unsigned idx, unsigned width=0, unsigned height=0); + + //-------------------------------------------------------------------- + // init() and run(). See description before the class for details. + // The necessity of calling init() after creation is that it's + // impossible to call the overridden virtual function (on_init()) + // from the constructor. On the other hand it's very useful to have + // some on_init() event handler when the window is created but + // not yet displayed. The rbuf_window() method (see below) is + // accessible from on_init(). + bool init(unsigned width, unsigned height, unsigned flags); + int run(); + + //-------------------------------------------------------------------- + // The very same parameters that were used in the constructor + pix_format_e format() const { return m_format; } + bool flip_y() const { return m_flip_y; } + unsigned bpp() const { return m_bpp; } + + //-------------------------------------------------------------------- + // The following provides a very simple mechanism of doing someting + // in background. It's not multithreading. When wait_mode is true + // the class waits for the events and it does not ever call on_idle(). + // When it's false it calls on_idle() when the event queue is empty. + // The mode can be changed anytime. This mechanism is satisfactory + // to create very simple animations. + bool wait_mode() const { return m_wait_mode; } + void wait_mode(bool wait_mode) { m_wait_mode = wait_mode; } + + //-------------------------------------------------------------------- + // These two functions control updating of the window. + // force_redraw() is an analog of the Win32 InvalidateRect() function. + // Being called it sets a flag (or sends a message) which results + // in calling on_draw() and updating the content of the window + // when the next event cycle comes. + // update_window() results in just putting immediately the content + // of the currently rendered buffer to the window without calling + // on_draw(). + void force_redraw(); + void update_window(); + + //-------------------------------------------------------------------- + // So, finally, how to draw anythig with AGG? Very simple. + // rbuf_window() returns a reference to the main rendering + // buffer which can be attached to any rendering class. + // rbuf_img() returns a reference to the previously created + // or loaded image buffer (see load_img()). The image buffers + // are not displayed directly, they should be copied to or + // combined somehow with the rbuf_window(). rbuf_window() is + // the only buffer that can be actually displayed. + rendering_buffer& rbuf_window() { return m_rbuf_window; } + rendering_buffer& rbuf_img(unsigned idx) { return m_rbuf_img[idx]; } + + + //-------------------------------------------------------------------- + // Returns file extension used in the implementation for the particular + // system. + const char* img_ext() const; + + //-------------------------------------------------------------------- + void copy_img_to_window(unsigned idx) + { + if(idx < max_images && rbuf_img(idx).buf()) + { + rbuf_window().copy_from(rbuf_img(idx)); + } + } + + //-------------------------------------------------------------------- + void copy_window_to_img(unsigned idx) + { + if(idx < max_images) + { + create_img(idx, rbuf_window().width(), rbuf_window().height()); + rbuf_img(idx).copy_from(rbuf_window()); + } + } + + //-------------------------------------------------------------------- + void copy_img_to_img(unsigned idx_to, unsigned idx_from) + { + if(idx_from < max_images && + idx_to < max_images && + rbuf_img(idx_from).buf()) + { + create_img(idx_to, + rbuf_img(idx_from).width(), + rbuf_img(idx_from).height()); + rbuf_img(idx_to).copy_from(rbuf_img(idx_from)); + } + } + + //-------------------------------------------------------------------- + // Event handlers. They are not pure functions, so you don't have + // to override them all. + // In my demo applications these functions are defined inside + // the the_application class (implicit inlining) which is in general + // very bad practice, I mean vitual inline methods. At least it does + // not make sense. + // But in this case it's quite appropriate bacause we have the only + // instance of the the_application class and it is in the same file + // where this class is defined. + virtual void on_init(); + virtual void on_resize(int sx, int sy); + virtual void on_idle(); + virtual void on_mouse_move(int x, int y, unsigned flags); + virtual void on_mouse_button_down(int x, int y, unsigned flags); + virtual void on_mouse_button_up(int x, int y, unsigned flags); + virtual void on_key(int x, int y, unsigned key, unsigned flags); + virtual void on_ctrl_change(); + virtual void on_draw(); + virtual void on_post_draw(void* raw_handler); + + //-------------------------------------------------------------------- + // Adding control elements. A control element once added will be + // working and reacting to the mouse and keyboard events. Still, you + // will have to render them in the on_draw() using function + // render_ctrl() because platform_support doesn't know anything about + // renderers you use. The controls will be also scaled automatically + // if they provide a proper scaling mechanism (all the controls + // included into the basic AGG package do). + // If you don't need a particular control to be scaled automatically + // call ctrl::no_transform() after adding. + void add_ctrl(ctrl& c) { m_ctrls.add(c); c.transform(m_resize_mtx); } + + //-------------------------------------------------------------------- + // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing + // matrix on the basis of the given width and height and the initial + // width and height of the window. The implementation should simply + // call this function every time when it catches the resizing event + // passing in the new values of width and height of the window. + // Nothing prevents you from "cheating" the scaling matrix if you + // call this function from somewhere with wrong arguments. + // trans_affine_resizing() accessor simply returns current resizing matrix + // which can be used to apply additional scaling of any of your + // stuff when the window is being resized. + // width(), height(), initial_width(), and initial_height() must be + // clear to understand with no comments :-) + void trans_affine_resizing(int width, int height) + { + if(m_window_flags & window_keep_aspect_ratio) + { + //double sx = double(width) / double(m_initial_width); + //double sy = double(height) / double(m_initial_height); + //if(sy < sx) sx = sy; + //m_resize_mtx = trans_affine_scaling(sx, sx); + trans_viewport vp; + vp.preserve_aspect_ratio(0.5, 0.5, aspect_ratio_meet); + vp.device_viewport(0, 0, width, height); + vp.world_viewport(0, 0, m_initial_width, m_initial_height); + m_resize_mtx = vp.to_affine(); + } + else + { + m_resize_mtx = trans_affine_scaling( + double(width) / double(m_initial_width), + double(height) / double(m_initial_height)); + } + } + trans_affine& trans_affine_resizing() { return m_resize_mtx; } + const trans_affine& trans_affine_resizing() const { return m_resize_mtx; } + double width() const { return m_rbuf_window.width(); } + double height() const { return m_rbuf_window.height(); } + double initial_width() const { return m_initial_width; } + double initial_height() const { return m_initial_height; } + unsigned window_flags() const { return m_window_flags; } + + //-------------------------------------------------------------------- + // Get raw display handler depending on the system. + // For win32 its an HDC, for other systems it can be a pointer to some + // structure. See the implementation files for detals. + // It's provided "as is", so, first you should check if it's not null. + // If it's null the raw_display_handler is not supported. Also, there's + // no guarantee that this function is implemented, so, in some + // implementations you may have simply an unresolved symbol when linking. + void* raw_display_handler(); + + //-------------------------------------------------------------------- + // display message box or print the message to the console + // (depending on implementation) + void message(const char* msg); + + //-------------------------------------------------------------------- + // Stopwatch functions. Function elapsed_time() returns time elapsed + // since the latest start_timer() invocation in millisecods. + // The resolutoin depends on the implementation. + // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter(). + void start_timer(); + double elapsed_time() const; + + //-------------------------------------------------------------------- + // Get the full file name. In most cases it simply returns + // file_name. As it's appropriate in many systems if you open + // a file by its name without specifying the path, it tries to + // open it in the current directory. The demos usually expect + // all the supplementary files to be placed in the current + // directory, that is usually coincides with the directory where + // the executable is. However, in some systems (BeOS) it's not so. + // For those kinds of systems full_file_name() can help access files + // preserving commonly used policy. + // So, it's a good idea to use in the demos the following: + // FILE* fd = fopen(full_file_name("some.file"), "r"); + // instead of + // FILE* fd = fopen("some.file", "r"); + const char* full_file_name(const char* file_name); + + public: + platform_specific* m_specific; + ctrl_container m_ctrls; + + // Sorry, I'm too tired to describe the private + // data membders. See the implementations for different + // platforms for details. + private: + platform_support(const platform_support&); + const platform_support& operator = (const platform_support&); + + pix_format_e m_format; + unsigned m_bpp; + rendering_buffer m_rbuf_window; + rendering_buffer m_rbuf_img[max_images]; + unsigned m_window_flags; + bool m_wait_mode; + bool m_flip_y; + char m_caption[256]; + int m_initial_width; + int m_initial_height; + trans_affine m_resize_mtx; + }; + + +} + + + +#endif + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/mac/agg_mac_pmap.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/mac/agg_mac_pmap.h new file mode 100644 index 00000000000..d7860b6fee9 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/mac/agg_mac_pmap.h @@ -0,0 +1,87 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) +// Copyright (C) 2002 Hansruedi Baer (MacOS support) +// +// 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 +// baer@karto.baug.eth.ch +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- +#ifndef AGG_MAC_PMAP_INCLUDED +#define AGG_MAC_PMAP_INCLUDED + + +#include +#include + + +namespace agg +{ + enum org_e + { + org_mono8 = 8, + org_color16 = 16, + org_color24 = 24, + org_color32 = 32 + }; + + class pixel_map + { + public: + ~pixel_map(); + pixel_map(); + + public: + void destroy(); + void create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val=255); + + void clear(unsigned clear_val=255); + bool load_from_qt(const char* filename); + bool save_as_qt(const char* filename) const; + + void draw(WindowRef window, + const Rect* device_rect=0, + const Rect* bmp_rect=0) const; + void draw(WindowRef window, int x, int y, double scale=1.0) const; + void blend(WindowRef window, + const Rect* device_rect=0, + const Rect* bmp_rect=0) const; + void blend(WindowRef window, int x, int y, double scale=1.0) const; + + unsigned char* buf(); + unsigned width() const; + unsigned height() const; + int row_bytes() const; + unsigned bpp() const { return m_bpp; } + + //Auxiliary static functions + static unsigned calc_row_len(unsigned width, unsigned bits_per_pixel); + private: + pixel_map(const pixel_map&); + const pixel_map& operator = (const pixel_map&); + + private: + GWorldPtr m_pmap; + unsigned char* m_buf; + unsigned m_bpp; + unsigned m_img_size; + }; + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/win32/agg_win32_bmp.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/win32/agg_win32_bmp.h new file mode 100644 index 00000000000..5391e8bb9bc --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/platform/win32/agg_win32_bmp.h @@ -0,0 +1,117 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- +#ifndef AGG_WIN32_BMP_INCLUDED +#define AGG_WIN32_BMP_INCLUDED + + +#include +#include + + +namespace agg +{ + enum org_e + { + org_mono8 = 8, + org_color16 = 16, + org_color24 = 24, + org_color32 = 32, + org_color48 = 48, + org_color64 = 64 + }; + + class pixel_map + { + public: + ~pixel_map(); + pixel_map(); + + public: + void destroy(); + void create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val=256); + HBITMAP create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val=256); + + void clear(unsigned clear_val=256); + void attach_to_bmp(BITMAPINFO* bmp); + BITMAPINFO* bitmap_info() { return m_bmp; } + bool load_from_bmp(FILE* fd); + bool save_as_bmp(FILE* fd) const; + bool load_from_bmp(const char* filename); + bool save_as_bmp(const char* filename) const; + + void draw(HDC h_dc, + const RECT* device_rect=0, + const RECT* bmp_rect=0) const; + void draw(HDC h_dc, int x, int y, double scale=1.0) const; + + void blend(HDC h_dc, + const RECT* device_rect=0, + const RECT* bmp_rect=0) const; + void blend(HDC h_dc, int x, int y, double scale=1.0) const; + + + unsigned char* buf(); + unsigned width() const; + unsigned height() const; + int stride() const; + unsigned bpp() const { return m_bpp; } + + //Auxiliary static functions + static unsigned calc_full_size(BITMAPINFO *bmp); + static unsigned calc_header_size(BITMAPINFO *bmp); + static unsigned calc_palette_size(unsigned clr_used, + unsigned bits_per_pixel); + static unsigned calc_palette_size(BITMAPINFO *bmp); + static unsigned char* calc_img_ptr(BITMAPINFO *bmp); + static BITMAPINFO* create_bitmap_info(unsigned width, + unsigned height, + unsigned bits_per_pixel); + static void create_gray_scale_palette(BITMAPINFO *bmp); + static unsigned calc_row_len(unsigned width, unsigned bits_per_pixel); + + private: + pixel_map(const pixel_map&); + const pixel_map& operator = (const pixel_map&); + void create_from_bmp(BITMAPINFO *bmp); + + HBITMAP create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel); + + private: + BITMAPINFO* m_bmp; + unsigned char* m_buf; + unsigned m_bpp; + bool m_is_internal; + unsigned m_img_size; + unsigned m_full_size; + }; + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv.h new file mode 100644 index 00000000000..8b8a0a55d2b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv.h @@ -0,0 +1,128 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Conversion from one colorspace/pixel format to another +// +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_INCLUDED +#define AGG_COLOR_CONV_INCLUDED + +#include +#include "agg_basics.h" +#include "agg_rendering_buffer.h" + + + + +namespace agg +{ + + //--------------------------------------------------------------color_conv + template + void color_conv(RenBuf* dst, const RenBuf* src, CopyRow copy_row_functor) + { + unsigned width = src->width(); + unsigned height = src->height(); + + if(dst->width() < width) width = dst->width(); + if(dst->height() < height) height = dst->height(); + + if(width) + { + unsigned y; + for(y = 0; y < height; y++) + { + copy_row_functor(dst->row_ptr(0, y, width), + src->row_ptr(y), + width); + } + } + } + + + //---------------------------------------------------------color_conv_row + template + void color_conv_row(int8u* dst, + const int8u* src, + unsigned width, + CopyRow copy_row_functor) + { + copy_row_functor(dst, src, width); + } + + + //---------------------------------------------------------color_conv_same + template class color_conv_same + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + memmove(dst, src, width*BPP); + } + }; + + + // Generic pixel converter. + template + struct conv_pixel + { + void operator()(void* dst, const void* src) const + { + // Read a pixel from the source format and write it to the destination format. + DstFormat::write_plain_color(dst, SrcFormat::read_plain_color(src)); + } + }; + + // Generic row converter. Uses conv_pixel to convert individual pixels. + template + struct conv_row + { + void operator()(void* dst, const void* src, unsigned width) const + { + conv_pixel conv; + do + { + conv(dst, src); + dst = (int8u*)dst + DstFormat::pix_width; + src = (int8u*)src + SrcFormat::pix_width; + } + while (--width); + } + }; + + // Specialization for case where source and destination formats are identical. + template + struct conv_row + { + void operator()(void* dst, const void* src, unsigned width) const + { + memmove(dst, src, width * Format::pix_width); + } + }; + + // Top-level conversion function, converts one pixel format to any other. + template + void convert(RenBuf* dst, const RenBuf* src) + { + color_conv(dst, src, conv_row()); + } +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb16.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb16.h new file mode 100644 index 00000000000..aaa41322c5b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb16.h @@ -0,0 +1,285 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// This part of the library 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. +// +//---------------------------------------------------------------------------- +// +// A set of functors used with color_conv(). See file agg_color_conv.h +// These functors can convert images with up to 8 bits per component. +// Use convertors in the following way: +// +// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_RGB16_INCLUDED +#define AGG_COLOR_CONV_RGB16_INCLUDED + +#include "agg_basics.h" +#include "agg_color_conv.h" + +namespace agg +{ + + //-------------------------------------------------color_conv_gray16_to_gray8 + class color_conv_gray16_to_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* s = (int16u*)src; + do + { + *dst++ = *s++ >> 8; + } + while(--width); + } + }; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template class color_conv_rgb24_rgb48 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = (src[I1] << 8) | src[I1]; + *d++ = (src[1] << 8) | src[1] ; + *d++ = (src[I3] << 8) | src[I3]; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_rgb48<0,2> color_conv_rgb24_to_rgb48; + typedef color_conv_rgb24_rgb48<0,2> color_conv_bgr24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_rgb24_to_bgr48; + typedef color_conv_rgb24_rgb48<2,0> color_conv_bgr24_to_rgb48; + + + //-----------------------------------------------------color_conv_rgb24_rgb48 + template class color_conv_rgb48_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + const int16u* s = (const int16u*)src; + do + { + *dst++ = s[I1] >> 8; + *dst++ = s[1] >> 8; + *dst++ = s[I3] >> 8; + s += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb48_rgb24<0,2> color_conv_rgb48_to_rgb24; + typedef color_conv_rgb48_rgb24<0,2> color_conv_bgr48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_rgb48_to_bgr24; + typedef color_conv_rgb48_rgb24<2,0> color_conv_bgr48_to_rgb24; + + + //----------------------------------------------color_conv_rgbAAA_rgb24 + template class color_conv_rgbAAA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 22); + dst[1] = int8u(rgb >> 12); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_rgbAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_rgbAAA_to_bgr24; + typedef color_conv_rgbAAA_rgb24<2,0> color_conv_bgrAAA_to_rgb24; + typedef color_conv_rgbAAA_rgb24<0,2> color_conv_bgrAAA_to_bgr24; + + + //----------------------------------------------color_conv_rgbBBA_rgb24 + template class color_conv_rgbBBA_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u rgb = *(int32u*)src; + dst[R] = int8u(rgb >> 24); + dst[1] = int8u(rgb >> 13); + dst[B] = int8u(rgb >> 2); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_rgbBBA_rgb24<0,2> color_conv_rgbBBA_to_rgb24; + typedef color_conv_rgbBBA_rgb24<2,0> color_conv_rgbBBA_to_bgr24; + + + //----------------------------------------------color_conv_bgrABB_rgb24 + template class color_conv_bgrABB_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int32u bgr = *(int32u*)src; + dst[R] = int8u(bgr >> 3); + dst[1] = int8u(bgr >> 14); + dst[B] = int8u(bgr >> 24); + src += 4; + dst += 3; + } + while(--width); + } + }; + + typedef color_conv_bgrABB_rgb24<2,0> color_conv_bgrABB_to_rgb24; + typedef color_conv_bgrABB_rgb24<0,2> color_conv_bgrABB_to_bgr24; + + + //-------------------------------------------------color_conv_rgba64_rgba32 + template class color_conv_rgba64_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = int8u(((int16u*)src)[I1] >> 8); + *dst++ = int8u(((int16u*)src)[I2] >> 8); + *dst++ = int8u(((int16u*)src)[I3] >> 8); + *dst++ = int8u(((int16u*)src)[I4] >> 8); + src += 8; + } + while(--width); + } + }; + + //------------------------------------------------------------------------ + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_rgba64_to_rgba32; //----color_conv_rgba64_to_rgba32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_argb64_to_argb32; //----color_conv_argb64_to_argb32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_bgra64_to_bgra32; //----color_conv_bgra64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,1,2,3> color_conv_abgr64_to_abgr32; //----color_conv_abgr64_to_abgr32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_argb64_to_abgr32; //----color_conv_argb64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_argb64_to_bgra32; //----color_conv_argb64_to_bgra32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_argb64_to_rgba32; //----color_conv_argb64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_bgra64_to_abgr32; //----color_conv_bgra64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_bgra64_to_argb32; //----color_conv_bgra64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_bgra64_to_rgba32; //----color_conv_bgra64_to_rgba32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_rgba64_to_abgr32; //----color_conv_rgba64_to_abgr32 + typedef color_conv_rgba64_rgba32<3,0,1,2> color_conv_rgba64_to_argb32; //----color_conv_rgba64_to_argb32 + typedef color_conv_rgba64_rgba32<2,1,0,3> color_conv_rgba64_to_bgra32; //----color_conv_rgba64_to_bgra32 + typedef color_conv_rgba64_rgba32<0,3,2,1> color_conv_abgr64_to_argb32; //----color_conv_abgr64_to_argb32 + typedef color_conv_rgba64_rgba32<1,2,3,0> color_conv_abgr64_to_bgra32; //----color_conv_abgr64_to_bgra32 + typedef color_conv_rgba64_rgba32<3,2,1,0> color_conv_abgr64_to_rgba32; //----color_conv_abgr64_to_rgba32 + + + + //--------------------------------------------color_conv_rgb24_rgba64 + template class color_conv_rgb24_rgba64 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + d[I1] = (src[0] << 8) | src[0]; + d[I2] = (src[1] << 8) | src[1]; + d[I3] = (src[2] << 8) | src[2]; + d[A] = 65535; + d += 4; + src += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_rgb24_to_argb64; //----color_conv_rgb24_to_argb64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_rgb24_to_abgr64; //----color_conv_rgb24_to_abgr64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_rgb24_to_bgra64; //----color_conv_rgb24_to_bgra64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_rgb24_to_rgba64; //----color_conv_rgb24_to_rgba64 + typedef color_conv_rgb24_rgba64<3,2,1,0> color_conv_bgr24_to_argb64; //----color_conv_bgr24_to_argb64 + typedef color_conv_rgb24_rgba64<1,2,3,0> color_conv_bgr24_to_abgr64; //----color_conv_bgr24_to_abgr64 + typedef color_conv_rgb24_rgba64<0,1,2,3> color_conv_bgr24_to_bgra64; //----color_conv_bgr24_to_bgra64 + typedef color_conv_rgb24_rgba64<2,1,0,3> color_conv_bgr24_to_rgba64; //----color_conv_bgr24_to_rgba64 + + + template class color_conv_rgb24_gray16 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + int16u* d = (int16u*)dst; + do + { + *d++ = src[R]*77 + src[1]*150 + src[B]*29; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray16<0,2> color_conv_rgb24_to_gray16; + typedef color_conv_rgb24_gray16<2,0> color_conv_bgr24_to_gray16; + + +} + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb8.h b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb8.h new file mode 100644 index 00000000000..609460dba41 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/include/util/agg_color_conv_rgb8.h @@ -0,0 +1,476 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// A set of functors used with color_conv(). See file agg_color_conv.h +// These functors can convert images with up to 8 bits per component. +// Use convertors in the following way: +// +// agg::color_conv(dst, src, agg::color_conv_XXXX_to_YYYY()); +// whare XXXX and YYYY can be any of: +// rgb24 +// bgr24 +// rgba32 +// abgr32 +// argb32 +// bgra32 +// rgb555 +// rgb565 +//---------------------------------------------------------------------------- + +#ifndef AGG_COLOR_CONV_RGB8_INCLUDED +#define AGG_COLOR_CONV_RGB8_INCLUDED + +#include "agg_basics.h" +#include "agg_color_conv.h" + +namespace agg +{ + + //-----------------------------------------------------color_conv_rgb24 + class color_conv_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int8u tmp[3]; + tmp[0] = *src++; + tmp[1] = *src++; + tmp[2] = *src++; + *dst++ = tmp[2]; + *dst++ = tmp[1]; + *dst++ = tmp[0]; + } + while(--width); + } + }; + + typedef color_conv_rgb24 color_conv_rgb24_to_bgr24; + typedef color_conv_rgb24 color_conv_bgr24_to_rgb24; + + typedef color_conv_same<3> color_conv_bgr24_to_bgr24; + typedef color_conv_same<3> color_conv_rgb24_to_rgb24; + + + + //------------------------------------------------------color_conv_rgba32 + template class color_conv_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int8u tmp[4]; + tmp[0] = *src++; + tmp[1] = *src++; + tmp[2] = *src++; + tmp[3] = *src++; + *dst++ = tmp[I1]; + *dst++ = tmp[I2]; + *dst++ = tmp[I3]; + *dst++ = tmp[I4]; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32<0,3,2,1> color_conv_argb32_to_abgr32; //----color_conv_argb32_to_abgr32 + typedef color_conv_rgba32<3,2,1,0> color_conv_argb32_to_bgra32; //----color_conv_argb32_to_bgra32 + typedef color_conv_rgba32<1,2,3,0> color_conv_argb32_to_rgba32; //----color_conv_argb32_to_rgba32 + typedef color_conv_rgba32<3,0,1,2> color_conv_bgra32_to_abgr32; //----color_conv_bgra32_to_abgr32 + typedef color_conv_rgba32<3,2,1,0> color_conv_bgra32_to_argb32; //----color_conv_bgra32_to_argb32 + typedef color_conv_rgba32<2,1,0,3> color_conv_bgra32_to_rgba32; //----color_conv_bgra32_to_rgba32 + typedef color_conv_rgba32<3,2,1,0> color_conv_rgba32_to_abgr32; //----color_conv_rgba32_to_abgr32 + typedef color_conv_rgba32<3,0,1,2> color_conv_rgba32_to_argb32; //----color_conv_rgba32_to_argb32 + typedef color_conv_rgba32<2,1,0,3> color_conv_rgba32_to_bgra32; //----color_conv_rgba32_to_bgra32 + typedef color_conv_rgba32<0,3,2,1> color_conv_abgr32_to_argb32; //----color_conv_abgr32_to_argb32 + typedef color_conv_rgba32<1,2,3,0> color_conv_abgr32_to_bgra32; //----color_conv_abgr32_to_bgra32 + typedef color_conv_rgba32<3,2,1,0> color_conv_abgr32_to_rgba32; //----color_conv_abgr32_to_rgba32 + + //------------------------------------------------------------------------ + typedef color_conv_same<4> color_conv_rgba32_to_rgba32; //----color_conv_rgba32_to_rgba32 + typedef color_conv_same<4> color_conv_argb32_to_argb32; //----color_conv_argb32_to_argb32 + typedef color_conv_same<4> color_conv_bgra32_to_bgra32; //----color_conv_bgra32_to_bgra32 + typedef color_conv_same<4> color_conv_abgr32_to_abgr32; //----color_conv_abgr32_to_abgr32 + + + //--------------------------------------------color_conv_rgb24_rgba32 + template class color_conv_rgb24_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + dst[I1] = *src++; + dst[I2] = *src++; + dst[I3] = *src++; + dst[A] = 255; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_rgb24_to_argb32; //----color_conv_rgb24_to_argb32 + typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_rgb24_to_abgr32; //----color_conv_rgb24_to_abgr32 + typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_rgb24_to_bgra32; //----color_conv_rgb24_to_bgra32 + typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_rgb24_to_rgba32; //----color_conv_rgb24_to_rgba32 + typedef color_conv_rgb24_rgba32<3,2,1,0> color_conv_bgr24_to_argb32; //----color_conv_bgr24_to_argb32 + typedef color_conv_rgb24_rgba32<1,2,3,0> color_conv_bgr24_to_abgr32; //----color_conv_bgr24_to_abgr32 + typedef color_conv_rgb24_rgba32<0,1,2,3> color_conv_bgr24_to_bgra32; //----color_conv_bgr24_to_bgra32 + typedef color_conv_rgb24_rgba32<2,1,0,3> color_conv_bgr24_to_rgba32; //----color_conv_bgr24_to_rgba32 + + + + //-------------------------------------------------color_conv_rgba32_rgb24 + template class color_conv_rgba32_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = src[I1]; + *dst++ = src[I2]; + *dst++ = src[I3]; + src += 4; + } + while(--width); + } + }; + + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb24<1,2,3> color_conv_argb32_to_rgb24; //----color_conv_argb32_to_rgb24 + typedef color_conv_rgba32_rgb24<3,2,1> color_conv_abgr32_to_rgb24; //----color_conv_abgr32_to_rgb24 + typedef color_conv_rgba32_rgb24<2,1,0> color_conv_bgra32_to_rgb24; //----color_conv_bgra32_to_rgb24 + typedef color_conv_rgba32_rgb24<0,1,2> color_conv_rgba32_to_rgb24; //----color_conv_rgba32_to_rgb24 + typedef color_conv_rgba32_rgb24<3,2,1> color_conv_argb32_to_bgr24; //----color_conv_argb32_to_bgr24 + typedef color_conv_rgba32_rgb24<1,2,3> color_conv_abgr32_to_bgr24; //----color_conv_abgr32_to_bgr24 + typedef color_conv_rgba32_rgb24<0,1,2> color_conv_bgra32_to_bgr24; //----color_conv_bgra32_to_bgr24 + typedef color_conv_rgba32_rgb24<2,1,0> color_conv_rgba32_to_bgr24; //----color_conv_rgba32_to_bgr24 + + + //------------------------------------------------color_conv_rgb555_rgb24 + template class color_conv_rgb555_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + dst[R] = (int8u)((rgb >> 7) & 0xF8); + dst[1] = (int8u)((rgb >> 2) & 0xF8); + dst[B] = (int8u)((rgb << 3) & 0xF8); + src += 2; + dst += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb555_rgb24<2,0> color_conv_rgb555_to_bgr24; //----color_conv_rgb555_to_bgr24 + typedef color_conv_rgb555_rgb24<0,2> color_conv_rgb555_to_rgb24; //----color_conv_rgb555_to_rgb24 + + + //-------------------------------------------------color_conv_rgb24_rgb555 + template class color_conv_rgb24_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | + ((unsigned(src[1]) << 2) & 0x3E0) | + ((unsigned(src[B]) >> 3))); + src += 3; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgb555<2,0> color_conv_bgr24_to_rgb555; //----color_conv_bgr24_to_rgb555 + typedef color_conv_rgb24_rgb555<0,2> color_conv_rgb24_to_rgb555; //----color_conv_rgb24_to_rgb555 + + + //-------------------------------------------------color_conv_rgb565_rgb24 + template class color_conv_rgb565_rgb24 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + dst[R] = (rgb >> 8) & 0xF8; + dst[1] = (rgb >> 3) & 0xFC; + dst[B] = (rgb << 3) & 0xF8; + src += 2; + dst += 3; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb565_rgb24<2,0> color_conv_rgb565_to_bgr24; //----color_conv_rgb565_to_bgr24 + typedef color_conv_rgb565_rgb24<0,2> color_conv_rgb565_to_rgb24; //----color_conv_rgb565_to_rgb24 + + + //-------------------------------------------------color_conv_rgb24_rgb565 + template class color_conv_rgb24_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | + ((unsigned(src[1]) << 3) & 0x7E0) | + ((unsigned(src[B]) >> 3))); + src += 3; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb24_rgb565<2,0> color_conv_bgr24_to_rgb565; //----color_conv_bgr24_to_rgb565 + typedef color_conv_rgb24_rgb565<0,2> color_conv_rgb24_to_rgb565; //----color_conv_rgb24_to_rgb565 + + + + //-------------------------------------------------color_conv_rgb555_rgba32 + template class color_conv_rgb555_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int rgb = *(int16*)src; + dst[R] = (int8u)((rgb >> 7) & 0xF8); + dst[G] = (int8u)((rgb >> 2) & 0xF8); + dst[B] = (int8u)((rgb << 3) & 0xF8); + dst[A] = (int8u)(rgb >> 15); + src += 2; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb555_rgba32<1,2,3,0> color_conv_rgb555_to_argb32; //----color_conv_rgb555_to_argb32 + typedef color_conv_rgb555_rgba32<3,2,1,0> color_conv_rgb555_to_abgr32; //----color_conv_rgb555_to_abgr32 + typedef color_conv_rgb555_rgba32<2,1,0,3> color_conv_rgb555_to_bgra32; //----color_conv_rgb555_to_bgra32 + typedef color_conv_rgb555_rgba32<0,1,2,3> color_conv_rgb555_to_rgba32; //----color_conv_rgb555_to_rgba32 + + + //------------------------------------------------color_conv_rgba32_rgb555 + template class color_conv_rgba32_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 7) & 0x7C00) | + ((unsigned(src[G]) << 2) & 0x3E0) | + ((unsigned(src[B]) >> 3)) | + ((unsigned(src[A]) << 8) & 0x8000)); + src += 4; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb555<1,2,3,0> color_conv_argb32_to_rgb555; //----color_conv_argb32_to_rgb555 + typedef color_conv_rgba32_rgb555<3,2,1,0> color_conv_abgr32_to_rgb555; //----color_conv_abgr32_to_rgb555 + typedef color_conv_rgba32_rgb555<2,1,0,3> color_conv_bgra32_to_rgb555; //----color_conv_bgra32_to_rgb555 + typedef color_conv_rgba32_rgb555<0,1,2,3> color_conv_rgba32_to_rgb555; //----color_conv_rgba32_to_rgb555 + + + + //------------------------------------------------color_conv_rgb565_rgba32 + template class color_conv_rgb565_rgba32 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + int rgb = *(int16*)src; + dst[R] = (rgb >> 8) & 0xF8; + dst[G] = (rgb >> 3) & 0xFC; + dst[B] = (rgb << 3) & 0xF8; + dst[A] = 255; + src += 2; + dst += 4; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgb565_rgba32<1,2,3,0> color_conv_rgb565_to_argb32; //----color_conv_rgb565_to_argb32 + typedef color_conv_rgb565_rgba32<3,2,1,0> color_conv_rgb565_to_abgr32; //----color_conv_rgb565_to_abgr32 + typedef color_conv_rgb565_rgba32<2,1,0,3> color_conv_rgb565_to_bgra32; //----color_conv_rgb565_to_bgra32 + typedef color_conv_rgb565_rgba32<0,1,2,3> color_conv_rgb565_to_rgba32; //----color_conv_rgb565_to_rgba32 + + + //------------------------------------------------color_conv_rgba32_rgb565 + template class color_conv_rgba32_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *(int16u*)dst = (int16u)(((unsigned(src[R]) << 8) & 0xF800) | + ((unsigned(src[G]) << 3) & 0x7E0) | + ((unsigned(src[B]) >> 3))); + src += 4; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_rgba32_rgb565<1,2,3> color_conv_argb32_to_rgb565; //----color_conv_argb32_to_rgb565 + typedef color_conv_rgba32_rgb565<3,2,1> color_conv_abgr32_to_rgb565; //----color_conv_abgr32_to_rgb565 + typedef color_conv_rgba32_rgb565<2,1,0> color_conv_bgra32_to_rgb565; //----color_conv_bgra32_to_rgb565 + typedef color_conv_rgba32_rgb565<0,1,2> color_conv_rgba32_to_rgb565; //----color_conv_rgba32_to_rgb565 + + + //---------------------------------------------color_conv_rgb555_to_rgb565 + class color_conv_rgb555_to_rgb565 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + *(int16u*)dst = (int16u)(((rgb << 1) & 0xFFC0) | (rgb & 0x1F)); + src += 2; + dst += 2; + } + while(--width); + } + }; + + + //----------------------------------------------color_conv_rgb565_to_rgb555 + class color_conv_rgb565_to_rgb555 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + unsigned rgb = *(int16u*)src; + *(int16u*)dst = (int16u)(((rgb >> 1) & 0x7FE0) | (rgb & 0x1F)); + src += 2; + dst += 2; + } + while(--width); + } + }; + + + //------------------------------------------------------------------------ + typedef color_conv_same<2> color_conv_rgb555_to_rgb555; //----color_conv_rgb555_to_rgb555 + typedef color_conv_same<2> color_conv_rgb565_to_rgb565; //----color_conv_rgb565_to_rgb565 + + + template class color_conv_rgb24_gray8 + { + public: + void operator () (int8u* dst, + const int8u* src, + unsigned width) const + { + do + { + *dst++ = (src[R]*77 + src[1]*150 + src[B]*29) >> 8; + src += 3; + } + while(--width); + } + }; + + typedef color_conv_rgb24_gray8<0,2> color_conv_rgb24_to_gray8; //----color_conv_rgb24_to_gray8 + typedef color_conv_rgb24_gray8<2,0> color_conv_bgr24_to_gray8; //----color_conv_bgr24_to_gray8 + + +} + + + +#endif diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ChangeLog b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ChangeLog new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arc.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arc.cpp new file mode 100644 index 00000000000..df2c43a5596 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arc.cpp @@ -0,0 +1,106 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc vertex generator +// +//---------------------------------------------------------------------------- + +#include +#include "agg_arc.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + arc::arc(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw) : + m_x(x), m_y(y), m_rx(rx), m_ry(ry), m_scale(1.0) + { + normalize(a1, a2, ccw); + } + + //------------------------------------------------------------------------ + void arc::init(double x, double y, + double rx, double ry, + double a1, double a2, + bool ccw) + { + m_x = x; m_y = y; + m_rx = rx; m_ry = ry; + normalize(a1, a2, ccw); + } + + //------------------------------------------------------------------------ + void arc::approximation_scale(double s) + { + m_scale = s; + if(m_initialized) + { + normalize(m_start, m_end, m_ccw); + } + } + + //------------------------------------------------------------------------ + void arc::rewind(unsigned) + { + m_path_cmd = path_cmd_move_to; + m_angle = m_start; + } + + //------------------------------------------------------------------------ + unsigned arc::vertex(double* x, double* y) + { + if(is_stop(m_path_cmd)) return path_cmd_stop; + if((m_angle < m_end - m_da/4) != m_ccw) + { + *x = m_x + cos(m_end) * m_rx; + *y = m_y + sin(m_end) * m_ry; + m_path_cmd = path_cmd_stop; + return path_cmd_line_to; + } + + *x = m_x + cos(m_angle) * m_rx; + *y = m_y + sin(m_angle) * m_ry; + + m_angle += m_da; + + unsigned pf = m_path_cmd; + m_path_cmd = path_cmd_line_to; + return pf; + } + + //------------------------------------------------------------------------ + void arc::normalize(double a1, double a2, bool ccw) + { + double ra = (fabs(m_rx) + fabs(m_ry)) / 2; + m_da = acos(ra / (ra + 0.125 / m_scale)) * 2; + if(ccw) + { + while(a2 < a1) a2 += pi * 2.0; + } + else + { + while(a1 < a2) a1 += pi * 2.0; + m_da = -m_da; + } + m_ccw = ccw; + m_start = a1; + m_end = a2; + m_initialized = true; + } + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arrowhead.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arrowhead.cpp new file mode 100644 index 00000000000..1a6f8b41005 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_arrowhead.cpp @@ -0,0 +1,110 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Simple arrowhead/arrowtail generator +// +//---------------------------------------------------------------------------- + +#include "agg_arrowhead.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + arrowhead::arrowhead() : + m_head_d1(1.0), + m_head_d2(1.0), + m_head_d3(1.0), + m_head_d4(0.0), + m_tail_d1(1.0), + m_tail_d2(1.0), + m_tail_d3(1.0), + m_tail_d4(0.0), + m_head_flag(false), + m_tail_flag(false), + m_curr_id(0), + m_curr_coord(0) + { + } + + + + //------------------------------------------------------------------------ + void arrowhead::rewind(unsigned path_id) + { + m_curr_id = path_id; + m_curr_coord = 0; + if(path_id == 0) + { + if(!m_tail_flag) + { + m_cmd[0] = path_cmd_stop; + return; + } + m_coord[0] = m_tail_d1; m_coord[1] = 0.0; + m_coord[2] = m_tail_d1 - m_tail_d4; m_coord[3] = m_tail_d3; + m_coord[4] = -m_tail_d2 - m_tail_d4; m_coord[5] = m_tail_d3; + m_coord[6] = -m_tail_d2; m_coord[7] = 0.0; + m_coord[8] = -m_tail_d2 - m_tail_d4; m_coord[9] = -m_tail_d3; + m_coord[10] = m_tail_d1 - m_tail_d4; m_coord[11] = -m_tail_d3; + + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_line_to; + m_cmd[5] = path_cmd_line_to; + m_cmd[7] = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_cmd[6] = path_cmd_stop; + return; + } + + if(path_id == 1) + { + if(!m_head_flag) + { + m_cmd[0] = path_cmd_stop; + return; + } + m_coord[0] = -m_head_d1; m_coord[1] = 0.0; + m_coord[2] = m_head_d2 + m_head_d4; m_coord[3] = -m_head_d3; + m_coord[4] = m_head_d2; m_coord[5] = 0.0; + m_coord[6] = m_head_d2 + m_head_d4; m_coord[7] = m_head_d3; + + m_cmd[0] = path_cmd_move_to; + m_cmd[1] = path_cmd_line_to; + m_cmd[2] = path_cmd_line_to; + m_cmd[3] = path_cmd_line_to; + m_cmd[4] = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_cmd[5] = path_cmd_stop; + return; + } + } + + + //------------------------------------------------------------------------ + unsigned arrowhead::vertex(double* x, double* y) + { + if(m_curr_id < 2) + { + unsigned curr_idx = m_curr_coord * 2; + *x = m_coord[curr_idx]; + *y = m_coord[curr_idx + 1]; + return m_cmd[m_curr_coord++]; + } + return path_cmd_stop; + } + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bezier_arc.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bezier_arc.cpp new file mode 100644 index 00000000000..844d300c091 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bezier_arc.cpp @@ -0,0 +1,258 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e., +// 4, 7, 10, or 13 vertices. +// +//---------------------------------------------------------------------------- + + +#include +#include "agg_bezier_arc.h" + + +namespace agg +{ + + // This epsilon is used to prevent us from adding degenerate curves + // (converging to a single point). + // The value isn't very critical. Function arc_to_bezier() has a limit + // of the sweep_angle. If fabs(sweep_angle) exceeds pi/2 the curve + // becomes inaccurate. But slight exceeding is quite appropriate. + //-------------------------------------------------bezier_arc_angle_epsilon + const double bezier_arc_angle_epsilon = 0.01; + + //------------------------------------------------------------arc_to_bezier + void arc_to_bezier(double cx, double cy, double rx, double ry, + double start_angle, double sweep_angle, + double* curve) + { + double x0 = cos(sweep_angle / 2.0); + double y0 = sin(sweep_angle / 2.0); + double tx = (1.0 - x0) * 4.0 / 3.0; + double ty = y0 - tx * x0 / y0; + double px[4]; + double py[4]; + px[0] = x0; + py[0] = -y0; + px[1] = x0 + tx; + py[1] = -ty; + px[2] = x0 + tx; + py[2] = ty; + px[3] = x0; + py[3] = y0; + + double sn = sin(start_angle + sweep_angle / 2.0); + double cs = cos(start_angle + sweep_angle / 2.0); + + unsigned i; + for(i = 0; i < 4; i++) + { + curve[i * 2] = cx + rx * (px[i] * cs - py[i] * sn); + curve[i * 2 + 1] = cy + ry * (px[i] * sn + py[i] * cs); + } + } + + + + //------------------------------------------------------------------------ + void bezier_arc::init(double x, double y, + double rx, double ry, + double start_angle, + double sweep_angle) + { + start_angle = fmod(start_angle, 2.0 * pi); + if(sweep_angle >= 2.0 * pi) sweep_angle = 2.0 * pi; + if(sweep_angle <= -2.0 * pi) sweep_angle = -2.0 * pi; + + if(fabs(sweep_angle) < 1e-10) + { + m_num_vertices = 4; + m_cmd = path_cmd_line_to; + m_vertices[0] = x + rx * cos(start_angle); + m_vertices[1] = y + ry * sin(start_angle); + m_vertices[2] = x + rx * cos(start_angle + sweep_angle); + m_vertices[3] = y + ry * sin(start_angle + sweep_angle); + return; + } + + double total_sweep = 0.0; + double local_sweep = 0.0; + double prev_sweep; + m_num_vertices = 2; + m_cmd = path_cmd_curve4; + bool done = false; + do + { + if(sweep_angle < 0.0) + { + prev_sweep = total_sweep; + local_sweep = -pi * 0.5; + total_sweep -= pi * 0.5; + if(total_sweep <= sweep_angle + bezier_arc_angle_epsilon) + { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } + else + { + prev_sweep = total_sweep; + local_sweep = pi * 0.5; + total_sweep += pi * 0.5; + if(total_sweep >= sweep_angle - bezier_arc_angle_epsilon) + { + local_sweep = sweep_angle - prev_sweep; + done = true; + } + } + + arc_to_bezier(x, y, rx, ry, + start_angle, + local_sweep, + m_vertices + m_num_vertices - 2); + + m_num_vertices += 6; + start_angle += local_sweep; + } + while(!done && m_num_vertices < 26); + } + + + + + //-------------------------------------------------------------------- + void bezier_arc_svg::init(double x0, double y0, + double rx, double ry, + double angle, + bool large_arc_flag, + bool sweep_flag, + double x2, double y2) + { + m_radii_ok = true; + + if(rx < 0.0) rx = -rx; + if(ry < 0.0) ry = -rx; + + // Calculate the middle point between + // the current and the final points + //------------------------ + double dx2 = (x0 - x2) / 2.0; + double dy2 = (y0 - y2) / 2.0; + + double cos_a = cos(angle); + double sin_a = sin(angle); + + // Calculate (x1, y1) + //------------------------ + double x1 = cos_a * dx2 + sin_a * dy2; + double y1 = -sin_a * dx2 + cos_a * dy2; + + // Ensure radii are large enough + //------------------------ + double prx = rx * rx; + double pry = ry * ry; + double px1 = x1 * x1; + double py1 = y1 * y1; + + // Check that radii are large enough + //------------------------ + double radii_check = px1/prx + py1/pry; + if(radii_check > 1.0) + { + rx = sqrt(radii_check) * rx; + ry = sqrt(radii_check) * ry; + prx = rx * rx; + pry = ry * ry; + if(radii_check > 10.0) m_radii_ok = false; + } + + // Calculate (cx1, cy1) + //------------------------ + double sign = (large_arc_flag == sweep_flag) ? -1.0 : 1.0; + double sq = (prx*pry - prx*py1 - pry*px1) / (prx*py1 + pry*px1); + double coef = sign * sqrt((sq < 0) ? 0 : sq); + double cx1 = coef * ((rx * y1) / ry); + double cy1 = coef * -((ry * x1) / rx); + + // + // Calculate (cx, cy) from (cx1, cy1) + //------------------------ + double sx2 = (x0 + x2) / 2.0; + double sy2 = (y0 + y2) / 2.0; + double cx = sx2 + (cos_a * cx1 - sin_a * cy1); + double cy = sy2 + (sin_a * cx1 + cos_a * cy1); + + // Calculate the start_angle (angle1) and the sweep_angle (dangle) + //------------------------ + double ux = (x1 - cx1) / rx; + double uy = (y1 - cy1) / ry; + double vx = (-x1 - cx1) / rx; + double vy = (-y1 - cy1) / ry; + double p, n; + + // Calculate the angle start + //------------------------ + n = sqrt(ux*ux + uy*uy); + p = ux; // (1 * ux) + (0 * uy) + sign = (uy < 0) ? -1.0 : 1.0; + double v = p / n; + if(v < -1.0) v = -1.0; + if(v > 1.0) v = 1.0; + double start_angle = sign * acos(v); + + // Calculate the sweep angle + //------------------------ + n = sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)); + p = ux * vx + uy * vy; + sign = (ux * vy - uy * vx < 0) ? -1.0 : 1.0; + v = p / n; + if(v < -1.0) v = -1.0; + if(v > 1.0) v = 1.0; + double sweep_angle = sign * acos(v); + if(!sweep_flag && sweep_angle > 0) + { + sweep_angle -= pi * 2.0; + } + else + if (sweep_flag && sweep_angle < 0) + { + sweep_angle += pi * 2.0; + } + + // We can now build and transform the resulting arc + //------------------------ + m_arc.init(0.0, 0.0, rx, ry, start_angle, sweep_angle); + trans_affine mtx = trans_affine_rotation(angle); + mtx *= trans_affine_translation(cx, cy); + + for(unsigned i = 2; i < m_arc.num_vertices()-2; i += 2) + { + mtx.transform(m_arc.vertices() + i, m_arc.vertices() + i + 1); + } + + // We must make sure that the starting and ending points + // exactly coincide with the initial (x0,y0) and (x2,y2) + m_arc.vertices()[0] = x0; + m_arc.vertices()[1] = y0; + if(m_arc.num_vertices() > 2) + { + m_arc.vertices()[m_arc.num_vertices() - 2] = x2; + m_arc.vertices()[m_arc.num_vertices() - 1] = y2; + } + } + + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bspline.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bspline.cpp new file mode 100644 index 00000000000..e1fda9f51f2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_bspline.cpp @@ -0,0 +1,284 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class bspline +// +//---------------------------------------------------------------------------- + +#include "agg_bspline.h" + +namespace agg +{ + //------------------------------------------------------------------------ + bspline::bspline() : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + } + + //------------------------------------------------------------------------ + bspline::bspline(int num) : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + init(num); + } + + //------------------------------------------------------------------------ + bspline::bspline(int num, const double* x, const double* y) : + m_max(0), + m_num(0), + m_x(0), + m_y(0), + m_last_idx(-1) + { + init(num, x, y); + } + + + //------------------------------------------------------------------------ + void bspline::init(int max) + { + if(max > 2 && max > m_max) + { + m_am.resize(max * 3); + m_max = max; + m_x = &m_am[m_max]; + m_y = &m_am[m_max * 2]; + } + m_num = 0; + m_last_idx = -1; + } + + + //------------------------------------------------------------------------ + void bspline::add_point(double x, double y) + { + if(m_num < m_max) + { + m_x[m_num] = x; + m_y[m_num] = y; + ++m_num; + } + } + + + //------------------------------------------------------------------------ + void bspline::prepare() + { + if(m_num > 2) + { + int i, k, n1; + double* temp; + double* r; + double* s; + double h, p, d, f, e; + + for(k = 0; k < m_num; k++) + { + m_am[k] = 0.0; + } + + n1 = 3 * m_num; + + pod_array al(n1); + temp = &al[0]; + + for(k = 0; k < n1; k++) + { + temp[k] = 0.0; + } + + r = temp + m_num; + s = temp + m_num * 2; + + n1 = m_num - 1; + d = m_x[1] - m_x[0]; + e = (m_y[1] - m_y[0]) / d; + + for(k = 1; k < n1; k++) + { + h = d; + d = m_x[k + 1] - m_x[k]; + f = e; + e = (m_y[k + 1] - m_y[k]) / d; + al[k] = d / (d + h); + r[k] = 1.0 - al[k]; + s[k] = 6.0 * (e - f) / (h + d); + } + + for(k = 1; k < n1; k++) + { + p = 1.0 / (r[k] * al[k - 1] + 2.0); + al[k] *= -p; + s[k] = (s[k] - r[k] * s[k - 1]) * p; + } + + m_am[n1] = 0.0; + al[n1 - 1] = s[n1 - 1]; + m_am[n1 - 1] = al[n1 - 1]; + + for(k = n1 - 2, i = 0; i < m_num - 2; i++, k--) + { + al[k] = al[k] * al[k + 1] + s[k]; + m_am[k] = al[k]; + } + } + m_last_idx = -1; + } + + + + //------------------------------------------------------------------------ + void bspline::init(int num, const double* x, const double* y) + { + if(num > 2) + { + init(num); + int i; + for(i = 0; i < num; i++) + { + add_point(*x++, *y++); + } + prepare(); + } + m_last_idx = -1; + } + + + //------------------------------------------------------------------------ + void bspline::bsearch(int n, const double *x, double x0, int *i) + { + int j = n - 1; + int k; + + for(*i = 0; (j - *i) > 1; ) + { + if(x0 < x[k = (*i + j) >> 1]) j = k; + else *i = k; + } + } + + + + //------------------------------------------------------------------------ + double bspline::interpolation(double x, int i) const + { + int j = i + 1; + double d = m_x[i] - m_x[j]; + double h = x - m_x[j]; + double r = m_x[i] - x; + double p = d * d / 6.0; + return (m_am[j] * r * r * r + m_am[i] * h * h * h) / 6.0 / d + + ((m_y[j] - m_am[j] * p) * r + (m_y[i] - m_am[i] * p) * h) / d; + } + + + //------------------------------------------------------------------------ + double bspline::extrapolation_left(double x) const + { + double d = m_x[1] - m_x[0]; + return (-d * m_am[1] / 6 + (m_y[1] - m_y[0]) / d) * + (x - m_x[0]) + + m_y[0]; + } + + //------------------------------------------------------------------------ + double bspline::extrapolation_right(double x) const + { + double d = m_x[m_num - 1] - m_x[m_num - 2]; + return (d * m_am[m_num - 2] / 6 + (m_y[m_num - 1] - m_y[m_num - 2]) / d) * + (x - m_x[m_num - 1]) + + m_y[m_num - 1]; + } + + //------------------------------------------------------------------------ + double bspline::get(double x) const + { + if(m_num > 2) + { + int i; + + // Extrapolation on the left + if(x < m_x[0]) return extrapolation_left(x); + + // Extrapolation on the right + if(x >= m_x[m_num - 1]) return extrapolation_right(x); + + // Interpolation + bsearch(m_num, m_x, x, &i); + return interpolation(x, i); + } + return 0.0; + } + + + //------------------------------------------------------------------------ + double bspline::get_stateful(double x) const + { + if(m_num > 2) + { + // Extrapolation on the left + if(x < m_x[0]) return extrapolation_left(x); + + // Extrapolation on the right + if(x >= m_x[m_num - 1]) return extrapolation_right(x); + + if(m_last_idx >= 0) + { + // Check if x is not in current range + if(x < m_x[m_last_idx] || x > m_x[m_last_idx + 1]) + { + // Check if x between next points (most probably) + if(m_last_idx < m_num - 2 && + x >= m_x[m_last_idx + 1] && + x <= m_x[m_last_idx + 2]) + { + ++m_last_idx; + } + else + if(m_last_idx > 0 && + x >= m_x[m_last_idx - 1] && + x <= m_x[m_last_idx]) + { + // x is between pevious points + --m_last_idx; + } + else + { + // Else perform full search + bsearch(m_num, m_x, x, &m_last_idx); + } + } + return interpolation(x, m_last_idx); + } + else + { + // Interpolation + bsearch(m_num, m_x, x, &m_last_idx); + return interpolation(x, m_last_idx); + } + } + return 0.0; + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_color_rgba.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_color_rgba.cpp new file mode 100644 index 00000000000..9fe1534b033 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_color_rgba.cpp @@ -0,0 +1,17 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2009 John Horigan (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: john@glyphic.com.com +// http://www.antigrain.com +//---------------------------------------------------------------------------- + +// rgbaN construction from grayN types is no longer required, +// as grayN types now define their own conversions to rgbaN. diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_curves.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_curves.cpp new file mode 100644 index 00000000000..47017347188 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_curves.cpp @@ -0,0 +1,613 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include +#include "agg_curves.h" +#include "agg_math.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + const double curve_distance_epsilon = 1e-30; + const double curve_collinearity_epsilon = 1e-30; + const double curve_angle_tolerance_epsilon = 0.01; + enum curve_recursion_limit_e { curve_recursion_limit = 32 }; + + + + //------------------------------------------------------------------------ + void curve3_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve3_inc::approximation_scale() const + { + return m_scale; + } + + //------------------------------------------------------------------------ + void curve3_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x3; + m_end_y = y3; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + + double len = sqrt(dx1 * dx1 + dy1 * dy1) + sqrt(dx2 * dx2 + dy2 * dy2); + + m_num_steps = uround(len * 0.25 * m_scale); + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + + double tmpx = (x1 - x2 * 2.0 + x3) * subdivide_step2; + double tmpy = (y1 - y2 * 2.0 + y3) * subdivide_step2; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = tmpx + (x2 - x1) * (2.0 * subdivide_step); + m_saved_dfy = m_dfy = tmpy + (y2 - y1) * (2.0 * subdivide_step); + + m_ddfx = tmpx * 2.0; + m_ddfy = tmpy * 2.0; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve3_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + } + + //------------------------------------------------------------------------ + unsigned curve3_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + //------------------------------------------------------------------------ + void curve3_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve3_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + + double dx = x3-x1; + double dy = y3-y1; + double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx)); + double da; + + if(d > curve_collinearity_epsilon) + { + // Regular case + //----------------- + if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x123, y123)); + return; + } + + // Angle & Cusp Condition + //---------------------- + da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da >= pi) da = 2*pi - da; + + if(da < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x123, y123)); + return; + } + } + } + else + { + // Collinear case + //------------------ + da = dx*dx + dy*dy; + if(da == 0) + { + d = calc_sq_distance(x1, y1, x2, y2); + } + else + { + d = ((x2 - x1)*dx + (y2 - y1)*dy) / da; + if(d > 0 && d < 1) + { + // Simple collinear case, 1---2---3 + // We can leave just two endpoints + return; + } + if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1); + else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3); + else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy); + } + if(d < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); + recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); + } + + //------------------------------------------------------------------------ + void curve3_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, 0); + m_points.add(point_d(x3, y3)); + } + + + + + + //------------------------------------------------------------------------ + void curve4_inc::approximation_scale(double s) + { + m_scale = s; + } + + //------------------------------------------------------------------------ + double curve4_inc::approximation_scale() const + { + return m_scale; + } + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + //------------------------------------------------------------------------ + static double MSC60_fix_ICE(double v) { return v; } +#endif + + //------------------------------------------------------------------------ + void curve4_inc::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_start_x = x1; + m_start_y = y1; + m_end_x = x4; + m_end_y = y4; + + double dx1 = x2 - x1; + double dy1 = y2 - y1; + double dx2 = x3 - x2; + double dy2 = y3 - y2; + double dx3 = x4 - x3; + double dy3 = y4 - y3; + + double len = (sqrt(dx1 * dx1 + dy1 * dy1) + + sqrt(dx2 * dx2 + dy2 * dy2) + + sqrt(dx3 * dx3 + dy3 * dy3)) * 0.25 * m_scale; + +#if defined(_MSC_VER) && _MSC_VER <= 1200 + m_num_steps = uround(MSC60_fix_ICE(len)); +#else + m_num_steps = uround(len); +#endif + + if(m_num_steps < 4) + { + m_num_steps = 4; + } + + double subdivide_step = 1.0 / m_num_steps; + double subdivide_step2 = subdivide_step * subdivide_step; + double subdivide_step3 = subdivide_step * subdivide_step * subdivide_step; + + double pre1 = 3.0 * subdivide_step; + double pre2 = 3.0 * subdivide_step2; + double pre4 = 6.0 * subdivide_step2; + double pre5 = 6.0 * subdivide_step3; + + double tmp1x = x1 - x2 * 2.0 + x3; + double tmp1y = y1 - y2 * 2.0 + y3; + + double tmp2x = (x2 - x3) * 3.0 - x1 + x4; + double tmp2y = (y2 - y3) * 3.0 - y1 + y4; + + m_saved_fx = m_fx = x1; + m_saved_fy = m_fy = y1; + + m_saved_dfx = m_dfx = (x2 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdivide_step3; + m_saved_dfy = m_dfy = (y2 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdivide_step3; + + m_saved_ddfx = m_ddfx = tmp1x * pre4 + tmp2x * pre5; + m_saved_ddfy = m_ddfy = tmp1y * pre4 + tmp2y * pre5; + + m_dddfx = tmp2x * pre5; + m_dddfy = tmp2y * pre5; + + m_step = m_num_steps; + } + + //------------------------------------------------------------------------ + void curve4_inc::rewind(unsigned) + { + if(m_num_steps == 0) + { + m_step = -1; + return; + } + m_step = m_num_steps; + m_fx = m_saved_fx; + m_fy = m_saved_fy; + m_dfx = m_saved_dfx; + m_dfy = m_saved_dfy; + m_ddfx = m_saved_ddfx; + m_ddfy = m_saved_ddfy; + } + + //------------------------------------------------------------------------ + unsigned curve4_inc::vertex(double* x, double* y) + { + if(m_step < 0) return path_cmd_stop; + if(m_step == m_num_steps) + { + *x = m_start_x; + *y = m_start_y; + --m_step; + return path_cmd_move_to; + } + + if(m_step == 0) + { + *x = m_end_x; + *y = m_end_y; + --m_step; + return path_cmd_line_to; + } + + m_fx += m_dfx; + m_fy += m_dfy; + m_dfx += m_ddfx; + m_dfy += m_ddfy; + m_ddfx += m_dddfx; + m_ddfy += m_dddfy; + + *x = m_fx; + *y = m_fy; + --m_step; + return path_cmd_line_to; + } + + + + + //------------------------------------------------------------------------ + void curve4_div::init(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.remove_all(); + m_distance_tolerance_square = 0.5 / m_approximation_scale; + m_distance_tolerance_square *= m_distance_tolerance_square; + bezier(x1, y1, x2, y2, x3, y3, x4, y4); + m_count = 0; + } + + //------------------------------------------------------------------------ + void curve4_div::recursive_bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4, + unsigned level) + { + if(level > curve_recursion_limit) + { + return; + } + + // Calculate all the mid-points of the line segments + //---------------------- + double x12 = (x1 + x2) / 2; + double y12 = (y1 + y2) / 2; + double x23 = (x2 + x3) / 2; + double y23 = (y2 + y3) / 2; + double x34 = (x3 + x4) / 2; + double y34 = (y3 + y4) / 2; + double x123 = (x12 + x23) / 2; + double y123 = (y12 + y23) / 2; + double x234 = (x23 + x34) / 2; + double y234 = (y23 + y34) / 2; + double x1234 = (x123 + x234) / 2; + double y1234 = (y123 + y234) / 2; + + + // Try to approximate the full cubic curve by a single straight line + //------------------ + double dx = x4-x1; + double dy = y4-y1; + + double d2 = fabs(((x2 - x4) * dy - (y2 - y4) * dx)); + double d3 = fabs(((x3 - x4) * dy - (y3 - y4) * dx)); + double da1, da2, k; + + switch((int(d2 > curve_collinearity_epsilon) << 1) + + int(d3 > curve_collinearity_epsilon)) + { + case 0: + // All collinear OR p1==p4 + //---------------------- + k = dx*dx + dy*dy; + if(k == 0) + { + d2 = calc_sq_distance(x1, y1, x2, y2); + d3 = calc_sq_distance(x4, y4, x3, y3); + } + else + { + k = 1 / k; + da1 = x2 - x1; + da2 = y2 - y1; + d2 = k * (da1*dx + da2*dy); + da1 = x3 - x1; + da2 = y3 - y1; + d3 = k * (da1*dx + da2*dy); + if(d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) + { + // Simple collinear case, 1---2---3---4 + // We can leave just two endpoints + return; + } + if(d2 <= 0) d2 = calc_sq_distance(x2, y2, x1, y1); + else if(d2 >= 1) d2 = calc_sq_distance(x2, y2, x4, y4); + else d2 = calc_sq_distance(x2, y2, x1 + d2*dx, y1 + d2*dy); + + if(d3 <= 0) d3 = calc_sq_distance(x3, y3, x1, y1); + else if(d3 >= 1) d3 = calc_sq_distance(x3, y3, x4, y4); + else d3 = calc_sq_distance(x3, y3, x1 + d3*dx, y1 + d3*dy); + } + if(d2 > d3) + { + if(d2 < m_distance_tolerance_square) + { + m_points.add(point_d(x2, y2)); + return; + } + } + else + { + if(d3 < m_distance_tolerance_square) + { + m_points.add(point_d(x3, y3)); + return; + } + } + break; + + case 1: + // p1,p2,p4 are collinear, p3 is significant + //---------------------- + if(d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + + case 2: + // p1,p3,p4 are collinear, p2 is significant + //---------------------- + if(d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle Condition + //---------------------- + da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1)); + if(da1 >= pi) da1 = 2*pi - da1; + + if(da1 < m_angle_tolerance) + { + m_points.add(point_d(x2, y2)); + m_points.add(point_d(x3, y3)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + } + } + break; + + case 3: + // Regular case + //----------------- + if((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy)) + { + // If the curvature doesn't exceed the distance_tolerance value + // we tend to finish subdivisions. + //---------------------- + if(m_angle_tolerance < curve_angle_tolerance_epsilon) + { + m_points.add(point_d(x23, y23)); + return; + } + + // Angle & Cusp Condition + //---------------------- + k = atan2(y3 - y2, x3 - x2); + da1 = fabs(k - atan2(y2 - y1, x2 - x1)); + da2 = fabs(atan2(y4 - y3, x4 - x3) - k); + if(da1 >= pi) da1 = 2*pi - da1; + if(da2 >= pi) da2 = 2*pi - da2; + + if(da1 + da2 < m_angle_tolerance) + { + // Finally we can stop the recursion + //---------------------- + m_points.add(point_d(x23, y23)); + return; + } + + if(m_cusp_limit != 0.0) + { + if(da1 > m_cusp_limit) + { + m_points.add(point_d(x2, y2)); + return; + } + + if(da2 > m_cusp_limit) + { + m_points.add(point_d(x3, y3)); + return; + } + } + } + break; + } + + // Continue subdivision + //---------------------- + recursive_bezier(x1, y1, x12, y12, x123, y123, x1234, y1234, level + 1); + recursive_bezier(x1234, y1234, x234, y234, x34, y34, x4, y4, level + 1); + } + + //------------------------------------------------------------------------ + void curve4_div::bezier(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_points.add(point_d(x1, y1)); + recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0); + m_points.add(point_d(x4, y4)); + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_embedded_raster_fonts.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_embedded_raster_fonts.cpp new file mode 100644 index 00000000000..ee4dc65ee44 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_embedded_raster_fonts.cpp @@ -0,0 +1,10426 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_embedded_raster_fonts.h" + +namespace agg +{ + + const int8u gse4x6[] = + { + 6, 0, 32, 128-32, + + 0x00,0x00,0x07,0x00,0x0e,0x00,0x15,0x00,0x1c,0x00,0x23,0x00,0x2a,0x00,0x31,0x00,0x38,0x00, + 0x3f,0x00,0x46,0x00,0x4d,0x00,0x54,0x00,0x5b,0x00,0x62,0x00,0x69,0x00,0x70,0x00,0x77,0x00, + 0x7e,0x00,0x85,0x00,0x8c,0x00,0x93,0x00,0x9a,0x00,0xa1,0x00,0xa8,0x00,0xaf,0x00,0xb6,0x00, + 0xbd,0x00,0xc4,0x00,0xcb,0x00,0xd2,0x00,0xd9,0x00,0xe0,0x00,0xe7,0x00,0xee,0x00,0xf5,0x00, + 0xfc,0x00,0x03,0x01,0x0a,0x01,0x11,0x01,0x18,0x01,0x1f,0x01,0x26,0x01,0x2d,0x01,0x34,0x01, + 0x3b,0x01,0x42,0x01,0x49,0x01,0x50,0x01,0x57,0x01,0x5e,0x01,0x65,0x01,0x6c,0x01,0x73,0x01, + 0x7a,0x01,0x81,0x01,0x88,0x01,0x8f,0x01,0x96,0x01,0x9d,0x01,0xa4,0x01,0xab,0x01,0xb2,0x01, + 0xb9,0x01,0xc0,0x01,0xc7,0x01,0xce,0x01,0xd5,0x01,0xdc,0x01,0xe3,0x01,0xea,0x01,0xf1,0x01, + 0xf8,0x01,0xff,0x01,0x06,0x02,0x0d,0x02,0x14,0x02,0x1b,0x02,0x22,0x02,0x29,0x02,0x30,0x02, + 0x37,0x02,0x3e,0x02,0x45,0x02,0x4c,0x02,0x53,0x02,0x5a,0x02,0x61,0x02,0x68,0x02,0x6f,0x02, + 0x76,0x02,0x7d,0x02,0x84,0x02,0x8b,0x02,0x92,0x02,0x99,0x02, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0xa0,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x23 '#' + 0x60,0xf0,0x60,0xf0,0x60,0x00, + + 4, // 0x24 '$' + 0x40,0x60,0xc0,0x60,0xc0,0x40, + + 4, // 0x25 '%' + 0xa0,0x20,0x40,0x80,0xa0,0x00, + + 4, // 0x26 '&' + 0xe0,0xa0,0x50,0xa0,0xd0,0x00, + + 4, // 0x27 ''' + 0x40,0x40,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x20,0x40,0x40,0x40,0x20,0x00, + + 4, // 0x29 ')' + 0x40,0x20,0x20,0x20,0x40,0x00, + + 4, // 0x2a '*' + 0xa0,0x40,0xe0,0x40,0xa0,0x00, + + 4, // 0x2b '+' + 0x40,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x2c ',' + 0x00,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x2d '-' + 0x00,0x00,0xe0,0x00,0x00,0x00, + + 4, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x40,0x00, + + 4, // 0x2f '/' + 0x10,0x20,0x20,0x40,0x40,0x80, + + 4, // 0x30 '0' + 0xe0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x31 '1' + 0x40,0xc0,0x40,0x40,0xe0,0x00, + + 4, // 0x32 '2' + 0xe0,0xa0,0x20,0x40,0xe0,0x00, + + 4, // 0x33 '3' + 0xe0,0x20,0x40,0x20,0xe0,0x00, + + 4, // 0x34 '4' + 0xa0,0xa0,0xe0,0x20,0x20,0x00, + + 4, // 0x35 '5' + 0xe0,0x80,0xc0,0x20,0xc0,0x00, + + 4, // 0x36 '6' + 0x40,0x80,0xe0,0xa0,0xe0,0x00, + + 4, // 0x37 '7' + 0xe0,0xa0,0x20,0x40,0x40,0x00, + + 4, // 0x38 '8' + 0xe0,0xa0,0x40,0xa0,0xe0,0x00, + + 4, // 0x39 '9' + 0xe0,0xa0,0xe0,0x20,0xc0,0x00, + + 4, // 0x3a ':' + 0x00,0x40,0x00,0x40,0x00,0x00, + + 4, // 0x3b ';' + 0x00,0x40,0x00,0x40,0x40,0x80, + + 4, // 0x3c '<' + 0x20,0x40,0x80,0x40,0x20,0x00, + + 4, // 0x3d '=' + 0x00,0xe0,0x00,0xe0,0x00,0x00, + + 4, // 0x3e '>' + 0x80,0x40,0x20,0x40,0x80,0x00, + + 4, // 0x3f '?' + 0xc0,0x20,0x40,0x00,0x40,0x00, + + 4, // 0x40 '@' + 0x40,0xa0,0xe0,0xe0,0x80,0x60, + + 4, // 0x41 'A' + 0x40,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x42 'B' + 0xc0,0xa0,0xc0,0xa0,0xc0,0x00, + + 4, // 0x43 'C' + 0x60,0x80,0x80,0x80,0x60,0x00, + + 4, // 0x44 'D' + 0xc0,0xa0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x45 'E' + 0xe0,0x80,0xc0,0x80,0xe0,0x00, + + 4, // 0x46 'F' + 0xe0,0x80,0xc0,0x80,0x80,0x00, + + 4, // 0x47 'G' + 0x60,0x80,0xa0,0xa0,0x40,0x00, + + 4, // 0x48 'H' + 0xa0,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x49 'I' + 0xe0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x4a 'J' + 0x20,0x20,0x20,0x20,0xa0,0x40, + + 4, // 0x4b 'K' + 0xa0,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x4c 'L' + 0x80,0x80,0x80,0x80,0xe0,0x00, + + 4, // 0x4d 'M' + 0xa0,0xe0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x4e 'N' + 0x90,0xd0,0xb0,0x90,0x90,0x00, + + 4, // 0x4f 'O' + 0x40,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x50 'P' + 0xc0,0xa0,0xa0,0xc0,0x80,0x00, + + 4, // 0x51 'Q' + 0x40,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x52 'R' + 0xc0,0xa0,0xa0,0xc0,0xa0,0x00, + + 4, // 0x53 'S' + 0x60,0x80,0x40,0x20,0xc0,0x00, + + 4, // 0x54 'T' + 0xe0,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x55 'U' + 0xa0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x56 'V' + 0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x57 'W' + 0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x58 'X' + 0xa0,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x59 'Y' + 0xa0,0xa0,0x40,0x40,0x40,0x00, + + 4, // 0x5a 'Z' + 0xe0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x5b '[' + 0xc0,0x80,0x80,0x80,0xc0,0x00, + + 4, // 0x5c '\' + 0x80,0x40,0x40,0x20,0x20,0x10, + + 4, // 0x5d ']' + 0xc0,0x40,0x40,0x40,0xc0,0x00, + + 4, // 0x5e '^' + 0x40,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0xf0, + + 4, // 0x60 '`' + 0x40,0x20,0x00,0x00,0x00,0x00, + + 4, // 0x61 'a' + 0x00,0x60,0xa0,0xa0,0x70,0x00, + + 4, // 0x62 'b' + 0x80,0x80,0xc0,0xa0,0xc0,0x00, + + 4, // 0x63 'c' + 0x00,0x60,0x80,0x80,0x60,0x00, + + 4, // 0x64 'd' + 0x20,0x20,0x60,0xa0,0x60,0x00, + + 4, // 0x65 'e' + 0x00,0x40,0xe0,0x80,0x60,0x00, + + 4, // 0x66 'f' + 0x20,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x67 'g' + 0x00,0x60,0xa0,0x60,0x20,0xc0, + + 4, // 0x68 'h' + 0x80,0x80,0xc0,0xa0,0xa0,0x00, + + 4, // 0x69 'i' + 0x40,0x00,0xc0,0x40,0xe0,0x00, + + 4, // 0x6a 'j' + 0x40,0x00,0xc0,0x40,0x40,0x80, + + 4, // 0x6b 'k' + 0x80,0x80,0xa0,0xc0,0xa0,0x00, + + 4, // 0x6c 'l' + 0xc0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x6d 'm' + 0x00,0xa0,0xf0,0xf0,0x90,0x00, + + 4, // 0x6e 'n' + 0x00,0xc0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x6f 'o' + 0x00,0x40,0xa0,0xa0,0x40,0x00, + + 4, // 0x70 'p' + 0x00,0xc0,0xa0,0xc0,0x80,0x80, + + 4, // 0x71 'q' + 0x00,0x60,0xa0,0x60,0x20,0x20, + + 4, // 0x72 'r' + 0x00,0xa0,0x50,0x40,0x40,0x00, + + 4, // 0x73 's' + 0x00,0x60,0xc0,0x20,0xc0,0x00, + + 4, // 0x74 't' + 0x40,0x40,0xe0,0x40,0x60,0x00, + + 4, // 0x75 'u' + 0x00,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x76 'v' + 0x00,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x77 'w' + 0x00,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x78 'x' + 0x00,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x79 'y' + 0x00,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x7a 'z' + 0x00,0xe0,0x40,0x80,0xe0,0x00, + + 4, // 0x7b '{' + 0x30,0x20,0xc0,0x20,0x30,0x00, + + 4, // 0x7c '|' + 0x40,0x40,0x00,0x40,0x40,0x40, + + 4, // 0x7d '}' + 0xc0,0x40,0x30,0x40,0xc0,0x00, + + 4, // 0x7e '~' + 0x50,0xa0,0x00,0x00,0x00,0x00, + + 4, // 0x7f '' + 0x00,0x60,0x90,0xf0,0x00,0x00, + 0 + }; + + const int8u gse4x8[] = + { + 8, 0, 32, 128-32, + + 0x00,0x00,0x09,0x00,0x12,0x00,0x1b,0x00,0x24,0x00,0x2d,0x00,0x36,0x00,0x3f,0x00,0x48,0x00, + 0x51,0x00,0x5a,0x00,0x63,0x00,0x6c,0x00,0x75,0x00,0x7e,0x00,0x87,0x00,0x90,0x00,0x99,0x00, + 0xa2,0x00,0xab,0x00,0xb4,0x00,0xbd,0x00,0xc6,0x00,0xcf,0x00,0xd8,0x00,0xe1,0x00,0xea,0x00, + 0xf3,0x00,0xfc,0x00,0x05,0x01,0x0e,0x01,0x17,0x01,0x20,0x01,0x29,0x01,0x32,0x01,0x3b,0x01, + 0x44,0x01,0x4d,0x01,0x56,0x01,0x5f,0x01,0x68,0x01,0x71,0x01,0x7a,0x01,0x83,0x01,0x8c,0x01, + 0x95,0x01,0x9e,0x01,0xa7,0x01,0xb0,0x01,0xb9,0x01,0xc2,0x01,0xcb,0x01,0xd4,0x01,0xdd,0x01, + 0xe6,0x01,0xef,0x01,0xf8,0x01,0x01,0x02,0x0a,0x02,0x13,0x02,0x1c,0x02,0x25,0x02,0x2e,0x02, + 0x37,0x02,0x40,0x02,0x49,0x02,0x52,0x02,0x5b,0x02,0x64,0x02,0x6d,0x02,0x76,0x02,0x7f,0x02, + 0x88,0x02,0x91,0x02,0x9a,0x02,0xa3,0x02,0xac,0x02,0xb5,0x02,0xbe,0x02,0xc7,0x02,0xd0,0x02, + 0xd9,0x02,0xe2,0x02,0xeb,0x02,0xf4,0x02,0xfd,0x02,0x06,0x03,0x0f,0x03,0x18,0x03,0x21,0x03, + 0x2a,0x03,0x33,0x03,0x3c,0x03,0x45,0x03,0x4e,0x03,0x57,0x03, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0x00,0xa0,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x23 '#' + 0x60,0x60,0xf0,0x60,0x60,0xf0,0x60,0x60, + + 4, // 0x24 '$' + 0x40,0x60,0xc0,0xc0,0x60,0x60,0xc0,0x40, + + 4, // 0x25 '%' + 0x00,0xa0,0x20,0x40,0x40,0x80,0xa0,0x00, + + 4, // 0x26 '&' + 0x00,0x40,0xa0,0xa0,0x40,0xb0,0xa0,0x70, + + 4, // 0x27 ''' + 0x00,0x40,0x40,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x20,0x40,0x80,0x80,0x80,0x80,0x40,0x20, + + 4, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x20,0x40,0x80, + + 4, // 0x2a '*' + 0x00,0xa0,0x40,0xe0,0x40,0xa0,0x00,0x00, + + 4, // 0x2b '+' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x00,0x00, + + 4, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x2d '-' + 0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00, + + 4, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 4, // 0x2f '/' + 0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + + 4, // 0x30 '0' + 0x00,0xe0,0xa0,0xa0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x31 '1' + 0x00,0x40,0xc0,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x32 '2' + 0x00,0xe0,0xa0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x33 '3' + 0x00,0xe0,0x20,0x40,0x20,0x20,0xe0,0x00, + + 4, // 0x34 '4' + 0x00,0x60,0xa0,0xa0,0xf0,0x20,0x20,0x00, + + 4, // 0x35 '5' + 0x00,0xe0,0x80,0xc0,0x20,0x20,0xc0,0x00, + + 4, // 0x36 '6' + 0x00,0x40,0x80,0xe0,0xa0,0xa0,0xe0,0x00, + + 4, // 0x37 '7' + 0x00,0xe0,0xa0,0x20,0x40,0x40,0x40,0x00, + + 4, // 0x38 '8' + 0x00,0xe0,0xa0,0x40,0xa0,0xa0,0xe0,0x00, + + 4, // 0x39 '9' + 0x00,0xe0,0xa0,0xe0,0x20,0x20,0x40,0x00, + + 4, // 0x3a ':' + 0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00, + + 4, // 0x3b ';' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x80, + + 4, // 0x3c '<' + 0x00,0x20,0x40,0x80,0x40,0x20,0x00,0x00, + + 4, // 0x3d '=' + 0x00,0x00,0xe0,0x00,0xe0,0x00,0x00,0x00, + + 4, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x40,0x80,0x00,0x00, + + 4, // 0x3f '?' + 0x00,0x40,0xa0,0x20,0x40,0x00,0x40,0x00, + + 4, // 0x40 '@' + 0x00,0x40,0xa0,0xe0,0xe0,0x80,0x60,0x00, + + 4, // 0x41 'A' + 0x00,0x40,0xa0,0xa0,0xe0,0xa0,0xa0,0x00, + + 4, // 0x42 'B' + 0x00,0xc0,0xa0,0xc0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x43 'C' + 0x00,0x40,0xa0,0x80,0x80,0xa0,0x40,0x00, + + 4, // 0x44 'D' + 0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x45 'E' + 0x00,0xe0,0x80,0xc0,0x80,0x80,0xe0,0x00, + + 4, // 0x46 'F' + 0x00,0xe0,0x80,0xc0,0x80,0x80,0x80,0x00, + + 4, // 0x47 'G' + 0x00,0x60,0x80,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x48 'H' + 0x00,0xa0,0xa0,0xe0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x49 'I' + 0x00,0xe0,0x40,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x4a 'J' + 0x00,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, + + 4, // 0x4b 'K' + 0x00,0xa0,0xa0,0xc0,0xc0,0xa0,0xa0,0x00, + + 4, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0xe0,0x00, + + 4, // 0x4d 'M' + 0x00,0xa0,0xe0,0xa0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x4e 'N' + 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x00, + + 4, // 0x4f 'O' + 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x50 'P' + 0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80,0x00, + + 4, // 0x51 'Q' + 0x00,0x40,0xa0,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x52 'R' + 0x00,0xc0,0xa0,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x53 'S' + 0x00,0x60,0x80,0x40,0x20,0x20,0xc0,0x00, + + 4, // 0x54 'T' + 0x00,0xe0,0x40,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x55 'U' + 0x00,0xa0,0xa0,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x56 'V' + 0x00,0xa0,0xa0,0xa0,0xa0,0x40,0x40,0x00, + + 4, // 0x57 'W' + 0x00,0xa0,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x58 'X' + 0x00,0xa0,0xa0,0x40,0xa0,0xa0,0xa0,0x00, + + 4, // 0x59 'Y' + 0x00,0xa0,0xa0,0x40,0x40,0x40,0x40,0x00, + + 4, // 0x5a 'Z' + 0x00,0xe0,0x20,0x40,0x40,0x80,0xe0,0x00, + + 4, // 0x5b '[' + 0xc0,0x80,0x80,0x80,0x80,0x80,0x80,0xc0, + + 4, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10, + + 4, // 0x5d ']' + 0xc0,0x40,0x40,0x40,0x40,0x40,0x40,0xc0, + + 4, // 0x5e '^' + 0x00,0x40,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0, + + 4, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x61 'a' + 0x00,0x00,0x60,0xa0,0xa0,0xa0,0x70,0x00, + + 4, // 0x62 'b' + 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xc0,0x00, + + 4, // 0x63 'c' + 0x00,0x00,0x40,0xa0,0x80,0xa0,0x40,0x00, + + 4, // 0x64 'd' + 0x00,0x20,0x20,0x60,0xa0,0xa0,0x60,0x00, + + 4, // 0x65 'e' + 0x00,0x00,0x40,0xa0,0xe0,0x80,0x60,0x00, + + 4, // 0x66 'f' + 0x00,0x20,0x40,0x40,0xe0,0x40,0x40,0x00, + + 4, // 0x67 'g' + 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x68 'h' + 0x00,0x80,0x80,0xc0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x69 'i' + 0x00,0x40,0x00,0xc0,0x40,0x40,0xe0,0x00, + + 4, // 0x6a 'j' + 0x00,0x40,0x00,0xc0,0x40,0x40,0x40,0x80, + + 4, // 0x6b 'k' + 0x00,0x80,0x80,0xa0,0xc0,0xc0,0xa0,0x00, + + 4, // 0x6c 'l' + 0x00,0xc0,0x40,0x40,0x40,0x40,0xe0,0x00, + + 4, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x00, + + 4, // 0x6e 'n' + 0x00,0x00,0xc0,0xa0,0xa0,0xa0,0xa0,0x00, + + 4, // 0x6f 'o' + 0x00,0x00,0x40,0xa0,0xa0,0xa0,0x40,0x00, + + 4, // 0x70 'p' + 0x00,0x00,0xc0,0xa0,0xa0,0xc0,0x80,0x80, + + 4, // 0x71 'q' + 0x00,0x00,0x60,0xa0,0xa0,0x60,0x20,0x20, + + 4, // 0x72 'r' + 0x00,0x00,0xa0,0x50,0x40,0x40,0x40,0x00, + + 4, // 0x73 's' + 0x00,0x00,0x60,0x80,0x40,0x20,0xc0,0x00, + + 4, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x20,0x00, + + 4, // 0x75 'u' + 0x00,0x00,0xa0,0xa0,0xa0,0xa0,0x60,0x00, + + 4, // 0x76 'v' + 0x00,0x00,0xa0,0xa0,0xa0,0x40,0x40,0x00, + + 4, // 0x77 'w' + 0x00,0x00,0xa0,0xa0,0xa0,0xe0,0xa0,0x00, + + 4, // 0x78 'x' + 0x00,0x00,0xa0,0xa0,0x40,0xa0,0xa0,0x00, + + 4, // 0x79 'y' + 0x00,0x00,0xa0,0xa0,0xa0,0x60,0x20,0xc0, + + 4, // 0x7a 'z' + 0x00,0x00,0xe0,0x20,0x40,0x80,0xe0,0x00, + + 4, // 0x7b '{' + 0x10,0x20,0x20,0xc0,0x20,0x20,0x10,0x00, + + 4, // 0x7c '|' + 0x00,0x40,0x40,0x40,0x00,0x40,0x40,0x40, + + 4, // 0x7d '}' + 0x80,0x40,0x40,0x30,0x40,0x40,0x80,0x00, + + 4, // 0x7e '~' + 0x00,0x50,0xa0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x7f '' + 0x00,0x00,0x00,0x60,0x90,0xf0,0x00,0x00, + 0 + }; + + const int8u gse5x7[] = + { + 7, 0, 32, 128-32, + + 0x00,0x00,0x08,0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x38,0x00,0x40,0x00, + 0x48,0x00,0x50,0x00,0x58,0x00,0x60,0x00,0x68,0x00,0x70,0x00,0x78,0x00,0x80,0x00,0x88,0x00, + 0x90,0x00,0x98,0x00,0xa0,0x00,0xa8,0x00,0xb0,0x00,0xb8,0x00,0xc0,0x00,0xc8,0x00,0xd0,0x00, + 0xd8,0x00,0xe0,0x00,0xe8,0x00,0xf0,0x00,0xf8,0x00,0x00,0x01,0x08,0x01,0x10,0x01,0x18,0x01, + 0x20,0x01,0x28,0x01,0x30,0x01,0x38,0x01,0x40,0x01,0x48,0x01,0x50,0x01,0x58,0x01,0x60,0x01, + 0x68,0x01,0x70,0x01,0x78,0x01,0x80,0x01,0x88,0x01,0x90,0x01,0x98,0x01,0xa0,0x01,0xa8,0x01, + 0xb0,0x01,0xb8,0x01,0xc0,0x01,0xc8,0x01,0xd0,0x01,0xd8,0x01,0xe0,0x01,0xe8,0x01,0xf0,0x01, + 0xf8,0x01,0x00,0x02,0x08,0x02,0x10,0x02,0x18,0x02,0x20,0x02,0x28,0x02,0x30,0x02,0x38,0x02, + 0x40,0x02,0x48,0x02,0x50,0x02,0x58,0x02,0x60,0x02,0x68,0x02,0x70,0x02,0x78,0x02,0x80,0x02, + 0x88,0x02,0x90,0x02,0x98,0x02,0xa0,0x02,0xa8,0x02,0xb0,0x02,0xb8,0x02,0xc0,0x02,0xc8,0x02, + 0xd0,0x02,0xd8,0x02,0xe0,0x02,0xe8,0x02,0xf0,0x02,0xf8,0x02, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0xf8,0x50,0xf8,0x50,0x00, + + 5, // 0x24 '$' + 0x20,0x78,0xa0,0x70,0x28,0xf0,0x20, + + 5, // 0x25 '%' + 0x00,0x88,0x10,0x20,0x40,0x88,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xa0,0x68,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x20,0x10, + + 5, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x40,0x80, + + 5, // 0x2a '*' + 0x00,0x20,0xa8,0x70,0xa8,0x20,0x00, + + 5, // 0x2b '+' + 0x00,0x20,0x20,0xf8,0x20,0x20,0x00, + + 5, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x2d '-' + 0x00,0x00,0x00,0xf0,0x00,0x00,0x00, + + 5, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 5, // 0x2f '/' + 0x00,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x20,0x40,0xf0,0x00, + + 5, // 0x33 '3' + 0x00,0xf0,0x20,0x60,0x10,0xe0,0x00, + + 5, // 0x34 '4' + 0x00,0x30,0x50,0x90,0xf0,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xf0,0x80,0xe0,0x10,0xe0,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0xe0,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xf0,0x90,0x20,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x60,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x70,0x10,0x60,0x00, + + 5, // 0x3a ':' + 0x00,0x00,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x3b ';' + 0x00,0x00,0x20,0x00,0x20,0x20,0x40, + + 5, // 0x3c '<' + 0x00,0x10,0x20,0x40,0x20,0x10,0x00, + + 5, // 0x3d '=' + 0x00,0x00,0xf0,0x00,0xf0,0x00,0x00, + + 5, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x40,0x80,0x00, + + 5, // 0x3f '?' + 0x00,0x60,0x90,0x20,0x00,0x20,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0xb0,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0xf0,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xe0,0x90,0xe0,0x90,0xe0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xe0,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x45 'E' + 0x00,0xf0,0x80,0xe0,0x80,0xf0,0x00, + + 5, // 0x46 'F' + 0x00,0xf0,0x80,0xe0,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x70,0x80,0xb0,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0xf0,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4a 'J' + 0x00,0x70,0x20,0x20,0xa0,0x40,0x00, + + 5, // 0x4b 'K' + 0x00,0x90,0xa0,0xc0,0xa0,0x90,0x00, + + 5, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0xf0,0x00, + + 5, // 0x4d 'M' + 0x00,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x4e 'N' + 0x00,0x90,0xd0,0xb0,0x90,0x90,0x00, + + 5, // 0x4f 'O' + 0x00,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xe0,0x90,0xe0,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0xa0,0x50,0x00, + + 5, // 0x52 'R' + 0x00,0xe0,0x90,0xe0,0xa0,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x70,0x80,0x60,0x10,0xe0,0x00, + + 5, // 0x54 'T' + 0x00,0x70,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x60,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x50,0x50,0x20,0x20,0x20,0x00, + + 5, // 0x5a 'Z' + 0x00,0xf0,0x10,0x20,0x40,0xf0,0x00, + + 5, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5c '\' + 0x00,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x5d ']' + 0xe0,0x20,0x20,0x20,0x20,0x20,0xe0, + + 5, // 0x5e '^' + 0x00,0x20,0x50,0x00,0x00,0x00,0x00, + + 5, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x60,0xa0,0xa0,0x50,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xe0,0x90,0xe0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x70,0x80,0x80,0x70,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x60,0xf0,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xe0,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x70,0x90,0x70,0x10,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x20,0x00,0x60,0x20,0x20,0x70,0x00, + + 5, // 0x6a 'j' + 0x20,0x00,0x60,0x20,0x20,0xa0,0x40, + + 5, // 0x6b 'k' + 0x80,0x80,0x90,0xa0,0xe0,0x90,0x00, + + 5, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0x90,0x00, + + 5, // 0x6e 'n' + 0x00,0x00,0xa0,0xd0,0x90,0x90,0x00, + + 5, // 0x6f 'o' + 0x00,0x00,0x60,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0xe0,0x90,0xe0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x70,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0xe0,0x90,0x80,0x80,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x70,0xe0,0x10,0xe0,0x00, + + 5, // 0x74 't' + 0x40,0x40,0xe0,0x40,0x40,0x70,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x50,0x50,0x50,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x90,0x60,0x60,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x90,0x90,0x70,0x10,0x60, + + 5, // 0x7a 'z' + 0x00,0x00,0xf0,0x20,0x40,0xf0,0x00, + + 5, // 0x7b '{' + 0x10,0x20,0x20,0xc0,0x20,0x20,0x10, + + 5, // 0x7c '|' + 0x20,0x20,0x20,0x00,0x20,0x20,0x20, + + 5, // 0x7d '}' + 0x40,0x20,0x20,0x18,0x20,0x20,0x40, + + 5, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00, + + 5, // 0x7f '' + 0x00,0x00,0x20,0x50,0x88,0xf8,0x00, + 0 + }; + + const int8u gse5x9[] = + { + 9, 0, 32, 128-32, + + 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, + 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, + 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, + 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, + 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, + 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, + 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, + 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, + 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, + 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, + 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x20,0x78,0xa0,0x70,0x28,0xf0,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xa0,0xa0,0x40,0xa8,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 5, // 0x29 ')' + 0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x80, + + 5, // 0x2a '*' + 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, + + 5, // 0x2b '+' + 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, + + 5, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x2d '-' + 0x00,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x00, + + 5, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 5, // 0x2f '/' + 0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80, + + 5, // 0x30 '0' + 0x00,0x60,0x90,0xb0,0xd0,0x90,0x90,0x60,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x33 '3' + 0x00,0xf0,0x10,0x20,0x60,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x30,0x50,0x90,0x90,0xf8,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xf0,0x80,0xe0,0x10,0x10,0x10,0xe0,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0xe0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xf0,0x90,0x10,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x70,0x10,0x90,0x60,0x00, + + 5, // 0x3a ':' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, + + 5, // 0x3b ';' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, + + 5, // 0x3c '<' + 0x00,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00, + + 5, // 0x3d '=' + 0x00,0x00,0x00,0xf0,0x00,0xf0,0x00,0x00,0x00, + + 5, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3f '?' + 0x00,0x60,0x90,0x10,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0xb0,0xb0,0xb0,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xe0,0x90,0x90,0xe0,0x90,0x90,0xe0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xe0,0x90,0x90,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x45 'E' + 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0xf0,0x00, + + 5, // 0x46 'F' + 0x00,0xf0,0x80,0x80,0xe0,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0xb0,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0xf0,0x90,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4a 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0xa0,0x40,0x00, + + 5, // 0x4b 'K' + 0x00,0x90,0x90,0xa0,0xc0,0xa0,0x90,0x90,0x00, + + 5, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf0,0x00, + + 5, // 0x4d 'M' + 0x00,0x90,0xf0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x4e 'N' + 0x00,0x90,0x90,0xd0,0xb0,0x90,0x90,0x90,0x00, + + 5, // 0x4f 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xe0,0x90,0x90,0xe0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0xa0,0x50,0x00, + + 5, // 0x52 'R' + 0x00,0xe0,0x90,0x90,0xe0,0xa0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x00, + + 5, // 0x54 'T' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x50,0x50,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x50,0x50,0x50,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5a 'Z' + 0x00,0xf0,0x10,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 5, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x00, + + 5, // 0x5d ']' + 0xe0,0x20,0x20,0x20,0x20,0x20,0x20,0xe0,0x00, + + 5, // 0x5e '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0xe0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x60,0x90,0xf0,0x80,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0x40,0xe0,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x70,0x90,0x90,0x70,0x10,0x90,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xe0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6a 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0xa0,0x40, + + 5, // 0x6b 'k' + 0x00,0x80,0x80,0x90,0xa0,0xc0,0xa0,0x90,0x00, + + 5, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6d 'm' + 0x00,0x00,0xa0,0xf0,0xf0,0xf0,0x90,0x90,0x00, + + 5, // 0x6e 'n' + 0x00,0x00,0xa0,0xd0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6f 'o' + 0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0xe0,0x90,0x90,0x90,0xe0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0xe0,0x90,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x50,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x50,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x90,0x90,0x90,0x90,0xf0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xe0, + + 5, // 0x7a 'z' + 0x00,0x00,0xf0,0x10,0x20,0x40,0x80,0xf0,0x00, + + 5, // 0x7b '{' + 0x10,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x10, + + 5, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, + + 5, // 0x7d '}' + 0x80,0x40,0x40,0x40,0x30,0x40,0x40,0x40,0x80, + + 5, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7f '' + 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, + 0 + }; + + const int8u gse6x12[] = + { + 12, 0, 32, 128-32, + + 0x00,0x00,0x0d,0x00,0x1a,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4e,0x00,0x5b,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8f,0x00,0x9c,0x00,0xa9,0x00,0xb6,0x00,0xc3,0x00,0xd0,0x00,0xdd,0x00, + 0xea,0x00,0xf7,0x00,0x04,0x01,0x11,0x01,0x1e,0x01,0x2b,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5f,0x01,0x6c,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xa0,0x01,0xad,0x01,0xba,0x01,0xc7,0x01, + 0xd4,0x01,0xe1,0x01,0xee,0x01,0xfb,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2f,0x02,0x3c,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7d,0x02,0x8a,0x02,0x97,0x02,0xa4,0x02,0xb1,0x02, + 0xbe,0x02,0xcb,0x02,0xd8,0x02,0xe5,0x02,0xf2,0x02,0xff,0x02,0x0c,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4d,0x03,0x5a,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8e,0x03,0x9b,0x03, + 0xa8,0x03,0xb5,0x03,0xc2,0x03,0xcf,0x03,0xdc,0x03,0xe9,0x03,0xf6,0x03,0x03,0x04,0x10,0x04, + 0x1d,0x04,0x2a,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5e,0x04,0x6b,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9f,0x04,0xac,0x04,0xb9,0x04,0xc6,0x04,0xd3,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0x50,0x50,0xf8,0x50,0x50,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x20,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x20,0x00,0x00, + + 6, // 0x25 '%' + 0x00,0xc8,0xd8,0x10,0x30,0x20,0x60,0x40,0xd8,0x98,0x00,0x00, + + 6, // 0x26 '&' + 0x00,0x60,0x90,0x90,0x90,0x60,0xa8,0x90,0x90,0x68,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00, + + 6, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, + + 6, // 0x2a '*' + 0x00,0x00,0x00,0x50,0x20,0xf8,0x20,0x50,0x00,0x00,0x00,0x00, + + 6, // 0x2b '+' + 0x00,0x00,0x20,0x20,0x20,0xf8,0x20,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 6, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00, + + 6, // 0x2f '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00,0x00, + + 6, // 0x30 '0' + 0x00,0x70,0x88,0x88,0x98,0xa8,0xc8,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x20,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0xf8,0x10,0x20,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x10,0x20,0x40,0x90,0x90,0xf8,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0xf8,0x80,0x80,0xf0,0x08,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x70,0x88,0x80,0x80,0xf0,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0xf8,0x88,0x08,0x08,0x10,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + + 6, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 6, // 0x3c '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00,0x00, + + 6, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00,0x00, + + 6, // 0x3f '?' + 0x00,0x70,0x88,0x88,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x70,0x88,0x88,0xb8,0xb8,0xb0,0x80,0x88,0x70,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x20,0x50,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x88,0x88,0x88,0xf0,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x70,0x88,0x88,0x80,0x80,0x80,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0xe0,0x90,0x88,0x88,0x88,0x88,0x88,0x90,0xe0,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0xf8,0x80,0x80,0x80,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x70,0x88,0x80,0x80,0xb8,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x88,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x4a 'J' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00, + + 6, // 0x4b 'K' + 0x00,0x88,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x88,0x00,0x00, + + 6, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x4d 'M' + 0x00,0x88,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x4e 'N' + 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x4f 'O' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0xa8,0x90,0x68,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x70,0x88,0x80,0x80,0x70,0x08,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x88,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x5a 'Z' + 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0xf8,0x00,0x00, + + 6, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 6, // 0x5c '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, + + 6, // 0x5d ']' + 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, + + 6, // 0x5e '^' + 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x88,0x08,0x78,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0xf0,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x08,0x08,0x08,0x78,0x88,0x88,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x70,0x88,0x88,0xf8,0x80,0x80,0x78,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0xf0, + + 6, // 0x68 'h' + 0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x6a 'j' + 0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6b 'k' + 0x00,0x80,0x80,0x80,0x88,0x90,0xa0,0xd0,0x88,0x88,0x00,0x00, + + 6, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x6d 'm' + 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0x00,0x00, + + 6, // 0x6e 'n' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x88,0x88,0x00,0x00, + + 6, // 0x6f 'o' + 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0xf0,0x88,0x88,0x88,0x88,0xf0,0x80,0x80,0x80, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0x08, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x80,0x80,0x80,0x80,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x40,0x40,0x40,0xe0,0x40,0x40,0x40,0x48,0x30,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x78,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x88,0x78,0x08,0x10,0xe0, + + 6, // 0x7a 'z' + 0x00,0x00,0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00, + + 6, // 0x7b '{' + 0x18,0x20,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x7d '}' + 0xc0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xc0,0x00, + + 6, // 0x7e '~' + 0x00,0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7f '' + 0x00,0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse6x9[] = + { + 9, 0, 32, 128-32, + + 0x00,0x00,0x0a,0x00,0x14,0x00,0x1e,0x00,0x28,0x00,0x32,0x00,0x3c,0x00,0x46,0x00,0x50,0x00, + 0x5a,0x00,0x64,0x00,0x6e,0x00,0x78,0x00,0x82,0x00,0x8c,0x00,0x96,0x00,0xa0,0x00,0xaa,0x00, + 0xb4,0x00,0xbe,0x00,0xc8,0x00,0xd2,0x00,0xdc,0x00,0xe6,0x00,0xf0,0x00,0xfa,0x00,0x04,0x01, + 0x0e,0x01,0x18,0x01,0x22,0x01,0x2c,0x01,0x36,0x01,0x40,0x01,0x4a,0x01,0x54,0x01,0x5e,0x01, + 0x68,0x01,0x72,0x01,0x7c,0x01,0x86,0x01,0x90,0x01,0x9a,0x01,0xa4,0x01,0xae,0x01,0xb8,0x01, + 0xc2,0x01,0xcc,0x01,0xd6,0x01,0xe0,0x01,0xea,0x01,0xf4,0x01,0xfe,0x01,0x08,0x02,0x12,0x02, + 0x1c,0x02,0x26,0x02,0x30,0x02,0x3a,0x02,0x44,0x02,0x4e,0x02,0x58,0x02,0x62,0x02,0x6c,0x02, + 0x76,0x02,0x80,0x02,0x8a,0x02,0x94,0x02,0x9e,0x02,0xa8,0x02,0xb2,0x02,0xbc,0x02,0xc6,0x02, + 0xd0,0x02,0xda,0x02,0xe4,0x02,0xee,0x02,0xf8,0x02,0x02,0x03,0x0c,0x03,0x16,0x03,0x20,0x03, + 0x2a,0x03,0x34,0x03,0x3e,0x03,0x48,0x03,0x52,0x03,0x5c,0x03,0x66,0x03,0x70,0x03,0x7a,0x03, + 0x84,0x03,0x8e,0x03,0x98,0x03,0xa2,0x03,0xac,0x03,0xb6,0x03, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 6, // 0x22 '"' + 0x00,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00, + + 6, // 0x24 '$' + 0x00,0x70,0xa8,0xa0,0x70,0x28,0xa8,0x70,0x00, + + 6, // 0x25 '%' + 0x00,0xc8,0xc8,0x10,0x20,0x40,0x98,0x98,0x00, + + 6, // 0x26 '&' + 0x00,0x60,0x90,0x90,0x60,0xa8,0x90,0x68,0x00, + + 6, // 0x27 ''' + 0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 6, // 0x29 ')' + 0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x40, + + 6, // 0x2a '*' + 0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00, + + 6, // 0x2b '+' + 0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00, + + 6, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40, + + 6, // 0x2d '-' + 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00, + + 6, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00, + + 6, // 0x2f '/' + 0x00,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0x00, + + 6, // 0x30 '0' + 0x00,0x70,0x88,0x98,0xa8,0xc8,0x88,0x70,0x00, + + 6, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x32 '2' + 0x00,0x70,0x88,0x08,0x10,0x20,0x40,0xf8,0x00, + + 6, // 0x33 '3' + 0x00,0xf8,0x10,0x20,0x70,0x08,0x88,0x70,0x00, + + 6, // 0x34 '4' + 0x00,0x10,0x20,0x40,0x90,0xf8,0x10,0x10,0x00, + + 6, // 0x35 '5' + 0x00,0xf8,0x80,0xf0,0x08,0x08,0x88,0x70,0x00, + + 6, // 0x36 '6' + 0x00,0x70,0x88,0x80,0xf0,0x88,0x88,0x70,0x00, + + 6, // 0x37 '7' + 0x00,0xf8,0x08,0x08,0x10,0x20,0x40,0x40,0x00, + + 6, // 0x38 '8' + 0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00, + + 6, // 0x39 '9' + 0x00,0x70,0x88,0x88,0x78,0x08,0x88,0x70,0x00, + + 6, // 0x3a ':' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x00,0x00, + + 6, // 0x3b ';' + 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40, + + 6, // 0x3c '<' + 0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00, + + 6, // 0x3d '=' + 0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00, + + 6, // 0x3e '>' + 0x00,0x80,0x40,0x20,0x10,0x20,0x40,0x80,0x00, + + 6, // 0x3f '?' + 0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00, + + 6, // 0x40 '@' + 0x00,0x70,0x88,0x88,0xb8,0xb8,0x80,0x70,0x00, + + 6, // 0x41 'A' + 0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00, + + 6, // 0x42 'B' + 0x00,0xf0,0x88,0x88,0xf0,0x88,0x88,0xf0,0x00, + + 6, // 0x43 'C' + 0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00, + + 6, // 0x44 'D' + 0x00,0xe0,0x90,0x88,0x88,0x88,0x90,0xe0,0x00, + + 6, // 0x45 'E' + 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00, + + 6, // 0x46 'F' + 0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00, + + 6, // 0x47 'G' + 0x00,0x70,0x88,0x80,0xb8,0x88,0x88,0x70,0x00, + + 6, // 0x48 'H' + 0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00, + + 6, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x4a 'J' + 0x00,0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x4b 'K' + 0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00, + + 6, // 0x4c 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00, + + 6, // 0x4d 'M' + 0x00,0x88,0xd8,0xa8,0x88,0x88,0x88,0x88,0x00, + + 6, // 0x4e 'N' + 0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00, + + 6, // 0x4f 'O' + 0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x50 'P' + 0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00, + + 6, // 0x51 'Q' + 0x00,0x70,0x88,0x88,0x88,0xa8,0x90,0x68,0x00, + + 6, // 0x52 'R' + 0x00,0xf0,0x88,0x88,0x88,0xf0,0x90,0x88,0x00, + + 6, // 0x53 'S' + 0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00, + + 6, // 0x54 'T' + 0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x55 'U' + 0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00, + + 6, // 0x58 'X' + 0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x5a 'Z' + 0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00, + + 6, // 0x5b '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 6, // 0x5c '\' + 0x00,0x80,0x80,0x40,0x20,0x10,0x08,0x08,0x00, + + 6, // 0x5d ']' + 0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 6, // 0x5e '^' + 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00, + + 6, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00, + + 6, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00, + + 6, // 0x62 'b' + 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00, + + 6, // 0x64 'd' + 0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x78,0x00, + + 6, // 0x66 'f' + 0x00,0x18,0x20,0x20,0xf8,0x20,0x20,0x20,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x70, + + 6, // 0x68 'h' + 0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x00, + + 6, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x6a 'j' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6b 'k' + 0x00,0x00,0x80,0x88,0x90,0xa0,0xd0,0x88,0x00, + + 6, // 0x6c 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x6d 'm' + 0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0x00, + + 6, // 0x6e 'n' + 0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x00, + + 6, // 0x6f 'o' + 0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x08, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xb8,0xc0,0x80,0x80,0x80,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x78,0x80,0x70,0x08,0xf0,0x00, + + 6, // 0x74 't' + 0x00,0x40,0x40,0xe0,0x40,0x40,0x48,0x30,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x88,0x88,0x88,0x88,0x78,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0xa8,0xd8,0x88,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x88,0x88,0x88,0x78,0x08,0x70, + + 6, // 0x7a 'z' + 0x00,0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00, + + 6, // 0x7b '{' + 0x18,0x20,0x20,0x20,0xc0,0x20,0x20,0x20,0x18, + + 6, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00, + + 6, // 0x7d '}' + 0xc0,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0xc0, + + 6, // 0x7e '~' + 0x00,0x40,0xa8,0x10,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7f '' + 0x00,0x00,0x00,0x20,0x50,0x88,0xf8,0x00,0x00, + 0 + }; + + const int8u gse7x11[] = + { + 11, 0, 32, 128-32, + + 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, + 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, + 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, + 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, + 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, + 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, + 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x10,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x42,0xa4,0x48,0x10,0x24,0x4a,0x84,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x6c,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x4c,0x54,0x64,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x7c,0x48,0x10,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x10,0x20,0x48,0x48,0x7c,0x08,0x1c,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7c,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7c,0x44,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x10,0x28,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x7c,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5c,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3c,0x44,0x44,0x3c,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x3c,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30,0x00, + + 7, // 0x6b 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x68,0x44,0x44,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x3c,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x3c,0x40,0x38,0x04,0x04,0x78,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x3c,0x04,0x08,0x30,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x44,0x7c,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x0c,0x10,0x10,0x10,0x60,0x10,0x10,0x0c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0x60,0x10,0x10,0x10,0x0c,0x10,0x10,0x60,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x11_bold[] = + { + 11, 0, 32, 128-32, + + 0x00,0x00,0x0c,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3c,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6c,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9c,0x00,0xa8,0x00,0xb4,0x00,0xc0,0x00,0xcc,0x00, + 0xd8,0x00,0xe4,0x00,0xf0,0x00,0xfc,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2c,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5c,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8c,0x01,0x98,0x01,0xa4,0x01, + 0xb0,0x01,0xbc,0x01,0xc8,0x01,0xd4,0x01,0xe0,0x01,0xec,0x01,0xf8,0x01,0x04,0x02,0x10,0x02, + 0x1c,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4c,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7c,0x02, + 0x88,0x02,0x94,0x02,0xa0,0x02,0xac,0x02,0xb8,0x02,0xc4,0x02,0xd0,0x02,0xdc,0x02,0xe8,0x02, + 0xf4,0x02,0x00,0x03,0x0c,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3c,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6c,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9c,0x03,0xa8,0x03,0xb4,0x03,0xc0,0x03, + 0xcc,0x03,0xd8,0x03,0xe4,0x03,0xf0,0x03,0xfc,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2c,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5c,0x04,0x68,0x04,0x74,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x00,0x00, + + 7, // 0x24 '$' + 0x30,0x30,0x78,0xcc,0xc0,0x78,0x0c,0xcc,0x78,0x30,0x30, + + 7, // 0x25 '%' + 0x00,0x00,0xc4,0x0c,0x18,0x30,0x60,0xc0,0x8c,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0x6c,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0xc0,0x60,0x30,0x30,0x30,0x30,0x60,0xc0,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x78,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0xfc,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x78,0xcc,0xcc,0x18,0x30,0x60,0xcc,0xfc,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0xfc,0x98,0x30,0x78,0x0c,0x0c,0xcc,0x78,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x18,0x30,0x68,0xd8,0xd8,0xfc,0x18,0x3c,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0xfc,0xc0,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x60,0xc0,0xf8,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0xfc,0x8c,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x78,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x78,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0x70,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x00,0x30,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0x68,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0xf8,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xf8,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0xfc,0xc4,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x78,0xcc,0xc0,0xc0,0xdc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x3c,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00, + + 7, // 0x52 'R' + 0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x70,0x18,0x78,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x78,0xcc,0xfc,0xc0,0xcc,0x78,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x18,0x34,0x30,0x78,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70, + + 7, // 0x68 'h' + 0x00,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x6c,0x6c,0x38, + + 7, // 0x6b 'k' + 0x00,0xc0,0xc0,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xc4,0xc4,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x78,0xcc,0x60,0x18,0xcc,0x78,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x68,0x30,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0xcc,0x78,0x30,0x78,0xcc,0xcc,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0xfc,0x98,0x30,0x60,0xc4,0xfc,0x00,0x00, + + 7, // 0x7b '{' + 0x1c,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x1c,0x00,0x00, + + 7, // 0x7c '|' + 0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x7d '}' + 0xe0,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0xe0,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x15[] = + { + 15, 0, 32, 128-32, + + 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, + 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, + 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, + 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, + 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, + 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, + 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, + 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, + 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, + 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, + 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x54,0x38,0x10,0x00,0x00,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x44,0x44,0x08,0x08,0x10,0x10,0x20,0x20,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x30,0x60,0x94,0x98,0x90,0x6c,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x00,0x20,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x08,0x04,0x00,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0x40,0x20,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x20,0x40,0x00,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x00,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x38,0x44,0x44,0x4c,0x54,0x64,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x10,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x7c,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x44,0x7c,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x7c,0x44,0x08,0x10,0x38,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x08,0x10,0x20,0x40,0x48,0x48,0x7c,0x08,0x08,0x1c,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x78,0x04,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x18,0x20,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x7c,0x44,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x08,0x30,0x00,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x00,0x78,0x84,0x84,0x84,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x00,0x00,0x30,0x48,0x04,0x34,0x54,0x54,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x00,0x10,0x28,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x00,0x38,0x44,0x44,0x40,0x40,0x40,0x40,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0x7c,0x40,0x40,0x40,0x70,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x5c,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0x44,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x00,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x00,0x44,0x6c,0x54,0x54,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x00,0x44,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x50,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x38,0x44,0x44,0x40,0x38,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x7c,0x54,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x00,0x7c,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x04,0x04,0x04,0x3c,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x7c,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x3a,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, + + 7, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x00,0x10,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00, + + 7, // 0x6b 'k' + 0x00,0x00,0x40,0x40,0x44,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0xa8,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0x00,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0xb8,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x04,0x00, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x58,0x64,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x20,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x3a,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x6c,0x44,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x08,0x70,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x40,0x7c,0x00,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0x60,0x10,0x10,0x10,0x10,0x10,0x0c,0x10,0x10,0x10,0x10,0x60,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x64,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x10,0x28,0x44,0x44,0x7c,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse7x15_bold[] = + { + 15, 0, 32, 128-32, + + 0x00,0x00,0x10,0x00,0x20,0x00,0x30,0x00,0x40,0x00,0x50,0x00,0x60,0x00,0x70,0x00,0x80,0x00, + 0x90,0x00,0xa0,0x00,0xb0,0x00,0xc0,0x00,0xd0,0x00,0xe0,0x00,0xf0,0x00,0x00,0x01,0x10,0x01, + 0x20,0x01,0x30,0x01,0x40,0x01,0x50,0x01,0x60,0x01,0x70,0x01,0x80,0x01,0x90,0x01,0xa0,0x01, + 0xb0,0x01,0xc0,0x01,0xd0,0x01,0xe0,0x01,0xf0,0x01,0x00,0x02,0x10,0x02,0x20,0x02,0x30,0x02, + 0x40,0x02,0x50,0x02,0x60,0x02,0x70,0x02,0x80,0x02,0x90,0x02,0xa0,0x02,0xb0,0x02,0xc0,0x02, + 0xd0,0x02,0xe0,0x02,0xf0,0x02,0x00,0x03,0x10,0x03,0x20,0x03,0x30,0x03,0x40,0x03,0x50,0x03, + 0x60,0x03,0x70,0x03,0x80,0x03,0x90,0x03,0xa0,0x03,0xb0,0x03,0xc0,0x03,0xd0,0x03,0xe0,0x03, + 0xf0,0x03,0x00,0x04,0x10,0x04,0x20,0x04,0x30,0x04,0x40,0x04,0x50,0x04,0x60,0x04,0x70,0x04, + 0x80,0x04,0x90,0x04,0xa0,0x04,0xb0,0x04,0xc0,0x04,0xd0,0x04,0xe0,0x04,0xf0,0x04,0x00,0x05, + 0x10,0x05,0x20,0x05,0x30,0x05,0x40,0x05,0x50,0x05,0x60,0x05,0x70,0x05,0x80,0x05,0x90,0x05, + 0xa0,0x05,0xb0,0x05,0xc0,0x05,0xd0,0x05,0xe0,0x05,0xf0,0x05, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x00,0x00,0x30,0x78,0x78,0x78,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6c,0x6c,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x48,0x48,0x48,0xfc,0x48,0x48,0xfc,0x48,0x48,0x48,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x30,0x30,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x30,0x30,0x00,0x00, + + 7, // 0x25 '%' + 0x00,0x00,0x00,0x64,0x6c,0x08,0x18,0x10,0x30,0x20,0x6c,0x4c,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x58,0x58,0x30,0x74,0xdc,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x0c,0x18,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, + + 7, // 0x29 ')' + 0x00,0xc0,0x60,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, + + 7, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x00,0x20,0xa8,0x70,0xa8,0x20,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2f '/' + 0x00,0x00,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xdc,0xec,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x30,0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0x30,0xfc,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x78,0xcc,0xcc,0x0c,0x18,0x30,0x60,0xc0,0xcc,0xfc,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0xfc,0x8c,0x18,0x30,0x78,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x18,0x30,0x60,0xc8,0xd8,0xd8,0xfc,0x18,0x18,0x3c,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0xfc,0xc0,0xc0,0xc0,0xf8,0x0c,0x0c,0x0c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x38,0x60,0xc0,0xc0,0xf8,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0xfc,0x8c,0x0c,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x18,0x70,0x00,0x00,0x00, + + 7, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00, + + 7, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00, + + 7, // 0x3c '<' + 0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x0c,0x00,0x00,0x00, + + 7, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3e '>' + 0x00,0x00,0x00,0xc0,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0xc0,0x00,0x00,0x00, + + 7, // 0x3f '?' + 0x00,0x00,0x78,0xcc,0xcc,0x18,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x00,0x00,0x70,0x88,0x04,0x74,0xb4,0xb4,0xb4,0xb4,0x68,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x00,0x30,0x78,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x00,0x78,0xcc,0xc4,0xc0,0xc0,0xc0,0xc0,0xc4,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0xf0,0xd8,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xd8,0xf0,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0xfc,0xc4,0xc0,0xd0,0xf0,0xd0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xdc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x4a 'J' + 0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00,0x00,0x00, + + 7, // 0x4b 'K' + 0x00,0x00,0xcc,0xcc,0xd8,0xd8,0xf0,0xd8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4c 'L' + 0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x4d 'M' + 0x00,0x00,0x84,0xcc,0xfc,0xb4,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4e 'N' + 0x00,0x00,0xcc,0xcc,0xcc,0xec,0xfc,0xdc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x4f 'O' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xdc,0x78,0x18,0x0c,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xf8,0xd8,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x78,0xcc,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x5a 'Z' + 0x00,0x00,0xfc,0x8c,0x0c,0x18,0x30,0x60,0xc0,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x5b '[' + 0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00, + + 7, // 0x5c '\' + 0x00,0x00,0xc0,0xc0,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x00,0x00,0x00, + + 7, // 0x5d ']' + 0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00, + + 7, // 0x5e '^' + 0x00,0x10,0x38,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x30,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x70,0xd8,0x18,0x78,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x78,0x6c,0x6c,0x6c,0x6c,0x6c,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xc0,0xc0,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x18,0x18,0x18,0x78,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xfc,0xc0,0xc0,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x00,0x30,0x68,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x6c,0xd8,0xd8,0xd8,0xd8,0xd8,0x78,0x18,0xd8,0x70,0x00, + + 7, // 0x68 'h' + 0x00,0x00,0xc0,0xc0,0xc0,0xd8,0xec,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x6a 'j' + 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x00, + + 7, // 0x6b 'k' + 0x00,0x00,0xc0,0xc0,0xcc,0xcc,0xcc,0xd8,0xf0,0xd8,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x6c 'l' + 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0xe8,0xfc,0xd4,0xd4,0xd4,0xc4,0xc4,0xc4,0x00,0x00,0x00, + + 7, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00, + + 7, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0xf8,0xcc,0xcc,0xcc,0xcc,0xcc,0xf8,0xc0,0xc0,0xc0,0x00, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x7c,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x0c,0x00, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0xd8,0xec,0xcc,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x78,0xcc,0xe0,0x70,0x38,0x1c,0xcc,0x78,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x20,0x60,0x60,0xf0,0x60,0x60,0x60,0x60,0x6c,0x38,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0x6c,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xb4,0xfc,0xcc,0x84,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0x78,0x30,0x78,0xcc,0xcc,0xcc,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x18,0xf0,0x00, + + 7, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0xfc,0x8c,0x18,0x30,0x60,0xc0,0xc4,0xfc,0x00,0x00,0x00, + + 7, // 0x7b '{' + 0x00,0x1c,0x30,0x30,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x30,0x1c,0x00,0x00, + + 7, // 0x7c '|' + 0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x7d '}' + 0x00,0xe0,0x30,0x30,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0x30,0xe0,0x00,0x00, + + 7, // 0x7e '~' + 0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x30,0x78,0xcc,0xcc,0xfc,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse8x16[] = + { + 16, 0, 32, 128-32, + + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, + 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, + 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, + 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, + 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, + 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, + 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, + 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, + 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, + 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, + 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, + + 8, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x21 '!' + 0x00,0x00,0x10,0x38,0x38,0x38,0x38,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x24,0x24,0x24,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x24,0x24,0x24,0x7e,0x24,0x24,0x7e,0x24,0x24,0x24,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x14,0x14,0x3e,0x55,0x54,0x54,0x3e,0x15,0x15,0x55,0x3e,0x14,0x14,0x00,0x00, + + 8, // 0x25 '%' + 0x00,0x00,0x32,0x56,0x6c,0x04,0x08,0x08,0x10,0x13,0x25,0x26,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x18,0x24,0x24,0x24,0x18,0x28,0x45,0x46,0x44,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x27 ''' + 0x00,0x00,0x08,0x08,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x04,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x04,0x00,0x00,0x00, + + 8, // 0x29 ')' + 0x00,0x10,0x08,0x04,0x04,0x02,0x02,0x02,0x02,0x04,0x04,0x08,0x10,0x00,0x00,0x00, + + 8, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x7f,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, + + 8, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x2f '/' + 0x00,0x02,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x3c,0x42,0x42,0x46,0x4a,0x52,0x62,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x08,0x08,0x18,0x38,0x08,0x08,0x08,0x08,0x08,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x3c,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x7e,0x42,0x04,0x08,0x1c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x04,0x08,0x10,0x24,0x44,0x44,0x7e,0x04,0x04,0x0e,0x00,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x7e,0x42,0x40,0x40,0x7c,0x02,0x02,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x1c,0x20,0x40,0x40,0x7c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x7e,0x42,0x42,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3e,0x02,0x02,0x04,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, + + 8, // 0x3c '<' + 0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x02,0x00,0x00,0x00,0x00, + + 8, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3e '>' + 0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x00,0x00,0x00,0x00, + + 8, // 0x3f '?' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x04,0x08,0x08,0x00,0x08,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x40 '@' + 0x00,0x00,0x3c,0x42,0x01,0x39,0x49,0x49,0x49,0x49,0x49,0x36,0x00,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x3c,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x40,0x40,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x7e,0x22,0x20,0x28,0x38,0x28,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x40,0x4e,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x42,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x4a 'J' + 0x00,0x00,0x0e,0x04,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x4b 'K' + 0x00,0x00,0x62,0x22,0x24,0x28,0x30,0x28,0x24,0x22,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x4c 'L' + 0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x4d 'M' + 0x00,0x00,0x41,0x63,0x55,0x49,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x4e 'N' + 0x00,0x00,0x42,0x42,0x62,0x52,0x4a,0x46,0x42,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x4f 'O' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x4a,0x44,0x3a,0x02,0x00,0x00,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x3c,0x28,0x24,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x3c,0x42,0x42,0x40,0x30,0x0c,0x02,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x7f,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x22,0x14,0x14,0x08,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x57 'W' + 0x00,0x00,0x41,0x41,0x41,0x41,0x41,0x49,0x49,0x55,0x63,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x42,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x22,0x22,0x22,0x22,0x14,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x5a 'Z' + 0x00,0x00,0x7e,0x42,0x02,0x04,0x08,0x10,0x20,0x40,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x5b '[' + 0x00,0x1e,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1e,0x00,0x00,0x00, + + 8, // 0x5c '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00,0x00,0x00, + + 8, // 0x5d ']' + 0x00,0x3c,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x3c,0x00,0x00,0x00, + + 8, // 0x5e '^' + 0x00,0x00,0x08,0x14,0x22,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x08,0x08,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x3c,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x20,0x20,0x38,0x24,0x22,0x22,0x22,0x22,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x40,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x0c,0x04,0x04,0x1c,0x24,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x7e,0x40,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x66 'f' + 0x00,0x00,0x0c,0x12,0x10,0x10,0x38,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x44,0x38,0x00, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x20,0x20,0x2c,0x32,0x22,0x22,0x22,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x69 'i' + 0x00,0x00,0x08,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x6a 'j' + 0x00,0x00,0x04,0x04,0x00,0x0c,0x04,0x04,0x04,0x04,0x04,0x44,0x44,0x38,0x00,0x00, + + 8, // 0x6b 'k' + 0x00,0x00,0x60,0x20,0x20,0x22,0x24,0x28,0x38,0x24,0x22,0x62,0x00,0x00,0x00,0x00, + + 8, // 0x6c 'l' + 0x00,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00,0x00,0x00,0x00, + + 8, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0x00,0x5c,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00, + + 8, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x22,0x22,0x22,0x3c,0x20,0x20,0x70,0x00, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x44,0x44,0x44,0x44,0x44,0x3c,0x04,0x04,0x0e,0x00, + + 8, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x7c,0x22,0x22,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x40,0x3c,0x02,0x42,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x74 't' + 0x00,0x00,0x10,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x12,0x0c,0x00,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x22,0x14,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x41,0x41,0x41,0x49,0x49,0x55,0x22,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3e,0x02,0x04,0x78,0x00, + + 8, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x00,0x7e,0x44,0x08,0x10,0x20,0x42,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x7b '{' + 0x00,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x00,0x00, + + 8, // 0x7c '|' + 0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00, + + 8, // 0x7d '}' + 0x00,0x30,0x08,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00,0x00, + + 8, // 0x7e '~' + 0x00,0x00,0x39,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x22,0x41,0x41,0x7f,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u gse8x16_bold[] = + { + 16, 0, 32, 128-32, + + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x44,0x00,0x55,0x00,0x66,0x00,0x77,0x00,0x88,0x00, + 0x99,0x00,0xaa,0x00,0xbb,0x00,0xcc,0x00,0xdd,0x00,0xee,0x00,0xff,0x00,0x10,0x01,0x21,0x01, + 0x32,0x01,0x43,0x01,0x54,0x01,0x65,0x01,0x76,0x01,0x87,0x01,0x98,0x01,0xa9,0x01,0xba,0x01, + 0xcb,0x01,0xdc,0x01,0xed,0x01,0xfe,0x01,0x0f,0x02,0x20,0x02,0x31,0x02,0x42,0x02,0x53,0x02, + 0x64,0x02,0x75,0x02,0x86,0x02,0x97,0x02,0xa8,0x02,0xb9,0x02,0xca,0x02,0xdb,0x02,0xec,0x02, + 0xfd,0x02,0x0e,0x03,0x1f,0x03,0x30,0x03,0x41,0x03,0x52,0x03,0x63,0x03,0x74,0x03,0x85,0x03, + 0x96,0x03,0xa7,0x03,0xb8,0x03,0xc9,0x03,0xda,0x03,0xeb,0x03,0xfc,0x03,0x0d,0x04,0x1e,0x04, + 0x2f,0x04,0x40,0x04,0x51,0x04,0x62,0x04,0x73,0x04,0x84,0x04,0x95,0x04,0xa6,0x04,0xb7,0x04, + 0xc8,0x04,0xd9,0x04,0xea,0x04,0xfb,0x04,0x0c,0x05,0x1d,0x05,0x2e,0x05,0x3f,0x05,0x50,0x05, + 0x61,0x05,0x72,0x05,0x83,0x05,0x94,0x05,0xa5,0x05,0xb6,0x05,0xc7,0x05,0xd8,0x05,0xe9,0x05, + 0xfa,0x05,0x0b,0x06,0x1c,0x06,0x2d,0x06,0x3e,0x06,0x4f,0x06, + + 8, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x21 '!' + 0x00,0x00,0x18,0x3c,0x3c,0x3c,0x3c,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x66,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x66,0x66,0x66,0xff,0x66,0x66,0xff,0x66,0x66,0x66,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x08,0x08,0x3e,0x6b,0x6b,0x68,0x3e,0x0b,0x6b,0x6b,0x3e,0x08,0x08,0x00,0x00, + + 8, // 0x25 '%' + 0x00,0x00,0x66,0xbe,0xcc,0x0c,0x18,0x18,0x30,0x33,0x65,0x66,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x1c,0x36,0x36,0x36,0x1c,0x3b,0x6e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x27 ''' + 0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x06,0x0c,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0c,0x06,0x00,0x00,0x00, + + 8, // 0x29 ')' + 0x00,0x30,0x18,0x0c,0x0c,0x06,0x06,0x06,0x06,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00, + + 8, // 0x2a '*' + 0x00,0x00,0x00,0x00,0x66,0x24,0x18,0xff,0x18,0x24,0x66,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2b '+' + 0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2c ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x20,0x00, + + 8, // 0x2d '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2e '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x2f '/' + 0x00,0x03,0x03,0x06,0x06,0x0c,0x0c,0x18,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x3e,0x63,0x63,0x67,0x6b,0x73,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x0c,0x0c,0x1c,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x3e,0x63,0x63,0x03,0x06,0x0c,0x18,0x30,0x61,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x7f,0x43,0x06,0x0c,0x1e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x06,0x0c,0x18,0x32,0x66,0x66,0x7f,0x06,0x06,0x0f,0x00,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x7f,0x61,0x60,0x60,0x7e,0x03,0x03,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x1e,0x30,0x60,0x60,0x7e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x7f,0x63,0x63,0x03,0x06,0x0c,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x3e,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x3f,0x03,0x03,0x06,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x3a ':' + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3b ';' + 0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x40,0x00, + + 8, // 0x3c '<' + 0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, + + 8, // 0x3d '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3e '>' + 0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, + + 8, // 0x3f '?' + 0x00,0x00,0x3e,0x63,0x63,0x63,0x06,0x0c,0x0c,0x00,0x0c,0x0c,0x00,0x00,0x00,0x00, + + 8, // 0x40 '@' + 0x00,0x00,0x7c,0x86,0x03,0x73,0xdb,0xdb,0xdb,0xdb,0xdb,0x6e,0x00,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x3e,0x33,0x33,0x33,0x33,0x7e,0x00,0x00,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x1e,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x7c,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7c,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x7f,0x33,0x31,0x34,0x3c,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x1f,0x33,0x61,0x60,0x60,0x6f,0x63,0x63,0x33,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x63,0x63,0x63,0x63,0x7f,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x4a 'J' + 0x00,0x00,0x0f,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x4b 'K' + 0x00,0x00,0x73,0x33,0x36,0x36,0x3c,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x4c 'L' + 0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x4d 'M' + 0x00,0x00,0x63,0x63,0x77,0x77,0x7f,0x6b,0x6b,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x4e 'N' + 0x00,0x00,0x63,0x63,0x73,0x7b,0x6f,0x67,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x4f 'O' + 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x1c,0x36,0x63,0x63,0x63,0x63,0x63,0x6f,0x36,0x1e,0x03,0x00,0x00,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x7e,0x33,0x33,0x33,0x33,0x3e,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x3e,0x63,0x63,0x30,0x18,0x0c,0x06,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x3f,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x57 'W' + 0x00,0x00,0x63,0x63,0x63,0x6b,0x6b,0x7f,0x77,0x77,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x63,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x33,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x5a 'Z' + 0x00,0x00,0x7f,0x63,0x43,0x06,0x0c,0x18,0x30,0x61,0x63,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x5b '[' + 0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00, + + 8, // 0x5c '\' + 0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x0c,0x0c,0x06,0x06,0x03,0x03,0x00,0x00,0x00, + + 8, // 0x5d ']' + 0x00,0x7c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x7c,0x00,0x00,0x00, + + 8, // 0x5e '^' + 0x00,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5f '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x18,0x18,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x70,0x30,0x30,0x3c,0x36,0x33,0x33,0x33,0x33,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x60,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x0e,0x06,0x06,0x1e,0x36,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x7f,0x60,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x66 'f' + 0x00,0x00,0x0e,0x1b,0x1b,0x18,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00, + + 8, // 0x68 'h' + 0x00,0x00,0x70,0x30,0x30,0x36,0x3b,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x69 'i' + 0x00,0x00,0x0c,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x6a 'j' + 0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00,0x00, + + 8, // 0x6b 'k' + 0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3c,0x36,0x33,0x73,0x00,0x00,0x00,0x00, + + 8, // 0x6c 'l' + 0x00,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, + + 8, // 0x6d 'm' + 0x00,0x00,0x00,0x00,0x00,0x76,0x7f,0x6b,0x6b,0x6b,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x6e 'n' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00, + + 8, // 0x6f 'o' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x63,0x63,0x63,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x33,0x33,0x33,0x33,0x33,0x3e,0x30,0x30,0x78,0x00, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3b,0x66,0x66,0x66,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00, + + 8, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3e,0x63,0x60,0x3e,0x03,0x63,0x3e,0x00,0x00,0x00,0x00, + + 8, // 0x74 't' + 0x00,0x00,0x08,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x1b,0x0e,0x00,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3b,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x36,0x1c,0x08,0x00,0x00,0x00,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x6b,0x6b,0x7f,0x36,0x36,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x1c,0x36,0x63,0x63,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x3f,0x03,0x06,0x7c,0x00, + + 8, // 0x7a 'z' + 0x00,0x00,0x00,0x00,0x00,0x7f,0x63,0x06,0x0c,0x18,0x31,0x7f,0x00,0x00,0x00,0x00, + + 8, // 0x7b '{' + 0x00,0x03,0x04,0x0c,0x0c,0x0c,0x08,0x30,0x08,0x0c,0x0c,0x0c,0x04,0x03,0x00,0x00, + + 8, // 0x7c '|' + 0x00,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x0c,0x0c,0x0c,0x0c,0x0c,0x00,0x00,0x00, + + 8, // 0x7d '}' + 0x00,0x60,0x10,0x18,0x18,0x18,0x08,0x06,0x08,0x18,0x18,0x18,0x10,0x60,0x00,0x00, + + 8, // 0x7e '~' + 0x00,0x00,0x3b,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x7f '' + 0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,0x00,0x00,0x00,0x00, + 0 + }; + + const int8u mcs11_prop[] = + { + 11, 2, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10, + + 6, // 0x25 '%' + 0x00,0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00, + + 3, // 0x27 ''' + 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x40,0x78,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00, + + 6, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00, + + 4, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00, + + 8, // 0x4D 'M' + 0x00,0x41,0x63,0x55,0x49,0x49,0x41,0x41,0x41,0x41,0x00, + + 7, // 0x4E 'N' + 0x00,0x42,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x42,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x40,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x44,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00, + + 8, // 0x57 'W' + 0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x49,0x55,0x22,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00, + + 5, // 0x5B '[' + 0x30,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x30, + + 7, // 0x5C '\' + 0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 4, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00, + + 4, // 0x66 'f' + 0x00,0x10,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, + + 2, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 3, // 0x6A 'j' + 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x40,0x40,0x48,0x50,0x60,0x60,0x50,0x48,0x48,0x00, + + 2, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 8, // 0x6D 'm' + 0x00,0x00,0x00,0x76,0x49,0x49,0x49,0x49,0x41,0x41,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x20,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x28,0x10,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00, + + 8, // 0x77 'w' + 0x00,0x00,0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x36,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0, + + 6, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs11_prop_condensed[] = + { + 11, 2, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x21 '!' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x40,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 4, // 0x29 ')' + 0x80,0x40,0x40,0x20,0x20,0x20,0x20,0x20,0x40,0x40,0x80, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00, + + 6, // 0x2F '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 3, // 0x31 '1' + 0x00,0x40,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x10,0x60,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x90,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x90,0x60,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xC0, + + 6, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0xB0,0x80,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x70,0x80,0x80,0x80,0xB0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 4, // 0x49 'I' + 0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xE0,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, + + 6, // 0x4D 'M' + 0x00,0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x88,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x90,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x80,0x60,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 6, // 0x56 'V' + 0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x57 'W' + 0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0xA8,0xA8,0x50,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x90,0x00, + + 6, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0xF0,0x00, + + 4, // 0x5B '[' + 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60,0x00, + + 6, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 4, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60,0x00, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x90,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x90,0x60,0x00, + + 4, // 0x66 'f' + 0x00,0x20,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x90,0x60, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 2, // 0x69 'i' + 0x00,0x80,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + + 4, // 0x6A 'j' + 0x00,0x20,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, + + 2, // 0x6C 'l' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0xD0,0xA8,0xA8,0xA8,0x88,0x88,0x88,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xA0,0xD0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0xB8,0x48,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x10,0x90,0x60,0x00, + + 4, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0x20,0xC0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0x80,0xF0,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x00,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs12_prop[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x62,0x02,0x6F,0x02,0x7C,0x02,0x89,0x02,0x96,0x02,0xA3,0x02,0xB0,0x02,0xBD,0x02, + 0xCA,0x02,0xD7,0x02,0xF0,0x02,0xFD,0x02,0x0A,0x03,0x17,0x03,0x24,0x03,0x31,0x03,0x3E,0x03, + 0x4B,0x03,0x58,0x03,0x65,0x03,0x72,0x03,0x7F,0x03,0x8C,0x03,0x99,0x03,0xA6,0x03,0xB3,0x03, + 0xC0,0x03,0xCD,0x03,0xDA,0x03,0xE7,0x03,0xF4,0x03,0x01,0x04,0x1A,0x04,0x27,0x04,0x34,0x04, + 0x41,0x04,0x4E,0x04,0x5B,0x04,0x68,0x04,0x75,0x04,0x82,0x04,0x8F,0x04,0xA8,0x04,0xB5,0x04, + 0xC2,0x04,0xCF,0x04,0xDC,0x04,0xE9,0x04,0xF6,0x04,0x03,0x05, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 4, // 0x22 '"' + 0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00, + + 3, // 0x27 ''' + 0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 6, // 0x3C '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 4, // 0x5B '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 4, // 0x5D ']' + 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs13_prop[] = + { + 13, 4, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x38,0x00,0x46,0x00,0x54,0x00,0x62,0x00,0x70,0x00, + 0x7E,0x00,0x8C,0x00,0x9A,0x00,0xA8,0x00,0xB6,0x00,0xC4,0x00,0xD2,0x00,0xE0,0x00,0xEE,0x00, + 0xFC,0x00,0x0A,0x01,0x18,0x01,0x26,0x01,0x34,0x01,0x42,0x01,0x50,0x01,0x5E,0x01,0x6C,0x01, + 0x7A,0x01,0x88,0x01,0x96,0x01,0xA4,0x01,0xB2,0x01,0xC0,0x01,0xCE,0x01,0xDC,0x01,0xEA,0x01, + 0xF8,0x01,0x06,0x02,0x14,0x02,0x22,0x02,0x30,0x02,0x3E,0x02,0x4C,0x02,0x5A,0x02,0x68,0x02, + 0x76,0x02,0x91,0x02,0x9F,0x02,0xAD,0x02,0xBB,0x02,0xC9,0x02,0xD7,0x02,0xE5,0x02,0xF3,0x02, + 0x01,0x03,0x0F,0x03,0x2A,0x03,0x38,0x03,0x46,0x03,0x54,0x03,0x62,0x03,0x70,0x03,0x7E,0x03, + 0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03,0xC4,0x03,0xD2,0x03,0xE0,0x03,0xEE,0x03,0xFC,0x03, + 0x0A,0x04,0x18,0x04,0x26,0x04,0x34,0x04,0x42,0x04,0x50,0x04,0x6B,0x04,0x79,0x04,0x87,0x04, + 0x95,0x04,0xA3,0x04,0xB1,0x04,0xBF,0x04,0xCD,0x04,0xDB,0x04,0xE9,0x04,0x04,0x05,0x12,0x05, + 0x20,0x05,0x2E,0x05,0x3C,0x05,0x4A,0x05,0x58,0x05,0x66,0x05, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 4, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x00,0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x00,0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x30,0x48,0x48,0x48,0x30,0x4A,0x4A,0x44,0x3A,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x00,0x00, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40,0x00,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x20,0x40,0x80, + + 6, // 0x3C '<' + 0x00,0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x41,0x00,0x63,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, + + 4, // 0x5B '[' + 0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,0x00,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00,0x00, + + 4, // 0x5D ']' + 0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xE0,0x00,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, + + 4, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0x60,0x00, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 5, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 3, // 0x7C '|' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x20,0xC0,0x00,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs5x10_mono[] = + { + 10, 2, 32, 128-32, + 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, + 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, + 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, + 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, + 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, + 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, + 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, + 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, + 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, + 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, + 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00, + + 5, // 0x2F '/' + 0x00,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x50,0x50,0x90,0xF0,0x10,0x10,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0x80,0xE0,0x10,0x10,0x90,0x60,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x80,0x80,0xE0,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x10,0x60,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0, + + 5, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0xF0,0x00,0x00,0x00, + + 5, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0xF0,0x80,0x80,0x80,0x80,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0xA0,0x40,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0xA0,0xA0,0xC0,0xC0,0xA0,0xA0,0x90,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00, + + 5, // 0x4D 'M' + 0x00,0x90,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00, + + 5, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x56 'V' + 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00, + + 5, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00, + + 5, // 0x5B '[' + 0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 5, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08, + + 5, // 0x5D ']' + 0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6A 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00, + + 5, // 0x6C 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00, + + 5, // 0x6D 'm' + 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0xB0,0x50,0x40,0x40,0x40,0xE0,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x50,0x20,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 5, // 0x7C '|' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs5x11_mono[] = + { + 11, 3, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x50,0x50,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x23 '#' + 0x00,0x50,0x50,0xF8,0x50,0x50,0x50,0xF8,0x50,0x50,0x00, + + 5, // 0x24 '$' + 0x00,0x40,0x60,0x90,0x80,0x60,0x10,0x90,0x60,0x20,0x00, + + 5, // 0x25 '%' + 0x00,0x00,0x90,0x90,0x20,0x20,0x40,0x40,0x90,0x90,0x00, + + 5, // 0x26 '&' + 0x00,0x40,0xA0,0xA0,0x40,0xA8,0x90,0x90,0x68,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 5, // 0x2A '*' + 0x00,0x00,0x90,0x60,0xF0,0x60,0x90,0x00,0x00,0x00,0x00, + + 5, // 0x2B '+' + 0x00,0x00,0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x40,0x80, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x2F '/' + 0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 5, // 0x30 '0' + 0x00,0x70,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x31 '1' + 0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x32 '2' + 0x00,0x60,0x90,0x90,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x33 '3' + 0x00,0x60,0x90,0x10,0x60,0x10,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x34 '4' + 0x00,0x10,0x30,0x50,0x50,0x90,0xF8,0x10,0x10,0x00,0x00, + + 5, // 0x35 '5' + 0x00,0xF0,0x80,0xE0,0x90,0x10,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x36 '6' + 0x00,0x60,0x90,0x80,0xE0,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x37 '7' + 0x00,0xF0,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x38 '8' + 0x00,0x60,0x90,0x90,0x60,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x39 '9' + 0x00,0x60,0x90,0x90,0x90,0x70,0x10,0x90,0x60,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x40,0x80, + + 5, // 0x3C '<' + 0x00,0x08,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x08,0x00, + + 5, // 0x3D '=' + 0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0xF0,0x00,0x00,0x00, + + 5, // 0x3E '>' + 0x00,0x80,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x80,0x00, + + 5, // 0x3F '?' + 0x00,0x60,0x90,0x10,0x10,0x20,0x40,0x00,0x40,0x00,0x00, + + 5, // 0x40 '@' + 0x00,0x60,0x90,0x90,0xB0,0xB0,0x80,0x80,0x70,0x00,0x00, + + 5, // 0x41 'A' + 0x00,0x60,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x42 'B' + 0x00,0xE0,0x90,0x90,0xE0,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x43 'C' + 0x00,0x60,0x90,0x80,0x80,0x80,0x80,0x90,0x60,0x00,0x00, + + 5, // 0x44 'D' + 0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x45 'E' + 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0xF0,0x00,0x00, + + 5, // 0x46 'F' + 0x00,0xF0,0x80,0x80,0xE0,0x80,0x80,0x80,0x80,0x00,0x00, + + 5, // 0x47 'G' + 0x00,0x60,0x90,0x80,0x80,0xB0,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x48 'H' + 0x00,0x90,0x90,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x70,0x20,0x20,0x20,0x20,0xA0,0xA0,0x40,0x00,0x00, + + 5, // 0x4B 'K' + 0x00,0x90,0xA0,0xA0,0xC0,0xA0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x4C 'L' + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF0,0x00,0x00, + + 5, // 0x4D 'M' + 0x00,0x90,0xF0,0xF0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x4E 'N' + 0x00,0x90,0x90,0xD0,0xD0,0xB0,0xB0,0x90,0x90,0x00,0x00, + + 5, // 0x4F 'O' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x50 'P' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0x80,0x80,0x80,0x00,0x00, + + 5, // 0x51 'Q' + 0x00,0x60,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x30,0x00, + + 5, // 0x52 'R' + 0x00,0xE0,0x90,0x90,0x90,0xE0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x53 'S' + 0x00,0x60,0x90,0x80,0x60,0x10,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x54 'T' + 0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00, + + 5, // 0x55 'U' + 0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x56 'V' + 0x00,0x90,0x90,0x90,0x50,0x50,0x50,0x20,0x20,0x00,0x00, + + 5, // 0x57 'W' + 0x00,0x90,0x90,0x90,0x90,0x90,0xF0,0xF0,0x90,0x00,0x00, + + 5, // 0x58 'X' + 0x00,0x90,0x90,0x90,0x60,0x60,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x59 'Y' + 0x00,0x88,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00, + + 5, // 0x5A 'Z' + 0x00,0xF0,0x10,0x20,0x20,0x40,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 5, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 5, // 0x5E '^' + 0x00,0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00, + + 5, // 0x60 '`' + 0x00,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x61 'a' + 0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x62 'b' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0xE0,0x00,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x60,0x90,0x80,0x80,0x90,0x60,0x00,0x00, + + 5, // 0x64 'd' + 0x00,0x10,0x10,0x70,0x90,0x90,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x65 'e' + 0x00,0x00,0x00,0x60,0x90,0x90,0xF0,0x80,0x70,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x30,0x40,0xE0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 5, // 0x67 'g' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x68 'h' + 0x00,0x80,0x80,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x69 'i' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0xA0,0x40, + + 5, // 0x6B 'k' + 0x00,0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x90,0x00,0x00, + + 5, // 0x6C 'l' + 0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x6D 'm' + 0x00,0x00,0x00,0x90,0xF0,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x6E 'n' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0x90,0x00,0x00, + + 5, // 0x6F 'o' + 0x00,0x00,0x00,0x60,0x90,0x90,0x90,0x90,0x60,0x00,0x00, + + 5, // 0x70 'p' + 0x00,0x00,0x00,0xE0,0x90,0x90,0x90,0x90,0xE0,0x80,0x80, + + 5, // 0x71 'q' + 0x00,0x00,0x00,0x70,0x90,0x90,0x90,0x90,0x70,0x10,0x10, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0xA0,0x50,0x40,0x40,0x40,0xE0,0x00,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x60,0x90,0x40,0x20,0x90,0x60,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, + + 5, // 0x75 'u' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x00,0x00, + + 5, // 0x76 'v' + 0x00,0x00,0x00,0x90,0x90,0x50,0x50,0x20,0x20,0x00,0x00, + + 5, // 0x77 'w' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0xF0,0x90,0x00,0x00, + + 5, // 0x78 'x' + 0x00,0x00,0x00,0x90,0x90,0x60,0x60,0x90,0x90,0x00,0x00, + + 5, // 0x79 'y' + 0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x70,0x10,0xE0, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0xF0,0x10,0x20,0x40,0x80,0xF0,0x00,0x00, + + 5, // 0x7B '{' + 0x30,0x40,0x40,0x40,0x40,0x80,0x40,0x40,0x40,0x40,0x30, + + 5, // 0x7C '|' + 0x00,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x20,0x00, + + 5, // 0x7D '}' + 0xC0,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0xC0, + + 5, // 0x7E '~' + 0x00,0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x7F '' + 0x00,0x20,0x70,0xD8,0x88,0x88,0xF8,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs6x10_mono[] = + { + 10, 3, 32, 128-32, + 0x00,0x00,0x0B,0x00,0x16,0x00,0x21,0x00,0x2C,0x00,0x37,0x00,0x42,0x00,0x4D,0x00,0x58,0x00, + 0x63,0x00,0x6E,0x00,0x79,0x00,0x84,0x00,0x8F,0x00,0x9A,0x00,0xA5,0x00,0xB0,0x00,0xBB,0x00, + 0xC6,0x00,0xD1,0x00,0xDC,0x00,0xE7,0x00,0xF2,0x00,0xFD,0x00,0x08,0x01,0x13,0x01,0x1E,0x01, + 0x29,0x01,0x34,0x01,0x3F,0x01,0x4A,0x01,0x55,0x01,0x60,0x01,0x6B,0x01,0x76,0x01,0x81,0x01, + 0x8C,0x01,0x97,0x01,0xA2,0x01,0xAD,0x01,0xB8,0x01,0xC3,0x01,0xCE,0x01,0xD9,0x01,0xE4,0x01, + 0xEF,0x01,0xFA,0x01,0x05,0x02,0x10,0x02,0x1B,0x02,0x26,0x02,0x31,0x02,0x3C,0x02,0x47,0x02, + 0x52,0x02,0x5D,0x02,0x68,0x02,0x73,0x02,0x7E,0x02,0x89,0x02,0x94,0x02,0x9F,0x02,0xAA,0x02, + 0xB5,0x02,0xC0,0x02,0xCB,0x02,0xD6,0x02,0xE1,0x02,0xEC,0x02,0xF7,0x02,0x02,0x03,0x0D,0x03, + 0x18,0x03,0x23,0x03,0x2E,0x03,0x39,0x03,0x44,0x03,0x4F,0x03,0x5A,0x03,0x65,0x03,0x70,0x03, + 0x7B,0x03,0x86,0x03,0x91,0x03,0x9C,0x03,0xA7,0x03,0xB2,0x03,0xBD,0x03,0xC8,0x03,0xD3,0x03, + 0xDE,0x03,0xE9,0x03,0xF4,0x03,0xFF,0x03,0x0A,0x04,0x15,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00, + + 6, // 0x24 '$' + 0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 6, // 0x25 '%' + 0x00,0x08,0xC8,0xD0,0x10,0x20,0x2C,0x4C,0x40,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x24,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 6, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x4C,0x54,0x64,0x44,0x38,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x40,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x38,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x3C '<' + 0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x18,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x5C,0x54,0x5C,0x40,0x38,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x4C,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x4E 'N' + 0x00,0x44,0x44,0x64,0x54,0x4C,0x44,0x44,0x00,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x10,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x28,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x78,0x08,0x10,0x20,0x40,0x40,0x78,0x00,0x00, + + 6, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 6, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 6, // 0x5E '^' + 0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x3C,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x3C,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x78,0x40,0x3C,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x0C,0x10,0x10,0x38,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x38, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, + + 6, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x10,0x10,0x38,0x10,0x10,0x14,0x08,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x10,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x78,0x08,0x30,0x40,0x78,0x00,0x00, + + 6, // 0x7B '{' + 0x18,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7C '|' + 0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60,0x00, + + 6, // 0x7E '~' + 0x00,0x48,0xA8,0x90,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs6x11_mono[] = + { + 11, 3, 32, 128-32, + 0x00,0x00,0x0C,0x00,0x18,0x00,0x24,0x00,0x30,0x00,0x3C,0x00,0x48,0x00,0x54,0x00,0x60,0x00, + 0x6C,0x00,0x78,0x00,0x84,0x00,0x90,0x00,0x9C,0x00,0xA8,0x00,0xB4,0x00,0xC0,0x00,0xCC,0x00, + 0xD8,0x00,0xE4,0x00,0xF0,0x00,0xFC,0x00,0x08,0x01,0x14,0x01,0x20,0x01,0x2C,0x01,0x38,0x01, + 0x44,0x01,0x50,0x01,0x5C,0x01,0x68,0x01,0x74,0x01,0x80,0x01,0x8C,0x01,0x98,0x01,0xA4,0x01, + 0xB0,0x01,0xBC,0x01,0xC8,0x01,0xD4,0x01,0xE0,0x01,0xEC,0x01,0xF8,0x01,0x04,0x02,0x10,0x02, + 0x1C,0x02,0x28,0x02,0x34,0x02,0x40,0x02,0x4C,0x02,0x58,0x02,0x64,0x02,0x70,0x02,0x7C,0x02, + 0x88,0x02,0x94,0x02,0xA0,0x02,0xAC,0x02,0xB8,0x02,0xC4,0x02,0xD0,0x02,0xDC,0x02,0xE8,0x02, + 0xF4,0x02,0x00,0x03,0x0C,0x03,0x18,0x03,0x24,0x03,0x30,0x03,0x3C,0x03,0x48,0x03,0x54,0x03, + 0x60,0x03,0x6C,0x03,0x78,0x03,0x84,0x03,0x90,0x03,0x9C,0x03,0xA8,0x03,0xB4,0x03,0xC0,0x03, + 0xCC,0x03,0xD8,0x03,0xE4,0x03,0xF0,0x03,0xFC,0x03,0x08,0x04,0x14,0x04,0x20,0x04,0x2C,0x04, + 0x38,0x04,0x44,0x04,0x50,0x04,0x5C,0x04,0x68,0x04,0x74,0x04, + + 6, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00, + + 6, // 0x25 '%' + 0x00,0x68,0xA8,0xD0,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, + + 6, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 6, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 6, // 0x2A '*' + 0x00,0x00,0x28,0x7C,0x38,0x7C,0x28,0x00,0x00,0x00,0x00, + + 6, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 6, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00, + + 6, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40, + + 6, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00, + + 6, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00, + + 6, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00, + + 6, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 6, // 0x40 '@' + 0x00,0x38,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 6, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x54,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00, + + 6, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 6, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 6, // 0x57 'W' + 0x00,0x44,0x44,0x54,0x54,0x54,0x54,0x54,0x28,0x00,0x00, + + 6, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 6, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 6, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 6, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 6, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x50,0x20, + + 6, // 0x6B 'k' + 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 6, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x44,0x44,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x18,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 6, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x7C,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 6, // 0x7B '{' + 0x18,0x20,0x20,0x20,0xC0,0xC0,0x20,0x20,0x20,0x18,0x00, + + 6, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00, + + 6, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x0C,0x0C,0x10,0x10,0x10,0x60,0x00, + + 6, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs7x12_mono_high[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, + 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, + 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, + 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00, + + 7, // 0x24 '$' + 0x10,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x10,0x00, + + 7, // 0x25 '%' + 0x32,0x54,0x64,0x08,0x08,0x10,0x10,0x26,0x2A,0x4C,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x27 ''' + 0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 7, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x54,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x20,0x40, + + 7, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x54,0x4C,0x40,0x38,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x5C,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x4D 'M' + 0x00,0x44,0x6C,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x44,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x40,0x38,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x7C,0x04,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00, + + 7, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 7, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 7, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x78, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x48,0x30, + + 7, // 0x6B 'k' + 0x00,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x20,0x24,0x18,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x3C,0x08,0x70, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 7, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 7, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, + + 7, // 0x7E '~' + 0x00,0x60,0x92,0x92,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u mcs7x12_mono_low[] = + { + 12, 4, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x4E,0x00,0x5B,0x00,0x68,0x00, + 0x75,0x00,0x82,0x00,0x8F,0x00,0x9C,0x00,0xA9,0x00,0xB6,0x00,0xC3,0x00,0xD0,0x00,0xDD,0x00, + 0xEA,0x00,0xF7,0x00,0x04,0x01,0x11,0x01,0x1E,0x01,0x2B,0x01,0x38,0x01,0x45,0x01,0x52,0x01, + 0x5F,0x01,0x6C,0x01,0x79,0x01,0x86,0x01,0x93,0x01,0xA0,0x01,0xAD,0x01,0xBA,0x01,0xC7,0x01, + 0xD4,0x01,0xE1,0x01,0xEE,0x01,0xFB,0x01,0x08,0x02,0x15,0x02,0x22,0x02,0x2F,0x02,0x3C,0x02, + 0x49,0x02,0x56,0x02,0x63,0x02,0x70,0x02,0x7D,0x02,0x8A,0x02,0x97,0x02,0xA4,0x02,0xB1,0x02, + 0xBE,0x02,0xCB,0x02,0xD8,0x02,0xE5,0x02,0xF2,0x02,0xFF,0x02,0x0C,0x03,0x19,0x03,0x26,0x03, + 0x33,0x03,0x40,0x03,0x4D,0x03,0x5A,0x03,0x67,0x03,0x74,0x03,0x81,0x03,0x8E,0x03,0x9B,0x03, + 0xA8,0x03,0xB5,0x03,0xC2,0x03,0xCF,0x03,0xDC,0x03,0xE9,0x03,0xF6,0x03,0x03,0x04,0x10,0x04, + 0x1D,0x04,0x2A,0x04,0x37,0x04,0x44,0x04,0x51,0x04,0x5E,0x04,0x6B,0x04,0x78,0x04,0x85,0x04, + 0x92,0x04,0x9F,0x04,0xAC,0x04,0xB9,0x04,0xC6,0x04,0xD3,0x04, + + 7, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x21 '!' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x22 '"' + 0x28,0x28,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x28,0x28,0x7C,0x28,0x28,0x28,0x7C,0x28,0x28,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x10,0x38,0x54,0x50,0x38,0x14,0x54,0x38,0x10,0x00,0x00, + + 7, // 0x25 '%' + 0x34,0x54,0x68,0x08,0x10,0x10,0x20,0x2C,0x54,0x58,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x20,0x50,0x50,0x20,0x54,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x27 ''' + 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x00, + + 7, // 0x29 ')' + 0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x00, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x7C,0x38,0x54,0x10,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00,0x00, + + 7, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x00,0x00, + + 7, // 0x30 '0' + 0x00,0x38,0x44,0x44,0x54,0x54,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x38,0x44,0x44,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x38,0x44,0x04,0x38,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x08,0x18,0x28,0x28,0x48,0x7C,0x08,0x08,0x00,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x7C,0x40,0x78,0x44,0x04,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x38,0x44,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x20,0x40,0x00, + + 7, // 0x3C '<' + 0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 7, // 0x40 '@' + 0x00,0x38,0x44,0x44,0x5C,0x54,0x4C,0x40,0x38,0x00,0x00,0x00, + + 7, // 0x41 'A' + 0x00,0x38,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x43 'C' + 0x00,0x38,0x44,0x40,0x40,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x70,0x48,0x44,0x44,0x44,0x44,0x48,0x70,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x38,0x44,0x40,0x40,0x4C,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x49 'I' + 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x1C,0x08,0x08,0x08,0x08,0x48,0x48,0x30,0x00,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x44,0x48,0x50,0x60,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x4D 'M' + 0x00,0x44,0x6C,0x54,0x54,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x44,0x64,0x64,0x54,0x54,0x4C,0x4C,0x44,0x00,0x00,0x00, + + 7, // 0x4F 'O' + 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x51 'Q' + 0x00,0x38,0x44,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,0x00, + + 7, // 0x52 'R' + 0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x44,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x57 'W' + 0x00,0x44,0x44,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x44,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x5B '[' + 0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 7, // 0x5C '\' + 0x00,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 7, // 0x5D ']' + 0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,0x00, + + 7, // 0x5E '^' + 0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00, + + 7, // 0x60 '`' + 0x00,0x20,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x66 'f' + 0x00,0x0C,0x10,0x38,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x44,0x38, + + 7, // 0x68 'h' + 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x69 'i' + 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6A 'j' + 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x08,0x48,0x48,0x30, + + 7, // 0x6B 'k' + 0x00,0x40,0x40,0x4C,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 7, // 0x6C 'l' + 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,0x00, + + 7, // 0x6D 'm' + 0x00,0x00,0x00,0x68,0x54,0x54,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04,0x04, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x58,0x24,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x38,0x44,0x30,0x08,0x44,0x38,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x24,0x18,0x00,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x4C,0x34,0x00,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x44,0x44,0x44,0x54,0x54,0x28,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x04,0x08,0x70, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x7C,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 7, // 0x7B '{' + 0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x20,0x18,0x00, + + 7, // 0x7C '|' + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 7, // 0x7D '}' + 0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60,0x00, + + 7, // 0x7E '~' + 0x00,0x24,0x54,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x7F '' + 0x00,0x10,0x38,0x6C,0x44,0x44,0x7C,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana12[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, + 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, + 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, + 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, + 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, + 0x61,0x02,0x7A,0x02,0x87,0x02,0xA0,0x02,0xAD,0x02,0xC6,0x02,0xD3,0x02,0xE0,0x02,0xED,0x02, + 0xFA,0x02,0x07,0x03,0x20,0x03,0x2D,0x03,0x3A,0x03,0x47,0x03,0x54,0x03,0x61,0x03,0x6E,0x03, + 0x7B,0x03,0x88,0x03,0x95,0x03,0xA2,0x03,0xAF,0x03,0xBC,0x03,0xC9,0x03,0xD6,0x03,0xE3,0x03, + 0xF0,0x03,0xFD,0x03,0x0A,0x04,0x17,0x04,0x24,0x04,0x31,0x04,0x4A,0x04,0x57,0x04,0x64,0x04, + 0x71,0x04,0x7E,0x04,0x8B,0x04,0x98,0x04,0xA5,0x04,0xB2,0x04,0xBF,0x04,0xCC,0x04,0xD9,0x04, + 0xE6,0x04,0xF3,0x04,0x00,0x05,0x0D,0x05,0x1A,0x05,0x27,0x05, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x28,0x7C,0x28,0x7C,0x28,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3C,0x50,0x30,0x18,0x14,0x78,0x10,0x10, + + 11, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x4A,0x00,0x4A,0x00,0x35,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, + + 7, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x3A,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x10, + + 4, // 0x29 ')' + 0x00,0x00,0x80,0x40,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0x80, + + 7, // 0x2A '*' + 0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 3, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80,0x00, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x00, + + 4, // 0x2F '/' + 0x00,0x00,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x80,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x7C,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x00,0x7C,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x00,0x38,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x00,0x40,0x40,0x80,0x00, + + 7, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x18,0x04,0x00,0x00,0x00, + + 7, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, + + 7, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x30,0x40,0x00,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x00,0x20,0x00,0x00, + + 10, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1F,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x00,0x70,0x48,0x48,0x78,0x44,0x44,0x78,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x22,0x1C,0x00,0x00, + + 8, // 0x44 'D' + 0x00,0x00,0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x00,0x00, + + 8, // 0x47 'G' + 0x00,0x00,0x00,0x1C,0x22,0x40,0x4E,0x42,0x22,0x1C,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x00,0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4E 'N' + 0x00,0x00,0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x42,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, + + 7, // 0x52 'R' + 0x00,0x00,0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00, + + 7, // 0x53 'S' + 0x00,0x00,0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, + + 9, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x10,0x00,0x00, + + 7, // 0x5A 'Z' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 4, // 0x5B '[' + 0x00,0x00,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x60, + + 4, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x00, + + 4, // 0x5D ']' + 0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x60, + + 7, // 0x5E '^' + 0x00,0x00,0x00,0x10,0x28,0x44,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, + + 6, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x30,0x08,0x38,0x48,0x38,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x00,0x08,0x08,0x08,0x38,0x48,0x48,0x48,0x38,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x30, + + 6, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x70,0x48,0x48,0x48,0x48,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 3, // 0x6A 'j' + 0x00,0x00,0x00,0x40,0x00,0xC0,0x40,0x40,0x40,0x40,0x40,0x80, + + 6, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x48,0x50,0x60,0x50,0x48,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x49,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x48,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x70,0x48,0x48,0x48,0x70,0x40,0x40, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x08, + + 4, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x50,0x60,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x30,0x08,0x70,0x00,0x00, + + 4, // 0x74 't' + 0x00,0x00,0x00,0x00,0x40,0xF0,0x40,0x40,0x40,0x30,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x38,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x30,0x00,0x00, + + 7, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x44,0x54,0x54,0x28,0x28,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x30,0x48,0x48,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x48,0x48,0x48,0x30,0x10,0x20,0x20, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x70,0x10,0x20,0x40,0x70,0x00,0x00, + + 6, // 0x7B '{' + 0x00,0x00,0x18,0x20,0x20,0x20,0x20,0xC0,0x20,0x20,0x20,0x18, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 6, // 0x7D '}' + 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x60, + + 7, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x58,0x00,0x00,0x00,0x00, + + 9, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana12_bold[] = + { + 12, 3, 32, 128-32, + 0x00,0x00,0x0D,0x00,0x1A,0x00,0x27,0x00,0x34,0x00,0x41,0x00,0x5A,0x00,0x67,0x00,0x74,0x00, + 0x81,0x00,0x8E,0x00,0x9B,0x00,0xA8,0x00,0xB5,0x00,0xC2,0x00,0xCF,0x00,0xDC,0x00,0xE9,0x00, + 0xF6,0x00,0x03,0x01,0x10,0x01,0x1D,0x01,0x2A,0x01,0x37,0x01,0x44,0x01,0x51,0x01,0x5E,0x01, + 0x6B,0x01,0x78,0x01,0x85,0x01,0x92,0x01,0x9F,0x01,0xAC,0x01,0xC5,0x01,0xD2,0x01,0xDF,0x01, + 0xEC,0x01,0xF9,0x01,0x06,0x02,0x13,0x02,0x20,0x02,0x2D,0x02,0x3A,0x02,0x47,0x02,0x54,0x02, + 0x61,0x02,0x6E,0x02,0x7B,0x02,0x88,0x02,0x95,0x02,0xA2,0x02,0xAF,0x02,0xBC,0x02,0xC9,0x02, + 0xD6,0x02,0xE3,0x02,0xFC,0x02,0x09,0x03,0x16,0x03,0x23,0x03,0x30,0x03,0x3D,0x03,0x4A,0x03, + 0x57,0x03,0x64,0x03,0x71,0x03,0x7E,0x03,0x8B,0x03,0x98,0x03,0xA5,0x03,0xB2,0x03,0xBF,0x03, + 0xCC,0x03,0xD9,0x03,0xE6,0x03,0xF3,0x03,0x00,0x04,0x0D,0x04,0x26,0x04,0x33,0x04,0x40,0x04, + 0x4D,0x04,0x5A,0x04,0x67,0x04,0x74,0x04,0x81,0x04,0x8E,0x04,0x9B,0x04,0xB4,0x04,0xC1,0x04, + 0xCE,0x04,0xDB,0x04,0xE8,0x04,0xF5,0x04,0x02,0x05,0x0F,0x05, + + 3, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0xD8,0xD8,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x23 '#' + 0x00,0x00,0x00,0x14,0x14,0x7E,0x28,0xFC,0x50,0x50,0x00,0x00, + + 6, // 0x24 '$' + 0x00,0x00,0x20,0x20,0x70,0xE8,0xE0,0x38,0xB8,0x70,0x20,0x20, + + 11, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x00,0x94,0x00,0x94,0x00,0x69,0x80,0x0A,0x40,0x0A,0x40,0x11,0x80,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0x76,0xDC,0xCC,0x76,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x30,0x60,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x60,0x30, + + 5, // 0x29 ')' + 0x00,0x00,0xC0,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xC0, + + 6, // 0x2A '*' + 0x00,0x00,0x20,0xA8,0x70,0xA8,0x20,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x10,0x10,0x7C,0x10,0x10,0x00,0x00,0x00, + + 3, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x80,0x00, + + 4, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0x80,0x00, + + 6, // 0x30 '0' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x31 '1' + 0x00,0x00,0x00,0x30,0x70,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 6, // 0x32 '2' + 0x00,0x00,0x00,0x70,0x98,0x18,0x30,0x60,0xC0,0xF8,0x00,0x00, + + 6, // 0x33 '3' + 0x00,0x00,0x00,0x70,0x98,0x18,0x70,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x34 '4' + 0x00,0x00,0x00,0x18,0x38,0x58,0x98,0xFC,0x18,0x18,0x00,0x00, + + 6, // 0x35 '5' + 0x00,0x00,0x00,0xF8,0xC0,0xF0,0x18,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x36 '6' + 0x00,0x00,0x00,0x70,0xC0,0xF0,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x37 '7' + 0x00,0x00,0x00,0xF8,0x18,0x30,0x30,0x60,0x60,0xC0,0x00,0x00, + + 6, // 0x38 '8' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0x70,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x39 '9' + 0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x78,0x18,0x70,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x40,0x00, + + 8, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x04,0x18,0x60,0x60,0x18,0x04,0x00,0x00, + + 8, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,0x00, + + 8, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x40,0x30,0x0C,0x0C,0x30,0x40,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0xF0,0x18,0x18,0x30,0x60,0x00,0x60,0x00,0x00, + + 9, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x9D,0x00,0xA5,0x00,0xA5,0x00,0x9E,0x00,0x40,0x00,0x3C,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x38,0x38,0x6C,0x6C,0x7C,0xC6,0xC6,0x00,0x00, + + 7, // 0x42 'B' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xCC,0xCC,0xF8,0x00,0x00, + + 6, // 0x43 'C' + 0x00,0x00,0x00,0x70,0xC8,0xC0,0xC0,0xC0,0xC8,0x70,0x00,0x00, + + 7, // 0x44 'D' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0xCC,0xF8,0x00,0x00, + + 6, // 0x45 'E' + 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xF8,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0xF8,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,0x00, + + 7, // 0x47 'G' + 0x00,0x00,0x00,0x78,0xC4,0xC0,0xC0,0xDC,0xCC,0x7C,0x00,0x00, + + 7, // 0x48 'H' + 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00, + + 7, // 0x4B 'K' + 0x00,0x00,0x00,0xCC,0xD8,0xF0,0xE0,0xF0,0xD8,0xCC,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xF8,0x00,0x00, + + 8, // 0x4D 'M' + 0x00,0x00,0x00,0x82,0xC6,0xEE,0xB6,0xB6,0x86,0x86,0x00,0x00, + + 7, // 0x4E 'N' + 0x00,0x00,0x00,0x84,0xC4,0xE4,0xB4,0x9C,0x8C,0x84,0x00,0x00, + + 8, // 0x4F 'O' + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xF8,0xC0,0xC0,0x00,0x00, + + 8, // 0x51 'Q' + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x18,0x0E, + + 7, // 0x52 'R' + 0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xD8,0xCC,0xC6,0x00,0x00, + + 6, // 0x53 'S' + 0x00,0x00,0x00,0x70,0xC8,0xC0,0x70,0x18,0x98,0x70,0x00,0x00, + + 6, // 0x54 'T' + 0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, + + 7, // 0x55 'U' + 0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00, + + 7, // 0x56 'V' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x78,0x78,0x30,0x30,0x00,0x00, + + 11, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xC0,0xCC,0xC0,0x6D,0x80,0x6D,0x80,0x73,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x58 'X' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x78,0xCC,0xCC,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x00,0x00, + + 6, // 0x5A 'Z' + 0x00,0x00,0x00,0xF8,0x18,0x30,0x60,0xC0,0xC0,0xF8,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x70, + + 6, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x70, + + 8, // 0x5E '^' + 0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC, + + 6, // 0x60 '`' + 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x70,0x18,0x78,0xD8,0x78,0x00,0x00, + + 6, // 0x62 'b' + 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xF0,0x00,0x00, + + 5, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xC0,0xC0,0x70,0x00,0x00, + + 6, // 0x64 'd' + 0x00,0x00,0x18,0x18,0x18,0x78,0xD8,0xD8,0xD8,0x78,0x00,0x00, + + 6, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xF8,0xC0,0x78,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x00,0x00, + + 6, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x70, + + 6, // 0x68 'h' + 0x00,0x00,0xC0,0xC0,0xC0,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0xC0,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x00,0x60,0x00,0xE0,0x60,0x60,0x60,0x60,0x60,0xC0, + + 6, // 0x6B 'k' + 0x00,0x00,0xC0,0xC0,0xC0,0xD8,0xD8,0xF0,0xD8,0xD8,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00, + + 9, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF6,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xD8,0x00,0x00, + + 6, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0xD8,0xD8,0x70,0x00,0x00, + + 6, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0xF0,0xD8,0xD8,0xD8,0xF0,0xC0,0xC0, + + 6, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x78,0xD8,0xD8,0xD8,0x78,0x18,0x18, + + 4, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0xD0,0xE0,0xC0,0xC0,0xC0,0x00,0x00, + + 5, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0xF0,0x30,0xE0,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x38,0x00,0x00, + + 6, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0xD8,0x78,0x00,0x00, + + 6, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0x66,0x00,0x66,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0x70,0xD8,0xD8,0x00,0x00, + + 6, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0xD8,0xD8,0xD8,0x70,0x70,0x30,0x60, + + 5, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0xF0,0x30,0x60,0xC0,0xF0,0x00,0x00, + + 6, // 0x7B '{' + 0x00,0x00,0x18,0x30,0x30,0x30,0xE0,0x30,0x30,0x30,0x30,0x18, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 6, // 0x7D '}' + 0x00,0x00,0xC0,0x60,0x60,0x60,0x38,0x60,0x60,0x60,0x60,0xC0, + + 8, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x92,0x8C,0x00,0x00,0x00, + + 9, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana13[] = + { + 13, 3, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x7C,0x00,0x8A,0x00, + 0x98,0x00,0xA6,0x00,0xB4,0x00,0xCF,0x00,0xDD,0x00,0xEB,0x00,0xF9,0x00,0x07,0x01,0x15,0x01, + 0x23,0x01,0x31,0x01,0x3F,0x01,0x4D,0x01,0x5B,0x01,0x69,0x01,0x77,0x01,0x85,0x01,0x93,0x01, + 0xA1,0x01,0xAF,0x01,0xCA,0x01,0xE5,0x01,0x00,0x02,0x0E,0x02,0x29,0x02,0x37,0x02,0x45,0x02, + 0x60,0x02,0x7B,0x02,0x89,0x02,0x97,0x02,0xB2,0x02,0xC0,0x02,0xCE,0x02,0xDC,0x02,0xEA,0x02, + 0xF8,0x02,0x13,0x03,0x21,0x03,0x3C,0x03,0x4A,0x03,0x65,0x03,0x73,0x03,0x81,0x03,0x8F,0x03, + 0x9D,0x03,0xAB,0x03,0xC6,0x03,0xD4,0x03,0xE2,0x03,0xF0,0x03,0xFE,0x03,0x0C,0x04,0x1A,0x04, + 0x35,0x04,0x43,0x04,0x51,0x04,0x5F,0x04,0x6D,0x04,0x7B,0x04,0x89,0x04,0x97,0x04,0xA5,0x04, + 0xB3,0x04,0xC1,0x04,0xCF,0x04,0xDD,0x04,0xEB,0x04,0xF9,0x04,0x14,0x05,0x22,0x05,0x30,0x05, + 0x3E,0x05,0x4C,0x05,0x5A,0x05,0x68,0x05,0x76,0x05,0x84,0x05,0x92,0x05,0xAD,0x05,0xBB,0x05, + 0xC9,0x05,0xD7,0x05,0xE5,0x05,0xF3,0x05,0x01,0x06,0x1C,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3C,0x50,0x50,0x38,0x14,0x14,0x78,0x10,0x10, + + 12, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x4A,0x00,0x32,0x00,0x04,0xC0,0x05,0x20,0x09,0x20,0x08,0xC0,0x00,0x00,0x00,0x00, + + 8, // 0x26 '&' + 0x00,0x00,0x00,0x30,0x48,0x48,0x32,0x4A,0x44,0x46,0x39,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 7, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 7, // 0x30 '0' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x31 '1' + 0x00,0x00,0x00,0x10,0x70,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00, + + 7, // 0x32 '2' + 0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 7, // 0x33 '3' + 0x00,0x00,0x00,0x38,0x44,0x04,0x18,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x34 '4' + 0x00,0x00,0x00,0x08,0x18,0x28,0x48,0x88,0xFC,0x08,0x08,0x00,0x00, + + 7, // 0x35 '5' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00, + + 7, // 0x36 '6' + 0x00,0x00,0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x37 '7' + 0x00,0x00,0x00,0x7C,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x00,0x00, + + 7, // 0x38 '8' + 0x00,0x00,0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x39 '9' + 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x3C,0x04,0x08,0x30,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3F '?' + 0x00,0x00,0x00,0x70,0x08,0x08,0x10,0x20,0x20,0x00,0x20,0x00,0x00, + + 10, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x4E,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4D,0x00,0x20,0x00,0x1E,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x24,0x7E,0x42,0x42,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x78,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x45 'E' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C,0x00,0x00, + + 6, // 0x46 'F' + 0x00,0x00,0x00,0x7C,0x40,0x40,0x78,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x48 'H' + 0x00,0x00,0x00,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00, + + 6, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C,0x00,0x00, + + 9, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x55,0x00,0x55,0x00,0x49,0x00,0x49,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4E 'N' + 0x00,0x00,0x00,0x62,0x62,0x52,0x52,0x4A,0x4A,0x46,0x46,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x50 'P' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x04,0x00,0x03,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x48,0x44,0x42,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x55 'U' + 0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00, + + 11, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x82,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x00, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 9, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE, + + 7, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x38,0x04,0x3C,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x78,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x44,0x38,0x00,0x00, + + 7, // 0x64 'd' + 0x00,0x00,0x04,0x04,0x04,0x3C,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x7C,0x40,0x44,0x38,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x38, + + 7, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x70,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, + + 7, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x00,0x00, + + 7, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x44,0x38,0x00,0x00, + + 7, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x44,0x78,0x40,0x40, + + 7, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x44,0x44,0x44,0x44,0x3C,0x04,0x04, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x00,0x00, + + 6, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x60,0x18,0x08,0x70,0x00,0x00, + + 4, // 0x74 't' + 0x00,0x00,0x00,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x30,0x00,0x00, + + 7, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x3C,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00, + + 9, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x49,0x00,0x49,0x00,0x55,0x00,0x55,0x00,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x10,0x10,0x28,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, + + 6, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x78,0x08,0x10,0x20,0x40,0x78,0x00,0x00, + + 7, // 0x7B '{' + 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x0C, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 7, // 0x7D '}' + 0x00,0x00,0x60,0x10,0x10,0x10,0x10,0x0C,0x10,0x10,0x10,0x10,0x60, + + 9, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana13_bold[] = + { + 13, 3, 32, 128-32, + 0x00,0x00,0x0E,0x00,0x1C,0x00,0x2A,0x00,0x45,0x00,0x53,0x00,0x6E,0x00,0x89,0x00,0x97,0x00, + 0xA5,0x00,0xB3,0x00,0xC1,0x00,0xDC,0x00,0xEA,0x00,0xF8,0x00,0x06,0x01,0x14,0x01,0x22,0x01, + 0x30,0x01,0x3E,0x01,0x4C,0x01,0x5A,0x01,0x68,0x01,0x76,0x01,0x84,0x01,0x92,0x01,0xA0,0x01, + 0xAE,0x01,0xBC,0x01,0xD7,0x01,0xF2,0x01,0x0D,0x02,0x1B,0x02,0x36,0x02,0x51,0x02,0x5F,0x02, + 0x6D,0x02,0x88,0x02,0x96,0x02,0xA4,0x02,0xBF,0x02,0xDA,0x02,0xE8,0x02,0xF6,0x02,0x04,0x03, + 0x12,0x03,0x2D,0x03,0x48,0x03,0x63,0x03,0x71,0x03,0x8C,0x03,0x9A,0x03,0xA8,0x03,0xB6,0x03, + 0xD1,0x03,0xDF,0x03,0xFA,0x03,0x08,0x04,0x16,0x04,0x24,0x04,0x32,0x04,0x40,0x04,0x4E,0x04, + 0x69,0x04,0x77,0x04,0x85,0x04,0x93,0x04,0xA1,0x04,0xAF,0x04,0xBD,0x04,0xCB,0x04,0xD9,0x04, + 0xE7,0x04,0xF5,0x04,0x03,0x05,0x11,0x05,0x1F,0x05,0x2D,0x05,0x48,0x05,0x56,0x05,0x64,0x05, + 0x72,0x05,0x80,0x05,0x8E,0x05,0x9C,0x05,0xAA,0x05,0xB8,0x05,0xC6,0x05,0xE1,0x05,0xEF,0x05, + 0xFD,0x05,0x0B,0x06,0x19,0x06,0x27,0x06,0x35,0x06,0x50,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x0A,0x00,0x3F,0x00,0x14,0x00,0x14,0x00,0x7E,0x00,0x28,0x00,0x28,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x08,0x08,0x3C,0x6A,0x68,0x3C,0x16,0x56,0x3C,0x10,0x10, + + 14, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x80,0x6C,0x80,0x6D,0x00,0x6D,0x70,0x3A,0xD8,0x02,0xD8,0x04,0xD8,0x04,0x70,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, + + 6, // 0x29 ')' + 0x00,0x00,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x30,0x30,0x60, + + 8, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 8, // 0x2F '/' + 0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x30,0x30,0x60,0x60, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x3C,0x66,0x06,0x1C,0x06,0x06,0x66,0x3C,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x04,0x0C,0x1C,0x2C,0x4C,0x7E,0x0C,0x0C,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x3C,0x06,0x06,0x66,0x3C,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x1C,0x30,0x60,0x7C,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x7E,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00,0x00, + + 4, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00, + + 4, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x00,0x00, + + 11, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x4F,0x40,0x5B,0x40,0x5B,0x40,0x5B,0x40,0x4F,0x80,0x20,0x00,0x1F,0x00,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x7C,0x66,0x66,0x66,0x7C,0x00,0x00, + + 8, // 0x43 'C' + 0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x66,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x60,0x00,0x67,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0xF0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x66,0x6C,0x78,0x70,0x70,0x78,0x6C,0x66,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0x00, + + 10, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x71,0x80,0x7B,0x80,0x5D,0x80,0x49,0x80,0x41,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x61,0x00,0x71,0x00,0x59,0x00,0x4D,0x00,0x47,0x00,0x43,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x00,0x00, + + 9, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x0C,0x00,0x07,0x00, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x7C,0x6C,0x66,0x63,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x00,0x00, + + 12, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x36,0xC0,0x3F,0xC0,0x39,0xC0,0x19,0x80,0x19,0x80,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x18,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x59 'Y' + 0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x18,0x18,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x06,0x0E,0x1C,0x38,0x70,0x60,0x7E,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, + + 8, // 0x5C '\' + 0x00,0x00,0x60,0x60,0x30,0x30,0x18,0x18,0x18,0x0C,0x0C,0x06,0x06, + + 6, // 0x5D ']' + 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + + 8, // 0x60 '`' + 0x00,0x00,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x60,0x60,0x3C,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 12, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7D,0xC0,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x78,0x3C,0x0C,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x18,0x00,0x00, + + 10, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x6D,0x80,0x33,0x00,0x33,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x18,0x30,0x30, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x30,0x60,0x7C,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E, + + 6, // 0x7C '|' + 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + + 8, // 0x7D '}' + 0x00,0x00,0x70,0x18,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70, + + 9, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x49,0x00,0x49,0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana14[] = + { + 14, 3, 32, 128-32, + 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x59,0x00,0x76,0x00,0x93,0x00,0xA2,0x00, + 0xB1,0x00,0xC0,0x00,0xCF,0x00,0xEC,0x00,0xFB,0x00,0x0A,0x01,0x19,0x01,0x28,0x01,0x37,0x01, + 0x46,0x01,0x55,0x01,0x64,0x01,0x73,0x01,0x82,0x01,0x91,0x01,0xA0,0x01,0xAF,0x01,0xBE,0x01, + 0xCD,0x01,0xDC,0x01,0xF9,0x01,0x16,0x02,0x33,0x02,0x42,0x02,0x5F,0x02,0x6E,0x02,0x7D,0x02, + 0x9A,0x02,0xB7,0x02,0xC6,0x02,0xD5,0x02,0xF2,0x02,0x0F,0x03,0x1E,0x03,0x2D,0x03,0x3C,0x03, + 0x4B,0x03,0x68,0x03,0x85,0x03,0xA2,0x03,0xB1,0x03,0xCE,0x03,0xDD,0x03,0xEC,0x03,0xFB,0x03, + 0x18,0x04,0x27,0x04,0x44,0x04,0x53,0x04,0x62,0x04,0x71,0x04,0x80,0x04,0x8F,0x04,0x9E,0x04, + 0xBB,0x04,0xCA,0x04,0xD9,0x04,0xE8,0x04,0xF7,0x04,0x06,0x05,0x15,0x05,0x24,0x05,0x33,0x05, + 0x42,0x05,0x51,0x05,0x60,0x05,0x6F,0x05,0x7E,0x05,0x8D,0x05,0xAA,0x05,0xB9,0x05,0xC8,0x05, + 0xD7,0x05,0xE6,0x05,0xF5,0x05,0x04,0x06,0x13,0x06,0x22,0x06,0x31,0x06,0x4E,0x06,0x5D,0x06, + 0x6C,0x06,0x7B,0x06,0x8A,0x06,0x99,0x06,0xA8,0x06,0xC5,0x06, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x00,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x12,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10, + + 13, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x49,0x00,0x49,0x00,0x4A,0x00,0x32,0x60,0x02,0x90,0x04,0x90,0x04,0x90,0x08,0x60,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x39,0x00,0x45,0x00,0x42,0x00,0x43,0x00,0x3C,0x80,0x00,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x28 '(' + 0x00,0x00,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10, + + 5, // 0x29 ')' + 0x00,0x00,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x20,0x40, + + 8, // 0x2A '*' + 0x00,0x00,0x10,0x54,0x38,0x54,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 5, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x2F '/' + 0x00,0x00,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x40,0x80, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x7C,0x02,0x02,0x02,0x42,0x3C,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x44,0x04,0x04,0x08,0x10,0x10,0x00,0x10,0x00,0x00, + + 12, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x27,0x40,0x49,0x20,0x49,0x20,0x49,0x20,0x49,0x20,0x27,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, + + 8, // 0x41 'A' + 0x00,0x00,0x00,0x18,0x18,0x24,0x24,0x42,0x42,0x7E,0x81,0x81,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00, + + 7, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00, + + 5, // 0x4A 'J' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00, + + 10, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x52,0x80,0x52,0x80,0x52,0x80,0x4C,0x80,0x4C,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00, + + 10, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80, + + 8, // 0x52 'R' + 0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x7C,0x48,0x44,0x42,0x41,0x00,0x00, + + 8, // 0x53 'S' + 0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00, + + 7, // 0x54 'T' + 0x00,0x00,0x00,0xFE,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x56 'V' + 0x00,0x00,0x00,0x81,0x81,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x00,0x00, + + 13, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00, + + 8, // 0x58 'X' + 0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x18,0x24,0x42,0x42,0x00,0x00, + + 7, // 0x59 'Y' + 0x00,0x00,0x00,0x82,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x10,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x10,0x20,0x40,0x7E,0x00,0x00, + + 5, // 0x5B '[' + 0x00,0x00,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70, + + 5, // 0x5C '\' + 0x00,0x00,0x80,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08, + + 5, // 0x5D ']' + 0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, + + 8, // 0x60 '`' + 0x00,0x00,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00, + + 6, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00, + + 4, // 0x66 'f' + 0x00,0x00,0x30,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7B,0x80,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x40,0x40,0xF8,0x40,0x40,0x40,0x40,0x40,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00, + + 7, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00, + + 7, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x28,0x10,0x10,0x10,0x20, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C, + + 5, // 0x7C '|' + 0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + + 8, // 0x7D '}' + 0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30, + + 10, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana14_bold[] = + { + 14, 3, 32, 128-32, + 0x00,0x00,0x0F,0x00,0x1E,0x00,0x2D,0x00,0x4A,0x00,0x67,0x00,0x84,0x00,0xA1,0x00,0xB0,0x00, + 0xBF,0x00,0xCE,0x00,0xEB,0x00,0x08,0x01,0x17,0x01,0x26,0x01,0x35,0x01,0x44,0x01,0x61,0x01, + 0x7E,0x01,0x9B,0x01,0xB8,0x01,0xD5,0x01,0xF2,0x01,0x0F,0x02,0x2C,0x02,0x49,0x02,0x66,0x02, + 0x75,0x02,0x84,0x02,0xA1,0x02,0xBE,0x02,0xDB,0x02,0xEA,0x02,0x07,0x03,0x24,0x03,0x41,0x03, + 0x5E,0x03,0x7B,0x03,0x8A,0x03,0x99,0x03,0xB6,0x03,0xD3,0x03,0xE2,0x03,0xF1,0x03,0x0E,0x04, + 0x1D,0x04,0x3A,0x04,0x57,0x04,0x74,0x04,0x91,0x04,0xAE,0x04,0xCB,0x04,0xE8,0x04,0xF7,0x04, + 0x14,0x05,0x31,0x05,0x4E,0x05,0x6B,0x05,0x88,0x05,0x97,0x05,0xA6,0x05,0xB5,0x05,0xC4,0x05, + 0xE1,0x05,0xFE,0x05,0x1B,0x06,0x2A,0x06,0x39,0x06,0x48,0x06,0x57,0x06,0x66,0x06,0x75,0x06, + 0x84,0x06,0x93,0x06,0xA2,0x06,0xB1,0x06,0xC0,0x06,0xCF,0x06,0xEC,0x06,0xFB,0x06,0x0A,0x07, + 0x19,0x07,0x28,0x07,0x37,0x07,0x46,0x07,0x55,0x07,0x64,0x07,0x73,0x07,0x90,0x07,0x9F,0x07, + 0xAE,0x07,0xBD,0x07,0xDA,0x07,0xE9,0x07,0x06,0x08,0x23,0x08, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x60,0x60,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x7E,0x00,0x3F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00, + + 15, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x6C,0x40,0x6C,0x80,0x6C,0xB8,0x6D,0x6C,0x3A,0x6C,0x02,0x6C,0x04,0x6C,0x04,0x38,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x6C,0x00,0x6C,0x00,0x6C,0x00,0x39,0x80,0x6D,0x00,0x66,0x00,0x63,0x00,0x3D,0x80,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18, + + 7, // 0x29 ')' + 0x00,0x00,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 6, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 8, // 0x2F '/' + 0x00,0x00,0x06,0x06,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x60,0x60, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x1E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x60,0x60,0x60,0x40, + + 10, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x38,0x4C,0x0C,0x18,0x30,0x30,0x00,0x30,0x30,0x00,0x00, + + 12, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x2F,0x40,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x5B,0x20,0x2F,0xC0,0x30,0x00,0x0F,0x00,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x7F,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x66,0x00,0x66,0x00,0x66,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x31,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x31,0x00,0x1E,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x7E,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x7E,0x60,0x60,0x60,0x7E,0x60,0x60,0x60,0x60,0x00,0x00, + + 10, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x30,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x67,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00, + + 10, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00, + + 9, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x70,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x71,0xC0,0x71,0xC0,0x5A,0xC0,0x5A,0xC0,0x4C,0xC0,0x4C,0xC0,0x40,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x41,0x80,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x06,0x00,0x03,0xC0, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00, + + 9, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5A 'Z' + 0x00,0x00,0x00,0x7E,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x7E,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78, + + 8, // 0x5C '\' + 0x00,0x00,0x60,0x60,0x30,0x30,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x06,0x06, + + 6, // 0x5D ']' + 0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x06,0x3E,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x60,0x60,0x62,0x3C,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x06,0x06,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x7E,0x60,0x62,0x3C,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 12, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xC0,0x77,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x66,0x60,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x06, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x3C,0x60,0x60,0x38,0x0C,0x0C,0x78,0x00,0x00, + + 5, // 0x74 't' + 0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3E,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x00,0x00, + + 12, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00, + + 8, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x3C,0x66,0x66,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x3C,0x3C,0x18,0x18,0x30, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x7C,0x0C,0x18,0x38,0x30,0x60,0x7C,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x0E,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0E,0x00, + + 6, // 0x7C '|' + 0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x38,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x38,0x00, + + 10, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x48,0x80,0x44,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0xE0,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana16[] = + { + 16, 4, 32, 128-32, + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x65,0x00,0x86,0x00,0xA7,0x00,0xB8,0x00, + 0xC9,0x00,0xDA,0x00,0xFB,0x00,0x1C,0x01,0x2D,0x01,0x3E,0x01,0x4F,0x01,0x60,0x01,0x71,0x01, + 0x82,0x01,0x93,0x01,0xA4,0x01,0xB5,0x01,0xC6,0x01,0xD7,0x01,0xE8,0x01,0xF9,0x01,0x0A,0x02, + 0x1B,0x02,0x2C,0x02,0x4D,0x02,0x6E,0x02,0x8F,0x02,0xA0,0x02,0xC1,0x02,0xE2,0x02,0xF3,0x02, + 0x14,0x03,0x35,0x03,0x46,0x03,0x57,0x03,0x78,0x03,0x99,0x03,0xAA,0x03,0xBB,0x03,0xCC,0x03, + 0xDD,0x03,0xFE,0x03,0x1F,0x04,0x40,0x04,0x51,0x04,0x72,0x04,0x93,0x04,0xB4,0x04,0xD5,0x04, + 0xF6,0x04,0x17,0x05,0x38,0x05,0x59,0x05,0x7A,0x05,0x9B,0x05,0xAC,0x05,0xBD,0x05,0xCE,0x05, + 0xEF,0x05,0x00,0x06,0x11,0x06,0x22,0x06,0x33,0x06,0x44,0x06,0x55,0x06,0x66,0x06,0x77,0x06, + 0x88,0x06,0x99,0x06,0xAA,0x06,0xBB,0x06,0xCC,0x06,0xDD,0x06,0xFE,0x06,0x0F,0x07,0x20,0x07, + 0x31,0x07,0x42,0x07,0x53,0x07,0x64,0x07,0x75,0x07,0x86,0x07,0x97,0x07,0xB8,0x07,0xC9,0x07, + 0xDA,0x07,0xEB,0x07,0xFC,0x07,0x0D,0x08,0x1E,0x08,0x3F,0x08, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 5, // 0x22 '"' + 0x00,0x00,0x00,0x50,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x12,0x00,0x12,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x24 '$' + 0x00,0x00,0x00,0x10,0x10,0x3E,0x50,0x50,0x30,0x1C,0x12,0x12,0x7C,0x10,0x10,0x00, + + 13, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x80,0x45,0x00,0x45,0x00,0x3A,0xE0,0x05,0x10,0x05,0x10,0x09,0x10,0x10,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x38,0x80,0x45,0x00,0x42,0x00,0x46,0x00,0x39,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 6, // 0x29 ')' + 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x00,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 8, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x08,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00,0x00, + + 8, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x7E,0x00,0x00,0x00, + + 8, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x1C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x04,0x0C,0x14,0x24,0x44,0x7F,0x04,0x04,0x04,0x00,0x00,0x00, + + 8, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x3E,0x20,0x20,0x20,0x3C,0x02,0x02,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x1C,0x20,0x40,0x7C,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x10,0x00,0x00,0x00, + + 8, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x3C,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x3E,0x02,0x04,0x38,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 9, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x00,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x38,0x44,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 13, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x10,0x40,0x27,0xA0,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x48,0x90,0x27,0xE0,0x10,0x00,0x0F,0x80,0x00,0x00, + + 9, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x14,0x00,0x22,0x00,0x22,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x7C,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, + + 9, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x7E,0x40,0x40,0x40,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 9, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x47,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7F,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, + + 8, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00,0x00, + + 7, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7E,0x00,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x00,0x61,0x00,0x51,0x00,0x51,0x00,0x49,0x00,0x45,0x00,0x45,0x00,0x43,0x00,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x7C,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40,0x00,0x00,0x00, + + 10, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x02,0x00,0x01,0x80,0x00,0x00, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x40,0x00,0x40,0x00,0x3E,0x00,0x01,0x00,0x01,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x45,0x10,0x45,0x10,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00, + + 6, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00, + + 11, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, + + 8, // 0x60 '`' + 0x00,0x00,0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x02,0x02,0x3E,0x42,0x42,0x3E,0x00,0x00,0x00, + + 8, // 0x62 'b' + 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x40,0x40,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x64 'd' + 0x00,0x00,0x00,0x02,0x02,0x02,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x40,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 8, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x3C, + + 8, // 0x68 'h' + 0x00,0x00,0x00,0x40,0x40,0x40,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 4, // 0x6A 'j' + 0x00,0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xC0, + + 7, // 0x6B 'k' + 0x00,0x00,0x00,0x40,0x40,0x40,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x80,0x66,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x44,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, + + 8, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00,0x00, + + 8, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x62,0x42,0x42,0x42,0x42,0x7C,0x40,0x40,0x40, + + 8, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x42,0x42,0x42,0x42,0x46,0x3A,0x02,0x02,0x02, + + 5, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x60,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 7, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x40,0x40,0x38,0x04,0x04,0x78,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x20,0x20,0x78,0x20,0x20,0x20,0x20,0x20,0x18,0x00,0x00,0x00, + + 8, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x10,0x10,0x20, + + 7, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x04,0x08,0x10,0x20,0x40,0x7C,0x00,0x00,0x00, + + 8, // 0x7B '{' + 0x00,0x00,0x00,0x0C,0x10,0x10,0x10,0x10,0x60,0x10,0x10,0x10,0x10,0x10,0x0C,0x00, + + 7, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00, + + 8, // 0x7D '}' + 0x00,0x00,0x00,0x30,0x08,0x08,0x08,0x08,0x06,0x08,0x08,0x08,0x08,0x08,0x30,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x80,0x4C,0x80,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana16_bold[] = + { + 16, 4, 32, 128-32, + 0x00,0x00,0x11,0x00,0x22,0x00,0x33,0x00,0x54,0x00,0x75,0x00,0xA6,0x00,0xC7,0x00,0xD8,0x00, + 0xE9,0x00,0xFA,0x00,0x1B,0x01,0x3C,0x01,0x4D,0x01,0x5E,0x01,0x6F,0x01,0x90,0x01,0xB1,0x01, + 0xD2,0x01,0xF3,0x01,0x14,0x02,0x35,0x02,0x56,0x02,0x77,0x02,0x98,0x02,0xB9,0x02,0xDA,0x02, + 0xEB,0x02,0xFC,0x02,0x1D,0x03,0x3E,0x03,0x5F,0x03,0x70,0x03,0x91,0x03,0xB2,0x03,0xD3,0x03, + 0xF4,0x03,0x15,0x04,0x36,0x04,0x57,0x04,0x78,0x04,0x99,0x04,0xAA,0x04,0xBB,0x04,0xDC,0x04, + 0xED,0x04,0x0E,0x05,0x2F,0x05,0x50,0x05,0x71,0x05,0x92,0x05,0xB3,0x05,0xD4,0x05,0xE5,0x05, + 0x06,0x06,0x27,0x06,0x48,0x06,0x69,0x06,0x8A,0x06,0xAB,0x06,0xBC,0x06,0xDD,0x06,0xEE,0x06, + 0x0F,0x07,0x30,0x07,0x51,0x07,0x72,0x07,0x93,0x07,0xA4,0x07,0xC5,0x07,0xE6,0x07,0xF7,0x07, + 0x18,0x08,0x39,0x08,0x4A,0x08,0x5B,0x08,0x6C,0x08,0x7D,0x08,0x9E,0x08,0xBF,0x08,0xE0,0x08, + 0x01,0x09,0x22,0x09,0x33,0x09,0x44,0x09,0x55,0x09,0x76,0x09,0x97,0x09,0xB8,0x09,0xD9,0x09, + 0xFA,0x09,0x0B,0x0A,0x2C,0x0A,0x3D,0x0A,0x5E,0x0A,0x7F,0x0A, + + 4, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x00,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,0x09,0x00,0x3F,0x80,0x3F,0x80,0x12,0x00,0x7F,0x00,0x7F,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x69,0x00,0x68,0x00,0x78,0x00,0x3E,0x00,0x0F,0x00,0x0B,0x00,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 17, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x20,0x00,0x66,0x20,0x00,0x66,0x40,0x00,0x66,0x5E,0x00,0x66,0xB3,0x00,0x3D,0x33,0x00,0x01,0x33,0x00,0x02,0x33,0x00,0x02,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x66,0x00,0x66,0x00,0x66,0xC0,0x3C,0xC0,0x66,0x80,0x63,0x00,0x63,0x80,0x3C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, + + 7, // 0x29 ')' + 0x00,0x00,0x00,0x60,0x30,0x18,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x18,0x30,0x60, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 9, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x03,0x00,0x0E,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0E,0x00,0x16,0x00,0x26,0x00,0x46,0x00,0x7F,0x80,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x30,0x00,0x60,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x03,0x00,0x06,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00, + + 5, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x38,0x30,0x30,0x60,0x60, + + 11, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x66,0x06,0x0C,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00, + + 13, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x27,0xA0,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x4D,0x90,0x27,0xE0,0x30,0x00,0x0F,0x80,0x00,0x00,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x7F,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x60,0x00,0x63,0x80,0x61,0x80,0x31,0x80,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xF8,0x00,0x00,0x00, + + 9, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x78,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0x00,0x00,0x00, + + 12, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0x70,0xE0,0x59,0x60,0x59,0x60,0x4E,0x60,0x4E,0x60,0x44,0x60,0x44,0x60,0x40,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x80,0x70,0x80,0x58,0x80,0x58,0x80,0x4C,0x80,0x46,0x80,0x46,0x80,0x43,0x80,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x03,0x00,0x01,0xC0,0x00,0x00, + + 9, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x6C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x70,0x00,0x3E,0x00,0x07,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x54 'T' + 0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x00, + + 9, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x78,0x00, + + 10, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x66 'f' + 0x00,0x00,0x00,0x38,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x3E,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x00,0x60,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0x63,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 14, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x03,0x00,0x03,0x00,0x03,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x7C,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x60,0x70,0x3C,0x0E,0x06,0x7C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x60,0x60,0xF8,0x60,0x60,0x60,0x60,0x60,0x38,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x67,0x00,0x3B,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x60,0x66,0x60,0x66,0x60,0x69,0x60,0x39,0xC0,0x30,0xC0,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x00,0x00,0x00, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x07,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x70,0x00,0x00,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana17[] = + { + 17, 4, 32, 128-32, + 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0x9F,0x00,0xC2,0x00,0xD4,0x00, + 0xE6,0x00,0xF8,0x00,0x1B,0x01,0x3E,0x01,0x50,0x01,0x62,0x01,0x74,0x01,0x86,0x01,0xA9,0x01, + 0xCC,0x01,0xEF,0x01,0x12,0x02,0x35,0x02,0x58,0x02,0x7B,0x02,0x9E,0x02,0xC1,0x02,0xE4,0x02, + 0xF6,0x02,0x08,0x03,0x2B,0x03,0x4E,0x03,0x71,0x03,0x83,0x03,0xA6,0x03,0xC9,0x03,0xEC,0x03, + 0x0F,0x04,0x32,0x04,0x55,0x04,0x67,0x04,0x8A,0x04,0xAD,0x04,0xBF,0x04,0xD1,0x04,0xF4,0x04, + 0x06,0x05,0x29,0x05,0x4C,0x05,0x6F,0x05,0x81,0x05,0xA4,0x05,0xC7,0x05,0xEA,0x05,0x0D,0x06, + 0x30,0x06,0x53,0x06,0x76,0x06,0x99,0x06,0xBC,0x06,0xDF,0x06,0xF1,0x06,0x03,0x07,0x15,0x07, + 0x38,0x07,0x5B,0x07,0x7E,0x07,0x90,0x07,0xB3,0x07,0xC5,0x07,0xE8,0x07,0xFA,0x07,0x0C,0x08, + 0x2F,0x08,0x52,0x08,0x64,0x08,0x76,0x08,0x88,0x08,0x9A,0x08,0xBD,0x08,0xE0,0x08,0x03,0x09, + 0x26,0x09,0x49,0x09,0x5B,0x09,0x6D,0x09,0x7F,0x09,0xA2,0x09,0xB4,0x09,0xD7,0x09,0xFA,0x09, + 0x0C,0x0A,0x1E,0x0A,0x41,0x0A,0x53,0x0A,0x76,0x0A,0x99,0x0A, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x22 '"' + 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x3E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 15, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x80,0x44,0x80,0x45,0x38,0x39,0x44,0x02,0x44,0x04,0x44,0x04,0x44,0x08,0x38,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x38,0x80,0x44,0x80,0x42,0x80,0x41,0x00,0x22,0x80,0x1C,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 6, // 0x29 ')' + 0x00,0x00,0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40, + + 9, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x2F '/' + 0x00,0x00,0x00,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40,0x80,0x80,0x00, + + 9, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x38,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x0C,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x01,0x00,0x02,0x00,0x1C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x06,0x00,0x0A,0x00,0x12,0x00,0x22,0x00,0x42,0x00,0x7F,0x80,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7C,0x00,0x02,0x00,0x01,0x00,0x01,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x30,0x00,0x20,0x00,0x40,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x21,0x00,0x1F,0x00,0x01,0x00,0x02,0x00,0x06,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x00, + + 11, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x0C,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0x80,0x20,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x30,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x7E,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x43,0xC0,0x40,0x40,0x20,0x40,0x30,0x40,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x7F,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 6, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF0,0x00,0x00,0x00, + + 10, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, + + 11, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x51,0x40,0x51,0x40,0x4A,0x40,0x4A,0x40,0x44,0x40,0x44,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x80,0x60,0x80,0x50,0x80,0x48,0x80,0x48,0x80,0x44,0x80,0x44,0x80,0x42,0x80,0x41,0x80,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x7C,0x42,0x41,0x41,0x42,0x7C,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 11, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x31,0x80,0x20,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x31,0x80,0x0E,0x00,0x02,0x00,0x02,0x00,0x01,0xC0, + + 10, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x44,0x00,0x78,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x38,0x00,0x07,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x5B '[' + 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, + + 6, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x08,0x08,0x04,0x00, + + 6, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, + + 11, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x00, + + 9, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x02,0x3E,0x42,0x42,0x46,0x3A,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x40,0x40,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x7E,0x40,0x40,0x22,0x1C,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x00,0x10,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, + + 8, // 0x6B 'k' + 0x00,0x00,0x00,0x40,0x40,0x40,0x42,0x44,0x48,0x50,0x70,0x48,0x44,0x42,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 13, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0xE0,0x63,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x00,0x00,0x00, + + 11, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x40,0x44,0x40,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x2A,0x80,0x11,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x18,0x10,0x10,0x20, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x02,0x04,0x08,0x10,0x20,0x40,0x7E,0x00,0x00,0x00, + + 9, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, + + 6, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + + 9, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x03,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x70,0x00, + + 11, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x40,0x44,0x40,0x44,0x40,0x43,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana17_bold[] = + { + 17, 4, 32, 128-32, + 0x00,0x00,0x12,0x00,0x24,0x00,0x36,0x00,0x59,0x00,0x7C,0x00,0xB0,0x00,0xD3,0x00,0xE5,0x00, + 0xF7,0x00,0x09,0x01,0x2C,0x01,0x4F,0x01,0x61,0x01,0x73,0x01,0x85,0x01,0xA8,0x01,0xCB,0x01, + 0xEE,0x01,0x11,0x02,0x34,0x02,0x57,0x02,0x7A,0x02,0x9D,0x02,0xC0,0x02,0xE3,0x02,0x06,0x03, + 0x18,0x03,0x2A,0x03,0x4D,0x03,0x70,0x03,0x93,0x03,0xB6,0x03,0xD9,0x03,0xFC,0x03,0x1F,0x04, + 0x42,0x04,0x65,0x04,0x88,0x04,0xAB,0x04,0xCE,0x04,0xF1,0x04,0x03,0x05,0x15,0x05,0x38,0x05, + 0x5B,0x05,0x7E,0x05,0xA1,0x05,0xC4,0x05,0xE7,0x05,0x0A,0x06,0x2D,0x06,0x50,0x06,0x73,0x06, + 0x96,0x06,0xB9,0x06,0xDC,0x06,0xFF,0x06,0x22,0x07,0x45,0x07,0x57,0x07,0x7A,0x07,0x8C,0x07, + 0xAF,0x07,0xD2,0x07,0xF5,0x07,0x18,0x08,0x3B,0x08,0x4D,0x08,0x70,0x08,0x93,0x08,0xA5,0x08, + 0xC8,0x08,0xEB,0x08,0xFD,0x08,0x0F,0x09,0x32,0x09,0x44,0x09,0x67,0x09,0x8A,0x09,0xAD,0x09, + 0xD0,0x09,0xF3,0x09,0x05,0x0A,0x17,0x0A,0x29,0x0A,0x4C,0x0A,0x6F,0x0A,0x92,0x0A,0xB5,0x0A, + 0xD8,0x0A,0xEA,0x0A,0x0D,0x0B,0x1F,0x0B,0x42,0x0B,0x65,0x0B, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 8, // 0x22 '"' + 0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x40,0x04,0x40,0x3F,0xE0,0x3F,0xE0,0x08,0x80,0x11,0x00,0x7F,0xC0,0x7F,0xC0,0x22,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x34,0x80,0x64,0x00,0x74,0x00,0x3C,0x00,0x0F,0x00,0x0B,0x80,0x09,0x80,0x4B,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x00,0x00, + + 18, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x08,0x00,0x66,0x10,0x00,0x66,0x20,0x00,0x66,0x2F,0x00,0x66,0x59,0x80,0x66,0x99,0x80,0x3D,0x19,0x80,0x01,0x19,0x80,0x02,0x19,0x80,0x04,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x36,0x00,0x1C,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x31,0xC0,0x1F,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C, + + 8, // 0x29 ')' + 0x00,0x00,0x00,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30, + + 10, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x7F,0xC0,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0xC0,0xC0,0x00, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 10, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x3C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x01,0x80,0x0F,0x00,0x03,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x07,0x00,0x0B,0x00,0x13,0x00,0x23,0x00,0x43,0x00,0x7F,0xC0,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x30,0x00,0x30,0x00,0x3E,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x38,0x00,0x30,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x03,0x00,0x07,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x60,0x60,0x00, + + 12, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x40,0x01,0x80,0x06,0x00,0x18,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xC0,0x18,0x20,0x20,0x10,0x27,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 11, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x1B,0x00,0x31,0x80,0x3F,0x80,0x31,0x80,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x61,0x80,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x61,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x63,0xC0,0x60,0xC0,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x7F,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, + + 8, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, + + 11, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7C,0x00,0x76,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x70,0x70,0x70,0x70,0xF0,0x58,0xB0,0x59,0xB0,0x4D,0x30,0x4F,0x30,0x46,0x30,0x46,0x30,0x40,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x40,0x70,0x40,0x58,0x40,0x4C,0x40,0x4C,0x40,0x46,0x40,0x43,0x40,0x43,0x40,0x41,0xC0,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x63,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x30,0xC0,0x0F,0x80,0x03,0x00,0x03,0x00,0x01,0xE0, + + 11, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x63,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x61,0x80,0x60,0x00,0x3E,0x00,0x1F,0x00,0x01,0x80,0x61,0x80,0x63,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 16, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x32,0x4C,0x36,0x6C,0x36,0x6C,0x34,0x2C,0x1C,0x38,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5B '[' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, + + 10, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, + + 8, // 0x5D ']' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, + + 12, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00, + + 10, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, + + 10, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x63,0x00,0x7F,0x00,0x60,0x00,0x60,0x00,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, + + 10, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, + + 9, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x63,0x00,0x66,0x00,0x6C,0x00,0x78,0x00,0x7C,0x00,0x66,0x00,0x63,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 14, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x70,0x73,0x98,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x63,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 10, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x62,0x60,0x7C,0x3E,0x06,0x46,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x60,0x60,0xFC,0x60,0x60,0x60,0x60,0x60,0x60,0x3C,0x00,0x00,0x00, + + 10, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x33,0x30,0x37,0xB0,0x34,0xB0,0x1C,0xE0,0x1C,0xE0,0x0C,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x36,0x00,0x63,0x00,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x00,0x63,0x00,0x63,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x1C,0x00,0x1C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 8, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x06,0x0C,0x18,0x18,0x30,0x60,0x7E,0x00,0x00,0x00, + + 10, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + + 10, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x06,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x78,0x00, + + 12, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x46,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana18[] = + { + 18, 4, 32, 128-32, + 0x00,0x00,0x13,0x00,0x26,0x00,0x39,0x00,0x5E,0x00,0x83,0x00,0xA8,0x00,0xCD,0x00,0xE0,0x00, + 0xF3,0x00,0x06,0x01,0x2B,0x01,0x50,0x01,0x63,0x01,0x76,0x01,0x89,0x01,0x9C,0x01,0xC1,0x01, + 0xE6,0x01,0x0B,0x02,0x30,0x02,0x55,0x02,0x7A,0x02,0x9F,0x02,0xC4,0x02,0xE9,0x02,0x0E,0x03, + 0x21,0x03,0x34,0x03,0x59,0x03,0x7E,0x03,0xA3,0x03,0xB6,0x03,0xDB,0x03,0x00,0x04,0x25,0x04, + 0x4A,0x04,0x6F,0x04,0x94,0x04,0xB9,0x04,0xDE,0x04,0x03,0x05,0x16,0x05,0x29,0x05,0x4E,0x05, + 0x61,0x05,0x86,0x05,0xAB,0x05,0xD0,0x05,0xF5,0x05,0x1A,0x06,0x3F,0x06,0x64,0x06,0x89,0x06, + 0xAE,0x06,0xD3,0x06,0xF8,0x06,0x1D,0x07,0x42,0x07,0x67,0x07,0x7A,0x07,0x8D,0x07,0xA0,0x07, + 0xC5,0x07,0xEA,0x07,0x0F,0x08,0x34,0x08,0x59,0x08,0x6C,0x08,0x91,0x08,0xB6,0x08,0xC9,0x08, + 0xEE,0x08,0x13,0x09,0x26,0x09,0x39,0x09,0x5E,0x09,0x71,0x09,0x96,0x09,0xBB,0x09,0xE0,0x09, + 0x05,0x0A,0x2A,0x0A,0x3D,0x0A,0x50,0x0A,0x63,0x0A,0x88,0x0A,0xAD,0x0A,0xD2,0x0A,0xF7,0x0A, + 0x1C,0x0B,0x41,0x0B,0x66,0x0B,0x79,0x0B,0x9E,0x0B,0xC3,0x0B, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x22 '"' + 0x00,0x00,0x00,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x80,0x04,0x80,0x09,0x00,0x3F,0xC0,0x09,0x00,0x11,0x00,0x12,0x00,0x7F,0x80,0x12,0x00,0x24,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x3E,0x00,0x49,0x00,0x48,0x00,0x48,0x00,0x38,0x00,0x0E,0x00,0x09,0x00,0x09,0x00,0x49,0x00,0x3E,0x00,0x08,0x00,0x08,0x00,0x08,0x00, + + 16, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x20,0x44,0x40,0x44,0x40,0x44,0x80,0x44,0x80,0x38,0x9C,0x01,0x22,0x01,0x22,0x02,0x22,0x02,0x22,0x04,0x1C,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x21,0x00,0x21,0x00,0x1E,0x40,0x24,0x40,0x42,0x40,0x41,0x40,0x40,0x80,0x21,0x40,0x1E,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x27 ''' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x28 '(' + 0x00,0x00,0x00,0x08,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x20,0x10,0x08, + + 7, // 0x29 ')' + 0x00,0x00,0x00,0x20,0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x20, + + 10, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x00,0x2A,0x00,0x1C,0x00,0x2A,0x00,0x49,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x40,0x40, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00, + + 7, // 0x2F '/' + 0x00,0x00,0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00, + + 10, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1C,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x41,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x40,0x80,0x00,0x80,0x01,0x00,0x0E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x00,0x05,0x00,0x09,0x00,0x11,0x00,0x21,0x00,0x41,0x00,0x7F,0xC0,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x20,0x00,0x20,0x00,0x20,0x00,0x3E,0x00,0x01,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x41,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x20,0x80,0x1F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, + + 7, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x20,0x20, + + 12, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x3C,0x42,0x02,0x02,0x04,0x08,0x10,0x10,0x00,0x10,0x10,0x00,0x00,0x00, + + 15, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x23,0xD0,0x44,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0x44,0x48,0x23,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 10, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x7F,0x80,0x40,0x80,0x80,0x40,0x80,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x80,0x40,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x41,0x80,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x40,0x00,0x40,0x00,0x40,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x30,0x60,0x20,0x20,0x40,0x00,0x40,0x00,0x41,0xE0,0x40,0x20,0x40,0x20,0x20,0x20,0x30,0x20,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0xC0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00, + + 7, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3C,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0xF0,0x00,0x00,0x00, + + 10, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x41,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x00,0x00,0x00, + + 13, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x50,0x50,0x50,0x50,0x48,0x90,0x48,0x90,0x45,0x10,0x45,0x10,0x42,0x10,0x42,0x10,0x40,0x10,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x60,0x40,0x50,0x40,0x48,0x40,0x48,0x40,0x44,0x40,0x42,0x40,0x42,0x40,0x41,0x40,0x40,0xC0,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x41,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x41,0x00,0x7E,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x30,0xC0,0x20,0x40,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x20,0x40,0x30,0xC0,0x0F,0x00,0x01,0x00,0x01,0x00,0x00,0xE0, + + 10, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x42,0x00,0x41,0x00,0x40,0x80,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x20,0x80,0x40,0x00,0x40,0x00,0x20,0x00,0x1E,0x00,0x01,0x00,0x00,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x20,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0x80,0x40,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x04,0x41,0x04,0x22,0x88,0x22,0x88,0x22,0x88,0x12,0x90,0x14,0x50,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x21,0x00,0x21,0x00,0x12,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x12,0x00,0x21,0x00,0x21,0x00,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x41,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x00,0x80,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x5B '[' + 0x00,0x00,0x00,0x3C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3C, + + 7, // 0x5C '\' + 0x00,0x00,0x00,0x80,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x04,0x02,0x00, + + 7, // 0x5D ']' + 0x00,0x00,0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78, + + 12, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x09,0x00,0x10,0x80,0x20,0x40,0x40,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00, + + 10, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x01,0x00,0x3F,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x21,0x40,0x40,0x40,0x40,0x21,0x1E,0x00,0x00,0x00, + + 9, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x41,0x00,0x7F,0x00,0x40,0x00,0x40,0x00,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x20,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00, + + 9, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x22,0x00,0x1C,0x00, + + 9, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x69 'i' + 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 5, // 0x6A 'j' + 0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0, + + 9, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x42,0x00,0x44,0x00,0x48,0x00,0x50,0x00,0x68,0x00,0x44,0x00,0x42,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 3, // 0x6C 'l' + 0x00,0x00,0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 15, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2E,0x70,0x31,0x88,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5E,0x00,0x61,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x21,0x00,0x40,0x80,0x40,0x80,0x40,0x80,0x40,0x80,0x21,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x00,0x62,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x42,0x00,0x7C,0x00,0x40,0x00,0x40,0x00,0x40,0x00, + + 9, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x21,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x23,0x00,0x1D,0x00,0x01,0x00,0x01,0x00,0x01,0x00, + + 6, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5C,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00, + + 8, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x40,0x30,0x0C,0x02,0x42,0x3C,0x00,0x00,0x00, + + 6, // 0x74 't' + 0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x7C,0x20,0x20,0x20,0x20,0x20,0x20,0x1C,0x00,0x00,0x00, + + 9, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x41,0x00,0x43,0x00,0x3D,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x10,0x42,0x10,0x25,0x20,0x25,0x20,0x28,0xA0,0x28,0xA0,0x10,0x40,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x14,0x00,0x22,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x00,0x41,0x00,0x22,0x00,0x22,0x00,0x22,0x00,0x14,0x00,0x14,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x10,0x00, + + 9, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10,0x00,0x20,0x00,0x40,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0x60,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x07,0x00, + + 7, // 0x7C '|' + 0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + + 10, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x38,0x00, + + 12, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x20,0x24,0x20,0x42,0x40,0x41,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + + const int8u verdana18_bold[] = + { + 18, 4, 32, 128-32, + 0x00,0x00,0x13,0x00,0x26,0x00,0x4B,0x00,0x70,0x00,0x95,0x00,0xCC,0x00,0xF1,0x00,0x04,0x01, + 0x17,0x01,0x2A,0x01,0x4F,0x01,0x74,0x01,0x87,0x01,0x9A,0x01,0xAD,0x01,0xD2,0x01,0xF7,0x01, + 0x1C,0x02,0x41,0x02,0x66,0x02,0x8B,0x02,0xB0,0x02,0xD5,0x02,0xFA,0x02,0x1F,0x03,0x44,0x03, + 0x57,0x03,0x6A,0x03,0x8F,0x03,0xB4,0x03,0xD9,0x03,0xFE,0x03,0x23,0x04,0x48,0x04,0x6D,0x04, + 0x92,0x04,0xB7,0x04,0xDC,0x04,0x01,0x05,0x26,0x05,0x4B,0x05,0x5E,0x05,0x71,0x05,0x96,0x05, + 0xBB,0x05,0xE0,0x05,0x05,0x06,0x2A,0x06,0x4F,0x06,0x74,0x06,0x99,0x06,0xBE,0x06,0xE3,0x06, + 0x08,0x07,0x2D,0x07,0x52,0x07,0x77,0x07,0x9C,0x07,0xC1,0x07,0xD4,0x07,0xF9,0x07,0x0C,0x08, + 0x31,0x08,0x56,0x08,0x7B,0x08,0xA0,0x08,0xC5,0x08,0xD8,0x08,0xFD,0x08,0x22,0x09,0x35,0x09, + 0x5A,0x09,0x7F,0x09,0x92,0x09,0xA5,0x09,0xCA,0x09,0xDD,0x09,0x02,0x0A,0x27,0x0A,0x4C,0x0A, + 0x71,0x0A,0x96,0x0A,0xA9,0x0A,0xCE,0x0A,0xE1,0x0A,0x06,0x0B,0x2B,0x0B,0x50,0x0B,0x75,0x0B, + 0x9A,0x0B,0xBF,0x0B,0xE4,0x0B,0xF7,0x0B,0x1C,0x0C,0x41,0x0C, + + 5, // 0x20 ' ' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x21 '!' + 0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x30,0x30,0x00,0x00,0x00, + + 9, // 0x22 '"' + 0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x23 '#' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x20,0x04,0x20,0x08,0x40,0x3F,0xF0,0x3F,0xF0,0x08,0x40,0x10,0x80,0x7F,0xE0,0x7F,0xE0,0x21,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x24 '$' + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x1F,0x80,0x34,0xC0,0x64,0xC0,0x64,0x00,0x3C,0x00,0x07,0x80,0x04,0xC0,0x64,0xC0,0x65,0x80,0x3F,0x00,0x04,0x00,0x04,0x00,0x00,0x00, + + 19, // 0x25 '%' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x08,0x00,0x63,0x10,0x00,0x63,0x10,0x00,0x63,0x20,0x00,0x63,0x2F,0x80,0x63,0x58,0xC0,0x3E,0x98,0xC0,0x00,0x98,0xC0,0x01,0x18,0xC0,0x01,0x18,0xC0,0x02,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x26 '&' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x60,0x36,0x60,0x63,0x60,0x61,0xC0,0x60,0xC0,0x30,0xE0,0x1F,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x27 ''' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x28 '(' + 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x30,0x60,0x60,0x60,0x60,0x60,0x30,0x30,0x18,0x0C,0x06, + + 8, // 0x29 ')' + 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x30,0x60, + + 11, // 0x2A '*' + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x24,0x80,0x15,0x00,0x0E,0x00,0x15,0x00,0x24,0x80,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x2B '+' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x3F,0xE0,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2C ',' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x60,0x60,0x60,0xC0,0xC0, + + 7, // 0x2D '-' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 5, // 0x2E '.' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x2F '/' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x60,0x00,0x00,0x00, + + 11, // 0x30 '0' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x31 '1' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x1E,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x32 '2' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x33 '3' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x61,0x80,0x60,0xC0,0x00,0xC0,0x01,0x80,0x0F,0x00,0x01,0x80,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x34 '4' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x80,0x05,0x80,0x09,0x80,0x11,0x80,0x21,0x80,0x41,0x80,0x7F,0xE0,0x01,0x80,0x01,0x80,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x35 '5' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x30,0x00,0x30,0x00,0x30,0x00,0x3F,0x00,0x01,0x80,0x00,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x36 '6' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x18,0x00,0x30,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x37 '7' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0xC0,0x01,0x80,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x38 '8' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x39 '9' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x31,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0xC0,0x1E,0xC0,0x00,0xC0,0x01,0x80,0x03,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x3A ':' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x00, + + 6, // 0x3B ';' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x00,0x00,0x38,0x30,0x30,0x30,0x60,0x60, + + 13, // 0x3C '<' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x30,0x00,0x0C,0x00,0x03,0x00,0x00,0xC0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x3D '=' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x3E '>' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x18,0x00,0x06,0x00,0x01,0x80,0x00,0x60,0x00,0x60,0x01,0x80,0x06,0x00,0x18,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 9, // 0x3F '?' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x63,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x40 '@' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x18,0x60,0x20,0x10,0x27,0xD0,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x4C,0xC8,0x27,0xF0,0x20,0x00,0x18,0x00,0x07,0xC0,0x00,0x00, + + 12, // 0x41 'A' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x0F,0x00,0x0F,0x00,0x19,0x80,0x19,0x80,0x30,0xC0,0x3F,0xC0,0x30,0xC0,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x42 'B' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x43 'C' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xC0,0x30,0xC0,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x30,0xC0,0x38,0xC0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x44 'D' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0xC0,0x60,0xC0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x61,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x45 'E' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x46 'F' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x47 'G' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x38,0x60,0x30,0x60,0x60,0x00,0x60,0x00,0x63,0xE0,0x60,0x60,0x60,0x60,0x30,0x60,0x38,0x60,0x0F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x48 'H' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7F,0xE0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x49 'I' + 0x00,0x00,0x00,0x00,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00, + + 8, // 0x4A 'J' + 0x00,0x00,0x00,0x00,0x3E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0C,0xF8,0x00,0x00,0x00, + + 12, // 0x4B 'K' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0xC0,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x4C 'L' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x4D 'M' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x38,0x70,0x38,0x70,0x78,0x58,0x58,0x58,0xD8,0x4C,0x98,0x4D,0x98,0x47,0x18,0x47,0x18,0x42,0x18,0x40,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x4E 'N' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x20,0x70,0x20,0x58,0x20,0x4C,0x20,0x4C,0x20,0x46,0x20,0x43,0x20,0x43,0x20,0x41,0xA0,0x40,0xE0,0x40,0xE0,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x4F 'O' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x50 'P' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 13, // 0x51 'Q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x38,0xE0,0x30,0x60,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x30,0x60,0x38,0xE0,0x0F,0x80,0x03,0x00,0x03,0x80,0x01,0xF0, + + 12, // 0x52 'R' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x61,0x80,0x60,0xC0,0x60,0x60,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x53 'S' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x30,0xC0,0x60,0xC0,0x60,0x00,0x7C,0x00,0x3F,0x80,0x03,0xC0,0x00,0xC0,0x60,0xC0,0x61,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x54 'T' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 12, // 0x55 'U' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0xC0,0x1F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x56 'V' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x60,0xC0,0x60,0xC0,0x31,0x80,0x31,0x80,0x31,0x80,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 16, // 0x57 'W' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x86,0x61,0x86,0x63,0xC6,0x33,0xCC,0x32,0x4C,0x32,0x4C,0x1E,0x78,0x1C,0x38,0x1C,0x38,0x0C,0x30,0x0C,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x58 'X' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xC0,0x31,0x80,0x31,0x80,0x1B,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x1B,0x00,0x31,0x80,0x31,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x59 'Y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x5A 'Z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x80,0x01,0x80,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x5B '[' + 0x00,0x00,0x00,0x3E,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3E, + + 10, // 0x5C '\' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0x00, + + 8, // 0x5D ']' + 0x00,0x00,0x00,0x7C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C, + + 13, // 0x5E '^' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0F,0x00,0x19,0x80,0x30,0xC0,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x5F '_' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xE0,0x00,0x00, + + 11, // 0x60 '`' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x61 'a' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00,0x01,0x80,0x01,0x80,0x3F,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x62 'b' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 8, // 0x63 'c' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x33,0x60,0x60,0x60,0x60,0x33,0x1E,0x00,0x00,0x00, + + 10, // 0x64 'd' + 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x65 'e' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x7F,0x80,0x60,0x00,0x60,0x00,0x31,0x80,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 6, // 0x66 'f' + 0x00,0x00,0x00,0x1C,0x30,0x30,0x30,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, + + 10, // 0x67 'g' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x03,0x00,0x3E,0x00, + + 10, // 0x68 'h' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x69 'i' + 0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 6, // 0x6A 'j' + 0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF0, + + 10, // 0x6B 'k' + 0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x61,0x80,0x63,0x00,0x66,0x00,0x6C,0x00,0x7E,0x00,0x73,0x00,0x61,0x80,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00, + + 4, // 0x6C 'l' + 0x00,0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 16, // 0x6D 'm' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x3C,0x71,0xC6,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6E 'n' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0x00,0x71,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x6F 'o' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x00,0x33,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x70 'p' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x00,0x73,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x00,0x7E,0x00,0x60,0x00,0x60,0x00,0x60,0x00, + + 10, // 0x71 'q' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x33,0x80,0x1D,0x80,0x01,0x80,0x01,0x80,0x01,0x80, + + 7, // 0x72 'r' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x7E,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00, + + 9, // 0x73 's' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x61,0x00,0x60,0x00,0x7E,0x00,0x3F,0x00,0x03,0x00,0x43,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 7, // 0x74 't' + 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x7E,0x30,0x30,0x30,0x30,0x30,0x30,0x1E,0x00,0x00,0x00, + + 10, // 0x75 'u' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x61,0x80,0x63,0x80,0x3D,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x76 'v' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 14, // 0x77 'w' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x18,0x63,0x18,0x63,0x18,0x37,0xB0,0x34,0xB0,0x3C,0xF0,0x18,0x60,0x18,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x78 'x' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x33,0x00,0x33,0x00,0x61,0x80,0x00,0x00,0x00,0x00,0x00,0x00, + + 10, // 0x79 'y' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x80,0x61,0x80,0x33,0x00,0x33,0x00,0x33,0x00,0x1E,0x00,0x1E,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00, + + 9, // 0x7A 'z' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 11, // 0x7B '{' + 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x80,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x70,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x07,0x80, + + 8, // 0x7C '|' + 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + + 11, // 0x7D '}' + 0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x01,0xC0,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3C,0x00, + + 13, // 0x7E '~' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x10,0x24,0x10,0x42,0x10,0x41,0x20,0x40,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + + 15, // 0x7F '' + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00, + + 0 + }; + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_gsv_text.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_gsv_text.cpp new file mode 100644 index 00000000000..ffb24eb9b63 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_gsv_text.cpp @@ -0,0 +1,675 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Class gsv_text +// +//---------------------------------------------------------------------------- +#include +#include +#include "agg_gsv_text.h" +#include "agg_bounding_rect.h" + + + +namespace agg +{ + int8u gsv_default_font[] = + { + 0x40,0x00,0x6c,0x0f,0x15,0x00,0x0e,0x00,0xf9,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0d,0x0a,0x0d,0x0a,0x46,0x6f,0x6e,0x74,0x20,0x28, + 0x63,0x29,0x20,0x4d,0x69,0x63,0x72,0x6f,0x50,0x72, + 0x6f,0x66,0x20,0x32,0x37,0x20,0x53,0x65,0x70,0x74, + 0x65,0x6d,0x62,0x2e,0x31,0x39,0x38,0x39,0x00,0x0d, + 0x0a,0x0d,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x00,0x12,0x00,0x34,0x00,0x46,0x00,0x94,0x00, + 0xd0,0x00,0x2e,0x01,0x3e,0x01,0x64,0x01,0x8a,0x01, + 0x98,0x01,0xa2,0x01,0xb4,0x01,0xba,0x01,0xc6,0x01, + 0xcc,0x01,0xf0,0x01,0xfa,0x01,0x18,0x02,0x38,0x02, + 0x44,0x02,0x68,0x02,0x98,0x02,0xa2,0x02,0xde,0x02, + 0x0e,0x03,0x24,0x03,0x40,0x03,0x48,0x03,0x52,0x03, + 0x5a,0x03,0x82,0x03,0xec,0x03,0xfa,0x03,0x26,0x04, + 0x4c,0x04,0x6a,0x04,0x7c,0x04,0x8a,0x04,0xb6,0x04, + 0xc4,0x04,0xca,0x04,0xe0,0x04,0xee,0x04,0xf8,0x04, + 0x0a,0x05,0x18,0x05,0x44,0x05,0x5e,0x05,0x8e,0x05, + 0xac,0x05,0xd6,0x05,0xe0,0x05,0xf6,0x05,0x00,0x06, + 0x12,0x06,0x1c,0x06,0x28,0x06,0x36,0x06,0x48,0x06, + 0x4e,0x06,0x60,0x06,0x6e,0x06,0x74,0x06,0x84,0x06, + 0xa6,0x06,0xc8,0x06,0xe6,0x06,0x08,0x07,0x2c,0x07, + 0x3c,0x07,0x68,0x07,0x7c,0x07,0x8c,0x07,0xa2,0x07, + 0xb0,0x07,0xb6,0x07,0xd8,0x07,0xec,0x07,0x10,0x08, + 0x32,0x08,0x54,0x08,0x64,0x08,0x88,0x08,0x98,0x08, + 0xac,0x08,0xb6,0x08,0xc8,0x08,0xd2,0x08,0xe4,0x08, + 0xf2,0x08,0x3e,0x09,0x48,0x09,0x94,0x09,0xc2,0x09, + 0xc4,0x09,0xd0,0x09,0xe2,0x09,0x04,0x0a,0x0e,0x0a, + 0x26,0x0a,0x34,0x0a,0x4a,0x0a,0x66,0x0a,0x70,0x0a, + 0x7e,0x0a,0x8e,0x0a,0x9a,0x0a,0xa6,0x0a,0xb4,0x0a, + 0xd8,0x0a,0xe2,0x0a,0xf6,0x0a,0x18,0x0b,0x22,0x0b, + 0x32,0x0b,0x56,0x0b,0x60,0x0b,0x6e,0x0b,0x7c,0x0b, + 0x8a,0x0b,0x9c,0x0b,0x9e,0x0b,0xb2,0x0b,0xc2,0x0b, + 0xd8,0x0b,0xf4,0x0b,0x08,0x0c,0x30,0x0c,0x56,0x0c, + 0x72,0x0c,0x90,0x0c,0xb2,0x0c,0xce,0x0c,0xe2,0x0c, + 0xfe,0x0c,0x10,0x0d,0x26,0x0d,0x36,0x0d,0x42,0x0d, + 0x4e,0x0d,0x5c,0x0d,0x78,0x0d,0x8c,0x0d,0x8e,0x0d, + 0x90,0x0d,0x92,0x0d,0x94,0x0d,0x96,0x0d,0x98,0x0d, + 0x9a,0x0d,0x9c,0x0d,0x9e,0x0d,0xa0,0x0d,0xa2,0x0d, + 0xa4,0x0d,0xa6,0x0d,0xa8,0x0d,0xaa,0x0d,0xac,0x0d, + 0xae,0x0d,0xb0,0x0d,0xb2,0x0d,0xb4,0x0d,0xb6,0x0d, + 0xb8,0x0d,0xba,0x0d,0xbc,0x0d,0xbe,0x0d,0xc0,0x0d, + 0xc2,0x0d,0xc4,0x0d,0xc6,0x0d,0xc8,0x0d,0xca,0x0d, + 0xcc,0x0d,0xce,0x0d,0xd0,0x0d,0xd2,0x0d,0xd4,0x0d, + 0xd6,0x0d,0xd8,0x0d,0xda,0x0d,0xdc,0x0d,0xde,0x0d, + 0xe0,0x0d,0xe2,0x0d,0xe4,0x0d,0xe6,0x0d,0xe8,0x0d, + 0xea,0x0d,0xec,0x0d,0x0c,0x0e,0x26,0x0e,0x48,0x0e, + 0x64,0x0e,0x88,0x0e,0x92,0x0e,0xa6,0x0e,0xb4,0x0e, + 0xd0,0x0e,0xee,0x0e,0x02,0x0f,0x16,0x0f,0x26,0x0f, + 0x3c,0x0f,0x58,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f, + 0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x6c,0x0f,0x10,0x80, + 0x05,0x95,0x00,0x72,0x00,0xfb,0xff,0x7f,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x05,0xfe,0x05,0x95,0xff,0x7f, + 0x00,0x7a,0x01,0x86,0xff,0x7a,0x01,0x87,0x01,0x7f, + 0xfe,0x7a,0x0a,0x87,0xff,0x7f,0x00,0x7a,0x01,0x86, + 0xff,0x7a,0x01,0x87,0x01,0x7f,0xfe,0x7a,0x05,0xf2, + 0x0b,0x95,0xf9,0x64,0x0d,0x9c,0xf9,0x64,0xfa,0x91, + 0x0e,0x00,0xf1,0xfa,0x0e,0x00,0x04,0xfc,0x08,0x99, + 0x00,0x63,0x04,0x9d,0x00,0x63,0x04,0x96,0xff,0x7f, + 0x01,0x7f,0x01,0x01,0x00,0x01,0xfe,0x02,0xfd,0x01, + 0xfc,0x00,0xfd,0x7f,0xfe,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x02,0x7f,0x06,0x7e,0x02,0x7f,0x02,0x7e, + 0xf2,0x89,0x02,0x7e,0x02,0x7f,0x06,0x7e,0x02,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7c,0xfe,0x7e,0xfd,0x7f, + 0xfc,0x00,0xfd,0x01,0xfe,0x02,0x00,0x01,0x01,0x01, + 0x01,0x7f,0xff,0x7f,0x10,0xfd,0x15,0x95,0xee,0x6b, + 0x05,0x95,0x02,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7f, + 0xfe,0x00,0xfe,0x02,0x00,0x02,0x01,0x02,0x02,0x01, + 0x02,0x00,0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01, + 0x02,0x01,0xfc,0xf2,0xfe,0x7f,0xff,0x7e,0x00,0x7e, + 0x02,0x7e,0x02,0x00,0x02,0x01,0x01,0x02,0x00,0x02, + 0xfe,0x02,0xfe,0x00,0x07,0xf9,0x15,0x8d,0xff,0x7f, + 0x01,0x7f,0x01,0x01,0x00,0x01,0xff,0x01,0xff,0x00, + 0xff,0x7f,0xff,0x7e,0xfe,0x7b,0xfe,0x7d,0xfe,0x7e, + 0xfe,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02,0x00,0x03, + 0x01,0x02,0x06,0x04,0x02,0x02,0x01,0x02,0x00,0x02, + 0xff,0x02,0xfe,0x01,0xfe,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7d,0x02,0x7d,0x05,0x79,0x02,0x7e,0x03,0x7f, + 0x01,0x00,0x01,0x01,0x00,0x01,0xf1,0xfe,0xfe,0x01, + 0xff,0x02,0x00,0x03,0x01,0x02,0x02,0x02,0x00,0x86, + 0x01,0x7e,0x08,0x75,0x02,0x7e,0x02,0x7f,0x05,0x80, + 0x05,0x93,0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e, + 0xff,0x7e,0xff,0x7f,0x06,0xf1,0x0b,0x99,0xfe,0x7e, + 0xfe,0x7d,0xfe,0x7c,0xff,0x7b,0x00,0x7c,0x01,0x7b, + 0x02,0x7c,0x02,0x7d,0x02,0x7e,0xfe,0x9e,0xfe,0x7c, + 0xff,0x7d,0xff,0x7b,0x00,0x7c,0x01,0x7b,0x01,0x7d, + 0x02,0x7c,0x05,0x85,0x03,0x99,0x02,0x7e,0x02,0x7d, + 0x02,0x7c,0x01,0x7b,0x00,0x7c,0xff,0x7b,0xfe,0x7c, + 0xfe,0x7d,0xfe,0x7e,0x02,0x9e,0x02,0x7c,0x01,0x7d, + 0x01,0x7b,0x00,0x7c,0xff,0x7b,0xff,0x7d,0xfe,0x7c, + 0x09,0x85,0x08,0x95,0x00,0x74,0xfb,0x89,0x0a,0x7a, + 0x00,0x86,0xf6,0x7a,0x0d,0xf4,0x0d,0x92,0x00,0x6e, + 0xf7,0x89,0x12,0x00,0x04,0xf7,0x06,0x81,0xff,0x7f, + 0xff,0x01,0x01,0x01,0x01,0x7f,0x00,0x7e,0xff,0x7e, + 0xff,0x7f,0x06,0x84,0x04,0x89,0x12,0x00,0x04,0xf7, + 0x05,0x82,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x05,0xfe,0x00,0xfd,0x0e,0x18,0x00,0xeb,0x09,0x95, + 0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7d,0x01,0x7b, + 0x02,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x03, + 0x01,0x05,0x00,0x03,0xff,0x05,0xfe,0x03,0xfd,0x01, + 0xfe,0x00,0x0b,0xeb,0x06,0x91,0x02,0x01,0x03,0x03, + 0x00,0x6b,0x09,0x80,0x04,0x90,0x00,0x01,0x01,0x02, + 0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7f, + 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xfe,0x7d,0xf6,0x76, + 0x0e,0x00,0x03,0x80,0x05,0x95,0x0b,0x00,0xfa,0x78, + 0x03,0x00,0x02,0x7f,0x01,0x7f,0x01,0x7d,0x00,0x7e, + 0xff,0x7d,0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01, + 0xff,0x01,0xff,0x02,0x11,0xfc,0x0d,0x95,0xf6,0x72, + 0x0f,0x00,0xfb,0x8e,0x00,0x6b,0x07,0x80,0x0f,0x95, + 0xf6,0x00,0xff,0x77,0x01,0x01,0x03,0x01,0x03,0x00, + 0x03,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e,0xff,0x7d, + 0xfe,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x01, + 0xff,0x02,0x11,0xfc,0x10,0x92,0xff,0x02,0xfd,0x01, + 0xfe,0x00,0xfd,0x7f,0xfe,0x7d,0xff,0x7b,0x00,0x7b, + 0x01,0x7c,0x02,0x7e,0x03,0x7f,0x01,0x00,0x03,0x01, + 0x02,0x02,0x01,0x03,0x00,0x01,0xff,0x03,0xfe,0x02, + 0xfd,0x01,0xff,0x00,0xfd,0x7f,0xfe,0x7e,0xff,0x7d, + 0x10,0xf9,0x11,0x95,0xf6,0x6b,0xfc,0x95,0x0e,0x00, + 0x03,0xeb,0x08,0x95,0xfd,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7e,0x02,0x7f,0x04,0x7f,0x03,0x7f,0x02,0x7e, + 0x01,0x7e,0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f, + 0xfc,0x00,0xfd,0x01,0xff,0x01,0xff,0x02,0x00,0x03, + 0x01,0x02,0x02,0x02,0x03,0x01,0x04,0x01,0x02,0x01, + 0x01,0x02,0x00,0x02,0xff,0x02,0xfd,0x01,0xfc,0x00, + 0x0c,0xeb,0x10,0x8e,0xff,0x7d,0xfe,0x7e,0xfd,0x7f, + 0xff,0x00,0xfd,0x01,0xfe,0x02,0xff,0x03,0x00,0x01, + 0x01,0x03,0x02,0x02,0x03,0x01,0x01,0x00,0x03,0x7f, + 0x02,0x7e,0x01,0x7c,0x00,0x7b,0xff,0x7b,0xfe,0x7d, + 0xfd,0x7f,0xfe,0x00,0xfd,0x01,0xff,0x02,0x10,0xfd, + 0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x00,0xf4,0xff,0x7f,0x01,0x7f,0x01,0x01,0xff,0x01, + 0x05,0xfe,0x05,0x8e,0xff,0x7f,0x01,0x7f,0x01,0x01, + 0xff,0x01,0x01,0xf3,0xff,0x7f,0xff,0x01,0x01,0x01, + 0x01,0x7f,0x00,0x7e,0xff,0x7e,0xff,0x7f,0x06,0x84, + 0x14,0x92,0xf0,0x77,0x10,0x77,0x04,0x80,0x04,0x8c, + 0x12,0x00,0xee,0xfa,0x12,0x00,0x04,0xfa,0x04,0x92, + 0x10,0x77,0xf0,0x77,0x14,0x80,0x03,0x90,0x00,0x01, + 0x01,0x02,0x01,0x01,0x02,0x01,0x04,0x00,0x02,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, + 0xfc,0x7e,0x00,0x7d,0x00,0xfb,0xff,0x7f,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x09,0xfe,0x12,0x8d,0xff,0x02, + 0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xff,0x7f,0xff,0x7d, + 0x00,0x7d,0x01,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x01,0x02,0xfb,0x88,0xfe,0x7e,0xff,0x7d,0x00,0x7d, + 0x01,0x7e,0x01,0x7f,0x07,0x8b,0xff,0x78,0x00,0x7e, + 0x02,0x7f,0x02,0x00,0x02,0x02,0x01,0x03,0x00,0x02, + 0xff,0x03,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfd,0x01, + 0xfd,0x00,0xfd,0x7f,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7d,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x03,0x7f,0x03,0x00,0x03,0x01,0x02,0x01, + 0x01,0x01,0xfe,0x8d,0xff,0x78,0x00,0x7e,0x01,0x7f, + 0x08,0xfb,0x09,0x95,0xf8,0x6b,0x08,0x95,0x08,0x6b, + 0xf3,0x87,0x0a,0x00,0x04,0xf9,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x80, + 0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, + 0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00,0x11,0x80, + 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, + 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, + 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, + 0x02,0x01,0x02,0x02,0x01,0x02,0x03,0xfb,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x07,0x00,0x03,0x7f,0x02,0x7e, + 0x01,0x7e,0x01,0x7d,0x00,0x7b,0xff,0x7d,0xff,0x7e, + 0xfe,0x7e,0xfd,0x7f,0xf9,0x00,0x11,0x80,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00, + 0xf8,0xf5,0x0d,0x00,0x02,0x80,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x0d,0x00,0xf3,0xf6,0x08,0x00,0x06,0xf5, + 0x12,0x90,0xff,0x02,0xfe,0x02,0xfe,0x01,0xfc,0x00, + 0xfe,0x7f,0xfe,0x7e,0xff,0x7e,0xff,0x7d,0x00,0x7b, + 0x01,0x7d,0x01,0x7e,0x02,0x7e,0x02,0x7f,0x04,0x00, + 0x02,0x01,0x02,0x02,0x01,0x02,0x00,0x03,0xfb,0x80, + 0x05,0x00,0x03,0xf8,0x04,0x95,0x00,0x6b,0x0e,0x95, + 0x00,0x6b,0xf2,0x8b,0x0e,0x00,0x04,0xf5,0x04,0x95, + 0x00,0x6b,0x04,0x80,0x0c,0x95,0x00,0x70,0xff,0x7d, + 0xff,0x7f,0xfe,0x7f,0xfe,0x00,0xfe,0x01,0xff,0x01, + 0xff,0x03,0x00,0x02,0x0e,0xf9,0x04,0x95,0x00,0x6b, + 0x0e,0x95,0xf2,0x72,0x05,0x85,0x09,0x74,0x03,0x80, + 0x04,0x95,0x00,0x6b,0x00,0x80,0x0c,0x00,0x01,0x80, + 0x04,0x95,0x00,0x6b,0x00,0x95,0x08,0x6b,0x08,0x95, + 0xf8,0x6b,0x08,0x95,0x00,0x6b,0x04,0x80,0x04,0x95, + 0x00,0x6b,0x00,0x95,0x0e,0x6b,0x00,0x95,0x00,0x6b, + 0x04,0x80,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, + 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, + 0xfe,0x01,0xfc,0x00,0x0d,0xeb,0x04,0x95,0x00,0x6b, + 0x00,0x95,0x09,0x00,0x03,0x7f,0x01,0x7f,0x01,0x7e, + 0x00,0x7d,0xff,0x7e,0xff,0x7f,0xfd,0x7f,0xf7,0x00, + 0x11,0xf6,0x09,0x95,0xfe,0x7f,0xfe,0x7e,0xff,0x7e, + 0xff,0x7d,0x00,0x7b,0x01,0x7d,0x01,0x7e,0x02,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x02,0x02,0x01,0x02, + 0x01,0x03,0x00,0x05,0xff,0x03,0xff,0x02,0xfe,0x02, + 0xfe,0x01,0xfc,0x00,0x03,0xef,0x06,0x7a,0x04,0x82, + 0x04,0x95,0x00,0x6b,0x00,0x95,0x09,0x00,0x03,0x7f, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f, + 0xfd,0x7f,0xf7,0x00,0x07,0x80,0x07,0x75,0x03,0x80, + 0x11,0x92,0xfe,0x02,0xfd,0x01,0xfc,0x00,0xfd,0x7f, + 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x02,0x7f, + 0x06,0x7e,0x02,0x7f,0x01,0x7f,0x01,0x7e,0x00,0x7d, + 0xfe,0x7e,0xfd,0x7f,0xfc,0x00,0xfd,0x01,0xfe,0x02, + 0x11,0xfd,0x08,0x95,0x00,0x6b,0xf9,0x95,0x0e,0x00, + 0x01,0xeb,0x04,0x95,0x00,0x71,0x01,0x7d,0x02,0x7e, + 0x03,0x7f,0x02,0x00,0x03,0x01,0x02,0x02,0x01,0x03, + 0x00,0x0f,0x04,0xeb,0x01,0x95,0x08,0x6b,0x08,0x95, + 0xf8,0x6b,0x09,0x80,0x02,0x95,0x05,0x6b,0x05,0x95, + 0xfb,0x6b,0x05,0x95,0x05,0x6b,0x05,0x95,0xfb,0x6b, + 0x07,0x80,0x03,0x95,0x0e,0x6b,0x00,0x95,0xf2,0x6b, + 0x11,0x80,0x01,0x95,0x08,0x76,0x00,0x75,0x08,0x95, + 0xf8,0x76,0x09,0xf5,0x11,0x95,0xf2,0x6b,0x00,0x95, + 0x0e,0x00,0xf2,0xeb,0x0e,0x00,0x03,0x80,0x03,0x93, + 0x00,0x6c,0x01,0x94,0x00,0x6c,0xff,0x94,0x05,0x00, + 0xfb,0xec,0x05,0x00,0x02,0x81,0x00,0x95,0x0e,0x68, + 0x00,0x83,0x06,0x93,0x00,0x6c,0x01,0x94,0x00,0x6c, + 0xfb,0x94,0x05,0x00,0xfb,0xec,0x05,0x00,0x03,0x81, + 0x03,0x87,0x08,0x05,0x08,0x7b,0xf0,0x80,0x08,0x04, + 0x08,0x7c,0x03,0xf9,0x01,0x80,0x10,0x00,0x01,0x80, + 0x06,0x95,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7f, + 0x01,0x01,0xff,0x01,0x05,0xef,0x0f,0x8e,0x00,0x72, + 0x00,0x8b,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, + 0x04,0x95,0x00,0x6b,0x00,0x8b,0x02,0x02,0x02,0x01, + 0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d,0x00,0x7e, + 0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00,0xfe,0x01, + 0xfe,0x02,0x0f,0xfd,0x0f,0x8b,0xfe,0x02,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x03,0xfd,0x0f,0x95,0x00,0x6b,0x00,0x8b, + 0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f,0xfe,0x7e, + 0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e,0x02,0x7f, + 0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd,0x03,0x88, + 0x0c,0x00,0x00,0x02,0xff,0x02,0xff,0x01,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x03,0xfd,0x0a,0x95,0xfe,0x00,0xfe,0x7f, + 0xff,0x7d,0x00,0x6f,0xfd,0x8e,0x07,0x00,0x03,0xf2, + 0x0f,0x8e,0x00,0x70,0xff,0x7d,0xff,0x7f,0xfe,0x7f, + 0xfd,0x00,0xfe,0x01,0x09,0x91,0xfe,0x02,0xfe,0x01, + 0xfd,0x00,0xfe,0x7f,0xfe,0x7e,0xff,0x7d,0x00,0x7e, + 0x01,0x7d,0x02,0x7e,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x02,0x02,0x04,0xfd,0x04,0x95,0x00,0x6b,0x00,0x8a, + 0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d, + 0x00,0x76,0x04,0x80,0x03,0x95,0x01,0x7f,0x01,0x01, + 0xff,0x01,0xff,0x7f,0x01,0xf9,0x00,0x72,0x04,0x80, + 0x05,0x95,0x01,0x7f,0x01,0x01,0xff,0x01,0xff,0x7f, + 0x01,0xf9,0x00,0x6f,0xff,0x7d,0xfe,0x7f,0xfe,0x00, + 0x09,0x87,0x04,0x95,0x00,0x6b,0x0a,0x8e,0xf6,0x76, + 0x04,0x84,0x07,0x78,0x02,0x80,0x04,0x95,0x00,0x6b, + 0x04,0x80,0x04,0x8e,0x00,0x72,0x00,0x8a,0x03,0x03, + 0x02,0x01,0x03,0x00,0x02,0x7f,0x01,0x7d,0x00,0x76, + 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, + 0x01,0x7d,0x00,0x76,0x04,0x80,0x04,0x8e,0x00,0x72, + 0x00,0x8a,0x03,0x03,0x02,0x01,0x03,0x00,0x02,0x7f, + 0x01,0x7d,0x00,0x76,0x04,0x80,0x08,0x8e,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x01,0x03, + 0x00,0x02,0xff,0x03,0xfe,0x02,0xfe,0x01,0xfd,0x00, + 0x0b,0xf2,0x04,0x8e,0x00,0x6b,0x00,0x92,0x02,0x02, + 0x02,0x01,0x03,0x00,0x02,0x7f,0x02,0x7e,0x01,0x7d, + 0x00,0x7e,0xff,0x7d,0xfe,0x7e,0xfe,0x7f,0xfd,0x00, + 0xfe,0x01,0xfe,0x02,0x0f,0xfd,0x0f,0x8e,0x00,0x6b, + 0x00,0x92,0xfe,0x02,0xfe,0x01,0xfd,0x00,0xfe,0x7f, + 0xfe,0x7e,0xff,0x7d,0x00,0x7e,0x01,0x7d,0x02,0x7e, + 0x02,0x7f,0x03,0x00,0x02,0x01,0x02,0x02,0x04,0xfd, + 0x04,0x8e,0x00,0x72,0x00,0x88,0x01,0x03,0x02,0x02, + 0x02,0x01,0x03,0x00,0x01,0xf2,0x0e,0x8b,0xff,0x02, + 0xfd,0x01,0xfd,0x00,0xfd,0x7f,0xff,0x7e,0x01,0x7e, + 0x02,0x7f,0x05,0x7f,0x02,0x7f,0x01,0x7e,0x00,0x7f, + 0xff,0x7e,0xfd,0x7f,0xfd,0x00,0xfd,0x01,0xff,0x02, + 0x0e,0xfd,0x05,0x95,0x00,0x6f,0x01,0x7d,0x02,0x7f, + 0x02,0x00,0xf8,0x8e,0x07,0x00,0x03,0xf2,0x04,0x8e, + 0x00,0x76,0x01,0x7d,0x02,0x7f,0x03,0x00,0x02,0x01, + 0x03,0x03,0x00,0x8a,0x00,0x72,0x04,0x80,0x02,0x8e, + 0x06,0x72,0x06,0x8e,0xfa,0x72,0x08,0x80,0x03,0x8e, + 0x04,0x72,0x04,0x8e,0xfc,0x72,0x04,0x8e,0x04,0x72, + 0x04,0x8e,0xfc,0x72,0x07,0x80,0x03,0x8e,0x0b,0x72, + 0x00,0x8e,0xf5,0x72,0x0e,0x80,0x02,0x8e,0x06,0x72, + 0x06,0x8e,0xfa,0x72,0xfe,0x7c,0xfe,0x7e,0xfe,0x7f, + 0xff,0x00,0x0f,0x87,0x0e,0x8e,0xf5,0x72,0x00,0x8e, + 0x0b,0x00,0xf5,0xf2,0x0b,0x00,0x03,0x80,0x09,0x99, + 0xfe,0x7f,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xfe,0x7e,0x01,0x8e, + 0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xfc,0x7e,0x04,0x7e,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e, + 0x01,0x7e,0xff,0x8e,0x02,0x7e,0x00,0x7e,0xff,0x7e, + 0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f, + 0x02,0x7f,0x05,0x87,0x04,0x95,0x00,0x77,0x00,0xfd, + 0x00,0x77,0x04,0x80,0x05,0x99,0x02,0x7f,0x01,0x7f, + 0x01,0x7e,0x00,0x7e,0xff,0x7e,0xff,0x7f,0xff,0x7e, + 0x00,0x7e,0x02,0x7e,0xff,0x8e,0x01,0x7e,0x00,0x7e, + 0xff,0x7e,0xff,0x7f,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x04,0x7e,0xfc,0x7e,0xff,0x7e,0x00,0x7e,0x01,0x7e, + 0x01,0x7f,0x01,0x7e,0x00,0x7e,0xff,0x7e,0x01,0x8e, + 0xfe,0x7e,0x00,0x7e,0x01,0x7e,0x01,0x7f,0x01,0x7e, + 0x00,0x7e,0xff,0x7e,0xff,0x7f,0xfe,0x7f,0x09,0x87, + 0x03,0x86,0x00,0x02,0x01,0x03,0x02,0x01,0x02,0x00, + 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, + 0x01,0x02,0xee,0xfe,0x01,0x02,0x02,0x01,0x02,0x00, + 0x02,0x7f,0x04,0x7d,0x02,0x7f,0x02,0x00,0x02,0x01, + 0x01,0x03,0x00,0x02,0x03,0xf4,0x10,0x80,0x03,0x80, + 0x07,0x15,0x08,0x6b,0xfe,0x85,0xf5,0x00,0x10,0xfb, + 0x0d,0x95,0xf6,0x00,0x00,0x6b,0x0a,0x00,0x02,0x02, + 0x00,0x08,0xfe,0x02,0xf6,0x00,0x0e,0xf4,0x03,0x80, + 0x00,0x15,0x0a,0x00,0x02,0x7e,0x00,0x7e,0x00,0x7d, + 0x00,0x7e,0xfe,0x7f,0xf6,0x00,0x0a,0x80,0x02,0x7e, + 0x01,0x7e,0x00,0x7d,0xff,0x7d,0xfe,0x7f,0xf6,0x00, + 0x10,0x80,0x03,0x80,0x00,0x15,0x0c,0x00,0xff,0x7e, + 0x03,0xed,0x03,0xfd,0x00,0x03,0x02,0x00,0x00,0x12, + 0x02,0x03,0x0a,0x00,0x00,0x6b,0x02,0x00,0x00,0x7d, + 0xfe,0x83,0xf4,0x00,0x11,0x80,0x0f,0x80,0xf4,0x00, + 0x00,0x15,0x0c,0x00,0xff,0xf6,0xf5,0x00,0x0f,0xf5, + 0x04,0x95,0x07,0x76,0x00,0x0a,0x07,0x80,0xf9,0x76, + 0x00,0x75,0xf8,0x80,0x07,0x0c,0x09,0xf4,0xf9,0x0c, + 0x09,0xf4,0x03,0x92,0x02,0x03,0x07,0x00,0x03,0x7d, + 0x00,0x7b,0xfc,0x7e,0x04,0x7d,0x00,0x7a,0xfd,0x7e, + 0xf9,0x00,0xfe,0x02,0x06,0x89,0x02,0x00,0x06,0xf5, + 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0x02,0x80, + 0x03,0x95,0x00,0x6b,0x0c,0x15,0x00,0x6b,0xf8,0x96, + 0x03,0x00,0x07,0xea,0x03,0x80,0x00,0x15,0x0c,0x80, + 0xf7,0x76,0xfd,0x00,0x03,0x80,0x0a,0x75,0x03,0x80, + 0x03,0x80,0x07,0x13,0x02,0x02,0x03,0x00,0x00,0x6b, + 0x02,0x80,0x03,0x80,0x00,0x15,0x09,0x6b,0x09,0x15, + 0x00,0x6b,0x03,0x80,0x03,0x80,0x00,0x15,0x00,0xf6, + 0x0d,0x00,0x00,0x8a,0x00,0x6b,0x03,0x80,0x07,0x80, + 0xfd,0x00,0xff,0x03,0x00,0x04,0x00,0x07,0x00,0x04, + 0x01,0x02,0x03,0x01,0x06,0x00,0x03,0x7f,0x01,0x7e, + 0x01,0x7c,0x00,0x79,0xff,0x7c,0xff,0x7d,0xfd,0x00, + 0xfa,0x00,0x0e,0x80,0x03,0x80,0x00,0x15,0x0c,0x00, + 0x00,0x6b,0x02,0x80,0x03,0x80,0x00,0x15,0x0a,0x00, + 0x02,0x7f,0x01,0x7d,0x00,0x7b,0xff,0x7e,0xfe,0x7f, + 0xf6,0x00,0x10,0xf7,0x11,0x8f,0xff,0x03,0xff,0x02, + 0xfe,0x01,0xfa,0x00,0xfd,0x7f,0xff,0x7e,0x00,0x7c, + 0x00,0x79,0x00,0x7b,0x01,0x7e,0x03,0x00,0x06,0x00, + 0x02,0x00,0x01,0x03,0x01,0x02,0x03,0xfb,0x03,0x95, + 0x0c,0x00,0xfa,0x80,0x00,0x6b,0x09,0x80,0x03,0x95, + 0x00,0x77,0x06,0x7a,0x06,0x06,0x00,0x09,0xfa,0xf1, + 0xfa,0x7a,0x0e,0x80,0x03,0x87,0x00,0x0b,0x02,0x02, + 0x03,0x00,0x02,0x7e,0x01,0x02,0x04,0x00,0x02,0x7e, + 0x00,0x75,0xfe,0x7e,0xfc,0x00,0xff,0x01,0xfe,0x7f, + 0xfd,0x00,0xfe,0x02,0x07,0x8e,0x00,0x6b,0x09,0x80, + 0x03,0x80,0x0e,0x15,0xf2,0x80,0x0e,0x6b,0x03,0x80, + 0x03,0x95,0x00,0x6b,0x0e,0x00,0x00,0x7d,0xfe,0x98, + 0x00,0x6b,0x05,0x80,0x03,0x95,0x00,0x75,0x02,0x7d, + 0x0a,0x00,0x00,0x8e,0x00,0x6b,0x02,0x80,0x03,0x95, + 0x00,0x6b,0x10,0x00,0x00,0x15,0xf8,0x80,0x00,0x6b, + 0x0a,0x80,0x03,0x95,0x00,0x6b,0x10,0x00,0x00,0x15, + 0xf8,0x80,0x00,0x6b,0x0a,0x00,0x00,0x7d,0x02,0x83, + 0x10,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, + 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0x89,0x00,0x6b, + 0x03,0x80,0x03,0x95,0x00,0x6b,0x09,0x00,0x03,0x02, + 0x00,0x08,0xfd,0x02,0xf7,0x00,0x0e,0xf4,0x03,0x92, + 0x02,0x03,0x07,0x00,0x03,0x7d,0x00,0x70,0xfd,0x7e, + 0xf9,0x00,0xfe,0x02,0x03,0x89,0x09,0x00,0x02,0xf5, + 0x03,0x80,0x00,0x15,0x00,0xf5,0x07,0x00,0x00,0x08, + 0x02,0x03,0x06,0x00,0x02,0x7d,0x00,0x70,0xfe,0x7e, + 0xfa,0x00,0xfe,0x02,0x00,0x08,0x0c,0xf6,0x0f,0x80, + 0x00,0x15,0xf6,0x00,0xfe,0x7d,0x00,0x79,0x02,0x7e, + 0x0a,0x00,0xf4,0xf7,0x07,0x09,0x07,0xf7,0x03,0x8c, + 0x01,0x02,0x01,0x01,0x05,0x00,0x02,0x7f,0x01,0x7e, + 0x00,0x74,0x00,0x86,0xff,0x01,0xfe,0x01,0xfb,0x00, + 0xff,0x7f,0xff,0x7f,0x00,0x7c,0x01,0x7e,0x01,0x00, + 0x05,0x00,0x02,0x00,0x01,0x02,0x03,0xfe,0x04,0x8e, + 0x02,0x01,0x04,0x00,0x02,0x7f,0x01,0x7e,0x00,0x77, + 0xff,0x7e,0xfe,0x7f,0xfc,0x00,0xfe,0x01,0xff,0x02, + 0x00,0x09,0x01,0x02,0x02,0x02,0x03,0x01,0x02,0x01, + 0x01,0x01,0x01,0x02,0x02,0xeb,0x03,0x80,0x00,0x15, + 0x03,0x00,0x02,0x7e,0x00,0x7b,0xfe,0x7e,0xfd,0x00, + 0x03,0x80,0x04,0x00,0x03,0x7e,0x00,0x78,0xfd,0x7e, + 0xf9,0x00,0x0c,0x80,0x03,0x8c,0x02,0x02,0x02,0x01, + 0x03,0x00,0x02,0x7f,0x01,0x7d,0xfe,0x7e,0xf9,0x7d, + 0xff,0x7e,0x00,0x7d,0x03,0x7f,0x02,0x00,0x03,0x01, + 0x02,0x01,0x02,0xfe,0x0d,0x8c,0xff,0x02,0xfe,0x01, + 0xfc,0x00,0xfe,0x7f,0xff,0x7e,0x00,0x77,0x01,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x02,0x00,0x0f, + 0xff,0x02,0xfe,0x01,0xf9,0x00,0x0c,0xeb,0x03,0x88, + 0x0a,0x00,0x00,0x02,0x00,0x03,0xfe,0x02,0xfa,0x00, + 0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c,0x01,0x7f, + 0x06,0x00,0x02,0x02,0x03,0xfe,0x03,0x8f,0x06,0x77, + 0x06,0x09,0xfa,0x80,0x00,0x71,0xff,0x87,0xfb,0x79, + 0x07,0x87,0x05,0x79,0x02,0x80,0x03,0x8d,0x02,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x7d,0xfc,0x7d,0x04,0x7e, + 0x00,0x7d,0xfe,0x7e,0xfa,0x00,0xfe,0x02,0x04,0x85, + 0x02,0x00,0x06,0xf9,0x03,0x8f,0x00,0x73,0x01,0x7e, + 0x07,0x00,0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e, + 0x03,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x07,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0xf8,0x90, + 0x03,0x00,0x08,0xf0,0x03,0x80,0x00,0x15,0x00,0xf3, + 0x02,0x00,0x06,0x07,0xfa,0xf9,0x07,0x78,0x03,0x80, + 0x03,0x80,0x04,0x0c,0x02,0x03,0x04,0x00,0x00,0x71, + 0x02,0x80,0x03,0x80,0x00,0x0f,0x06,0x77,0x06,0x09, + 0x00,0x71,0x02,0x80,0x03,0x80,0x00,0x0f,0x0a,0xf1, + 0x00,0x0f,0xf6,0xf8,0x0a,0x00,0x02,0xf9,0x05,0x80, + 0xff,0x01,0xff,0x04,0x00,0x05,0x01,0x03,0x01,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x7d,0x00,0x7b,0x00,0x7c, + 0xfe,0x7f,0xfa,0x00,0x0b,0x80,0x03,0x80,0x00,0x0f, + 0x00,0xfb,0x01,0x03,0x01,0x02,0x05,0x00,0x02,0x7e, + 0x01,0x7d,0x00,0x76,0x03,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80, + 0x10,0x80,0x0a,0x8f,0x02,0x7f,0x01,0x7e,0x00,0x76, + 0xff,0x7f,0xfe,0x7f,0xfb,0x00,0xff,0x01,0xff,0x01, + 0x00,0x0a,0x01,0x02,0x01,0x01,0x05,0x00,0xf9,0x80, + 0x00,0x6b,0x0c,0x86,0x0d,0x8a,0xff,0x03,0xfe,0x02, + 0xfb,0x00,0xff,0x7e,0xff,0x7d,0x00,0x7b,0x01,0x7c, + 0x01,0x7f,0x05,0x00,0x02,0x01,0x01,0x03,0x03,0xfc, + 0x03,0x80,0x00,0x0f,0x00,0xfb,0x01,0x03,0x01,0x02, + 0x04,0x00,0x01,0x7e,0x01,0x7d,0x00,0x76,0x00,0x8a, + 0x01,0x03,0x02,0x02,0x03,0x00,0x02,0x7e,0x01,0x7d, + 0x00,0x76,0x03,0x80,0x03,0x8f,0x00,0x74,0x01,0x7e, + 0x02,0x7f,0x04,0x00,0x02,0x01,0x01,0x01,0x00,0x8d, + 0x00,0x6e,0xff,0x7e,0xfe,0x7f,0xfb,0x00,0xfe,0x01, + 0x0c,0x85,0x03,0x8d,0x01,0x02,0x03,0x00,0x02,0x7e, + 0x01,0x02,0x03,0x00,0x02,0x7e,0x00,0x74,0xfe,0x7f, + 0xfd,0x00,0xff,0x01,0xfe,0x7f,0xfd,0x00,0xff,0x01, + 0x00,0x0c,0x06,0x82,0x00,0x6b,0x08,0x86,0x03,0x80, + 0x0a,0x0f,0xf6,0x80,0x0a,0x71,0x03,0x80,0x03,0x8f, + 0x00,0x73,0x01,0x7e,0x07,0x00,0x02,0x02,0x00,0x0d, + 0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82,0x03,0x8f, + 0x00,0x79,0x02,0x7e,0x08,0x00,0x00,0x89,0x00,0x71, + 0x02,0x80,0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00, + 0x02,0x02,0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x80, + 0x03,0x8f,0x00,0x73,0x01,0x7e,0x03,0x00,0x02,0x02, + 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x03,0x00,0x02,0x02, + 0x00,0x0d,0x00,0xf3,0x01,0x7e,0x00,0x7e,0x03,0x82, + 0x03,0x8d,0x00,0x02,0x02,0x00,0x00,0x71,0x08,0x00, + 0x02,0x02,0x00,0x06,0xfe,0x02,0xf8,0x00,0x0c,0xf6, + 0x03,0x8f,0x00,0x71,0x07,0x00,0x02,0x02,0x00,0x06, + 0xfe,0x02,0xf9,0x00,0x0c,0x85,0x00,0x71,0x02,0x80, + 0x03,0x8f,0x00,0x71,0x07,0x00,0x03,0x02,0x00,0x06, + 0xfd,0x02,0xf9,0x00,0x0c,0xf6,0x03,0x8d,0x02,0x02, + 0x06,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfa,0x00, + 0xfe,0x02,0x04,0x85,0x06,0x00,0x02,0xf9,0x03,0x80, + 0x00,0x0f,0x00,0xf8,0x04,0x00,0x00,0x06,0x02,0x02, + 0x04,0x00,0x02,0x7e,0x00,0x75,0xfe,0x7e,0xfc,0x00, + 0xfe,0x02,0x00,0x05,0x0a,0xf9,0x0d,0x80,0x00,0x0f, + 0xf7,0x00,0xff,0x7e,0x00,0x7b,0x01,0x7e,0x09,0x00, + 0xf6,0xfa,0x04,0x06,0x08,0xfa + }; + + //------------------------------------------------------------------------- + gsv_text::gsv_text() : + m_x(0.0), + m_y(0.0), + m_start_x(0.0), + m_width(10.0), + m_height(0.0), + m_space(0.0), + m_line_space(0.0), + m_text(m_chr), + m_text_buf(), + m_cur_chr(m_chr), + m_font(gsv_default_font), + m_loaded_font(), + m_status(initial), + m_big_endian(false), + m_flip(false) + { + m_chr[0] = m_chr[1] = 0; + + int t = 1; + if(*(char*)&t == 0) m_big_endian = true; + } + + //------------------------------------------------------------------------- + void gsv_text::font(const void* font) + { + m_font = font; + if(m_font == 0) m_font = &m_loaded_font[0]; + } + + //------------------------------------------------------------------------- + void gsv_text::size(double height, double width) + { + m_height = height; + m_width = width; + } + + //------------------------------------------------------------------------- + void gsv_text::space(double space) + { + m_space = space; + } + + //------------------------------------------------------------------------- + void gsv_text::line_space(double line_space) + { + m_line_space = line_space; + } + + //------------------------------------------------------------------------- + void gsv_text::start_point(double x, double y) + { + m_x = m_start_x = x; + m_y = y; + //if(m_flip) m_y += m_height; + } + + //------------------------------------------------------------------------- + void gsv_text::load_font(const char* file) + { + m_loaded_font.resize(0); + FILE* fd = fopen(file, "rb"); + if(fd) + { + unsigned len; + + fseek(fd, 0l, SEEK_END); + len = ftell(fd); + fseek(fd, 0l, SEEK_SET); + if(len > 0) + { + m_loaded_font.resize(len); + fread(&m_loaded_font[0], 1, len, fd); + m_font = &m_loaded_font[0]; + } + fclose(fd); + } + } + + //------------------------------------------------------------------------- + void gsv_text::text(const char* text) + { + if(text == 0) + { + m_chr[0] = 0; + m_text = m_chr; + return; + } + unsigned new_size = strlen(text) + 1; + if(new_size > m_text_buf.size()) + { + m_text_buf.resize(new_size); + } + memcpy(&m_text_buf[0], text, new_size); + m_text = &m_text_buf[0]; + } + + //------------------------------------------------------------------------- + void gsv_text::rewind(unsigned) + { + m_status = initial; + if(m_font == 0) return; + + m_indices = (int8u*)m_font; + double base_height = value(m_indices + 4); + m_indices += value(m_indices); + m_glyphs = (int8*)(m_indices + 257*2); + m_h = m_height / base_height; + m_w = (m_width == 0.0) ? m_h : m_width / base_height; + if(m_flip) m_h = -m_h; + m_cur_chr = m_text; + } + + //------------------------------------------------------------------------- + unsigned gsv_text::vertex(double* x, double* y) + { + unsigned idx; + int8 yc, yf; + int dx, dy; + bool quit = false; + + while(!quit) + { + switch(m_status) + { + case initial: + if(m_font == 0) + { + quit = true; + break; + } + m_status = next_char; + + case next_char: + if(*m_cur_chr == 0) + { + quit = true; + break; + } + idx = (*m_cur_chr++) & 0xFF; + if(idx == '\n') + { + m_x = m_start_x; + m_y -= m_flip ? -m_height - m_line_space : m_height + m_line_space; + break; + } + idx <<= 1; + m_bglyph = m_glyphs + value(m_indices + idx); + m_eglyph = m_glyphs + value(m_indices + idx + 2); + m_status = start_glyph; + + case start_glyph: + *x = m_x; + *y = m_y; + m_status = glyph; + return path_cmd_move_to; + + case glyph: + if(m_bglyph >= m_eglyph) + { + m_status = next_char; + m_x += m_space; + break; + } + dx = int(*m_bglyph++); + yf = (yc = *m_bglyph++) & 0x80; + yc <<= 1; + yc >>= 1; + dy = int(yc); + m_x += double(dx) * m_w; + m_y += double(dy) * m_h; + *x = m_x; + *y = m_y; + return yf ? path_cmd_move_to : path_cmd_line_to; + } + + } + return path_cmd_stop; + } + + //------------------------------------------------------------------------- + double gsv_text::text_width() + { + double x1, y1, x2, y2; + bounding_rect_single(*this, 0, &x1, &y1, &x2, &y2); + return x2 - x1; + } + + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_image_filters.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_image_filters.cpp new file mode 100644 index 00000000000..549d9adbf5a --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_image_filters.cpp @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Filtering class image_filter_lut implemantation +// +//---------------------------------------------------------------------------- + + +#include "agg_image_filters.h" + + +namespace agg +{ + //-------------------------------------------------------------------- + void image_filter_lut::realloc_lut(double radius) + { + m_radius = radius; + m_diameter = uceil(radius) * 2; + m_start = -int(m_diameter / 2 - 1); + unsigned size = m_diameter << image_subpixel_shift; + if(size > m_weight_array.size()) + { + m_weight_array.resize(size); + } + } + + + + //-------------------------------------------------------------------- + // This function normalizes integer values and corrects the rounding + // errors. It doesn't do anything with the source floating point values + // (m_weight_array_dbl), it corrects only integers according to the rule + // of 1.0 which means that any sum of pixel weights must be equal to 1.0. + // So, the filter function must produce a graph of the proper shape. + //-------------------------------------------------------------------- + void image_filter_lut::normalize() + { + unsigned i; + int flip = 1; + + for(i = 0; i < image_subpixel_scale; i++) + { + for(;;) + { + int sum = 0; + unsigned j; + for(j = 0; j < m_diameter; j++) + { + sum += m_weight_array[j * image_subpixel_scale + i]; + } + + if(sum == image_filter_scale) break; + + double k = double(image_filter_scale) / double(sum); + sum = 0; + for(j = 0; j < m_diameter; j++) + { + sum += m_weight_array[j * image_subpixel_scale + i] = + iround(m_weight_array[j * image_subpixel_scale + i] * k); + } + + sum -= image_filter_scale; + int inc = (sum > 0) ? -1 : 1; + + for(j = 0; j < m_diameter && sum; j++) + { + flip ^= 1; + unsigned idx = flip ? m_diameter/2 + j/2 : m_diameter/2 - j/2; + int v = m_weight_array[idx * image_subpixel_scale + i]; + if(v < image_filter_scale) + { + m_weight_array[idx * image_subpixel_scale + i] += inc; + sum += inc; + } + } + } + } + + unsigned pivot = m_diameter << (image_subpixel_shift - 1); + + for(i = 0; i < pivot; i++) + { + m_weight_array[pivot + i] = m_weight_array[pivot - i]; + } + unsigned end = (diameter() << image_subpixel_shift) - 1; + m_weight_array[0] = m_weight_array[end]; + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_aa_basics.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_aa_basics.cpp new file mode 100644 index 00000000000..018d65366f2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_aa_basics.cpp @@ -0,0 +1,82 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include +#include "agg_line_aa_basics.h" + +namespace agg +{ + //------------------------------------------------------------------------- + // The number of the octant is determined as a 3-bit value as follows: + // bit 0 = vertical flag + // bit 1 = sx < 0 + // bit 2 = sy < 0 + // + // [N] shows the number of the orthogonal quadrant + // shows the number of the diagonal quadrant + // <1> + // [1] | [0] + // . (3)011 | 001(1) . + // . | . + // . | . + // . | . + // (2)010 .|. 000(0) + // <2> ----------.+.----------- <0> + // (6)110 . | . 100(4) + // . | . + // . | . + // . | . + // (7)111 | 101(5) + // [2] | [3] + // <3> + // 0,1,2,3,4,5,6,7 + const int8u line_parameters::s_orthogonal_quadrant[8] = { 0,0,1,1,3,3,2,2 }; + const int8u line_parameters::s_diagonal_quadrant[8] = { 0,1,2,1,0,3,2,3 }; + + + + //------------------------------------------------------------------------- + void bisectrix(const line_parameters& l1, + const line_parameters& l2, + int* x, int* y) + { + double k = double(l2.len) / double(l1.len); + double tx = l2.x2 - (l2.x1 - l1.x1) * k; + double ty = l2.y2 - (l2.y1 - l1.y1) * k; + + //All bisectrices must be on the right of the line + //If the next point is on the left (l1 => l2.2) + //then the bisectix should be rotated by 180 degrees. + if(double(l2.x2 - l2.x1) * double(l2.y1 - l1.y1) < + double(l2.y2 - l2.y1) * double(l2.x1 - l1.x1) + 100.0) + { + tx -= (tx - l2.x1) * 2.0; + ty -= (ty - l2.y1) * 2.0; + } + + // Check if the bisectrix is too short + double dx = tx - l2.x1; + double dy = ty - l2.y1; + if((int)sqrt(dx * dx + dy * dy) < line_subpixel_scale) + { + *x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1; + *y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1; + return; + } + *x = iround(tx); + *y = iround(ty); + } + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_profile_aa.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_profile_aa.cpp new file mode 100644 index 00000000000..6066662cb9d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_line_profile_aa.cpp @@ -0,0 +1,116 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_renderer_outline_aa.h" + +namespace agg +{ + + //--------------------------------------------------------------------- + void line_profile_aa::width(double w) + { + if(w < 0.0) w = 0.0; + + if(w < m_smoother_width) w += w; + else w += m_smoother_width; + + w *= 0.5; + + w -= m_smoother_width; + double s = m_smoother_width; + if(w < 0.0) + { + s += w; + w = 0.0; + } + set(w, s); + } + + + //--------------------------------------------------------------------- + line_profile_aa::value_type* line_profile_aa::profile(double w) + { + m_subpixel_width = uround(w * subpixel_scale); + unsigned size = m_subpixel_width + subpixel_scale * 6; + if(size > m_profile.size()) + { + m_profile.resize(size); + } + return &m_profile[0]; + } + + + //--------------------------------------------------------------------- + void line_profile_aa::set(double center_width, double smoother_width) + { + double base_val = 1.0; + if(center_width == 0.0) center_width = 1.0 / subpixel_scale; + if(smoother_width == 0.0) smoother_width = 1.0 / subpixel_scale; + + double width = center_width + smoother_width; + if(width < m_min_width) + { + double k = width / m_min_width; + base_val *= k; + center_width /= k; + smoother_width /= k; + } + + value_type* ch = profile(center_width + smoother_width); + + unsigned subpixel_center_width = unsigned(center_width * subpixel_scale); + unsigned subpixel_smoother_width = unsigned(smoother_width * subpixel_scale); + + value_type* ch_center = ch + subpixel_scale*2; + value_type* ch_smoother = ch_center + subpixel_center_width; + + unsigned i; + + unsigned val = m_gamma[unsigned(base_val * aa_mask)]; + ch = ch_center; + for(i = 0; i < subpixel_center_width; i++) + { + *ch++ = (value_type)val; + } + + for(i = 0; i < subpixel_smoother_width; i++) + { + *ch_smoother++ = + m_gamma[unsigned((base_val - + base_val * + (double(i) / subpixel_smoother_width)) * aa_mask)]; + } + + unsigned n_smoother = profile_size() - + subpixel_smoother_width - + subpixel_center_width - + subpixel_scale*2; + + val = m_gamma[0]; + for(i = 0; i < n_smoother; i++) + { + *ch_smoother++ = (value_type)val; + } + + ch = ch_center; + for(i = 0; i < subpixel_scale*2; i++) + { + *--ch = *ch_center++; + } + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_rounded_rect.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_rounded_rect.cpp new file mode 100644 index 00000000000..bebc0636288 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_rounded_rect.cpp @@ -0,0 +1,164 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Rounded rectangle vertex generator +// +//---------------------------------------------------------------------------- + +#include +#include "agg_rounded_rect.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + rounded_rect::rounded_rect(double x1, double y1, double x2, double y2, double r) : + m_x1(x1), m_y1(y1), m_x2(x2), m_y2(y2), + m_rx1(r), m_ry1(r), m_rx2(r), m_ry2(r), + m_rx3(r), m_ry3(r), m_rx4(r), m_ry4(r) + { + if(x1 > x2) { m_x1 = x2; m_x2 = x1; } + if(y1 > y2) { m_y1 = y2; m_y2 = y1; } + } + + //-------------------------------------------------------------------- + void rounded_rect::rect(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + if(x1 > x2) { m_x1 = x2; m_x2 = x1; } + if(y1 > y2) { m_y1 = y2; m_y2 = y1; } + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double r) + { + m_rx1 = m_ry1 = m_rx2 = m_ry2 = m_rx3 = m_ry3 = m_rx4 = m_ry4 = r; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx, double ry) + { + m_rx1 = m_rx2 = m_rx3 = m_rx4 = rx; + m_ry1 = m_ry2 = m_ry3 = m_ry4 = ry; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx_bottom, double ry_bottom, + double rx_top, double ry_top) + { + m_rx1 = m_rx2 = rx_bottom; + m_rx3 = m_rx4 = rx_top; + m_ry1 = m_ry2 = ry_bottom; + m_ry3 = m_ry4 = ry_top; + } + + //-------------------------------------------------------------------- + void rounded_rect::radius(double rx1, double ry1, double rx2, double ry2, + double rx3, double ry3, double rx4, double ry4) + { + m_rx1 = rx1; m_ry1 = ry1; m_rx2 = rx2; m_ry2 = ry2; + m_rx3 = rx3; m_ry3 = ry3; m_rx4 = rx4; m_ry4 = ry4; + } + + //-------------------------------------------------------------------- + void rounded_rect::normalize_radius() + { + double dx = fabs(m_y2 - m_y1); + double dy = fabs(m_x2 - m_x1); + + double k = 1.0; + double t; + t = dx / (m_rx1 + m_rx2); if(t < k) k = t; + t = dx / (m_rx3 + m_rx4); if(t < k) k = t; + t = dy / (m_ry1 + m_ry2); if(t < k) k = t; + t = dy / (m_ry3 + m_ry4); if(t < k) k = t; + + if(k < 1.0) + { + m_rx1 *= k; m_ry1 *= k; m_rx2 *= k; m_ry2 *= k; + m_rx3 *= k; m_ry3 *= k; m_rx4 *= k; m_ry4 *= k; + } + } + + //-------------------------------------------------------------------- + void rounded_rect::rewind(unsigned) + { + m_status = 0; + } + + //-------------------------------------------------------------------- + unsigned rounded_rect::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_status) + { + case 0: + m_arc.init(m_x1 + m_rx1, m_y1 + m_ry1, m_rx1, m_ry1, + pi, pi+pi*0.5); + m_arc.rewind(0); + m_status++; + + case 1: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return cmd; + + case 2: + m_arc.init(m_x2 - m_rx2, m_y1 + m_ry2, m_rx2, m_ry2, + pi+pi*0.5, 0.0); + m_arc.rewind(0); + m_status++; + + case 3: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 4: + m_arc.init(m_x2 - m_rx3, m_y2 - m_ry3, m_rx3, m_ry3, + 0.0, pi*0.5); + m_arc.rewind(0); + m_status++; + + case 5: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 6: + m_arc.init(m_x1 + m_rx4, m_y2 - m_ry4, m_rx4, m_ry4, + pi*0.5, pi); + m_arc.rewind(0); + m_status++; + + case 7: + cmd = m_arc.vertex(x, y); + if(is_stop(cmd)) m_status++; + else return path_cmd_line_to; + + case 8: + cmd = path_cmd_end_poly | path_flags_close | path_flags_ccw; + m_status++; + break; + } + return cmd; + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_sqrt_tables.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_sqrt_tables.cpp new file mode 100644 index 00000000000..19a1bd8cb79 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_sqrt_tables.cpp @@ -0,0 +1,115 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// static tables for fast integer sqrt +// +//---------------------------------------------------------------------------- + +#include "agg_basics.h" + +namespace agg +{ + int16u g_sqrt_table[1024] = //----------g_sqrt_table + { + 0, + 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, + 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585, + 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890, + 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864, + 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618, + 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212, + 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684, + 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058, + 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351, + 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576, + 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743, + 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859, + 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931, + 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963, + 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960, + 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924, + 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859, + 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768, + 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652, + 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514, + 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354, + 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175, + 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978, + 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763, + 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533, + 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287, + 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028, + 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755, + 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469, + 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171, + 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861, + 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541, + 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210, + 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869, + 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519, + 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160, + 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791, + 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415, + 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030, + 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637, + 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237, + 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830, + 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416, + 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995, + 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567, + 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134, + 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694, + 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248, + 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797, + 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340, + 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877, + 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410, + 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937, + 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459, + 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977, + 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490, + 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999, + 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503, + 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002, + 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498, + 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989, + 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477, + 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960, + 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440, + 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916, + 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388, + 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857, + 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323, + 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785, + 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243, + 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699, + 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151, + 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 + }; + + + int8 g_elder_bit_table[256] = //---------g_elder_bit_table + { + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_affine.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_affine.cpp new file mode 100644 index 00000000000..99febc953a1 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_affine.cpp @@ -0,0 +1,194 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Affine transformations +// +//---------------------------------------------------------------------------- +#include "agg_trans_affine.h" + + + +namespace agg +{ + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::parl_to_parl(const double* src, + const double* dst) + { + sx = src[2] - src[0]; + shy = src[3] - src[1]; + shx = src[4] - src[0]; + sy = src[5] - src[1]; + tx = src[0]; + ty = src[1]; + invert(); + multiply(trans_affine(dst[2] - dst[0], dst[3] - dst[1], + dst[4] - dst[0], dst[5] - dst[1], + dst[0], dst[1])); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::rect_to_parl(double x1, double y1, + double x2, double y2, + const double* parl) + { + double src[6]; + src[0] = x1; src[1] = y1; + src[2] = x2; src[3] = y1; + src[4] = x2; src[5] = y2; + parl_to_parl(src, parl); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::parl_to_rect(const double* parl, + double x1, double y1, + double x2, double y2) + { + double dst[6]; + dst[0] = x1; dst[1] = y1; + dst[2] = x2; dst[3] = y1; + dst[4] = x2; dst[5] = y2; + parl_to_parl(parl, dst); + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::multiply(const trans_affine& m) + { + double t0 = sx * m.sx + shy * m.shx; + double t2 = shx * m.sx + sy * m.shx; + double t4 = tx * m.sx + ty * m.shx + m.tx; + shy = sx * m.shy + shy * m.sy; + sy = shx * m.shy + sy * m.sy; + ty = tx * m.shy + ty * m.sy + m.ty; + sx = t0; + shx = t2; + tx = t4; + return *this; + } + + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::invert() + { + double d = determinant_reciprocal(); + + double t0 = sy * d; + sy = sx * d; + shy = -shy * d; + shx = -shx * d; + + double t4 = -tx * t0 - ty * shx; + ty = -tx * shy - ty * sy; + + sx = t0; + tx = t4; + return *this; + } + + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::flip_x() + { + sx = -sx; + shy = -shy; + tx = -tx; + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::flip_y() + { + shx = -shx; + sy = -sy; + ty = -ty; + return *this; + } + + //------------------------------------------------------------------------ + const trans_affine& trans_affine::reset() + { + sx = sy = 1.0; + shy = shx = tx = ty = 0.0; + return *this; + } + + //------------------------------------------------------------------------ + bool trans_affine::is_identity(double epsilon) const + { + return is_equal_eps(sx, 1.0, epsilon) && + is_equal_eps(shy, 0.0, epsilon) && + is_equal_eps(shx, 0.0, epsilon) && + is_equal_eps(sy, 1.0, epsilon) && + is_equal_eps(tx, 0.0, epsilon) && + is_equal_eps(ty, 0.0, epsilon); + } + + //------------------------------------------------------------------------ + bool trans_affine::is_valid(double epsilon) const + { + return fabs(sx) > epsilon && fabs(sy) > epsilon; + } + + //------------------------------------------------------------------------ + bool trans_affine::is_equal(const trans_affine& m, double epsilon) const + { + return is_equal_eps(sx, m.sx, epsilon) && + is_equal_eps(shy, m.shy, epsilon) && + is_equal_eps(shx, m.shx, epsilon) && + is_equal_eps(sy, m.sy, epsilon) && + is_equal_eps(tx, m.tx, epsilon) && + is_equal_eps(ty, m.ty, epsilon); + } + + //------------------------------------------------------------------------ + double trans_affine::rotation() const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 0.0; + transform(&x1, &y1); + transform(&x2, &y2); + return atan2(y2-y1, x2-x1); + } + + //------------------------------------------------------------------------ + void trans_affine::translation(double* dx, double* dy) const + { + *dx = tx; + *dy = ty; + } + + //------------------------------------------------------------------------ + void trans_affine::scaling(double* x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double x2 = 1.0; + double y2 = 1.0; + trans_affine t(*this); + t *= trans_affine_rotation(-rotation()); + t.transform(&x1, &y1); + t.transform(&x2, &y2); + *x = x2 - x1; + *y = y2 - y1; + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_double_path.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_double_path.cpp new file mode 100644 index 00000000000..cd40c7f5869 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_double_path.cpp @@ -0,0 +1,273 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_math.h" +#include "agg_trans_double_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + trans_double_path::trans_double_path() : + m_kindex1(0.0), + m_kindex2(0.0), + m_base_length(0.0), + m_base_height(1.0), + m_status1(initial), + m_status2(initial), + m_preserve_x_scale(true) + { + } + + + //------------------------------------------------------------------------ + void trans_double_path::reset() + { + m_src_vertices1.remove_all(); + m_src_vertices2.remove_all(); + m_kindex1 = 0.0; + m_kindex1 = 0.0; + m_status1 = initial; + m_status2 = initial; + } + + + //------------------------------------------------------------------------ + void trans_double_path::move_to1(double x, double y) + { + if(m_status1 == initial) + { + m_src_vertices1.modify_last(vertex_dist(x, y)); + m_status1 = making_path; + } + else + { + line_to1(x, y); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::line_to1(double x, double y) + { + if(m_status1 == making_path) + { + m_src_vertices1.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::move_to2(double x, double y) + { + if(m_status2 == initial) + { + m_src_vertices2.modify_last(vertex_dist(x, y)); + m_status2 = making_path; + } + else + { + line_to2(x, y); + } + } + + + //------------------------------------------------------------------------ + void trans_double_path::line_to2(double x, double y) + { + if(m_status2 == making_path) + { + m_src_vertices2.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + double trans_double_path::finalize_path(vertex_storage& vertices) + { + unsigned i; + double dist; + double d; + + vertices.close(false); + if(vertices.size() > 2) + { + if(vertices[vertices.size() - 2].dist * 10.0 < + vertices[vertices.size() - 3].dist) + { + d = vertices[vertices.size() - 3].dist + + vertices[vertices.size() - 2].dist; + + vertices[vertices.size() - 2] = + vertices[vertices.size() - 1]; + + vertices.remove_last(); + vertices[vertices.size() - 2].dist = d; + } + } + + dist = 0; + for(i = 0; i < vertices.size(); i++) + { + vertex_dist& v = vertices[i]; + d = v.dist; + v.dist = dist; + dist += d; + } + + return (vertices.size() - 1) / dist; + } + + + //------------------------------------------------------------------------ + void trans_double_path::finalize_paths() + { + if(m_status1 == making_path && m_src_vertices1.size() > 1 && + m_status2 == making_path && m_src_vertices2.size() > 1) + { + m_kindex1 = finalize_path(m_src_vertices1); + m_kindex2 = finalize_path(m_src_vertices2); + m_status1 = ready; + m_status2 = ready; + } + } + + + //------------------------------------------------------------------------ + double trans_double_path::total_length1() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status1 == ready) ? + m_src_vertices1[m_src_vertices1.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + double trans_double_path::total_length2() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status2 == ready) ? + m_src_vertices2[m_src_vertices2.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + void trans_double_path::transform1(const vertex_storage& vertices, + double kindex, double kx, + double *x, double* y) const + { + double x1 = 0.0; + double y1 = 0.0; + double dx = 1.0; + double dy = 1.0; + double d = 0.0; + double dd = 1.0; + *x *= kx; + if(*x < 0.0) + { + // Extrapolation on the left + //-------------------------- + x1 = vertices[0].x; + y1 = vertices[0].y; + dx = vertices[1].x - x1; + dy = vertices[1].y - y1; + dd = vertices[1].dist - vertices[0].dist; + d = *x; + } + else + if(*x > vertices[vertices.size() - 1].dist) + { + // Extrapolation on the right + //-------------------------- + unsigned i = vertices.size() - 2; + unsigned j = vertices.size() - 1; + x1 = vertices[j].x; + y1 = vertices[j].y; + dx = x1 - vertices[i].x; + dy = y1 - vertices[i].y; + dd = vertices[j].dist - vertices[i].dist; + d = *x - vertices[j].dist; + } + else + { + // Interpolation + //-------------------------- + unsigned i = 0; + unsigned j = vertices.size() - 1; + if(m_preserve_x_scale) + { + unsigned k; + for(i = 0; (j - i) > 1; ) + { + if(*x < vertices[k = (i + j) >> 1].dist) + { + j = k; + } + else + { + i = k; + } + } + d = vertices[i].dist; + dd = vertices[j].dist - d; + d = *x - d; + } + else + { + i = unsigned(*x * kindex); + j = i + 1; + dd = vertices[j].dist - vertices[i].dist; + d = ((*x * kindex) - i) * dd; + } + x1 = vertices[i].x; + y1 = vertices[i].y; + dx = vertices[j].x - x1; + dy = vertices[j].y - y1; + } + *x = x1 + dx * d / dd; + *y = y1 + dy * d / dd; + } + + + //------------------------------------------------------------------------ + void trans_double_path::transform(double *x, double *y) const + { + if(m_status1 == ready && m_status2 == ready) + { + if(m_base_length > 1e-10) + { + *x *= m_src_vertices1[m_src_vertices1.size() - 1].dist / + m_base_length; + } + + double x1 = *x; + double y1 = *y; + double x2 = *x; + double y2 = *y; + double dd = m_src_vertices2[m_src_vertices2.size() - 1].dist / + m_src_vertices1[m_src_vertices1.size() - 1].dist; + + transform1(m_src_vertices1, m_kindex1, 1.0, &x1, &y1); + transform1(m_src_vertices2, m_kindex2, dd, &x2, &y2); + + *x = x1 + *y * (x2 - x1) / m_base_height; + *y = y1 + *y * (y2 - y1) / m_base_height; + } + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_single_path.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_single_path.cpp new file mode 100644 index 00000000000..2120fc9b9b6 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_single_path.cpp @@ -0,0 +1,202 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_math.h" +#include "agg_vertex_sequence.h" +#include "agg_trans_single_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + trans_single_path::trans_single_path() : + m_base_length(0.0), + m_kindex(0.0), + m_status(initial), + m_preserve_x_scale(true) + { + } + + //------------------------------------------------------------------------ + void trans_single_path::reset() + { + m_src_vertices.remove_all(); + m_kindex = 0.0; + m_status = initial; + } + + //------------------------------------------------------------------------ + void trans_single_path::move_to(double x, double y) + { + if(m_status == initial) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + m_status = making_path; + } + else + { + line_to(x, y); + } + } + + //------------------------------------------------------------------------ + void trans_single_path::line_to(double x, double y) + { + if(m_status == making_path) + { + m_src_vertices.add(vertex_dist(x, y)); + } + } + + + //------------------------------------------------------------------------ + void trans_single_path::finalize_path() + { + if(m_status == making_path && m_src_vertices.size() > 1) + { + unsigned i; + double dist; + double d; + + m_src_vertices.close(false); + if(m_src_vertices.size() > 2) + { + if(m_src_vertices[m_src_vertices.size() - 2].dist * 10.0 < + m_src_vertices[m_src_vertices.size() - 3].dist) + { + d = m_src_vertices[m_src_vertices.size() - 3].dist + + m_src_vertices[m_src_vertices.size() - 2].dist; + + m_src_vertices[m_src_vertices.size() - 2] = + m_src_vertices[m_src_vertices.size() - 1]; + + m_src_vertices.remove_last(); + m_src_vertices[m_src_vertices.size() - 2].dist = d; + } + } + + dist = 0.0; + for(i = 0; i < m_src_vertices.size(); i++) + { + vertex_dist& v = m_src_vertices[i]; + double d = v.dist; + v.dist = dist; + dist += d; + } + m_kindex = (m_src_vertices.size() - 1) / dist; + m_status = ready; + } + } + + + + //------------------------------------------------------------------------ + double trans_single_path::total_length() const + { + if(m_base_length >= 1e-10) return m_base_length; + return (m_status == ready) ? + m_src_vertices[m_src_vertices.size() - 1].dist : + 0.0; + } + + + //------------------------------------------------------------------------ + void trans_single_path::transform(double *x, double *y) const + { + if(m_status == ready) + { + if(m_base_length > 1e-10) + { + *x *= m_src_vertices[m_src_vertices.size() - 1].dist / + m_base_length; + } + + double x1 = 0.0; + double y1 = 0.0; + double dx = 1.0; + double dy = 1.0; + double d = 0.0; + double dd = 1.0; + if(*x < 0.0) + { + // Extrapolation on the left + //-------------------------- + x1 = m_src_vertices[0].x; + y1 = m_src_vertices[0].y; + dx = m_src_vertices[1].x - x1; + dy = m_src_vertices[1].y - y1; + dd = m_src_vertices[1].dist - m_src_vertices[0].dist; + d = *x; + } + else + if(*x > m_src_vertices[m_src_vertices.size() - 1].dist) + { + // Extrapolation on the right + //-------------------------- + unsigned i = m_src_vertices.size() - 2; + unsigned j = m_src_vertices.size() - 1; + x1 = m_src_vertices[j].x; + y1 = m_src_vertices[j].y; + dx = x1 - m_src_vertices[i].x; + dy = y1 - m_src_vertices[i].y; + dd = m_src_vertices[j].dist - m_src_vertices[i].dist; + d = *x - m_src_vertices[j].dist; + } + else + { + // Interpolation + //-------------------------- + unsigned i = 0; + unsigned j = m_src_vertices.size() - 1; + if(m_preserve_x_scale) + { + unsigned k; + for(i = 0; (j - i) > 1; ) + { + if(*x < m_src_vertices[k = (i + j) >> 1].dist) + { + j = k; + } + else + { + i = k; + } + } + d = m_src_vertices[i].dist; + dd = m_src_vertices[j].dist - d; + d = *x - d; + } + else + { + i = unsigned(*x * m_kindex); + j = i + 1; + dd = m_src_vertices[j].dist - m_src_vertices[i].dist; + d = ((*x * m_kindex) - i) * dd; + } + x1 = m_src_vertices[i].x; + y1 = m_src_vertices[i].y; + dx = m_src_vertices[j].x - x1; + dy = m_src_vertices[j].y - y1; + } + double x2 = x1 + dx * d / dd; + double y2 = y1 + dy * d / dd; + *x = x2 - *y * dy / dd; + *y = y2 + *y * dx / dd; + } + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_warp_magnifier.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_warp_magnifier.cpp new file mode 100644 index 00000000000..e65afabba78 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_trans_warp_magnifier.cpp @@ -0,0 +1,70 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include +#include "agg_trans_warp_magnifier.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + void trans_warp_magnifier::transform(double* x, double* y) const + { + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = sqrt(dx * dx + dy * dy); + if(r < m_radius) + { + *x = m_xc + dx * m_magn; + *y = m_yc + dy * m_magn; + return; + } + + double m = (r + m_radius * (m_magn - 1.0)) / r; + *x = m_xc + dx * m; + *y = m_yc + dy * m; + } + + //------------------------------------------------------------------------ + void trans_warp_magnifier::inverse_transform(double* x, double* y) const + { + // New version by Andrew Skalkin + //----------------- + double dx = *x - m_xc; + double dy = *y - m_yc; + double r = sqrt(dx * dx + dy * dy); + + if(r < m_radius * m_magn) + { + *x = m_xc + dx / m_magn; + *y = m_yc + dy / m_magn; + } + else + { + double rnew = r - m_radius * (m_magn - 1.0); + *x = m_xc + rnew * dx / r; + *y = m_yc + rnew * dy / r; + } + + // Old version + //----------------- + //trans_warp_magnifier t(*this); + //t.magnification(1.0 / m_magn); + //t.radius(m_radius * m_magn); + //t.transform(x, y); + } + + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_bspline.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_bspline.cpp new file mode 100644 index 00000000000..4a0be6693ee --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_bspline.cpp @@ -0,0 +1,194 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_vcgen_bspline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_bspline::vcgen_bspline() : + m_src_vertices(), + m_spline_x(), + m_spline_y(), + m_interpolation_step(1.0/50.0), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(point_d(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(point_d(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_bspline::rewind(unsigned) + { + m_cur_abscissa = 0.0; + m_max_abscissa = 0.0; + m_src_vertex = 0; + if(m_status == initial && m_src_vertices.size() > 2) + { + if(m_closed) + { + m_spline_x.init(m_src_vertices.size() + 8); + m_spline_y.init(m_src_vertices.size() + 8); + m_spline_x.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).x); + m_spline_y.add_point(0.0, m_src_vertices.prev(m_src_vertices.size() - 3).y); + m_spline_x.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].x); + m_spline_y.add_point(1.0, m_src_vertices[m_src_vertices.size() - 3].y); + m_spline_x.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].x); + m_spline_y.add_point(2.0, m_src_vertices[m_src_vertices.size() - 2].y); + m_spline_x.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].x); + m_spline_y.add_point(3.0, m_src_vertices[m_src_vertices.size() - 1].y); + } + else + { + m_spline_x.init(m_src_vertices.size()); + m_spline_y.init(m_src_vertices.size()); + } + unsigned i; + for(i = 0; i < m_src_vertices.size(); i++) + { + double x = m_closed ? i + 4 : i; + m_spline_x.add_point(x, m_src_vertices[i].x); + m_spline_y.add_point(x, m_src_vertices[i].y); + } + m_cur_abscissa = 0.0; + m_max_abscissa = m_src_vertices.size() - 1; + if(m_closed) + { + m_cur_abscissa = 4.0; + m_max_abscissa += 5.0; + m_spline_x.add_point(m_src_vertices.size() + 4, m_src_vertices[0].x); + m_spline_y.add_point(m_src_vertices.size() + 4, m_src_vertices[0].y); + m_spline_x.add_point(m_src_vertices.size() + 5, m_src_vertices[1].x); + m_spline_y.add_point(m_src_vertices.size() + 5, m_src_vertices[1].y); + m_spline_x.add_point(m_src_vertices.size() + 6, m_src_vertices[2].x); + m_spline_y.add_point(m_src_vertices.size() + 6, m_src_vertices[2].y); + m_spline_x.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).x); + m_spline_y.add_point(m_src_vertices.size() + 7, m_src_vertices.next(2).y); + } + m_spline_x.prepare(); + m_spline_y.prepare(); + } + m_status = ready; + } + + + + + + + //------------------------------------------------------------------------ + unsigned vcgen_bspline::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + + if(m_src_vertices.size() == 2) + { + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + if(m_src_vertex == 1) return path_cmd_move_to; + if(m_src_vertex == 2) return path_cmd_line_to; + cmd = path_cmd_stop; + break; + } + + cmd = path_cmd_move_to; + m_status = polygon; + m_src_vertex = 0; + + case polygon: + if(m_cur_abscissa >= m_max_abscissa) + { + if(m_closed) + { + m_status = end_poly; + break; + } + else + { + *x = m_src_vertices[m_src_vertices.size() - 1].x; + *y = m_src_vertices[m_src_vertices.size() - 1].y; + m_status = end_poly; + return path_cmd_line_to; + } + } + + *x = m_spline_x.get_stateful(m_cur_abscissa); + *y = m_spline_y.get_stateful(m_cur_abscissa); + m_src_vertex++; + m_cur_abscissa += m_interpolation_step; + return (m_src_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; + + case end_poly: + m_status = stop; + return path_cmd_end_poly | m_closed; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_contour.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_contour.cpp new file mode 100644 index 00000000000..a6a99405ad2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_contour.cpp @@ -0,0 +1,165 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Contour generator +// +//---------------------------------------------------------------------------- + +#include +#include "agg_vcgen_contour.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_contour::vcgen_contour() : + m_stroker(), + m_width(1), + m_src_vertices(), + m_out_vertices(), + m_status(initial), + m_src_vertex(0), + m_closed(0), + m_orientation(0), + m_auto_detect(false) + { + } + + //------------------------------------------------------------------------ + void vcgen_contour::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_orientation = 0; + m_status = initial; + } + + //------------------------------------------------------------------------ + void vcgen_contour::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + if(is_end_poly(cmd)) + { + m_closed = get_close_flag(cmd); + if(m_orientation == path_flags_none) + { + m_orientation = get_orientation(cmd); + } + } + } + } + } + + //------------------------------------------------------------------------ + void vcgen_contour::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(true); + if(m_auto_detect) + { + if(!is_oriented(m_orientation)) + { + m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? + path_flags_ccw : + path_flags_cw; + } + } + if(is_oriented(m_orientation)) + { + m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width); + } + } + m_status = ready; + m_src_vertex = 0; + } + + //------------------------------------------------------------------------ + unsigned vcgen_contour::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) + { + cmd = path_cmd_stop; + break; + } + m_status = outline; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; + + case outline: + if(m_src_vertex >= m_src_vertices.size()) + { + m_status = end_poly; + break; + } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_status = out_vertices; + m_out_vertex = 0; + + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = outline; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } + break; + + case end_poly: + if(!m_closed) return path_cmd_stop; + m_status = stop; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_dash.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_dash.cpp new file mode 100644 index 00000000000..129505786c9 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_dash.cpp @@ -0,0 +1,235 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Line dash generator +// +//---------------------------------------------------------------------------- + +#include +#include "agg_vcgen_dash.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_dash::vcgen_dash() : + m_total_dash_len(0.0), + m_num_dashes(0), + m_dash_start(0.0), + m_shorten(0.0), + m_curr_dash_start(0.0), + m_curr_dash(0), + m_src_vertices(), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + + //------------------------------------------------------------------------ + void vcgen_dash::remove_all_dashes() + { + m_total_dash_len = 0.0; + m_num_dashes = 0; + m_curr_dash_start = 0.0; + m_curr_dash = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_dash::add_dash(double dash_len, double gap_len) + { + if(m_num_dashes < max_dashes) + { + m_total_dash_len += dash_len + gap_len; + m_dashes[m_num_dashes++] = dash_len; + m_dashes[m_num_dashes++] = gap_len; + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::dash_start(double ds) + { + m_dash_start = ds; + calc_dash_start(fabs(ds)); + } + + + //------------------------------------------------------------------------ + void vcgen_dash::calc_dash_start(double ds) + { + m_curr_dash = 0; + m_curr_dash_start = 0.0; + while(ds > 0.0) + { + if(ds > m_dashes[m_curr_dash]) + { + ds -= m_dashes[m_curr_dash]; + ++m_curr_dash; + m_curr_dash_start = 0.0; + if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; + } + else + { + m_curr_dash_start = ds; + ds = 0.0; + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::remove_all() + { + m_status = initial; + m_src_vertices.remove_all(); + m_closed = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_dash::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_dash::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + shorten_path(m_src_vertices, m_shorten, m_closed); + } + m_status = ready; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_dash::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_move_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_num_dashes < 2 || m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + m_status = polyline; + m_src_vertex = 1; + m_v1 = &m_src_vertices[0]; + m_v2 = &m_src_vertices[1]; + m_curr_rest = m_v1->dist; + *x = m_v1->x; + *y = m_v1->y; + if(m_dash_start >= 0.0) calc_dash_start(m_dash_start); + return path_cmd_move_to; + + case polyline: + { + double dash_rest = m_dashes[m_curr_dash] - m_curr_dash_start; + + unsigned cmd = (m_curr_dash & 1) ? + path_cmd_move_to : + path_cmd_line_to; + + if(m_curr_rest > dash_rest) + { + m_curr_rest -= dash_rest; + ++m_curr_dash; + if(m_curr_dash >= m_num_dashes) m_curr_dash = 0; + m_curr_dash_start = 0.0; + *x = m_v2->x - (m_v2->x - m_v1->x) * m_curr_rest / m_v1->dist; + *y = m_v2->y - (m_v2->y - m_v1->y) * m_curr_rest / m_v1->dist; + } + else + { + m_curr_dash_start += m_curr_rest; + *x = m_v2->x; + *y = m_v2->y; + ++m_src_vertex; + m_v1 = m_v2; + m_curr_rest = m_v1->dist; + if(m_closed) + { + if(m_src_vertex > m_src_vertices.size()) + { + m_status = stop; + } + else + { + m_v2 = &m_src_vertices + [ + (m_src_vertex >= m_src_vertices.size()) ? 0 : + m_src_vertex + ]; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size()) + { + m_status = stop; + } + else + { + m_v2 = &m_src_vertices[m_src_vertex]; + } + } + } + return cmd; + } + break; + + case stop: + cmd = path_cmd_stop; + break; + } + + } + return path_cmd_stop; + } + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_markers_term.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_markers_term.cpp new file mode 100644 index 00000000000..3374ab5e82a --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_markers_term.cpp @@ -0,0 +1,103 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Terminal markers generator (arrowhead/arrowtail) +// +//---------------------------------------------------------------------------- + +#include "agg_vcgen_markers_term.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + void vcgen_markers_term::remove_all() + { + m_markers.remove_all(); + } + + + //------------------------------------------------------------------------ + void vcgen_markers_term::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + if(m_markers.size() & 1) + { + // Initial state, the first coordinate was added. + // If two of more calls of start_vertex() occures + // we just modify the last one. + m_markers.modify_last(coord_type(x, y)); + } + else + { + m_markers.add(coord_type(x, y)); + } + } + else + { + if(is_vertex(cmd)) + { + if(m_markers.size() & 1) + { + // Initial state, the first coordinate was added. + // Add three more points, 0,1,1,0 + m_markers.add(coord_type(x, y)); + m_markers.add(m_markers[m_markers.size() - 1]); + m_markers.add(m_markers[m_markers.size() - 3]); + } + else + { + if(m_markers.size()) + { + // Replace two last points: 0,1,1,0 -> 0,1,2,1 + m_markers[m_markers.size() - 1] = m_markers[m_markers.size() - 2]; + m_markers[m_markers.size() - 2] = coord_type(x, y); + } + } + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_markers_term::rewind(unsigned path_id) + { + m_curr_id = path_id * 2; + m_curr_idx = m_curr_id; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_markers_term::vertex(double* x, double* y) + { + if(m_curr_id > 2 || m_curr_idx >= m_markers.size()) + { + return path_cmd_stop; + } + const coord_type& c = m_markers[m_curr_idx]; + *x = c.x; + *y = c.y; + if(m_curr_idx & 1) + { + m_curr_idx += 3; + return path_cmd_line_to; + } + ++m_curr_idx; + return path_cmd_move_to; + } + + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_smooth_poly1.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_smooth_poly1.cpp new file mode 100644 index 00000000000..ff7d488d399 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_smooth_poly1.cpp @@ -0,0 +1,225 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Smooth polygon generator +// +//---------------------------------------------------------------------------- + +#include "agg_vcgen_smooth_poly1.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_smooth_poly1::vcgen_smooth_poly1() : + m_src_vertices(), + m_smooth_value(0.5), + m_closed(0), + m_status(initial), + m_src_vertex(0) + { + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + } + m_status = ready; + m_src_vertex = 0; + } + + + //------------------------------------------------------------------------ + void vcgen_smooth_poly1::calculate(const vertex_dist& v0, + const vertex_dist& v1, + const vertex_dist& v2, + const vertex_dist& v3) + { + + double k1 = v0.dist / (v0.dist + v1.dist); + double k2 = v1.dist / (v1.dist + v2.dist); + + double xm1 = v0.x + (v2.x - v0.x) * k1; + double ym1 = v0.y + (v2.y - v0.y) * k1; + double xm2 = v1.x + (v3.x - v1.x) * k2; + double ym2 = v1.y + (v3.y - v1.y) * k2; + + m_ctrl1_x = v1.x + m_smooth_value * (v2.x - xm1); + m_ctrl1_y = v1.y + m_smooth_value * (v2.y - ym1); + m_ctrl2_x = v2.x + m_smooth_value * (v1.x - xm2); + m_ctrl2_y = v2.y + m_smooth_value * (v1.y - ym2); + } + + + //------------------------------------------------------------------------ + unsigned vcgen_smooth_poly1::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2) + { + cmd = path_cmd_stop; + break; + } + + if(m_src_vertices.size() == 2) + { + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + if(m_src_vertex == 1) return path_cmd_move_to; + if(m_src_vertex == 2) return path_cmd_line_to; + cmd = path_cmd_stop; + break; + } + + cmd = path_cmd_move_to; + m_status = polygon; + m_src_vertex = 0; + + case polygon: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + *x = m_src_vertices[0].x; + *y = m_src_vertices[0].y; + m_status = end_poly; + return path_cmd_curve4; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + *x = m_src_vertices[m_src_vertices.size() - 1].x; + *y = m_src_vertices[m_src_vertices.size() - 1].y; + m_status = end_poly; + return path_cmd_curve3; + } + } + + calculate(m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.next(m_src_vertex + 1)); + + *x = m_src_vertices[m_src_vertex].x; + *y = m_src_vertices[m_src_vertex].y; + m_src_vertex++; + + if(m_closed) + { + m_status = ctrl1; + return ((m_src_vertex == 1) ? + path_cmd_move_to : + path_cmd_curve4); + } + else + { + if(m_src_vertex == 1) + { + m_status = ctrl_b; + return path_cmd_move_to; + } + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = ctrl_e; + return path_cmd_curve3; + } + m_status = ctrl1; + return path_cmd_curve4; + } + break; + + case ctrl_b: + *x = m_ctrl2_x; + *y = m_ctrl2_y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl_e: + *x = m_ctrl1_x; + *y = m_ctrl1_y; + m_status = polygon; + return path_cmd_curve3; + + case ctrl1: + *x = m_ctrl1_x; + *y = m_ctrl1_y; + m_status = ctrl2; + return path_cmd_curve4; + + case ctrl2: + *x = m_ctrl2_x; + *y = m_ctrl2_y; + m_status = polygon; + return path_cmd_curve4; + + case end_poly: + m_status = stop; + return path_cmd_end_poly | m_closed; + + case stop: + return path_cmd_stop; + } + } + return cmd; + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_stroke.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_stroke.cpp new file mode 100644 index 00000000000..2dae3e122b8 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vcgen_stroke.cpp @@ -0,0 +1,213 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// Stroke generator +// +//---------------------------------------------------------------------------- +#include +#include "agg_vcgen_stroke.h" +#include "agg_shorten_path.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + vcgen_stroke::vcgen_stroke() : + m_stroker(), + m_src_vertices(), + m_out_vertices(), + m_shorten(0.0), + m_closed(0), + m_status(initial), + m_src_vertex(0), + m_out_vertex(0) + { + } + + //------------------------------------------------------------------------ + void vcgen_stroke::remove_all() + { + m_src_vertices.remove_all(); + m_closed = 0; + m_status = initial; + } + + + //------------------------------------------------------------------------ + void vcgen_stroke::add_vertex(double x, double y, unsigned cmd) + { + m_status = initial; + if(is_move_to(cmd)) + { + m_src_vertices.modify_last(vertex_dist(x, y)); + } + else + { + if(is_vertex(cmd)) + { + m_src_vertices.add(vertex_dist(x, y)); + } + else + { + m_closed = get_close_flag(cmd); + } + } + } + + //------------------------------------------------------------------------ + void vcgen_stroke::rewind(unsigned) + { + if(m_status == initial) + { + m_src_vertices.close(m_closed != 0); + shorten_path(m_src_vertices, m_shorten, m_closed); + if(m_src_vertices.size() < 3) m_closed = 0; + } + m_status = ready; + m_src_vertex = 0; + m_out_vertex = 0; + } + + + //------------------------------------------------------------------------ + unsigned vcgen_stroke::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + while(!is_stop(cmd)) + { + switch(m_status) + { + case initial: + rewind(0); + + case ready: + if(m_src_vertices.size() < 2 + unsigned(m_closed != 0)) + { + cmd = path_cmd_stop; + break; + } + m_status = m_closed ? outline1 : cap1; + cmd = path_cmd_move_to; + m_src_vertex = 0; + m_out_vertex = 0; + break; + + case cap1: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[0], + m_src_vertices[1], + m_src_vertices[0].dist); + m_src_vertex = 1; + m_prev_status = outline1; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case cap2: + m_stroker.calc_cap(m_out_vertices, + m_src_vertices[m_src_vertices.size() - 1], + m_src_vertices[m_src_vertices.size() - 2], + m_src_vertices[m_src_vertices.size() - 2].dist); + m_prev_status = outline2; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case outline1: + if(m_closed) + { + if(m_src_vertex >= m_src_vertices.size()) + { + m_prev_status = close_first; + m_status = end_poly1; + break; + } + } + else + { + if(m_src_vertex >= m_src_vertices.size() - 1) + { + m_status = cap2; + break; + } + } + m_stroker.calc_join(m_out_vertices, + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.next(m_src_vertex), + m_src_vertices.prev(m_src_vertex).dist, + m_src_vertices.curr(m_src_vertex).dist); + ++m_src_vertex; + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case close_first: + m_status = outline2; + cmd = path_cmd_move_to; + + case outline2: + if(m_src_vertex <= unsigned(m_closed == 0)) + { + m_status = end_poly2; + m_prev_status = stop; + break; + } + + --m_src_vertex; + m_stroker.calc_join(m_out_vertices, + m_src_vertices.next(m_src_vertex), + m_src_vertices.curr(m_src_vertex), + m_src_vertices.prev(m_src_vertex), + m_src_vertices.curr(m_src_vertex).dist, + m_src_vertices.prev(m_src_vertex).dist); + + m_prev_status = m_status; + m_status = out_vertices; + m_out_vertex = 0; + break; + + case out_vertices: + if(m_out_vertex >= m_out_vertices.size()) + { + m_status = m_prev_status; + } + else + { + const point_d& c = m_out_vertices[m_out_vertex++]; + *x = c.x; + *y = c.y; + return cmd; + } + break; + + case end_poly1: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_ccw; + + case end_poly2: + m_status = m_prev_status; + return path_cmd_end_poly | path_flags_close | path_flags_cw; + + case stop: + cmd = path_cmd_stop; + break; + } + } + return cmd; + } + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polygon.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polygon.cpp new file mode 100644 index 00000000000..45245260172 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polygon.cpp @@ -0,0 +1,133 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_vpgen_clip_polygon.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + // Determine the clipping code of the vertex according to the + // Cyrus-Beck line clipping algorithm + // + // | | + // 0110 | 0010 | 0011 + // | | + // -------+--------+-------- clip_box.y2 + // | | + // 0100 | 0000 | 0001 + // | | + // -------+--------+-------- clip_box.y1 + // | | + // 1100 | 1000 | 1001 + // | | + // clip_box.x1 clip_box.x2 + // + // + unsigned vpgen_clip_polygon::clipping_flags(double x, double y) + { + if(x < m_clip_box.x1) + { + if(y > m_clip_box.y2) return 6; + if(y < m_clip_box.y1) return 12; + return 4; + } + + if(x > m_clip_box.x2) + { + if(y > m_clip_box.y2) return 3; + if(y < m_clip_box.y1) return 9; + return 1; + } + + if(y > m_clip_box.y2) return 2; + if(y < m_clip_box.y1) return 8; + + return 0; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::reset() + { + m_vertex = 0; + m_num_vertices = 0; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::move_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + m_clip_flags = clipping_flags(x, y); + if(m_clip_flags == 0) + { + m_x[0] = x; + m_y[0] = y; + m_num_vertices = 1; + } + m_x1 = x; + m_y1 = y; + m_cmd = path_cmd_move_to; + } + + + //---------------------------------------------------------------------------- + void vpgen_clip_polygon::line_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + unsigned flags = clipping_flags(x, y); + + if(m_clip_flags == flags) + { + if(flags == 0) + { + m_x[0] = x; + m_y[0] = y; + m_num_vertices = 1; + } + } + else + { + m_num_vertices = clip_liang_barsky(m_x1, m_y1, + x, y, + m_clip_box, + m_x, m_y); + } + + m_clip_flags = flags; + m_x1 = x; + m_y1 = y; + } + + + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polygon::vertex(double* x, double* y) + { + if(m_vertex < m_num_vertices) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + ++m_vertex; + unsigned cmd = m_cmd; + m_cmd = path_cmd_line_to; + return cmd; + } + return path_cmd_stop; + } + + +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polyline.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polyline.cpp new file mode 100644 index 00000000000..6840803a988 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_clip_polyline.cpp @@ -0,0 +1,77 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include "agg_vpgen_clip_polyline.h" +#include "agg_clip_liang_barsky.h" + +namespace agg +{ + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::reset() + { + m_vertex = 0; + m_num_vertices = 0; + m_move_to = false; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::move_to(double x, double y) + { + m_vertex = 0; + m_num_vertices = 0; + m_x1 = x; + m_y1 = y; + m_move_to = true; + } + + //---------------------------------------------------------------------------- + void vpgen_clip_polyline::line_to(double x, double y) + { + double x2 = x; + double y2 = y; + unsigned flags = clip_line_segment(&m_x1, &m_y1, &x2, &y2, m_clip_box); + + m_vertex = 0; + m_num_vertices = 0; + if((flags & 4) == 0) + { + if((flags & 1) != 0 || m_move_to) + { + m_x[0] = m_x1; + m_y[0] = m_y1; + m_cmd[0] = path_cmd_move_to; + m_num_vertices = 1; + } + m_x[m_num_vertices] = x2; + m_y[m_num_vertices] = y2; + m_cmd[m_num_vertices++] = path_cmd_line_to; + m_move_to = (flags & 2) != 0; + } + m_x1 = x; + m_y1 = y; + } + + //---------------------------------------------------------------------------- + unsigned vpgen_clip_polyline::vertex(double* x, double* y) + { + if(m_vertex < m_num_vertices) + { + *x = m_x[m_vertex]; + *y = m_y[m_vertex]; + return m_cmd[m_vertex++]; + } + return path_cmd_stop; + } +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_segmentator.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_segmentator.cpp new file mode 100644 index 00000000000..49a45b6b13d --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/agg_vpgen_segmentator.cpp @@ -0,0 +1,67 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- + +#include +#include "agg_vpgen_segmentator.h" + +namespace agg +{ + + void vpgen_segmentator::move_to(double x, double y) + { + m_x1 = x; + m_y1 = y; + m_dx = 0.0; + m_dy = 0.0; + m_dl = 2.0; + m_ddl = 2.0; + m_cmd = path_cmd_move_to; + } + + void vpgen_segmentator::line_to(double x, double y) + { + m_x1 += m_dx; + m_y1 += m_dy; + m_dx = x - m_x1; + m_dy = y - m_y1; + double len = sqrt(m_dx * m_dx + m_dy * m_dy) * m_approximation_scale; + if(len < 1e-30) len = 1e-30; + m_ddl = 1.0 / len; + m_dl = (m_cmd == path_cmd_move_to) ? 0.0 : m_ddl; + if(m_cmd == path_cmd_stop) m_cmd = path_cmd_line_to; + } + + unsigned vpgen_segmentator::vertex(double* x, double* y) + { + if(m_cmd == path_cmd_stop) return path_cmd_stop; + + unsigned cmd = m_cmd; + m_cmd = path_cmd_line_to; + if(m_dl >= 1.0 - m_ddl) + { + m_dl = 1.0; + m_cmd = path_cmd_stop; + *x = m_x1 + m_dx; + *y = m_y1 + m_dy; + return cmd; + } + *x = m_x1 + m_dx * m_dl; + *y = m_y1 + m_dy * m_dl; + m_dl += m_ddl; + return cmd; + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/authors b/contrib/python/matplotlib/py2/extern/agg24-svn/src/authors new file mode 100644 index 00000000000..e69de29bb2d diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/copying b/contrib/python/matplotlib/py2/extern/agg24-svn/src/copying new file mode 100644 index 00000000000..a08de15faa5 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/copying @@ -0,0 +1,11 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry - Version 2.4 +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +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. diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_bezier_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_bezier_ctrl.cpp new file mode 100644 index 00000000000..13a4c15af9c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_bezier_ctrl.cpp @@ -0,0 +1,370 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes bezier_ctrl_impl, bezier_ctrl +// +//---------------------------------------------------------------------------- + +#include +#include +#include "ctrl/agg_bezier_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + bezier_ctrl_impl::bezier_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(4, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + m_poly.xn(3) = 0.0; + m_poly.yn(3) = 100.0; + } + + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3, + double x4, double y4) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + m_poly.xn(3) = x4; + m_poly.yn(3) = y4; + curve(); + } + + //------------------------------------------------------------------------ + curve4& bezier_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + return m_curve; + } + + //------------------------------------------------------------------------ + void bezier_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + m_curve.approximation_scale(scale()); + switch(idx) + { + default: + case 0: // Control line 1 + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(2), m_poly.yn(2), + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + (m_poly.xn(2) + m_poly.xn(3)) * 0.5, + (m_poly.yn(2) + m_poly.yn(3)) * 0.5, + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2), + m_poly.xn(3), m_poly.yn(3)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 6: // Point 4 + m_ellipse.init(m_poly.xn(3), m_poly.yn(3), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned bezier_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + case 7: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool bezier_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + //------------------------------------------------------------------------ + curve3_ctrl_impl::curve3_ctrl_impl() : + ctrl(0,0,1,1,false), + m_stroke(m_curve), + m_poly(3, 5.0), + m_idx(0) + { + m_poly.in_polygon_check(false); + m_poly.xn(0) = 100.0; + m_poly.yn(0) = 0.0; + m_poly.xn(1) = 100.0; + m_poly.yn(1) = 50.0; + m_poly.xn(2) = 50.0; + m_poly.yn(2) = 100.0; + } + + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::curve(double x1, double y1, + double x2, double y2, + double x3, double y3) + { + m_poly.xn(0) = x1; + m_poly.yn(0) = y1; + m_poly.xn(1) = x2; + m_poly.yn(1) = y2; + m_poly.xn(2) = x3; + m_poly.yn(2) = y3; + curve(); + } + + //------------------------------------------------------------------------ + curve3& curve3_ctrl_impl::curve() + { + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + return m_curve; + } + + //------------------------------------------------------------------------ + void curve3_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + case 0: // Control line + m_curve.init(m_poly.xn(0), m_poly.yn(0), + (m_poly.xn(0) + m_poly.xn(1)) * 0.5, + (m_poly.yn(0) + m_poly.yn(1)) * 0.5, + m_poly.xn(1), m_poly.yn(1)); + m_stroke.rewind(0); + break; + + case 1: // Control line 2 + m_curve.init(m_poly.xn(1), m_poly.yn(1), + (m_poly.xn(1) + m_poly.xn(2)) * 0.5, + (m_poly.yn(1) + m_poly.yn(2)) * 0.5, + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 2: // Curve itself + m_curve.init(m_poly.xn(0), m_poly.yn(0), + m_poly.xn(1), m_poly.yn(1), + m_poly.xn(2), m_poly.yn(2)); + m_stroke.rewind(0); + break; + + case 3: // Point 1 + m_ellipse.init(m_poly.xn(0), m_poly.yn(0), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 4: // Point 2 + m_ellipse.init(m_poly.xn(1), m_poly.yn(1), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + + case 5: // Point 3 + m_ellipse.init(m_poly.xn(2), m_poly.yn(2), point_radius(), point_radius(), 20); + m_ellipse.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned curve3_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + switch(m_idx) + { + case 0: + case 1: + case 2: + cmd = m_stroke.vertex(x, y); + break; + + case 3: + case 4: + case 5: + case 6: + cmd = m_ellipse.vertex(x, y); + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_button_down(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + return m_poly.on_mouse_move(x, y, button_flag); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_mouse_button_up(double x, double y) + { + return m_poly.on_mouse_button_up(x, y); + } + + + //------------------------------------------------------------------------ + bool curve3_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return m_poly.on_arrow_keys(left, right, down, up); + } + + + + + + + + + + + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_cbox_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_cbox_ctrl.cpp new file mode 100644 index 00000000000..3cf14f6a854 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_cbox_ctrl.cpp @@ -0,0 +1,214 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes rbox_ctrl_impl, rbox_ctrl +// +//---------------------------------------------------------------------------- + +#include +#include "ctrl/agg_cbox_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + cbox_ctrl_impl::cbox_ctrl_impl(double x, double y, + const char* l, + bool flip_y) : + ctrl(x, y, x + 9.0 * 1.5, y + 9.0 * 1.5, flip_y), + m_text_thickness(1.5), + m_text_height(9.0), + m_text_width(0.0), + m_status(false), + m_text_poly(m_text) + { + label(l); + } + + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + } + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::label(const char* l) + { + unsigned len = strlen(l); + if(len > 127) len = 127; + memcpy(m_label, l, len); + m_label[len] = 0; + } + + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + if(x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2) + { + m_status = !m_status; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_move(double, double, bool) + { + return false; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && y >= m_y1 && x <= m_x2 && y <= m_y2; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_mouse_button_up(double, double) + { + return false; + } + + //------------------------------------------------------------------------ + bool cbox_ctrl_impl::on_arrow_keys(bool, bool, bool, bool) + { + return false; + } + + + //------------------------------------------------------------------------ + void cbox_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + double d2; + double t; + + switch(idx) + { + default: + case 0: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_text_thickness; + m_vy[4] = m_y1 + m_text_thickness; + m_vx[5] = m_x1 + m_text_thickness; + m_vy[5] = m_y2 - m_text_thickness; + m_vx[6] = m_x2 - m_text_thickness; + m_vy[6] = m_y2 - m_text_thickness; + m_vx[7] = m_x2 - m_text_thickness; + m_vy[7] = m_y1 + m_text_thickness; + break; + + case 1: // Text + m_text.text(m_label); + m_text.start_point(m_x1 + m_text_height * 2.0, m_y1 + m_text_height / 5.0); + m_text.size(m_text_height, m_text_width); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 2: // Active item + m_vertex = 0; + d2 = (m_y2 - m_y1) / 2.0; + t = m_text_thickness * 1.5; + m_vx[0] = m_x1 + m_text_thickness; + m_vy[0] = m_y1 + m_text_thickness; + m_vx[1] = m_x1 + d2; + m_vy[1] = m_y1 + d2 - t; + m_vx[2] = m_x2 - m_text_thickness; + m_vy[2] = m_y1 + m_text_thickness; + m_vx[3] = m_x1 + d2 + t; + m_vy[3] = m_y1 + d2; + m_vx[4] = m_x2 - m_text_thickness; + m_vy[4] = m_y2 - m_text_thickness; + m_vx[5] = m_x1 + d2; + m_vy[5] = m_y1 + d2 + t; + m_vx[6] = m_x1 + m_text_thickness; + m_vy[6] = m_y2 - m_text_thickness; + m_vx[7] = m_x1 + d2 - t; + m_vy[7] = m_y1 + d2; + break; + + } + } + + + + + //------------------------------------------------------------------------ + unsigned cbox_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + cmd = m_text_poly.vertex(x, y); + break; + + case 2: + if(m_status) + { + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + } + else + { + cmd = path_cmd_stop; + } + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } +} + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_ctrl.cpp new file mode 100644 index 00000000000..7fd6448cd5b --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_ctrl.cpp @@ -0,0 +1,433 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class gamma_ctrl_impl +// +//---------------------------------------------------------------------------- + +#include +#include "agg_math.h" +#include "ctrl/agg_gamma_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + gamma_ctrl_impl::gamma_ctrl_impl(double x1, double y1, double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(2.0), + m_border_extra(0.0), + m_curve_width(2.0), + m_grid_width(0.2), + m_text_thickness(1.5), + m_point_size(5.0), + m_text_height(9.0), + m_text_width(0.0), + m_xc1(x1), + m_yc1(y1), + m_xc2(x2), + m_yc2(y2 - m_text_height * 2.0), + m_xt1(x1), + m_yt1(y2 - m_text_height * 2.0), + m_xt2(x2), + m_yt2(y2), + m_curve_poly(m_gamma_spline), + m_text_poly(m_text), + m_idx(0), + m_vertex(0), + m_p1_active(true), + m_mouse_point(0), + m_pdx(0.0), + m_pdy(0.0) + { + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_spline_box() + { + m_xs1 = m_xc1 + m_border_width; + m_ys1 = m_yc1 + m_border_width; + m_xs2 = m_xc2 - m_border_width; + m_ys2 = m_yc2 - m_border_width * 0.5; + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_points() + { + double kx1, ky1, kx2, ky2; + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + m_xp1 = m_xs1 + (m_xs2 - m_xs1) * kx1 * 0.25; + m_yp1 = m_ys1 + (m_ys2 - m_ys1) * ky1 * 0.25; + m_xp2 = m_xs2 - (m_xs2 - m_xs1) * kx2 * 0.25; + m_yp2 = m_ys2 - (m_ys2 - m_ys1) * ky2 * 0.25; + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::calc_values() + { + double kx1, ky1, kx2, ky2; + + kx1 = (m_xp1 - m_xs1) * 4.0 / (m_xs2 - m_xs1); + ky1 = (m_yp1 - m_ys1) * 4.0 / (m_ys2 - m_ys1); + kx2 = (m_xs2 - m_xp2) * 4.0 / (m_xs2 - m_xs1); + ky2 = (m_ys2 - m_yp2) * 4.0 / (m_ys2 - m_ys1); + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + m_yc2 = m_y2 - m_text_height * 2.0; + m_yt1 = m_y2 - m_text_height * 2.0; + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_spline_box(); + } + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::values(double kx1, double ky1, double kx2, double ky2) + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::values(double* kx1, double* ky1, double* kx2, double* ky2) const + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::rewind(unsigned idx) + { + double kx1, ky1, kx2, ky2; + char tbuf[32]; + + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + m_vx[8] = m_xc1 + m_border_width; + m_vy[8] = m_yc2 - m_border_width * 0.5; + m_vx[9] = m_xc2 - m_border_width; + m_vy[9] = m_yc2 - m_border_width * 0.5; + m_vx[10] = m_xc2 - m_border_width; + m_vy[10] = m_yc2 + m_border_width * 0.5; + m_vx[11] = m_xc1 + m_border_width; + m_vy[11] = m_yc2 + m_border_width * 0.5; + break; + + case 2: // Curve + m_gamma_spline.box(m_xs1, m_ys1, m_xs2, m_ys2); + m_curve_poly.width(m_curve_width); + m_curve_poly.rewind(0); + break; + + case 3: // Grid + m_vertex = 0; + m_vx[0] = m_xs1; + m_vy[0] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5; + m_vx[1] = m_xs2; + m_vy[1] = (m_ys1 + m_ys2) * 0.5 - m_grid_width * 0.5; + m_vx[2] = m_xs2; + m_vy[2] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5; + m_vx[3] = m_xs1; + m_vy[3] = (m_ys1 + m_ys2) * 0.5 + m_grid_width * 0.5; + m_vx[4] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5; + m_vy[4] = m_ys1; + m_vx[5] = (m_xs1 + m_xs2) * 0.5 - m_grid_width * 0.5; + m_vy[5] = m_ys2; + m_vx[6] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5; + m_vy[6] = m_ys2; + m_vx[7] = (m_xs1 + m_xs2) * 0.5 + m_grid_width * 0.5; + m_vy[7] = m_ys1; + calc_points(); + m_vx[8] = m_xs1; + m_vy[8] = m_yp1 - m_grid_width * 0.5; + m_vx[9] = m_xp1 - m_grid_width * 0.5; + m_vy[9] = m_yp1 - m_grid_width * 0.5; + m_vx[10] = m_xp1 - m_grid_width * 0.5; + m_vy[10] = m_ys1; + m_vx[11] = m_xp1 + m_grid_width * 0.5; + m_vy[11] = m_ys1; + m_vx[12] = m_xp1 + m_grid_width * 0.5; + m_vy[12] = m_yp1 + m_grid_width * 0.5; + m_vx[13] = m_xs1; + m_vy[13] = m_yp1 + m_grid_width * 0.5; + m_vx[14] = m_xs2; + m_vy[14] = m_yp2 + m_grid_width * 0.5; + m_vx[15] = m_xp2 + m_grid_width * 0.5; + m_vy[15] = m_yp2 + m_grid_width * 0.5; + m_vx[16] = m_xp2 + m_grid_width * 0.5; + m_vy[16] = m_ys2; + m_vx[17] = m_xp2 - m_grid_width * 0.5; + m_vy[17] = m_ys2; + m_vx[18] = m_xp2 - m_grid_width * 0.5; + m_vy[18] = m_yp2 - m_grid_width * 0.5; + m_vx[19] = m_xs2; + m_vy[19] = m_yp2 - m_grid_width * 0.5; + break; + + case 4: // Point1 + calc_points(); + if(m_p1_active) m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32); + else m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32); + break; + + case 5: // Point2 + calc_points(); + if(m_p1_active) m_ellipse.init(m_xp1, m_yp1, m_point_size, m_point_size, 32); + else m_ellipse.init(m_xp2, m_yp2, m_point_size, m_point_size, 32); + break; + + case 6: // Text + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + sprintf(tbuf, "%5.3f %5.3f %5.3f %5.3f", kx1, ky1, kx2, ky2); + m_text.text(tbuf); + m_text.size(m_text_height, m_text_width); + m_text.start_point(m_xt1 + m_border_width * 2.0, (m_yt1 + m_yt2) * 0.5 - m_text_height * 0.5); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + } + } + + + //------------------------------------------------------------------------ + unsigned gamma_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4 || m_vertex == 8) cmd = path_cmd_move_to; + if(m_vertex >= 12) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_curve_poly.vertex(x, y); + break; + + case 3: + if(m_vertex == 0 || + m_vertex == 4 || + m_vertex == 8 || + m_vertex == 14) cmd = path_cmd_move_to; + + if(m_vertex >= 20) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 4: // Point1 + case 5: // Point2 + cmd = m_ellipse.vertex(x, y); + break; + + case 6: + cmd = m_text_poly.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double kx1, ky1, kx2, ky2; + bool ret = false; + m_gamma_spline.values(&kx1, &ky1, &kx2, &ky2); + if(m_p1_active) + { + if(left) { kx1 -= 0.005; ret = true; } + if(right) { kx1 += 0.005; ret = true; } + if(down) { ky1 -= 0.005; ret = true; } + if(up) { ky1 += 0.005; ret = true; } + } + else + { + if(left) { kx2 += 0.005; ret = true; } + if(right) { kx2 -= 0.005; ret = true; } + if(down) { ky2 += 0.005; ret = true; } + if(up) { ky2 -= 0.005; ret = true; } + } + if(ret) + { + m_gamma_spline.values(kx1, ky1, kx2, ky2); + } + return ret; + } + + + + //------------------------------------------------------------------------ + void gamma_ctrl_impl::change_active_point() + { + m_p1_active = m_p1_active ? false : true; + } + + + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + calc_points(); + + if(calc_distance(x, y, m_xp1, m_yp1) <= m_point_size + 1) + { + m_mouse_point = 1; + m_pdx = m_xp1 - x; + m_pdy = m_yp1 - y; + m_p1_active = true; + return true; + } + + if(calc_distance(x, y, m_xp2, m_yp2) <= m_point_size + 1) + { + m_mouse_point = 2; + m_pdx = m_xp2 - x; + m_pdy = m_yp2 - y; + m_p1_active = false; + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_button_up(double, double) + { + if(m_mouse_point) + { + m_mouse_point = 0; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool gamma_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + if(m_mouse_point == 1) + { + m_xp1 = x + m_pdx; + m_yp1 = y + m_pdy; + calc_values(); + return true; + } + if(m_mouse_point == 2) + { + m_xp2 = x + m_pdx; + m_yp2 = y + m_pdy; + calc_values(); + return true; + } + return false; + } + + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_spline.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_spline.cpp new file mode 100644 index 00000000000..f720fddd8e7 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_gamma_spline.cpp @@ -0,0 +1,130 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class gamma_spline +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_gamma_spline.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + gamma_spline::gamma_spline() : + m_x1(0), m_y1(0), m_x2(10), m_y2(10), m_cur_x(0.0) + { + values(1.0, 1.0, 1.0, 1.0); + } + + + //------------------------------------------------------------------------ + double gamma_spline::y(double x) const + { + if(x < 0.0) x = 0.0; + if(x > 1.0) x = 1.0; + double val = m_spline.get(x); + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + return val; + } + + + + //------------------------------------------------------------------------ + void gamma_spline::values(double kx1, double ky1, double kx2, double ky2) + { + if(kx1 < 0.001) kx1 = 0.001; + if(kx1 > 1.999) kx1 = 1.999; + if(ky1 < 0.001) ky1 = 0.001; + if(ky1 > 1.999) ky1 = 1.999; + if(kx2 < 0.001) kx2 = 0.001; + if(kx2 > 1.999) kx2 = 1.999; + if(ky2 < 0.001) ky2 = 0.001; + if(ky2 > 1.999) ky2 = 1.999; + + m_x[0] = 0.0; + m_y[0] = 0.0; + m_x[1] = kx1 * 0.25; + m_y[1] = ky1 * 0.25; + m_x[2] = 1.0 - kx2 * 0.25; + m_y[2] = 1.0 - ky2 * 0.25; + m_x[3] = 1.0; + m_y[3] = 1.0; + + m_spline.init(4, m_x, m_y); + + int i; + for(i = 0; i < 256; i++) + { + m_gamma[i] = (unsigned char)(y(double(i) / 255.0) * 255.0); + } + } + + + //------------------------------------------------------------------------ + void gamma_spline::values(double* kx1, double* ky1, double* kx2, double* ky2) const + { + *kx1 = m_x[1] * 4.0; + *ky1 = m_y[1] * 4.0; + *kx2 = (1.0 - m_x[2]) * 4.0; + *ky2 = (1.0 - m_y[2]) * 4.0; + } + + + //------------------------------------------------------------------------ + void gamma_spline::box(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + } + + + //------------------------------------------------------------------------ + void gamma_spline::rewind(unsigned) + { + m_cur_x = 0.0; + } + + + //------------------------------------------------------------------------ + unsigned gamma_spline::vertex(double* vx, double* vy) + { + if(m_cur_x == 0.0) + { + *vx = m_x1; + *vy = m_y1; + m_cur_x += 1.0 / (m_x2 - m_x1); + return path_cmd_move_to; + } + + if(m_cur_x > 1.0) + { + return path_cmd_stop; + } + + *vx = m_x1 + m_cur_x * (m_x2 - m_x1); + *vy = m_y1 + y(m_cur_x) * (m_y2 - m_y1); + + m_cur_x += 1.0 / (m_x2 - m_x1); + return path_cmd_line_to; + } + + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_polygon_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_polygon_ctrl.cpp new file mode 100644 index 00000000000..40daee45e83 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_polygon_ctrl.cpp @@ -0,0 +1,332 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes polygon_ctrl_impl +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_polygon_ctrl.h" + +namespace agg +{ + + polygon_ctrl_impl::polygon_ctrl_impl(unsigned np, double point_radius) : + ctrl(0, 0, 1, 1, false), + m_polygon(np * 2), + m_num_points(np), + m_node(-1), + m_edge(-1), + m_vs(&m_polygon[0], m_num_points, false), + m_stroke(m_vs), + m_point_radius(point_radius), + m_status(0), + m_dx(0.0), + m_dy(0.0), + m_in_polygon_check(true) + { + m_stroke.width(1.0); + } + + + void polygon_ctrl_impl::rewind(unsigned) + { + m_status = 0; + m_stroke.rewind(0); + } + + unsigned polygon_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_stop; + double r = m_point_radius; + if(m_status == 0) + { + cmd = m_stroke.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + } + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + return cmd; + } + if(m_status >= m_num_points) return path_cmd_stop; + if(m_node >= 0 && m_node == int(m_status)) r *= 1.2; + m_ellipse.init(xn(m_status), yn(m_status), r, r, 32); + ++m_status; + cmd = m_ellipse.vertex(x, y); + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + return cmd; + } + + + bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const + { + bool ret = false; + + unsigned n1 = i; + unsigned n2 = (i + m_num_points - 1) % m_num_points; + double x1 = xn(n1); + double y1 = yn(n1); + double x2 = xn(n2); + double y2 = yn(n2); + + double dx = x2 - x1; + double dy = y2 - y1; + + if(sqrt(dx*dx + dy*dy) > 0.0000001) + { + double x3 = x; + double y3 = y; + double x4 = x3 - dy; + double y4 = y3 + dx; + + double den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1); + double u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den; + + double xi = x1 + u1 * (x2 - x1); + double yi = y1 + u1 * (y2 - y1); + + dx = xi - x; + dy = yi - y; + + if (u1 > 0.0 && u1 < 1.0 && sqrt(dx*dx + dy*dy) <= m_point_radius) + { + ret = true; + } + } + return ret; + } + + + + bool polygon_ctrl_impl::in_rect(double x, double y) const + { + return false; + } + + + bool polygon_ctrl_impl::on_mouse_button_down(double x, double y) + { + unsigned i; + bool ret = false; + m_node = -1; + m_edge = -1; + inverse_transform_xy(&x, &y); + for (i = 0; i < m_num_points; i++) + { + if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius) + { + m_dx = x - xn(i); + m_dy = y - yn(i); + m_node = int(i); + ret = true; + break; + } + } + + if(!ret) + { + for (i = 0; i < m_num_points; i++) + { + if(check_edge(i, x, y)) + { + m_dx = x; + m_dy = y; + m_edge = int(i); + ret = true; + break; + } + } + } + + if(!ret) + { + if(point_in_polygon(x, y)) + { + m_dx = x; + m_dy = y; + m_node = int(m_num_points); + ret = true; + } + } + return ret; + } + + + bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + bool ret = false; + double dx; + double dy; + inverse_transform_xy(&x, &y); + if(m_node == int(m_num_points)) + { + dx = x - m_dx; + dy = y - m_dy; + unsigned i; + for(i = 0; i < m_num_points; i++) + { + xn(i) += dx; + yn(i) += dy; + } + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_edge >= 0) + { + unsigned n1 = m_edge; + unsigned n2 = (n1 + m_num_points - 1) % m_num_points; + dx = x - m_dx; + dy = y - m_dy; + xn(n1) += dx; + yn(n1) += dy; + xn(n2) += dx; + yn(n2) += dy; + m_dx = x; + m_dy = y; + ret = true; + } + else + { + if(m_node >= 0) + { + xn(m_node) = x - m_dx; + yn(m_node) = y - m_dy; + ret = true; + } + } + } + return ret; + } + + bool polygon_ctrl_impl::on_mouse_button_up(double x, double y) + { + bool ret = (m_node >= 0) || (m_edge >= 0); + m_node = -1; + m_edge = -1; + return ret; + } + + + bool polygon_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + return false; + } + + + //======= Crossings Multiply algorithm of InsideTest ======================== + // + // By Eric Haines, 3D/Eye Inc, erich@eye.com + // + // This version is usually somewhat faster than the original published in + // Graphics Gems IV; by turning the division for testing the X axis crossing + // into a tricky multiplication test this part of the test became faster, + // which had the additional effect of making the test for "both to left or + // both to right" a bit slower for triangles than simply computing the + // intersection each time. The main increase is in triangle testing speed, + // which was about 15% faster; all other polygon complexities were pretty much + // the same as before. On machines where division is very expensive (not the + // case on the HP 9000 series on which I tested) this test should be much + // faster overall than the old code. Your mileage may (in fact, will) vary, + // depending on the machine and the test data, but in general I believe this + // code is both shorter and faster. This test was inspired by unpublished + // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson. + // Related work by Samosky is in: + // + // Samosky, Joseph, "SectionView: A system for interactively specifying and + // visualizing sections through three-dimensional medical image data", + // M.S. Thesis, Department of Electrical Engineering and Computer Science, + // Massachusetts Institute of Technology, 1993. + // + // Shoot a test ray along +X axis. The strategy is to compare vertex Y values + // to the testing point's Y and quickly discard edges which are entirely to one + // side of the test ray. Note that CONVEX and WINDING code can be added as + // for the CrossingsTest() code; it is left out here for clarity. + // + // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point + // _point_, returns 1 if inside, 0 if outside. + bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const + { + if(m_num_points < 3) return false; + if(!m_in_polygon_check) return false; + + unsigned j; + int yflag0, yflag1, inside_flag; + double vtx0, vty0, vtx1, vty1; + + vtx0 = xn(m_num_points - 1); + vty0 = yn(m_num_points - 1); + + // get test bit for above/below X axis + yflag0 = (vty0 >= ty); + + vtx1 = xn(0); + vty1 = yn(0); + + inside_flag = 0; + for (j = 1; j <= m_num_points; ++j) + { + yflag1 = (vty1 >= ty); + // Check if endpoints straddle (are on opposite sides) of X axis + // (i.e. the Y's differ); if so, +X ray could intersect this edge. + // The old test also checked whether the endpoints are both to the + // right or to the left of the test point. However, given the faster + // intersection point computation used below, this test was found to + // be a break-even proposition for most polygons and a loser for + // triangles (where 50% or more of the edges which survive this test + // will cross quadrants and so have to have the X intersection computed + // anyway). I credit Joseph Samosky with inspiring me to try dropping + // the "both left or both right" part of my code. + if (yflag0 != yflag1) + { + // Check intersection of pgon segment with +X ray. + // Note if >= point's X; if so, the ray hits it. + // The division operation is avoided for the ">=" test by checking + // the sign of the first vertex wrto the test point; idea inspired + // by Joseph Samosky's and Mark Haigh-Hutchinson's different + // polygon inclusion tests. + if ( ((vty1-ty) * (vtx0-vtx1) >= + (vtx1-tx) * (vty0-vty1)) == yflag1 ) + { + inside_flag ^= 1; + } + } + + // Move to the next pair of vertices, retaining info as possible. + yflag0 = yflag1; + vtx0 = vtx1; + vty0 = vty1; + + unsigned k = (j >= m_num_points) ? j - m_num_points : j; + vtx1 = xn(k); + vty1 = yn(k); + } + return inside_flag != 0; + } +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_rbox_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_rbox_ctrl.cpp new file mode 100644 index 00000000000..4e36b3b26b9 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_rbox_ctrl.cpp @@ -0,0 +1,325 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes rbox_ctrl_impl, rbox_ctrl +// +//---------------------------------------------------------------------------- + +#include +#include "ctrl/agg_rbox_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + rbox_ctrl_impl::rbox_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(1.0), + m_border_extra(0.0), + m_text_thickness(1.5), + m_text_height(9.0), + m_text_width(0.0), + m_num_items(0), + m_cur_item(-1), + m_ellipse_poly(m_ellipse), + m_text_poly(m_text), + m_idx(0), + m_vertex(0) + { + calc_rbox(); + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::calc_rbox() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::add_item(const char* text) + { + if(m_num_items < 32) + { + m_items[m_num_items].resize(strlen(text) + 1); + strcpy(&m_items[m_num_items][0], text); + m_num_items++; + } + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_rbox(); + } + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::text_size(double h, double w) + { + m_text_width = w; + m_text_height = h; + } + + + + //------------------------------------------------------------------------ + void rbox_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + m_dy = m_text_height * 2.0; + m_draw_item = 0; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + break; + + case 2: // Text + m_text.text(&m_items[0][0]); + m_text.start_point(m_xs1 + m_dy * 1.5, m_ys1 + m_dy / 2.0); + m_text.size(m_text_height, m_text_width); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 3: // Inactive items + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy / 1.3, + m_text_height / 1.5, + m_text_height / 1.5, 32); + m_ellipse_poly.width(m_text_thickness); + m_ellipse_poly.rewind(0); + break; + + + case 4: // Active Item + if(m_cur_item >= 0) + { + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy * m_cur_item + m_dy / 1.3, + m_text_height / 2.0, + m_text_height / 2.0, 32); + m_ellipse.rewind(0); + } + break; + + } + } + + + //------------------------------------------------------------------------ + unsigned rbox_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_text_poly.vertex(x, y); + if(is_stop(cmd)) + { + m_draw_item++; + if(m_draw_item >= m_num_items) + { + break; + } + else + { + m_text.text(&m_items[m_draw_item][0]); + m_text.start_point(m_xs1 + m_dy * 1.5, + m_ys1 + m_dy * (m_draw_item + 1) - m_dy / 2.0); + + m_text_poly.rewind(0); + cmd = m_text_poly.vertex(x, y); + } + } + break; + + case 3: + cmd = m_ellipse_poly.vertex(x, y); + if(is_stop(cmd)) + { + m_draw_item++; + if(m_draw_item >= m_num_items) + { + break; + } + else + { + m_ellipse.init(m_xs1 + m_dy / 1.3, + m_ys1 + m_dy * m_draw_item + m_dy / 1.3, + m_text_height / 1.5, + m_text_height / 1.5, 32); + m_ellipse_poly.rewind(0); + cmd = m_ellipse_poly.vertex(x, y); + } + } + break; + + + case 4: + if(m_cur_item >= 0) + { + cmd = m_ellipse.vertex(x, y); + } + else + { + cmd = path_cmd_stop; + } + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + unsigned i; + for(i = 0; i < m_num_items; i++) + { + double xp = m_xs1 + m_dy / 1.3; + double yp = m_ys1 + m_dy * i + m_dy / 1.3; + if(calc_distance(x, y, xp, yp) <= m_text_height / 1.5) + { + m_cur_item = int(i); + return true; + } + } + return false; + } + + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_move(double, double, bool) + { + return false; + } + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_mouse_button_up(double, double) + { + return false; + } + + //------------------------------------------------------------------------ + bool rbox_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + if(m_cur_item >= 0) + { + if(up || right) + { + m_cur_item++; + if(m_cur_item >= int(m_num_items)) + { + m_cur_item = 0; + } + return true; + } + + if(down || left) + { + m_cur_item--; + if(m_cur_item < 0) + { + m_cur_item = m_num_items - 1; + } + return true; + } + } + return false; + } + + +} + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_scale_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_scale_ctrl.cpp new file mode 100644 index 00000000000..7f167792bd9 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_scale_ctrl.cpp @@ -0,0 +1,454 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes scale_ctrl_impl, scale_ctrl +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_scale_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + scale_ctrl_impl::scale_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_thickness(1.0), + m_border_extra((fabs(x2 - x1) > fabs(y2 - y1)) ? (y2 - y1) / 2 : (x2 - x1) / 2), + m_pdx(0.0), + m_pdy(0.0), + m_move_what(move_nothing), + m_value1(0.3), + m_value2(0.7), + m_min_d(0.01) + { + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::calc_box() + { + m_xs1 = m_x1 + m_border_thickness; + m_ys1 = m_y1 + m_border_thickness; + m_xs2 = m_x2 - m_border_thickness; + m_ys2 = m_y2 - m_border_thickness; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::border_thickness(double t, double extra) + { + m_border_thickness = t; + m_border_extra = extra; + calc_box(); + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::resize(double x1, double y1, double x2, double y2) + { + m_x1 = x1; + m_y1 = y1; + m_x2 = x2; + m_y2 = y2; + calc_box(); + m_border_extra = (fabs(x2 - x1) > fabs(y2 - y1)) ? + (y2 - y1) / 2 : + (x2 - x1) / 2; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value1(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value2 - value < m_min_d) value = m_value2 - m_min_d; + m_value1 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::value2(double value) + { + if(value < 0.0) value = 0.0; + if(value > 1.0) value = 1.0; + if(m_value1 + value < m_min_d) value = m_value1 + m_min_d; + m_value2 = value; + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::move(double d) + { + m_value1 += d; + m_value2 += d; + if(m_value1 < 0.0) + { + m_value2 -= m_value1; + m_value1 = 0.0; + } + if(m_value2 > 1.0) + { + m_value1 -= m_value2 - 1.0; + m_value2 = 1.0; + } + } + + + //------------------------------------------------------------------------ + void scale_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_thickness; + m_vy[4] = m_y1 + m_border_thickness; + m_vx[5] = m_x1 + m_border_thickness; + m_vy[5] = m_y2 - m_border_thickness; + m_vx[6] = m_x2 - m_border_thickness; + m_vy[6] = m_y2 - m_border_thickness; + m_vx[7] = m_x2 - m_border_thickness; + m_vy[7] = m_y1 + m_border_thickness; + break; + + case 2: // pointer1 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value1, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value1, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 3: // pointer2 + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value2, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + } + else + { + m_ellipse.init((m_xs1 + m_xs2) / 2.0, + m_ys1 + (m_ys2 - m_ys1) * m_value2, + m_x2 - m_x1, + m_x2 - m_x1, + 32); + } + m_ellipse.rewind(0); + break; + + case 4: // slider + m_vertex = 0; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_vx[0] = m_xs1 + (m_xs2 - m_xs1) * m_value1; + m_vy[0] = m_y1 - m_border_extra / 2.0; + m_vx[1] = m_xs1 + (m_xs2 - m_xs1) * m_value2; + m_vy[1] = m_vy[0]; + m_vx[2] = m_vx[1]; + m_vy[2] = m_y2 + m_border_extra / 2.0; + m_vx[3] = m_vx[0]; + m_vy[3] = m_vy[2]; + } + else + { + m_vx[0] = m_x1 - m_border_extra / 2.0; + m_vy[0] = m_ys1 + (m_ys2 - m_ys1) * m_value1; + m_vx[1] = m_vx[0]; + m_vy[1] = m_ys1 + (m_ys2 - m_ys1) * m_value2; + m_vx[2] = m_x2 + m_border_extra / 2.0; + m_vy[2] = m_vy[1]; + m_vx[3] = m_vx[2]; + m_vy[3] = m_vy[0]; + } + break; + } + } + + + //------------------------------------------------------------------------ + unsigned scale_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + case 4: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + case 3: + cmd = m_ellipse.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + + double xp1; + double xp2; + double ys1; + double ys2; + double xp; + double yp; + + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + xp1 = m_xs1 + (m_xs2 - m_xs1) * m_value1; + xp2 = m_xs1 + (m_xs2 - m_xs1) * m_value2; + ys1 = m_y1 - m_border_extra / 2.0; + ys2 = m_y2 + m_border_extra / 2.0; + yp = (m_ys1 + m_ys2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdx = xp1 - x; + m_move_what = move_slider; + return true; + } + + //if(x < xp1 && calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp1, yp) <= m_y2 - m_y1) + { + m_pdx = xp1 - x; + m_move_what = move_value1; + return true; + } + + //if(x > xp2 && calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + if(calc_distance(x, y, xp2, yp) <= m_y2 - m_y1) + { + m_pdx = xp2 - x; + m_move_what = move_value2; + return true; + } + } + else + { + xp1 = m_x1 - m_border_extra / 2.0; + xp2 = m_x2 + m_border_extra / 2.0; + ys1 = m_ys1 + (m_ys2 - m_ys1) * m_value1; + ys2 = m_ys1 + (m_ys2 - m_ys1) * m_value2; + xp = (m_xs1 + m_xs2) / 2.0; + + if(x > xp1 && y > ys1 && x < xp2 && y < ys2) + { + m_pdy = ys1 - y; + m_move_what = move_slider; + return true; + } + + //if(y < ys1 && calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys1) <= m_x2 - m_x1) + { + m_pdy = ys1 - y; + m_move_what = move_value1; + return true; + } + + //if(y > ys2 && calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + if(calc_distance(x, y, xp, ys2) <= m_x2 - m_x1) + { + m_pdy = ys2 - y; + m_move_what = move_value2; + return true; + } + } + + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + double xp = x + m_pdx; + double yp = y + m_pdy; + double dv; + + switch(m_move_what) + { + case move_value1: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value1 < 0.0) m_value1 = 0.0; + if(m_value1 > m_value2 - m_min_d) m_value1 = m_value2 - m_min_d; + return true; + + case move_value2: + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value2 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value2 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + if(m_value2 > 1.0) m_value2 = 1.0; + if(m_value2 < m_value1 + m_min_d) m_value2 = m_value1 + m_min_d; + return true; + + case move_slider: + dv = m_value2 - m_value1; + if(fabs(m_x2 - m_x1) > fabs(m_y2 - m_y1)) + { + m_value1 = (xp - m_xs1) / (m_xs2 - m_xs1); + } + else + { + m_value1 = (yp - m_ys1) / (m_ys2 - m_ys1); + } + m_value2 = m_value1 + dv; + if(m_value1 < 0.0) + { + dv = m_value2 - m_value1; + m_value1 = 0.0; + m_value2 = m_value1 + dv; + } + if(m_value2 > 1.0) + { + dv = m_value2 - m_value1; + m_value2 = 1.0; + m_value1 = m_value2 - dv; + } + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_mouse_button_up(double, double) + { + m_move_what = move_nothing; + return false; + } + + + //------------------------------------------------------------------------ + bool scale_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { +/* + if(right || up) + { + m_value += 0.005; + if(m_value > 1.0) m_value = 1.0; + return true; + } + + if(left || down) + { + m_value -= 0.005; + if(m_value < 0.0) m_value = 0.0; + return true; + } +*/ + return false; + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_slider_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_slider_ctrl.cpp new file mode 100644 index 00000000000..ad0048631cf --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_slider_ctrl.cpp @@ -0,0 +1,349 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes slider_ctrl_impl, slider_ctrl +// +//---------------------------------------------------------------------------- + +#include +#include +#include "ctrl/agg_slider_ctrl.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + slider_ctrl_impl::slider_ctrl_impl(double x1, double y1, + double x2, double y2, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_border_width(1.0), + m_border_extra((y2 - y1) / 2), + m_text_thickness(1.0), + m_pdx(0.0), + m_mouse_move(false), + m_value(0.5), + m_preview_value(0.5), + m_min(0.0), + m_max(1.0), + m_num_steps(0), + m_descending(false), + m_text_poly(m_text) + { + m_label[0] = 0; + calc_box(); + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::calc_box() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::normalize_value(bool preview_value_flag) + { + bool ret = true; + if(m_num_steps) + { + int step = int(m_preview_value * m_num_steps + 0.5); + ret = m_value != step / double(m_num_steps); + m_value = step / double(m_num_steps); + } + else + { + m_value = m_preview_value; + } + + if(preview_value_flag) + { + m_preview_value = m_value; + } + return ret; + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_box(); + } + + + //------------------------------------------------------------------------ + void slider_ctrl_impl::value(double value) + { + m_preview_value = (value - m_min) / (m_max - m_min); + if(m_preview_value > 1.0) m_preview_value = 1.0; + if(m_preview_value < 0.0) m_preview_value = 0.0; + normalize_value(true); + } + + //------------------------------------------------------------------------ + void slider_ctrl_impl::label(const char* fmt) + { + m_label[0] = 0; + if(fmt) + { + unsigned len = strlen(fmt); + if(len > 63) len = 63; + memcpy(m_label, fmt, len); + m_label[len] = 0; + } + } + + //------------------------------------------------------------------------ + void slider_ctrl_impl::rewind(unsigned idx) + { + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Triangle + m_vertex = 0; + if(m_descending) + { + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x1; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y1; + } + else + { + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y1; + } + break; + + case 2: + m_text.text(m_label); + if(m_label[0]) + { + char buf[256]; + sprintf(buf, m_label, value()); + m_text.text(buf); + } + m_text.start_point(m_x1, m_y1); + m_text.size((m_y2 - m_y1) * 1.2, m_y2 - m_y1); + m_text_poly.width(m_text_thickness); + m_text_poly.line_join(round_join); + m_text_poly.line_cap(round_cap); + m_text_poly.rewind(0); + break; + + case 3: // pointer preview + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_preview_value, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + break; + + + case 4: // pointer + normalize_value(false); + m_ellipse.init(m_xs1 + (m_xs2 - m_xs1) * m_value, + (m_ys1 + m_ys2) / 2.0, + m_y2 - m_y1, + m_y2 - m_y1, + 32); + m_ellipse.rewind(0); + break; + + case 5: + m_storage.remove_all(); + if(m_num_steps) + { + unsigned i; + double d = (m_xs2 - m_xs1) / m_num_steps; + if(d > 0.004) d = 0.004; + for(i = 0; i < m_num_steps + 1; i++) + { + double x = m_xs1 + (m_xs2 - m_xs1) * i / m_num_steps; + m_storage.move_to(x, m_y1); + m_storage.line_to(x - d * (m_x2 - m_x1), m_y1 - m_border_extra); + m_storage.line_to(x + d * (m_x2 - m_x1), m_y1 - m_border_extra); + } + } + } + } + + + //------------------------------------------------------------------------ + unsigned slider_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_text_poly.vertex(x, y); + break; + + case 3: + case 4: + cmd = m_ellipse.vertex(x, y); + break; + + case 5: + cmd = m_storage.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + + double xp = m_xs1 + (m_xs2 - m_xs1) * m_value; + double yp = (m_ys1 + m_ys2) / 2.0; + + if(calc_distance(x, y, xp, yp) <= m_y2 - m_y1) + { + m_pdx = xp - x; + m_mouse_move = true; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + on_mouse_button_up(x, y); + return false; + } + + if(m_mouse_move) + { + double xp = x + m_pdx; + m_preview_value = (xp - m_xs1) / (m_xs2 - m_xs1); + if(m_preview_value < 0.0) m_preview_value = 0.0; + if(m_preview_value > 1.0) m_preview_value = 1.0; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_mouse_button_up(double, double) + { + m_mouse_move = false; + normalize_value(true); + return true; + } + + + //------------------------------------------------------------------------ + bool slider_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double d = 0.005; + if(m_num_steps) + { + d = 1.0 / m_num_steps; + } + + if(right || up) + { + m_preview_value += d; + if(m_preview_value > 1.0) m_preview_value = 1.0; + normalize_value(true); + return true; + } + + if(left || down) + { + m_preview_value -= d; + if(m_preview_value < 0.0) m_preview_value = 0.0; + normalize_value(true); + return true; + } + return false; + } + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_spline_ctrl.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_spline_ctrl.cpp new file mode 100644 index 00000000000..74808d4f87f --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/ctrl/agg_spline_ctrl.cpp @@ -0,0 +1,407 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// classes spline_ctrl_impl, spline_ctrl +// +//---------------------------------------------------------------------------- + +#include "ctrl/agg_spline_ctrl.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + spline_ctrl_impl::spline_ctrl_impl(double x1, double y1, double x2, double y2, + unsigned num_pnt, bool flip_y) : + ctrl(x1, y1, x2, y2, flip_y), + m_num_pnt(num_pnt), + m_border_width(1.0), + m_border_extra(0.0), + m_curve_width(1.0), + m_point_size(3.0), + m_curve_poly(m_curve_pnt), + m_idx(0), + m_vertex(0), + m_active_pnt(-1), + m_move_pnt(-1), + m_pdx(0.0), + m_pdy(0.0) + { + if(m_num_pnt < 4) m_num_pnt = 4; + if(m_num_pnt > 32) m_num_pnt = 32; + + unsigned i; + for(i = 0; i < m_num_pnt; i++) + { + m_xp[i] = double(i) / double(m_num_pnt - 1); + m_yp[i] = 0.5; + } + calc_spline_box(); + update_spline(); + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::border_width(double t, double extra) + { + m_border_width = t; + m_border_extra = extra; + calc_spline_box(); + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::calc_spline_box() + { + m_xs1 = m_x1 + m_border_width; + m_ys1 = m_y1 + m_border_width; + m_xs2 = m_x2 - m_border_width; + m_ys2 = m_y2 - m_border_width; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::update_spline() + { + int i; + m_spline.init(m_num_pnt, m_xp, m_yp); + for(i = 0; i < 256; i++) + { + m_spline_values[i] = m_spline.get(double(i) / 255.0); + if(m_spline_values[i] < 0.0) m_spline_values[i] = 0.0; + if(m_spline_values[i] > 1.0) m_spline_values[i] = 1.0; + m_spline_values8[i] = (int8u)(m_spline_values[i] * 255.0); + } + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::calc_curve() + { + int i; + m_curve_pnt.remove_all(); + m_curve_pnt.move_to(m_xs1, m_ys1 + (m_ys2 - m_ys1) * m_spline_values[0]); + for(i = 1; i < 256; i++) + { + m_curve_pnt.line_to(m_xs1 + (m_xs2 - m_xs1) * double(i) / 255.0, + m_ys1 + (m_ys2 - m_ys1) * m_spline_values[i]); + } + } + + + //------------------------------------------------------------------------ + double spline_ctrl_impl::calc_xp(unsigned idx) + { + return m_xs1 + (m_xs2 - m_xs1) * m_xp[idx]; + } + + + //------------------------------------------------------------------------ + double spline_ctrl_impl::calc_yp(unsigned idx) + { + return m_ys1 + (m_ys2 - m_ys1) * m_yp[idx]; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::set_xp(unsigned idx, double val) + { + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + + if(idx == 0) + { + val = 0.0; + } + else if(idx == m_num_pnt - 1) + { + val = 1.0; + } + else + { + if(val < m_xp[idx - 1] + 0.001) val = m_xp[idx - 1] + 0.001; + if(val > m_xp[idx + 1] - 0.001) val = m_xp[idx + 1] - 0.001; + } + m_xp[idx] = val; + } + + //------------------------------------------------------------------------ + void spline_ctrl_impl::set_yp(unsigned idx, double val) + { + if(val < 0.0) val = 0.0; + if(val > 1.0) val = 1.0; + m_yp[idx] = val; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::point(unsigned idx, double x, double y) + { + if(idx < m_num_pnt) + { + set_xp(idx, x); + set_yp(idx, y); + } + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::value(unsigned idx, double y) + { + if(idx < m_num_pnt) + { + set_yp(idx, y); + } + } + + //------------------------------------------------------------------------ + double spline_ctrl_impl::value(double x) const + { + x = m_spline.get(x); + if(x < 0.0) x = 0.0; + if(x > 1.0) x = 1.0; + return x; + } + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::rewind(unsigned idx) + { + unsigned i; + + m_idx = idx; + + switch(idx) + { + default: + + case 0: // Background + m_vertex = 0; + m_vx[0] = m_x1 - m_border_extra; + m_vy[0] = m_y1 - m_border_extra; + m_vx[1] = m_x2 + m_border_extra; + m_vy[1] = m_y1 - m_border_extra; + m_vx[2] = m_x2 + m_border_extra; + m_vy[2] = m_y2 + m_border_extra; + m_vx[3] = m_x1 - m_border_extra; + m_vy[3] = m_y2 + m_border_extra; + break; + + case 1: // Border + m_vertex = 0; + m_vx[0] = m_x1; + m_vy[0] = m_y1; + m_vx[1] = m_x2; + m_vy[1] = m_y1; + m_vx[2] = m_x2; + m_vy[2] = m_y2; + m_vx[3] = m_x1; + m_vy[3] = m_y2; + m_vx[4] = m_x1 + m_border_width; + m_vy[4] = m_y1 + m_border_width; + m_vx[5] = m_x1 + m_border_width; + m_vy[5] = m_y2 - m_border_width; + m_vx[6] = m_x2 - m_border_width; + m_vy[6] = m_y2 - m_border_width; + m_vx[7] = m_x2 - m_border_width; + m_vy[7] = m_y1 + m_border_width; + break; + + case 2: // Curve + calc_curve(); + m_curve_poly.width(m_curve_width); + m_curve_poly.rewind(0); + break; + + + case 3: // Inactive points + m_curve_pnt.remove_all(); + for(i = 0; i < m_num_pnt; i++) + { + if(int(i) != m_active_pnt) + { + m_ellipse.init(calc_xp(i), calc_yp(i), + m_point_size, m_point_size, 32); + m_curve_pnt.concat_path(m_ellipse); + } + } + m_curve_poly.rewind(0); + break; + + + case 4: // Active point + m_curve_pnt.remove_all(); + if(m_active_pnt >= 0) + { + m_ellipse.init(calc_xp(m_active_pnt), calc_yp(m_active_pnt), + m_point_size, m_point_size, 32); + + m_curve_pnt.concat_path(m_ellipse); + } + m_curve_poly.rewind(0); + break; + + } + } + + + //------------------------------------------------------------------------ + unsigned spline_ctrl_impl::vertex(double* x, double* y) + { + unsigned cmd = path_cmd_line_to; + switch(m_idx) + { + case 0: + if(m_vertex == 0) cmd = path_cmd_move_to; + if(m_vertex >= 4) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 1: + if(m_vertex == 0 || m_vertex == 4) cmd = path_cmd_move_to; + if(m_vertex >= 8) cmd = path_cmd_stop; + *x = m_vx[m_vertex]; + *y = m_vy[m_vertex]; + m_vertex++; + break; + + case 2: + cmd = m_curve_poly.vertex(x, y); + break; + + case 3: + case 4: + cmd = m_curve_pnt.vertex(x, y); + break; + + default: + cmd = path_cmd_stop; + break; + } + + if(!is_stop(cmd)) + { + transform_xy(x, y); + } + + return cmd; + } + + + + //------------------------------------------------------------------------ + void spline_ctrl_impl::active_point(int i) + { + m_active_pnt = i; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::in_rect(double x, double y) const + { + inverse_transform_xy(&x, &y); + return x >= m_x1 && x <= m_x2 && y >= m_y1 && y <= m_y2; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_button_down(double x, double y) + { + inverse_transform_xy(&x, &y); + unsigned i; + for(i = 0; i < m_num_pnt; i++) + { + double xp = calc_xp(i); + double yp = calc_yp(i); + if(calc_distance(x, y, xp, yp) <= m_point_size + 1) + { + m_pdx = xp - x; + m_pdy = yp - y; + m_active_pnt = m_move_pnt = int(i); + return true; + } + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_button_up(double, double) + { + if(m_move_pnt >= 0) + { + m_move_pnt = -1; + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_mouse_move(double x, double y, bool button_flag) + { + inverse_transform_xy(&x, &y); + if(!button_flag) + { + return on_mouse_button_up(x, y); + } + + if(m_move_pnt >= 0) + { + double xp = x + m_pdx; + double yp = y + m_pdy; + + set_xp(m_move_pnt, (xp - m_xs1) / (m_xs2 - m_xs1)); + set_yp(m_move_pnt, (yp - m_ys1) / (m_ys2 - m_ys1)); + + update_spline(); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + bool spline_ctrl_impl::on_arrow_keys(bool left, bool right, bool down, bool up) + { + double kx = 0.0; + double ky = 0.0; + bool ret = false; + if(m_active_pnt >= 0) + { + kx = m_xp[m_active_pnt]; + ky = m_yp[m_active_pnt]; + if(left) { kx -= 0.001; ret = true; } + if(right) { kx += 0.001; ret = true; } + if(down) { ky -= 0.001; ret = true; } + if(up) { ky += 0.001; ret = true; } + } + if(ret) + { + set_xp(m_active_pnt, kx); + set_yp(m_active_pnt, ky); + update_spline(); + } + return ret; + } + + + + +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/AmigaOS/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/AmigaOS/agg_platform_support.cpp new file mode 100644 index 00000000000..b14d09cd1c1 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/AmigaOS/agg_platform_support.cpp @@ -0,0 +1,977 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- + +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +Library* DataTypesBase = 0; +Library* GraphicsBase = 0; +Library* IntuitionBase = 0; +Library* KeymapBase = 0; +Library* P96Base = 0; + +DataTypesIFace* IDataTypes = 0; +GraphicsIFace* IGraphics = 0; +IntuitionIFace* IIntuition = 0; +KeymapIFace* IKeymap = 0; +P96IFace* IP96 = 0; + +Class* RequesterClass = 0; +Class* WindowClass = 0; + + +namespace agg +{ + void handle_idcmp(Hook* hook, APTR win, IntuiMessage* msg); + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(platform_support& support, pix_format_e format, + bool flip_y); + ~platform_specific(); + bool handle_input(); + bool load_img(const char* file, unsigned idx, rendering_buffer* rbuf); + bool create_img(unsigned idx, rendering_buffer* rbuf, unsigned width, + unsigned height); + bool make_bitmap(); + public: + platform_support& m_support; + RGBFTYPE m_ftype; + pix_format_e m_format; + unsigned m_bpp; + BitMap* m_bitmap; + bool m_flip_y; + uint16 m_width; + uint16 m_height; + APTR m_window_obj; + Window* m_window; + Hook* m_idcmp_hook; + unsigned m_input_flags; + bool m_dragging; + double m_start_time; + uint16 m_last_key; + BitMap* m_img_bitmaps[platform_support::max_images]; + }; + + //------------------------------------------------------------------------ + platform_specific::platform_specific(platform_support& support, + pix_format_e format, bool flip_y) : + m_support(support), + m_ftype(RGBFB_NONE), + m_format(format), + m_bpp(0), + m_bitmap(0), + m_flip_y(flip_y), + m_width(0), + m_height(0), + m_window_obj(0), + m_window(0), + m_idcmp_hook(0), + m_input_flags(0), + m_dragging(false), + m_start_time(0.0), + m_last_key(0) + { + switch ( format ) + { + case pix_format_gray8: + // Not supported. + break; + case pix_format_rgb555: + m_ftype = RGBFB_R5G5B5; + m_bpp = 15; + break; + case pix_format_rgb565: + m_ftype = RGBFB_R5G6B5; + m_bpp = 16; + break; + case pix_format_rgb24: + m_ftype = RGBFB_R8G8B8; + m_bpp = 24; + break; + case pix_format_bgr24: + m_ftype = RGBFB_B8G8R8; + m_bpp = 24; + break; + case pix_format_bgra32: + m_ftype = RGBFB_B8G8R8A8; + m_bpp = 32; + break; + case pix_format_abgr32: + m_ftype = RGBFB_A8B8G8R8; + m_bpp = 32; + break; + case pix_format_argb32: + m_ftype = RGBFB_A8R8G8B8; + m_bpp = 32; + break; + case pix_format_rgba32: + m_ftype = RGBFB_R8G8B8A8; + m_bpp = 32; + break; + } + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + m_img_bitmaps[i] = 0; + } + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + IIntuition->DisposeObject(m_window_obj); + + IP96->p96FreeBitMap(m_bitmap); + + for ( unsigned i = 0; i < platform_support::max_images; ++i ) + { + IP96->p96FreeBitMap(m_img_bitmaps[i]); + } + + if ( m_idcmp_hook != 0 ) + { + IExec->FreeSysObject(ASOT_HOOK, m_idcmp_hook); + } + } + + //------------------------------------------------------------------------ + bool platform_specific::handle_input() + { + int16 code = 0; + uint32 result = 0; + Object* obj = reinterpret_cast(m_window_obj); + + while ( (result = IIntuition->IDoMethod(obj, WM_HANDLEINPUT, + &code)) != WMHI_LASTMSG ) + { + switch ( result & WMHI_CLASSMASK ) + { + case WMHI_CLOSEWINDOW: + return true; + break; + case WMHI_INTUITICK: + if ( !m_support.wait_mode() ) + { + m_support.on_idle(); + } + break; + case WMHI_NEWSIZE: + if ( make_bitmap() ) + { + m_support.trans_affine_resizing(m_width, m_height); + m_support.on_resize(m_width, m_height); + m_support.force_redraw(); + } + break; + } + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::load_img(const char* file, unsigned idx, + rendering_buffer* rbuf) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + bool result = false; + + Object* picture = IDataTypes->NewDTObject(const_cast(file), + DTA_GroupID, GID_PICTURE, + PDTA_DestMode, PMODE_V43, + PDTA_Remap, FALSE, + TAG_END); + if ( picture != 0 ) + { + gpLayout layout; + layout.MethodID = DTM_PROCLAYOUT; + layout.gpl_GInfo = 0; + layout.gpl_Initial = 1; + ULONG loaded = IDataTypes->DoDTMethodA(picture, 0, 0, + reinterpret_cast(&layout)); + if ( loaded != 0 ) + { + BitMap* src_bitmap = 0; + IDataTypes->GetDTAttrs(picture, + PDTA_ClassBitMap, &src_bitmap, + TAG_END); + + bool supported = false; + + RGBFTYPE ftype = static_cast(IP96->p96GetBitMapAttr( + src_bitmap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_R8G8B8: + supported = true; + break; + default: + m_support.message("File uses unsupported graphics mode."); + break; + } + + if ( supported ) { + uint16 width = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_WIDTH); + uint16 height = IP96->p96GetBitMapAttr(src_bitmap, + P96BMA_HEIGHT); + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, 0, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + rbuf->attach(buf, width, height, stride); + + // P96 sets the alpha to zero so it can't be used to + // color convert true color modes. + if ( m_bpp == 32 ) + { + RenderInfo ri; + int32 lock = IP96->p96LockBitMap(src_bitmap, + reinterpret_cast(&ri), + sizeof(RenderInfo)); + + rendering_buffer rbuf_src; + rbuf_src.attach( + reinterpret_cast(ri.Memory), + width, height, (m_flip_y) ? + -ri.BytesPerRow : ri.BytesPerRow); + + switch ( m_format ) + { + case pix_format_bgra32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_bgra32()); + break; + case pix_format_abgr32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_abgr32()); + break; + case pix_format_argb32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_argb32()); + break; + case pix_format_rgba32: + color_conv(rbuf, &rbuf_src, + color_conv_rgb24_to_rgba32()); + break; + } + + IP96->p96UnlockBitMap(src_bitmap, lock); + } + else + { + IGraphics->BltBitMap(src_bitmap, 0, 0, + m_img_bitmaps[idx], 0, 0, width, height, + ABC|ABNC, 0xFF, 0); + } + + result = true; + } + } + } + } + + IGraphics->WaitBlit(); + IDataTypes->DisposeDTObject(picture); + + return result; + } + + //------------------------------------------------------------------------ + bool platform_specific::create_img(unsigned idx, rendering_buffer* rbuf, + unsigned width, unsigned height) + { + if ( m_img_bitmaps[idx] != 0 ) + { + IP96->p96FreeBitMap(m_img_bitmaps[idx]); + m_img_bitmaps[idx] = 0; + } + + m_img_bitmaps[idx] = IP96->p96AllocBitMap(width, height, + m_bpp, BMF_USERPRIVATE, m_bitmap, m_ftype); + if ( m_img_bitmaps[idx] != 0 ) + { + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(m_img_bitmaps[idx], + P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + rbuf->attach(buf, width, height, stride); + + return true; + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_specific::make_bitmap() + { + uint32 width = 0; + uint32 height = 0; + IIntuition->GetWindowAttrs(m_window, + WA_InnerWidth, &width, + WA_InnerHeight, &height, + TAG_END); + + BitMap* bm = IP96->p96AllocBitMap(width, height, m_bpp, + BMF_USERPRIVATE|BMF_CLEAR, 0, m_ftype); + if ( bm == 0 ) + { + return false; + } + + int8u* buf = reinterpret_cast( + IP96->p96GetBitMapAttr(bm, P96BMA_MEMORY)); + int bpr = IP96->p96GetBitMapAttr(bm, P96BMA_BYTESPERROW); + int stride = (m_flip_y) ? -bpr : bpr; + + m_support.rbuf_window().attach(buf, width, height, stride); + + if ( m_bitmap != 0 ) + { + IP96->p96FreeBitMap(m_bitmap); + m_bitmap = 0; + } + + m_bitmap = bm; + m_width = width; + m_height = height; + + return true; + } + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(*this, format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + std::strncpy(m_caption, "Anti-Grain Geometry", 256); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + std::strncpy(m_caption, cap, 256); + if ( m_specific->m_window != 0 ) + { + const char* ignore = reinterpret_cast(-1); + IIntuition->SetWindowAttr(m_specific->m_window, + WA_Title, m_caption, sizeof(char*)); + } + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + timeval tv; + gettimeofday(&tv, 0); + m_specific->m_start_time = tv.tv_secs + tv.tv_micro/1e6; + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + timeval tv; + gettimeofday(&tv, 0); + double end_time = tv.tv_secs + tv.tv_micro/1e6; + + double elasped_seconds = end_time - m_specific->m_start_time; + double elasped_millis = elasped_seconds*1e3; + + return elasped_millis; + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + return 0; // Not available. + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + APTR req = IIntuition->NewObject(RequesterClass, 0, + REQ_TitleText, "Anti-Grain Geometry", + REQ_Image, REQIMAGE_INFO, + REQ_BodyText, msg, + REQ_GadgetText, "_Ok", + TAG_END); + if ( req == 0 ) + { + IDOS->Printf("Message: %s\n", msg); + return; + } + + orRequest reqmsg; + reqmsg.MethodID = RM_OPENREQ; + reqmsg.or_Attrs = 0; + reqmsg.or_Window = m_specific->m_window; + reqmsg.or_Screen = 0; + + IIntuition->IDoMethodA(reinterpret_cast(req), + reinterpret_cast(&reqmsg)); + IIntuition->DisposeObject(req); + } + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, + unsigned flags) + { + if( m_specific->m_ftype == RGBFB_NONE ) + { + message("Unsupported mode requested."); + return false; + } + + m_window_flags = flags; + + m_specific->m_idcmp_hook = reinterpret_cast( + IExec->AllocSysObjectTags(ASOT_HOOK, + ASOHOOK_Entry, handle_idcmp, + ASOHOOK_Data, this, + TAG_END)); + if ( m_specific->m_idcmp_hook == 0 ) + { + return false; + } + + m_specific->m_window_obj = IIntuition->NewObject(WindowClass, 0, + WA_Title, m_caption, + WA_AutoAdjustDClip, TRUE, + WA_InnerWidth, width, + WA_InnerHeight, height, + WA_Activate, TRUE, + WA_SmartRefresh, TRUE, + WA_NoCareRefresh, TRUE, + WA_CloseGadget, TRUE, + WA_DepthGadget, TRUE, + WA_SizeGadget, (flags & agg::window_resize) ? TRUE : FALSE, + WA_DragBar, TRUE, + WA_AutoAdjust, TRUE, + WA_ReportMouse, TRUE, + WA_RMBTrap, TRUE, + WA_MouseQueue, 1, + WA_IDCMP, + IDCMP_NEWSIZE | + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY | + IDCMP_INTUITICKS, + WINDOW_IDCMPHook, m_specific->m_idcmp_hook, + WINDOW_IDCMPHookBits, + IDCMP_MOUSEBUTTONS | + IDCMP_MOUSEMOVE | + IDCMP_RAWKEY, + TAG_END); + if ( m_specific->m_window_obj == 0 ) + { + return false; + } + + Object* obj = reinterpret_cast(m_specific->m_window_obj); + m_specific->m_window = + reinterpret_cast(IIntuition->IDoMethod(obj, WM_OPEN)); + if ( m_specific->m_window == 0 ) + { + return false; + } + + RGBFTYPE ftype = static_cast(IP96->p96GetBitMapAttr( + m_specific->m_window->RPort->BitMap, P96BMA_RGBFORMAT)); + + switch ( ftype ) + { + case RGBFB_A8R8G8B8: + case RGBFB_B8G8R8A8: + case RGBFB_R5G6B5PC: + break; + default: + message("Unsupported screen mode.\n"); + return false; + } + + if ( !m_specific->make_bitmap() ) + { + return false; + } + + m_initial_width = width; + m_initial_height = height; + + on_init(); + on_resize(width, height); + force_redraw(); + + return true; + } + + //------------------------------------------------------------------------ + int platform_support::run() + { + uint32 window_mask = 0; + IIntuition->GetAttr(WINDOW_SigMask, m_specific->m_window_obj, + &window_mask); + uint32 wait_mask = window_mask | SIGBREAKF_CTRL_C; + + bool done = false; + + while ( !done ) + { + uint32 sig_mask = IExec->Wait(wait_mask); + if ( sig_mask & SIGBREAKF_CTRL_C ) + { + done = true; + } + else + { + done = m_specific->handle_input(); + } + } + + return 0; + } + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const + { + return ".bmp"; + } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if ( idx < max_images ) + { + static char fn[1024]; + std::strncpy(fn, file, 1024); + int len = std::strlen(fn); + if ( len < 4 || std::strcmp(fn + len - 4, ".bmp") != 0 ) + { + std::strncat(fn, ".bmp", 1024); + } + + return m_specific->load_img(fn, idx, &m_rbuf_img[idx]); + } + + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + message("Not supported"); + return false; + } + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, + unsigned height) + { + if ( idx < max_images ) + { + if ( width == 0 ) + { + width = m_specific->m_width; + } + + if ( height == 0 ) + { + height = m_specific->m_height; + } + + return m_specific->create_img(idx, &m_rbuf_img[idx], width, + height); + } + + return false; + } + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + on_draw(); + update_window(); + } + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + // Note this function does automatic color conversion. + IGraphics->BltBitMapRastPort(m_specific->m_bitmap, 0, 0, + m_specific->m_window->RPort, m_specific->m_window->BorderLeft, + m_specific->m_window->BorderTop, m_specific->m_width, + m_specific->m_height, ABC|ABNC); + } + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + //------------------------------------------------------------------------ + void handle_idcmp(Hook* hook, APTR obj, IntuiMessage* msg) + { + platform_support* app = + reinterpret_cast(hook->h_Data); + Window* window = app->m_specific->m_window; + + int16 x = msg->MouseX - window->BorderLeft; + + int16 y = 0; + if ( app->flip_y() ) + { + y = window->Height - window->BorderBottom - msg->MouseY; + } + else + { + y = msg->MouseY - window->BorderTop; + } + + switch ( msg->Class ) + { + case IDCMP_MOUSEBUTTONS: + if ( msg->Code & IECODE_UP_PREFIX ) + { + if ( msg->Code == SELECTUP ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = false; + } + else if ( msg->Code == MENUUP ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = false; + } + else + { + return; + } + + + if ( app->m_ctrls.on_mouse_button_up(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + + app->on_mouse_button_up(x, y, app->m_specific->m_input_flags); + } + else + { + if ( msg->Code == SELECTDOWN ) + { + app->m_specific->m_input_flags = mouse_left; + app->m_specific->m_dragging = true; + } + else if ( msg->Code == MENUDOWN ) + { + app->m_specific->m_input_flags = mouse_right; + app->m_specific->m_dragging = true; + } + else + { + return; + } + + app->m_ctrls.set_cur(x, y); + if ( app->m_ctrls.on_mouse_button_down(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( app->m_ctrls.in_rect(x, y) ) + { + if ( app->m_ctrls.set_cur(x, y) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_MOUSEMOVE: + if ( app->m_specific->m_dragging ) { + if ( app->m_ctrls.on_mouse_move(x, y, + app->m_specific->m_input_flags & mouse_left) != 0 ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if ( !app->m_ctrls.in_rect(x, y) ) + { + app->on_mouse_move(x, y, + app->m_specific->m_input_flags); + } + } + } + break; + case IDCMP_RAWKEY: + { + static InputEvent ie = { 0 }; + ie.ie_Class = IECLASS_RAWKEY; + ie.ie_Code = msg->Code; + ie.ie_Qualifier = msg->Qualifier; + + static const unsigned BUF_SIZE = 16; + static char key_buf[BUF_SIZE]; + int16 num_chars = IKeymap->MapRawKey(&ie, key_buf, BUF_SIZE, 0); + + uint32 code = 0x00000000; + switch ( num_chars ) + { + case 1: + code = key_buf[0]; + break; + case 2: + code = key_buf[0]<<8 | key_buf[1]; + break; + case 3: + code = key_buf[0]<<16 | key_buf[1]<<8 | key_buf[2]; + break; + } + + uint16 key_code = 0; + + if ( num_chars == 1 ) + { + if ( code >= IECODE_ASCII_FIRST && code <= IECODE_ASCII_LAST ) + { + key_code = code; + } + } + + if ( key_code == 0 ) + { + switch ( code ) + { + case 0x00000008: key_code = key_backspace; break; + case 0x00000009: key_code = key_tab; break; + case 0x0000000D: key_code = key_return; break; + case 0x0000001B: key_code = key_escape; break; + case 0x0000007F: key_code = key_delete; break; + case 0x00009B41: + case 0x00009B54: key_code = key_up; break; + case 0x00009B42: + case 0x00009B53: key_code = key_down; break; + case 0x00009B43: + case 0x009B2040: key_code = key_right; break; + case 0x00009B44: + case 0x009B2041: key_code = key_left; break; + case 0x009B307E: key_code = key_f1; break; + case 0x009B317E: key_code = key_f2; break; + case 0x009B327E: key_code = key_f3; break; + case 0x009B337E: key_code = key_f4; break; + case 0x009B347E: key_code = key_f5; break; + case 0x009B357E: key_code = key_f6; break; + case 0x009B367E: key_code = key_f7; break; + case 0x009B377E: key_code = key_f8; break; + case 0x009B387E: key_code = key_f9; break; + case 0x009B397E: key_code = key_f10; break; + case 0x009B3F7E: key_code = key_scrollock; break; + } + } + + if ( ie.ie_Code & IECODE_UP_PREFIX ) + { + if ( app->m_specific->m_last_key != 0 ) + { + bool left = (key_code == key_left) ? true : false; + bool right = (key_code == key_right) ? true : false; + bool down = (key_code == key_down) ? true : false; + bool up = (key_code == key_up) ? true : false; + + if ( app->m_ctrls.on_arrow_keys(left, right, down, up) ) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(x, y, app->m_specific->m_last_key, 0); + } + + app->m_specific->m_last_key = 0; + } + } + else + { + app->m_specific->m_last_key = key_code; + } + break; + } + default: + break; + } + } +} + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); +bool open_libs(); +void close_libs(); + +//---------------------------------------------------------------------------- +bool open_libs() +{ + DataTypesBase = IExec->OpenLibrary("datatypes.library", 51); + GraphicsBase = IExec->OpenLibrary("graphics.library", 51); + IntuitionBase = IExec->OpenLibrary("intuition.library", 51); + KeymapBase = IExec->OpenLibrary("keymap.library", 51); + P96Base = IExec->OpenLibrary("Picasso96API.library", 2); + + IDataTypes = reinterpret_cast( + IExec->GetInterface(DataTypesBase, "main", 1, 0)); + IGraphics = reinterpret_cast( + IExec->GetInterface(GraphicsBase, "main", 1, 0)); + IIntuition = reinterpret_cast( + IExec->GetInterface(IntuitionBase, "main", 1, 0)); + IKeymap = reinterpret_cast( + IExec->GetInterface(KeymapBase, "main", 1, 0)); + IP96 = reinterpret_cast( + IExec->GetInterface(P96Base, "main", 1, 0)); + + if ( IDataTypes == 0 || + IGraphics == 0 || + IIntuition == 0 || + IKeymap == 0 || + IP96 == 0 ) + { + close_libs(); + return false; + } + else + { + return true; + } +} + +//---------------------------------------------------------------------------- +void close_libs() +{ + IExec->DropInterface(reinterpret_cast(IP96)); + IExec->DropInterface(reinterpret_cast(IKeymap)); + IExec->DropInterface(reinterpret_cast(IIntuition)); + IExec->DropInterface(reinterpret_cast(IGraphics)); + IExec->DropInterface(reinterpret_cast(IDataTypes)); + + IExec->CloseLibrary(P96Base); + IExec->CloseLibrary(KeymapBase); + IExec->CloseLibrary(IntuitionBase); + IExec->CloseLibrary(GraphicsBase); + IExec->CloseLibrary(DataTypesBase); +} + +//---------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + if ( !open_libs() ) { + IDOS->Printf("Can't open libraries.\n"); + return -1; + } + + ClassLibrary* requester = + IIntuition->OpenClass("requester.class", 51, &RequesterClass); + ClassLibrary* window = + IIntuition->OpenClass("window.class", 51, &WindowClass); + if ( requester == 0 || window == 0 ) + { + IDOS->Printf("Can't open classes.\n"); + IIntuition->CloseClass(requester); + IIntuition->CloseClass(window); + close_libs(); + return -1; + } + + int rc = agg_main(argc, argv); + + IIntuition->CloseClass(window); + IIntuition->CloseClass(requester); + close_libs(); + + return rc; +} diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/BeOS/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/BeOS/agg_platform_support.cpp new file mode 100644 index 00000000000..078e141ccb0 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/BeOS/agg_platform_support.cpp @@ -0,0 +1,990 @@ +//---------------------------------------------------------------------------- +// 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: superstippi@gmx.de +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "platform/agg_platform_support.h" +#include "util/agg_color_conv_rgb8.h" + +using std::nothrow; + + +static void +attach_buffer_to_BBitmap(agg::rendering_buffer& buffer, BBitmap* bitmap, bool flipY) +{ + uint8* bits = (uint8*)bitmap->Bits(); + uint32 width = bitmap->Bounds().IntegerWidth() + 1; + uint32 height = bitmap->Bounds().IntegerHeight() + 1; + int32 bpr = bitmap->BytesPerRow(); + if (flipY) { +// XXX: why don't I have to do this?!? +// bits += bpr * (height - 1); + bpr = -bpr; + } + buffer.attach(bits, width, height, bpr); +} + + +static color_space +pix_format_to_color_space(agg::pix_format_e format) +{ + color_space bitmapFormat = B_NO_COLOR_SPACE; + switch (format) { + case agg::pix_format_rgb555: + + bitmapFormat = B_RGB15; + break; + + case agg::pix_format_rgb565: + + bitmapFormat = B_RGB16; + break; + + case agg::pix_format_rgb24: + case agg::pix_format_bgr24: + + bitmapFormat = B_RGB24; + break; + + case agg::pix_format_rgba32: + case agg::pix_format_argb32: + case agg::pix_format_abgr32: + case agg::pix_format_bgra32: + + bitmapFormat = B_RGBA32; + break; + } + return bitmapFormat; +} + + +// #pragma mark - + + +class AGGView : public BView { + public: + AGGView(BRect frame, agg::platform_support* agg, + agg::pix_format_e format, bool flipY); + virtual ~AGGView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + + virtual void MessageReceived(BMessage* message); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + + virtual void KeyDown(const char* bytes, int32 numBytes); + + virtual void MouseDown(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMesage); + virtual void MouseUp(BPoint where); + + BBitmap* Bitmap() const; + + uint8 LastKeyDown() const; + uint32 MouseButtons(); + + void Update(); + void ForceRedraw(); + + unsigned GetKeyFlags(); + + private: + BBitmap* fBitmap; + agg::pix_format_e fFormat; + bool fFlipY; + + agg::platform_support* fAGG; + + uint32 fMouseButtons; + int32 fMouseX; + int32 fMouseY; + + uint8 fLastKeyDown; + + bool fRedraw; + + BMessageRunner* fPulse; + bigtime_t fLastPulse; + bool fEnableTicks; +}; + +AGGView::AGGView(BRect frame, + agg::platform_support* agg, + agg::pix_format_e format, + bool flipY) + : BView(frame, "AGG View", B_FOLLOW_ALL, + B_FRAME_EVENTS | B_WILL_DRAW), + fFormat(format), + fFlipY(flipY), + + fAGG(agg), + + fMouseButtons(0), + fMouseX(-1), + fMouseY(-1), + + fLastKeyDown(0), + + fRedraw(true), + + fPulse(NULL), + fLastPulse(0), + fEnableTicks(true) +{ + SetViewColor(B_TRANSPARENT_32_BIT); + + frame.OffsetTo(0.0, 0.0); + fBitmap = new BBitmap(frame, 0, pix_format_to_color_space(fFormat)); + if (fBitmap->IsValid()) { + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + } else { + delete fBitmap; + fBitmap = NULL; + } +} + + +AGGView::~AGGView() +{ + delete fBitmap; + delete fPulse; +} + + +void +AGGView::AttachedToWindow() +{ + BMessage message('tick'); + BMessenger target(this, Looper()); + delete fPulse; +// BScreen screen; +// TODO: calc screen retrace + fPulse = new BMessageRunner(target, &message, 40000); + + // make sure we call this once + fAGG->on_resize(Bounds().IntegerWidth() + 1, + Bounds().IntegerHeight() + 1); + MakeFocus(); +} + + +void +AGGView::DetachedFromWindow() +{ + delete fPulse; + fPulse = NULL; +} + + +void +AGGView::MessageReceived(BMessage* message) +{ + bigtime_t now = system_time(); + switch (message->what) { + case 'tick': + // drop messages that have piled up + if (/*now - fLastPulse > 30000*/fEnableTicks) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + Window()->PostMessage('entk', this); + fEnableTicks = false; + } else { +// printf("dropping tick message (%lld)\n", now - fLastPulse); + } + break; + case 'entk': + fEnableTicks = true; + if (now - fLastPulse > 30000) { + fLastPulse = now; + if (!fAGG->wait_mode()) + fAGG->on_idle(); + } + break; + default: + BView::MessageReceived(message); + break; + } +} + + +void +AGGView::Draw(BRect updateRect) +{ + if (fBitmap) { + if (fRedraw) { + fAGG->on_draw(); + fRedraw = false; + } + if (fFormat == agg::pix_format_bgra32) { + DrawBitmap(fBitmap, updateRect, updateRect); + } else { + BBitmap* bitmap = new BBitmap(fBitmap->Bounds(), 0, B_RGBA32); + + agg::rendering_buffer rbufSrc; + attach_buffer_to_BBitmap(rbufSrc, fBitmap, false); + + agg::rendering_buffer rbufDst; + attach_buffer_to_BBitmap(rbufDst, bitmap, false); + + switch(fFormat) { + case agg::pix_format_rgb555: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb555_to_bgra32()); + break; + case agg::pix_format_rgb565: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb565_to_bgra32()); + break; + case agg::pix_format_rgb24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgb24_to_bgra32()); + break; + case agg::pix_format_bgr24: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgr24_to_bgra32()); + break; + case agg::pix_format_rgba32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_rgba32_to_bgra32()); + break; + case agg::pix_format_argb32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_argb32_to_bgra32()); + break; + case agg::pix_format_abgr32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_abgr32_to_bgra32()); + break; + case agg::pix_format_bgra32: + agg::color_conv(&rbufDst, &rbufSrc, + agg::color_conv_bgra32_to_bgra32()); + break; + } + DrawBitmap(bitmap, updateRect, updateRect); + delete bitmap; + } + } else { + FillRect(updateRect); + } +} + + +void +AGGView::FrameResized(float width, float height) +{ + BRect r(0.0, 0.0, width, height); + BBitmap* bitmap = new BBitmap(r, 0, pix_format_to_color_space(fFormat)); + if (bitmap->IsValid()) { + delete fBitmap; + fBitmap = bitmap; + attach_buffer_to_BBitmap(fAGG->rbuf_window(), fBitmap, fFlipY); + + fAGG->trans_affine_resizing((int)width + 1, + (int)height + 1); + + // pass the event on to AGG + fAGG->on_resize((int)width + 1, (int)height + 1); + + fRedraw = true; + Invalidate(); + } else + delete bitmap; +} + + +void +AGGView::KeyDown(const char* bytes, int32 numBytes) +{ + if (bytes && numBytes > 0) { + fLastKeyDown = bytes[0]; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch (fLastKeyDown) { + + case B_LEFT_ARROW: + left = true; + break; + + case B_UP_ARROW: + up = true; + break; + + case B_RIGHT_ARROW: + right = true; + break; + + case B_DOWN_ARROW: + down = true; + break; + } + +/* case key_f2: +fAGG->copy_window_to_img(agg::platform_support::max_images - 1); +fAGG->save_img(agg::platform_support::max_images - 1, "screenshot"); +break; +}*/ + + + if (fAGG->m_ctrls.on_arrow_keys(left, right, down, up)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + } +// fAGG->on_key(fMouseX, fMouseY, fLastKeyDown, GetKeyFlags()); + + } +} + + +void +AGGView::MouseDown(BPoint where) +{ + BMessage* currentMessage = Window()->CurrentMessage(); + if (currentMessage) { + if (currentMessage->FindInt32("buttons", (int32*)&fMouseButtons) < B_OK) + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + } else + fMouseButtons = B_PRIMARY_MOUSE_BUTTON; + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + // left mouse button -> see if to handle in controls + fAGG->m_ctrls.set_cur(fMouseX, fMouseY); + if (fAGG->m_ctrls.on_mouse_button_down(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + if (fAGG->m_ctrls.set_cur(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + } else { + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + } + } else if (fMouseButtons & B_SECONDARY_MOUSE_BUTTON) { + // right mouse button -> simple + fAGG->on_mouse_button_down(fMouseX, fMouseY, GetKeyFlags()); + } + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); +} + + +void +AGGView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMesage) +{ + // workarround missed mouse up events + // (if we react too slowly, app_server might have dropped events) + BMessage* currentMessage = Window()->CurrentMessage(); + int32 buttons = 0; + if (currentMessage->FindInt32("buttons", &buttons) < B_OK) { + buttons = 0; + } + if (!buttons) + MouseUp(where); + + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fAGG->m_ctrls.on_mouse_move(fMouseX, fMouseY, + (GetKeyFlags() & agg::mouse_left) != 0)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } else { + if (!fAGG->m_ctrls.in_rect(fMouseX, fMouseY)) { + fAGG->on_mouse_move(fMouseX, fMouseY, GetKeyFlags()); + } + } +} + + +void +AGGView::MouseUp(BPoint where) +{ + fMouseX = (int)where.x; + fMouseY = fFlipY ? (int)(Bounds().Height() - where.y) : (int)where.y; + + // pass the event on to AGG + if (fMouseButtons == B_PRIMARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + if (fAGG->m_ctrls.on_mouse_button_up(fMouseX, fMouseY)) { + fAGG->on_ctrl_change(); + fAGG->force_redraw(); + } + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } else if (fMouseButtons == B_SECONDARY_MOUSE_BUTTON) { + fMouseButtons = 0; + + fAGG->on_mouse_button_up(fMouseX, fMouseY, GetKeyFlags()); + } +} + + +BBitmap* +AGGView::Bitmap() const +{ + return fBitmap; +} + + +uint8 +AGGView::LastKeyDown() const +{ + return fLastKeyDown; +} + + +uint32 +AGGView::MouseButtons() +{ + uint32 buttons = 0; + if (LockLooper()) { + buttons = fMouseButtons; + UnlockLooper(); + } + return buttons; +} + + +void +AGGView::Update() +{ + // trigger display update + if (LockLooper()) { + Invalidate(); + UnlockLooper(); + } +} + + +void +AGGView::ForceRedraw() +{ + // force a redraw (fRedraw = true;) + // and trigger display update + if (LockLooper()) { + fRedraw = true; + Invalidate(); + UnlockLooper(); + } +} + + +unsigned +AGGView::GetKeyFlags() +{ + uint32 buttons = fMouseButtons; + uint32 mods = modifiers(); + unsigned flags = 0; + if (buttons & B_PRIMARY_MOUSE_BUTTON) flags |= agg::mouse_left; + if (buttons & B_SECONDARY_MOUSE_BUTTON) flags |= agg::mouse_right; + if (mods & B_SHIFT_KEY) flags |= agg::kbd_shift; + if (mods & B_COMMAND_KEY) flags |= agg::kbd_ctrl; + return flags; +} + +// #pragma mark - + + +class AGGWindow : public BWindow { + public: + AGGWindow() + : BWindow(BRect(-50.0, -50.0, -10.0, -10.0), + "AGG Application", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) + { + } + + virtual bool QuitRequested() + { + be_app->PostMessage(B_QUIT_REQUESTED); + return true; + } + + bool Init(BRect frame, agg::platform_support* agg, agg::pix_format_e format, + bool flipY, uint32 flags) + { + MoveTo(frame.LeftTop()); + ResizeTo(frame.Width(), frame.Height()); + + SetFlags(flags); + + frame.OffsetTo(0.0, 0.0); + fView = new AGGView(frame, agg, format, flipY); + AddChild(fView); + + return fView->Bitmap() != NULL; + } + + + AGGView* View() const + { + return fView; + } + private: + AGGView* fView; +}; + +// #pragma mark - + + +class AGGApplication : public BApplication { + public: + AGGApplication() + : BApplication("application/x-vnd.AGG-AGG") + { + fWindow = new AGGWindow(); + } + + virtual void ReadyToRun() + { + if (fWindow) { + fWindow->Show(); + } + } + + virtual bool Init(agg::platform_support* agg, int width, int height, + agg::pix_format_e format, bool flipY, uint32 flags) + { + BRect r(50.0, 50.0, + 50.0 + width - 1.0, + 50.0 + height - 1.0); + uint32 windowFlags = B_ASYNCHRONOUS_CONTROLS; + if (!(flags & agg::window_resize)) + windowFlags |= B_NOT_RESIZABLE; + + return fWindow->Init(r, agg, format, flipY, windowFlags);; + } + + + AGGWindow* Window() const + { + return fWindow; + } + + private: + AGGWindow* fWindow; +}; + + +// #pragma mark - + + +namespace agg +{ + +class platform_specific { + public: + platform_specific(agg::platform_support* agg, + agg::pix_format_e format, bool flip_y) + : fAGG(agg), + fApp(NULL), + fFormat(format), + fFlipY(flip_y), + fTimerStart(system_time()) + { + memset(fImages, 0, sizeof(fImages)); + fApp = new AGGApplication(); + fAppPath[0] = 0; + // figure out where we're running from + app_info info; + status_t ret = fApp->GetAppInfo(&info); + if (ret >= B_OK) { + BPath path(&info.ref); + ret = path.InitCheck(); + if (ret >= B_OK) { + ret = path.GetParent(&path); + if (ret >= B_OK) { + sprintf(fAppPath, "%s", path.Path()); + } else { + fprintf(stderr, "getting app parent folder failed: %s\n", strerror(ret)); + } + } else { + fprintf(stderr, "making app path failed: %s\n", strerror(ret)); + } + } else { + fprintf(stderr, "GetAppInfo() failed: %s\n", strerror(ret)); + } + } + ~platform_specific() + { + for (int32 i = 0; i < agg::platform_support::max_images; i++) + delete fImages[i]; + delete fApp; + } + + bool Init(int width, int height, unsigned flags) + { + return fApp->Init(fAGG, width, height, fFormat, fFlipY, flags); + } + + int Run() + { + status_t ret = B_NO_INIT; + if (fApp) { + fApp->Run(); + ret = B_OK; + } + return ret; + } + + void SetTitle(const char* title) + { + if (fApp && fApp->Window() && fApp->Window()->Lock()) { + fApp->Window()->SetTitle(title); + fApp->Window()->Unlock(); + } + } + void StartTimer() + { + fTimerStart = system_time(); + } + double ElapsedTime() const + { + return (system_time() - fTimerStart) / 1000.0; + } + + void ForceRedraw() + { + fApp->Window()->View()->ForceRedraw(); + } + void UpdateWindow() + { + fApp->Window()->View()->Update(); + } + + + agg::platform_support* fAGG; + AGGApplication* fApp; + agg::pix_format_e fFormat; + bool fFlipY; + bigtime_t fTimerStart; + BBitmap* fImages[agg::platform_support::max_images]; + + char fAppPath[B_PATH_NAME_LENGTH]; + char fFilePath[B_PATH_NAME_LENGTH]; +}; + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(this, format, flip_y)), + m_format(format), + m_bpp(32/*m_specific->m_bpp*/), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + m_specific->SetTitle(cap); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->StartTimer(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + return m_specific->ElapsedTime(); + } + + //------------------------------------------------------------------------ + void* platform_support::raw_display_handler() + { + // TODO: if we ever support BDirectWindow here, that would + // be the frame buffer pointer with offset to the window top left + return NULL; + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + BAlert* alert = new BAlert("AGG Message", msg, "Ok"); + alert->Go(/*NULL*/); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_initial_width = width; + m_initial_height = height; + m_window_flags = flags; + + if (m_specific->Init(width, height, flags)) { + on_init(); + return true; + } + + return false; + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + return m_specific->Run(); + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + + const char* platform_support::full_file_name(const char* file_name) + { + sprintf(m_specific->fFilePath, "%s/%s", m_specific->fAppPath, file_name); + return m_specific->fFilePath; + } + + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if (idx < max_images) + { + char path[B_PATH_NAME_LENGTH]; + sprintf(path, "%s/%s%s", m_specific->fAppPath, file, img_ext()); + BBitmap* transBitmap = BTranslationUtils::GetBitmap(path); + if (transBitmap && transBitmap->IsValid()) { + if(transBitmap->ColorSpace() != B_RGB32 && transBitmap->ColorSpace() != B_RGBA32) { + // ups we got a smart ass Translator making our live harder + delete transBitmap; + return false; + } + + color_space format = B_RGB24; + + switch (m_format) { + case pix_format_gray8: + format = B_GRAY8; + break; + case pix_format_rgb555: + format = B_RGB15; + break; + case pix_format_rgb565: + format = B_RGB16; + break; + case pix_format_rgb24: + format = B_RGB24_BIG; + break; + case pix_format_bgr24: + format = B_RGB24; + break; + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_bgra32: + format = B_RGB32; + break; + case pix_format_rgba32: + format = B_RGB32_BIG; + break; + } + BBitmap* bitmap = new (nothrow) BBitmap(transBitmap->Bounds(), 0, format); + if (!bitmap || !bitmap->IsValid()) { + fprintf(stderr, "failed to allocate temporary bitmap!\n"); + delete transBitmap; + delete bitmap; + return false; + } + + delete m_specific->fImages[idx]; + + rendering_buffer rbuf_tmp; + attach_buffer_to_BBitmap(rbuf_tmp, transBitmap, m_flip_y); + + m_specific->fImages[idx] = bitmap; + + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + + rendering_buffer* dst = &m_rbuf_img[idx]; + + switch(m_format) + { + case pix_format_gray8: + return false; +// color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + break; + + case pix_format_rgb555: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; + break; + + case pix_format_rgb565: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; + break; + + case pix_format_rgb24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; + break; + + case pix_format_bgr24: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; + break; + + case pix_format_abgr32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; + break; + + case pix_format_argb32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; + break; + + case pix_format_bgra32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; + break; + + case pix_format_rgba32: + color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; + break; + } + delete transBitmap; + + return true; + + } else { + fprintf(stderr, "failed to load bitmap: '%s'\n", full_file_name(file)); + } + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + // TODO: implement using BTranslatorRoster and friends + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerWidth() + 1; + if(height == 0) height = m_specific->fApp->Window()->View()->Bitmap()->Bounds().IntegerHeight() + 1; + BBitmap* bitmap = new BBitmap(BRect(0.0, 0.0, width - 1, height - 1), 0, B_RGBA32);; + if (bitmap && bitmap->IsValid()) { + delete m_specific->fImages[idx]; + m_specific->fImages[idx] = bitmap; + attach_buffer_to_BBitmap(m_rbuf_img[idx], bitmap, m_flip_y); + return true; + } else { + delete bitmap; + } + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->ForceRedraw(); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->UpdateWindow(); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} +} + + + + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + + +int +main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/X11/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/X11/agg_platform_support.cpp new file mode 100644 index 00000000000..46b874d7385 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/X11/agg_platform_support.cpp @@ -0,0 +1,1601 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class platform_support. X11 version. +// +//---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "agg_basics.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" +#include "util/agg_color_conv_rgb8.h" +#include "platform/agg_platform_support.h" + + +namespace agg +{ + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + ~platform_specific(); + + void caption(const char* capt); + void put_image(const rendering_buffer* src); + + pix_format_e m_format; + pix_format_e m_sys_format; + int m_byte_order; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + Display* m_display; + int m_screen; + int m_depth; + Visual* m_visual; + Window m_window; + GC m_gc; + XImage* m_ximg_window; + XSetWindowAttributes m_window_attributes; + Atom m_close_atom; + unsigned char* m_buf_window; + unsigned char* m_buf_img[platform_support::max_images]; + unsigned m_keymap[256]; + + bool m_update_flag; + bool m_resize_flag; + bool m_initialized; + //bool m_wait_mode; + clock_t m_sw_start; + }; + + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_byte_order(LSBFirst), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_display(0), + m_screen(0), + m_depth(0), + m_visual(0), + m_window(0), + m_gc(0), + m_ximg_window(0), + m_close_atom(0), + + m_buf_window(0), + + m_update_flag(true), + m_resize_flag(true), + m_initialized(false) + //m_wait_mode(true) + { + memset(m_buf_img, 0, sizeof(m_buf_img)); + + unsigned i; + for(i = 0; i < 256; i++) + { + m_keymap[i] = i; + } + + m_keymap[XK_Pause&0xFF] = key_pause; + m_keymap[XK_Clear&0xFF] = key_clear; + + m_keymap[XK_KP_0&0xFF] = key_kp0; + m_keymap[XK_KP_1&0xFF] = key_kp1; + m_keymap[XK_KP_2&0xFF] = key_kp2; + m_keymap[XK_KP_3&0xFF] = key_kp3; + m_keymap[XK_KP_4&0xFF] = key_kp4; + m_keymap[XK_KP_5&0xFF] = key_kp5; + m_keymap[XK_KP_6&0xFF] = key_kp6; + m_keymap[XK_KP_7&0xFF] = key_kp7; + m_keymap[XK_KP_8&0xFF] = key_kp8; + m_keymap[XK_KP_9&0xFF] = key_kp9; + + m_keymap[XK_KP_Insert&0xFF] = key_kp0; + m_keymap[XK_KP_End&0xFF] = key_kp1; + m_keymap[XK_KP_Down&0xFF] = key_kp2; + m_keymap[XK_KP_Page_Down&0xFF] = key_kp3; + m_keymap[XK_KP_Left&0xFF] = key_kp4; + m_keymap[XK_KP_Begin&0xFF] = key_kp5; + m_keymap[XK_KP_Right&0xFF] = key_kp6; + m_keymap[XK_KP_Home&0xFF] = key_kp7; + m_keymap[XK_KP_Up&0xFF] = key_kp8; + m_keymap[XK_KP_Page_Up&0xFF] = key_kp9; + m_keymap[XK_KP_Delete&0xFF] = key_kp_period; + m_keymap[XK_KP_Decimal&0xFF] = key_kp_period; + m_keymap[XK_KP_Divide&0xFF] = key_kp_divide; + m_keymap[XK_KP_Multiply&0xFF] = key_kp_multiply; + m_keymap[XK_KP_Subtract&0xFF] = key_kp_minus; + m_keymap[XK_KP_Add&0xFF] = key_kp_plus; + m_keymap[XK_KP_Enter&0xFF] = key_kp_enter; + m_keymap[XK_KP_Equal&0xFF] = key_kp_equals; + + m_keymap[XK_Up&0xFF] = key_up; + m_keymap[XK_Down&0xFF] = key_down; + m_keymap[XK_Right&0xFF] = key_right; + m_keymap[XK_Left&0xFF] = key_left; + m_keymap[XK_Insert&0xFF] = key_insert; + m_keymap[XK_Home&0xFF] = key_delete; + m_keymap[XK_End&0xFF] = key_end; + m_keymap[XK_Page_Up&0xFF] = key_page_up; + m_keymap[XK_Page_Down&0xFF] = key_page_down; + + m_keymap[XK_F1&0xFF] = key_f1; + m_keymap[XK_F2&0xFF] = key_f2; + m_keymap[XK_F3&0xFF] = key_f3; + m_keymap[XK_F4&0xFF] = key_f4; + m_keymap[XK_F5&0xFF] = key_f5; + m_keymap[XK_F6&0xFF] = key_f6; + m_keymap[XK_F7&0xFF] = key_f7; + m_keymap[XK_F8&0xFF] = key_f8; + m_keymap[XK_F9&0xFF] = key_f9; + m_keymap[XK_F10&0xFF] = key_f10; + m_keymap[XK_F11&0xFF] = key_f11; + m_keymap[XK_F12&0xFF] = key_f12; + m_keymap[XK_F13&0xFF] = key_f13; + m_keymap[XK_F14&0xFF] = key_f14; + m_keymap[XK_F15&0xFF] = key_f15; + + m_keymap[XK_Num_Lock&0xFF] = key_numlock; + m_keymap[XK_Caps_Lock&0xFF] = key_capslock; + m_keymap[XK_Scroll_Lock&0xFF] = key_scrollock; + + switch(m_format) + { + default: break; + case pix_format_gray8: + case pix_format_sgray8: + m_bpp = 8; + break; + + case pix_format_gray16: + m_bpp = 16; + break; + + case pix_format_gray32: + m_bpp = 32; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_bpp = 16; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + case pix_format_srgb24: + case pix_format_sbgr24: + m_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + case pix_format_sbgra32: + case pix_format_sabgr32: + case pix_format_sargb32: + case pix_format_srgba32: + m_bpp = 32; + break; + + case pix_format_rgb48: + case pix_format_bgr48: + m_bpp = 48; + break; + + case pix_format_bgra64: + case pix_format_abgr64: + case pix_format_argb64: + case pix_format_rgba64: + m_bpp = 64; + break; + + case pix_format_rgb96: + case pix_format_bgr96: + m_bpp = 96; + break; + + case pix_format_bgra128: + case pix_format_abgr128: + case pix_format_argb128: + case pix_format_rgba128: + m_bpp = 128; + break; + } + m_sw_start = clock(); + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + } + + //------------------------------------------------------------------------ + void platform_specific::caption(const char* capt) + { + XTextProperty tp; + tp.value = (unsigned char *)capt; + tp.encoding = XA_WM_NAME; + tp.format = 8; + tp.nitems = strlen(capt); + XSetWMName(m_display, m_window, &tp); + XStoreName(m_display, m_window, capt); + XSetIconName(m_display, m_window, capt); + XSetWMIconName(m_display, m_window, &tp); + } + + + //------------------------------------------------------------------------ + void platform_specific::put_image(const rendering_buffer* src) + { + if(m_ximg_window == 0) return; + m_ximg_window->data = (char*)m_buf_window; + + if(m_format == m_sys_format) + { + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + } + else + { + int row_len = src->width() * m_sys_bpp / 8; + unsigned char* buf_tmp = + new unsigned char[row_len * src->height()]; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(buf_tmp, + src->width(), + src->height(), + m_flip_y ? -row_len : row_len); + + switch(m_sys_format) + { + default: break; + case pix_format_rgb555: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb555()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb555()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb555()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb555()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb555()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb555()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(m_format) + { + default: break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgb565()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb565()); break; + case pix_format_rgb24: color_conv(&rbuf_tmp, src, color_conv_rgb24_to_rgb565()); break; + case pix_format_bgr24: color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb565()); break; + case pix_format_rgba32: color_conv(&rbuf_tmp, src, color_conv_rgba32_to_rgb565()); break; + case pix_format_argb32: color_conv(&rbuf_tmp, src, color_conv_argb32_to_rgb565()); break; + case pix_format_bgra32: color_conv(&rbuf_tmp, src, color_conv_bgra32_to_rgb565()); break; + case pix_format_abgr32: color_conv(&rbuf_tmp, src, color_conv_abgr32_to_rgb565()); break; + } + break; + + case pix_format_rgba32: + switch(m_format) + { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_rgba32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgba32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; + } + break; + + case pix_format_abgr32: + switch(m_format) + { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_abgr32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_abgr32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; + } + break; + + case pix_format_argb32: + switch(m_format) + { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_argb32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_argb32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; + } + break; + + case pix_format_bgra32: + switch(m_format) + { + default: break; + case pix_format_sgray8: convert(&rbuf_tmp, src); break; + case pix_format_gray8: convert(&rbuf_tmp, src); break; + case pix_format_gray16: convert(&rbuf_tmp, src); break; + case pix_format_gray32: convert(&rbuf_tmp, src); break; + case pix_format_rgb555: color_conv(&rbuf_tmp, src, color_conv_rgb555_to_bgra32()); break; + case pix_format_rgb565: color_conv(&rbuf_tmp, src, color_conv_rgb565_to_bgra32()); break; + case pix_format_srgb24: convert(&rbuf_tmp, src); break; + case pix_format_sbgr24: convert(&rbuf_tmp, src); break; + case pix_format_rgb24: convert(&rbuf_tmp, src); break; + case pix_format_bgr24: convert(&rbuf_tmp, src); break; + case pix_format_srgba32: convert(&rbuf_tmp, src); break; + case pix_format_sargb32: convert(&rbuf_tmp, src); break; + case pix_format_sabgr32: convert(&rbuf_tmp, src); break; + case pix_format_sbgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgba32: convert(&rbuf_tmp, src); break; + case pix_format_argb32: convert(&rbuf_tmp, src); break; + case pix_format_abgr32: convert(&rbuf_tmp, src); break; + case pix_format_bgra32: convert(&rbuf_tmp, src); break; + case pix_format_rgb48: convert(&rbuf_tmp, src); break; + case pix_format_bgr48: convert(&rbuf_tmp, src); break; + case pix_format_rgba64: convert(&rbuf_tmp, src); break; + case pix_format_argb64: convert(&rbuf_tmp, src); break; + case pix_format_abgr64: convert(&rbuf_tmp, src); break; + case pix_format_bgra64: convert(&rbuf_tmp, src); break; + case pix_format_rgb96: convert(&rbuf_tmp, src); break; + case pix_format_bgr96: convert(&rbuf_tmp, src); break; + case pix_format_rgba128: convert(&rbuf_tmp, src); break; + case pix_format_argb128: convert(&rbuf_tmp, src); break; + case pix_format_abgr128: convert(&rbuf_tmp, src); break; + case pix_format_bgra128: convert(&rbuf_tmp, src); break; + } + break; + } + + m_ximg_window->data = (char*)buf_tmp; + XPutImage(m_display, + m_window, + m_gc, + m_ximg_window, + 0, 0, 0, 0, + src->width(), + src->height()); + + delete [] buf_tmp; + } + } + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "AGG Application"); + } + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_initialized) + { + m_specific->caption(cap); + } + } + + + //------------------------------------------------------------------------ + enum xevent_mask_e + { + xevent_mask = + PointerMotionMask| + ButtonPressMask| + ButtonReleaseMask| + ExposureMask| + KeyPressMask| + StructureNotifyMask + }; + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_window_flags = flags; + + m_specific->m_display = XOpenDisplay(NULL); + if(m_specific->m_display == 0) + { + fprintf(stderr, "Unable to open DISPLAY!\n"); + return false; + } + + m_specific->m_screen = XDefaultScreen(m_specific->m_display); + m_specific->m_depth = XDefaultDepth(m_specific->m_display, + m_specific->m_screen); + m_specific->m_visual = XDefaultVisual(m_specific->m_display, + m_specific->m_screen); + unsigned long r_mask = m_specific->m_visual->red_mask; + unsigned long g_mask = m_specific->m_visual->green_mask; + unsigned long b_mask = m_specific->m_visual->blue_mask; + +//printf("depth=%d, red=%08x, green=%08x, blue=%08x\n", +// m_specific->m_depth, +// m_specific->m_visual->red_mask, +// m_specific->m_visual->green_mask, +// m_specific->m_visual->blue_mask); + + +// // NOT COMPLETED YET! +// // Try to find an appropriate Visual if the default doesn't fit. +// if(m_specific->m_depth < 15 || +// r_mask == 0 || g_mask == 0 || b_mask == 0) +// { +// +// // This is an attempt to find an appropriate Visual if +// // the default one doesn't match the minumum requirements +// static int depth[] = { 32, 24, 16, 15 }; +// int i; +// for(int i = 0; i < 4; i++) +// { +// XVisualInfo vi; +// if(XMatchVisualInfo(m_specific->m_display, +// m_specific->m_screen, +// depth[i], +// TrueColor, +// &vi)) +// { +// // printf("TrueColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // vi.depth, +// // vi.visual->red_mask, +// // vi.visual->green_mask, +// // vi.visual->blue_mask, +// // vi.bits_per_rgb); +// m_specific->m_depth = vi.depth; +// m_specific->m_visual = vi.visual; +// r_mask = m_specific->m_visual->red_mask; +// g_mask = m_specific->m_visual->green_mask; +// b_mask = m_specific->m_visual->blue_mask; +// break; +// } +// if(XMatchVisualInfo(m_specific->m_display, +// m_specific->m_screen, +// depth[i], +// DirectColor, +// &vi)) +// { +// // printf("DirectColor depth=%d, red=%08x, green=%08x, blue=%08x, bits=%d\n", +// // vi.depth, +// // vi.visual->red_mask, +// // vi.visual->green_mask, +// // vi.visual->blue_mask, +// // vi.bits_per_rgb); +// m_specific->m_depth = vi.depth; +// m_specific->m_visual = vi.visual; +// r_mask = m_specific->m_visual->red_mask; +// g_mask = m_specific->m_visual->green_mask; +// b_mask = m_specific->m_visual->blue_mask; +// break; +// } +// } +// } + + if(m_specific->m_depth < 15 || + r_mask == 0 || g_mask == 0 || b_mask == 0) + { + fprintf(stderr, + "There's no Visual compatible with minimal AGG requirements:\n" + "At least 15-bit color depth and True- or DirectColor class.\n\n"); + XCloseDisplay(m_specific->m_display); + return false; + } + + int t = 1; + int hw_byte_order = LSBFirst; + if(*(char*)&t == 0) hw_byte_order = MSBFirst; + + // Perceive SYS-format by mask + switch(m_specific->m_depth) + { + case 15: + m_specific->m_sys_bpp = 16; + if(r_mask == 0x7C00 && g_mask == 0x3E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb555; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 16: + m_specific->m_sys_bpp = 16; + if(r_mask == 0xF800 && g_mask == 0x7E0 && b_mask == 0x1F) + { + m_specific->m_sys_format = pix_format_rgb565; + m_specific->m_byte_order = hw_byte_order; + } + break; + + case 24: + case 32: + m_specific->m_sys_bpp = 32; + if(g_mask == 0xFF00) + { + if(r_mask == 0xFF && b_mask == 0xFF0000) + { + switch(m_specific->m_format) + { + case pix_format_rgba32: + m_specific->m_sys_format = pix_format_rgba32; + m_specific->m_byte_order = LSBFirst; + break; + + case pix_format_abgr32: + m_specific->m_sys_format = pix_format_abgr32; + m_specific->m_byte_order = MSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == LSBFirst) ? + pix_format_rgba32 : + pix_format_abgr32; + break; + } + } + + if(r_mask == 0xFF0000 && b_mask == 0xFF) + { + switch(m_specific->m_format) + { + case pix_format_argb32: + m_specific->m_sys_format = pix_format_argb32; + m_specific->m_byte_order = MSBFirst; + break; + + case pix_format_bgra32: + m_specific->m_sys_format = pix_format_bgra32; + m_specific->m_byte_order = LSBFirst; + break; + + default: + m_specific->m_byte_order = hw_byte_order; + m_specific->m_sys_format = + (hw_byte_order == MSBFirst) ? + pix_format_argb32 : + pix_format_bgra32; + break; + } + } + } + break; + } + + if(m_specific->m_sys_format == pix_format_undefined) + { + fprintf(stderr, + "RGB masks are not compatible with AGG pixel formats:\n" + "R=%08x, R=%08x, B=%08x\n", r_mask, g_mask, b_mask); + XCloseDisplay(m_specific->m_display); + return false; + } + + + + memset(&m_specific->m_window_attributes, + 0, + sizeof(m_specific->m_window_attributes)); + + m_specific->m_window_attributes.border_pixel = + XBlackPixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.background_pixel = + XWhitePixel(m_specific->m_display, m_specific->m_screen); + + m_specific->m_window_attributes.override_redirect = 0; + + unsigned long window_mask = CWBackPixel | CWBorderPixel; + + m_specific->m_window = + XCreateWindow(m_specific->m_display, + XDefaultRootWindow(m_specific->m_display), + 0, 0, + width, + height, + 0, + m_specific->m_depth, + InputOutput, + CopyFromParent, + window_mask, + &m_specific->m_window_attributes); + + + m_specific->m_gc = XCreateGC(m_specific->m_display, + m_specific->m_window, + 0, 0); + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + memset(m_specific->m_buf_window, 255, width * height * (m_bpp / 8)); + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? -width * (m_bpp / 8) : width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + m_specific->caption(m_caption); + m_initial_width = width; + m_initial_height = height; + + if(!m_specific->m_initialized) + { + on_init(); + m_specific->m_initialized = true; + } + + trans_affine_resizing(width, height); + on_resize(width, height); + m_specific->m_update_flag = true; + + XSizeHints *hints = XAllocSizeHints(); + if(hints) + { + if(flags & window_resize) + { + hints->min_width = 32; + hints->min_height = 32; + hints->max_width = 4096; + hints->max_height = 4096; + } + else + { + hints->min_width = width; + hints->min_height = height; + hints->max_width = width; + hints->max_height = height; + } + hints->flags = PMaxSize | PMinSize; + + XSetWMNormalHints(m_specific->m_display, + m_specific->m_window, + hints); + + XFree(hints); + } + + + XMapWindow(m_specific->m_display, + m_specific->m_window); + + XSelectInput(m_specific->m_display, + m_specific->m_window, + xevent_mask); + + + m_specific->m_close_atom = XInternAtom(m_specific->m_display, + "WM_DELETE_WINDOW", + false); + + XSetWMProtocols(m_specific->m_display, + m_specific->m_window, + &m_specific->m_close_atom, + 1); + + return true; + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->put_image(&m_rbuf_window); + + // When m_wait_mode is true we can discard all the events + // came while the image is being drawn. In this case + // the X server does not accumulate mouse motion events. + // When m_wait_mode is false, i.e. we have some idle drawing + // we cannot afford to miss any events + XSync(m_specific->m_display, m_wait_mode); + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + XFlush(m_specific->m_display); + + bool quit = false; + unsigned flags; + int cur_x; + int cur_y; + + while(!quit) + { + if(m_specific->m_update_flag) + { + on_draw(); + update_window(); + m_specific->m_update_flag = false; + } + + if(!m_wait_mode) + { + if(XPending(m_specific->m_display) == 0) + { + on_idle(); + continue; + } + } + + XEvent x_event; + XNextEvent(m_specific->m_display, &x_event); + + // In the Idle mode discard all intermediate MotionNotify events + if(!m_wait_mode && x_event.type == MotionNotify) + { + XEvent te = x_event; + for(;;) + { + if(XPending(m_specific->m_display) == 0) break; + XNextEvent(m_specific->m_display, &te); + if(te.type != MotionNotify) break; + } + x_event = te; + } + + switch(x_event.type) + { + case ConfigureNotify: + { + if(x_event.xconfigure.width != int(m_rbuf_window.width()) || + x_event.xconfigure.height != int(m_rbuf_window.height())) + { + int width = x_event.xconfigure.width; + int height = x_event.xconfigure.height; + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + + m_specific->m_buf_window = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_window.attach(m_specific->m_buf_window, + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + + m_specific->m_ximg_window = + XCreateImage(m_specific->m_display, + m_specific->m_visual, //CopyFromParent, + m_specific->m_depth, + ZPixmap, + 0, + (char*)m_specific->m_buf_window, + width, + height, + m_specific->m_sys_bpp, + width * (m_specific->m_sys_bpp / 8)); + m_specific->m_ximg_window->byte_order = m_specific->m_byte_order; + + trans_affine_resizing(width, height); + on_resize(width, height); + on_draw(); + update_window(); + } + } + break; + + case Expose: + m_specific->put_image(&m_rbuf_window); + XFlush(m_specific->m_display); + XSync(m_specific->m_display, false); + break; + + case KeyPress: + { + KeySym key = XLookupKeysym(&x_event.xkey, 0); + flags = 0; + if(x_event.xkey.state & Button1Mask) flags |= mouse_left; + if(x_event.xkey.state & Button3Mask) flags |= mouse_right; + if(x_event.xkey.state & ShiftMask) flags |= kbd_shift; + if(x_event.xkey.state & ControlMask) flags |= kbd_ctrl; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(m_specific->m_keymap[key & 0xFF]) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + case key_f2: + copy_window_to_img(max_images - 1); + save_img(max_images - 1, "screenshot"); + break; + } + + if(m_ctrls.on_arrow_keys(left, right, down, up)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_key(x_event.xkey.x, + m_flip_y ? + m_rbuf_window.height() - x_event.xkey.y : + x_event.xkey.y, + m_specific->m_keymap[key & 0xFF], + flags); + } + } + break; + + + case ButtonPress: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_down(cur_x, cur_y)) + { + m_ctrls.set_cur(cur_x, cur_y); + on_ctrl_change(); + force_redraw(); + } + else + { + if(m_ctrls.in_rect(cur_x, cur_y)) + { + if(m_ctrls.set_cur(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(cur_x, cur_y, flags); + } + } + } + if(flags & mouse_right) + { + on_mouse_button_down(cur_x, cur_y, flags); + } + //m_specific->m_wait_mode = m_wait_mode; + //m_wait_mode = true; + } + break; + + + case MotionNotify: + { + flags = 0; + if(x_event.xmotion.state & Button1Mask) flags |= mouse_left; + if(x_event.xmotion.state & Button3Mask) flags |= mouse_right; + if(x_event.xmotion.state & ShiftMask) flags |= kbd_shift; + if(x_event.xmotion.state & ControlMask) flags |= kbd_ctrl; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(m_ctrls.on_mouse_move(cur_x, cur_y, (flags & mouse_left) != 0)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + if(!m_ctrls.in_rect(cur_x, cur_y)) + { + on_mouse_move(cur_x, cur_y, flags); + } + } + } + break; + + case ButtonRelease: + { + flags = 0; + if(x_event.xbutton.state & ShiftMask) flags |= kbd_shift; + if(x_event.xbutton.state & ControlMask) flags |= kbd_ctrl; + if(x_event.xbutton.button == Button1) flags |= mouse_left; + if(x_event.xbutton.button == Button3) flags |= mouse_right; + + cur_x = x_event.xbutton.x; + cur_y = m_flip_y ? m_rbuf_window.height() - x_event.xbutton.y : + x_event.xbutton.y; + + if(flags & mouse_left) + { + if(m_ctrls.on_mouse_button_up(cur_x, cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + if(flags & (mouse_left | mouse_right)) + { + on_mouse_button_up(cur_x, cur_y, flags); + } + } + //m_wait_mode = m_specific->m_wait_mode; + break; + + case ClientMessage: + if((x_event.xclient.format == 32) && + (x_event.xclient.data.l[0] == int(m_specific->m_close_atom))) + { + quit = true; + } + break; + } + } + + + unsigned i = platform_support::max_images; + while(i--) + { + if(m_specific->m_buf_img[i]) + { + delete [] m_specific->m_buf_img[i]; + } + } + + delete [] m_specific->m_buf_window; + m_specific->m_ximg_window->data = 0; + XDestroyImage(m_specific->m_ximg_window); + XFreeGC(m_specific->m_display, m_specific->m_gc); + XDestroyWindow(m_specific->m_display, m_specific->m_window); + XCloseDisplay(m_specific->m_display); + + return 0; + } + + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".ppm"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "rb"); + if(fd == 0) return false; + + if((len = fread(buf, 1, 1022, fd)) == 0) + { + fclose(fd); + return false; + } + buf[len] = 0; + + if(buf[0] != 'P' && buf[1] != '6') + { + fclose(fd); + return false; + } + + char* ptr = buf + 2; + + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + + unsigned width = atoi(ptr); + if(width == 0 || width > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + unsigned height = atoi(ptr); + if(height == 0 || height > 4096) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + while(*ptr && !isdigit(*ptr)) ptr++; + if(atoi(ptr) != 255) + { + fclose(fd); + return false; + } + while(*ptr && isdigit(*ptr)) ptr++; + if(*ptr == 0) + { + fclose(fd); + return false; + } + ptr++; + fseek(fd, long(ptr - buf), SEEK_SET); + + create_img(idx, width, height); + bool ret = true; + + if(m_format == pix_format_rgb24) + { + fread(m_specific->m_buf_img[idx], 1, width * height * 3, fd); + } + else + { + unsigned char* buf_img = new unsigned char [width * height * 3]; + rendering_buffer rbuf_img; + rbuf_img.attach(buf_img, + width, + height, + m_flip_y ? + -width * 3 : + width * 3); + + fread(buf_img, 1, width * height * 3, fd); + + switch(m_format) + { + case pix_format_sgray8: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray8: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray16: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_gray32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb555: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb555()); + break; + + case pix_format_rgb565: + color_conv(m_rbuf_img+idx, &rbuf_img, color_conv_rgb24_to_rgb565()); + break; + + case pix_format_sbgr24: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb24: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgr24: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_srgba32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sargb32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sbgra32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_sabgr32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgba32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_argb32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgra32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_abgr32: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb48: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgr48: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgba64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_argb64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgra64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_abgr64: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgb96: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgr96: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_rgba128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_argb128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_bgra128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + case pix_format_abgr128: + convert(m_rbuf_img+idx, &rbuf_img); + break; + + default: + ret = false; + } + delete [] buf_img; + } + + fclose(fd); + return ret; + } + return false; + } + + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images && rbuf_img(idx).buf()) + { + char buf[1024]; + strcpy(buf, file); + int len = strlen(buf); + if(len < 4 || strcasecmp(buf + len - 4, ".ppm") != 0) + { + strcat(buf, ".ppm"); + } + + FILE* fd = fopen(buf, "wb"); + if(fd == 0) return false; + + unsigned w = rbuf_img(idx).width(); + unsigned h = rbuf_img(idx).height(); + + fprintf(fd, "P6\n%d %d\n255\n", w, h); + + unsigned y; + unsigned char* tmp_buf = new unsigned char [w * 3]; + for(y = 0; y < rbuf_img(idx).height(); y++) + { + const unsigned char* src = rbuf_img(idx).row_ptr(m_flip_y ? h - 1 - y : y); + switch(m_format) + { + case pix_format_sgray8: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray8: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray16: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_gray32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + default: break; + case pix_format_rgb555: + color_conv_row(tmp_buf, src, w, color_conv_rgb555_to_rgb24()); + break; + + case pix_format_rgb565: + color_conv_row(tmp_buf, src, w, color_conv_rgb565_to_rgb24()); + break; + + case pix_format_sbgr24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_srgb24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgr24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgb24: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_srgba32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sargb32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sbgra32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_sabgr32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgba32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_argb32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgra32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_abgr32: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgr48: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgb48: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgba64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_argb64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgra64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_abgr64: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgr96: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgb96: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_rgba128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_argb128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_bgra128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + + case pix_format_abgr128: + color_conv_row(tmp_buf, src, w, conv_row()); + break; + } + fwrite(tmp_buf, 1, w * 3, fd); + } + delete [] tmp_buf; + fclose(fd); + return true; + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = rbuf_window().width(); + if(height == 0) height = rbuf_window().height(); + delete [] m_specific->m_buf_img[idx]; + m_specific->m_buf_img[idx] = + new unsigned char[width * height * (m_bpp / 8)]; + + m_rbuf_img[idx].attach(m_specific->m_buf_img[idx], + width, + height, + m_flip_y ? + -width * (m_bpp / 8) : + width * (m_bpp / 8)); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_update_flag = true; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + fprintf(stderr, "%s\n", msg); + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->m_sw_start = clock(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + clock_t stop = clock(); + return double(stop - m_specific->m_sw_start) * 1000.0 / CLOCKS_PER_SEC; + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + + +} + + +int agg_main(int argc, char* argv[]); + + +int main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + + + + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_mac_pmap.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_mac_pmap.cpp new file mode 100644 index 00000000000..dc85fd69ffd --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_mac_pmap.cpp @@ -0,0 +1,298 @@ +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// Contact: mcseemagg@yahoo.com +// baer@karto.baug.ethz.ch +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include "platform/mac/agg_mac_pmap.h" +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + pixel_map::~pixel_map() + { + destroy(); + } + + + //------------------------------------------------------------------------ + pixel_map::pixel_map() : + m_pmap(0), + m_buf(0), + m_bpp(0), + m_img_size(0) + + { + } + + + //------------------------------------------------------------------------ + void pixel_map::destroy() + { + delete[] m_buf; + m_buf = NULL; + if (m_pmap != nil) + { + DisposeGWorld(m_pmap); + m_pmap = nil; + } + } + + + //------------------------------------------------------------------------ + void pixel_map::create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + + Rect r; + int row_bytes = calc_row_len (width, m_bpp); + MacSetRect(&r, 0, 0, width, height); + m_buf = new unsigned char[m_img_size = row_bytes * height]; + // The Quicktime version for creating GWorlds is more flexible than the classical function. + QTNewGWorldFromPtr (&m_pmap, m_bpp, &r, nil, nil, 0, m_buf, row_bytes); + + // create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far. + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + } + + + + //------------------------------------------------------------------------ + void pixel_map::clear(unsigned clear_val) + { + if(m_buf) memset(m_buf, clear_val, m_img_size); + } + + + //static + //This function is just copied from the Win32 plattform support. + //Is also seems to be appropriate for MacOS as well, but it is not + //thouroughly tested so far. + //------------------------------------------------------------------------ + + unsigned pixel_map::calc_row_len(unsigned width, unsigned bits_per_pixel) + { + unsigned n = width; + unsigned k; + + switch(bits_per_pixel) + { + case 1: k = n; + n = n >> 3; + if(k & 7) n++; + break; + + case 4: k = n; + n = n >> 1; + if(k & 3) n++; + break; + + case 8: + break; + + case 16: n = n << 1; + break; + + case 24: n = (n << 1) + n; + break; + + case 32: n = n << 2; + break; + + default: n = 0; + break; + } + return ((n + 3) >> 2) << 2; + } + + + + + //------------------------------------------------------------------------ + void pixel_map::draw(WindowRef window, const Rect *device_rect, const Rect *pmap_rect) const + { + if(m_pmap == nil || m_buf == NULL) return; + + PixMapHandle pm = GetGWorldPixMap (m_pmap); + CGrafPtr port = GetWindowPort (window); + Rect dest_rect; + + // Again, I used the Quicktime version. + // Good old 'CopyBits' does better interpolation when scaling + // but does not support all pixel depths. + MacSetRect (&dest_rect, 0, 0, this->width(), this->height()); + ImageDescriptionHandle image_description; + MakeImageDescriptionForPixMap (pm, &image_description); + if (image_description != nil) + { + DecompressImage (GetPixBaseAddr (pm), image_description, GetPortPixMap (port), nil, &dest_rect, ditherCopy, nil); + DisposeHandle ((Handle) image_description); + } + } + + + //------------------------------------------------------------------------ + void pixel_map::draw(WindowRef window, int x, int y, double scale) const + { + if(m_pmap == nil || m_buf == NULL) return; + unsigned width = (unsigned)(this->width() * scale); + unsigned height = (unsigned)(this->height() * scale); + Rect rect; + SetRect (&rect, x, y, x + width, y + height); + draw(window, &rect); + } + + + + //------------------------------------------------------------------------ + void pixel_map::blend(WindowRef window, const Rect *device_rect, const Rect *bmp_rect) const + { + draw (window, device_rect, bmp_rect); // currently just mapped to drawing method + } + + + //------------------------------------------------------------------------ + void pixel_map::blend(WindowRef window, int x, int y, double scale) const + { + draw(window, x, y, scale); // currently just mapped to drawing method + } + + + // I let Quicktime handle image import since it supports most popular + // image formats such as: + // *.psd, *.bmp, *.tif, *.png, *.jpg, *.gif, *.pct, *.pcx + //------------------------------------------------------------------------ + bool pixel_map::load_from_qt(const char *filename) + { + FSSpec fss; + OSErr err; + + // get file specification to application directory + err = HGetVol(nil, &fss.vRefNum, &fss.parID); + if (err == noErr) + { + CopyCStringToPascal(filename, fss.name); + GraphicsImportComponent gi; + err = GetGraphicsImporterForFile (&fss, &gi); + if (err == noErr) + { + ImageDescriptionHandle desc; + GraphicsImportGetImageDescription(gi, &desc); +// For simplicity, all images are currently converted to 32 bit. + // create an empty pixelmap + short depth = 32; + create ((**desc).width, (**desc).height, (org_e)depth, 0xff); + DisposeHandle ((Handle)desc); + // let Quicktime draw to pixelmap + GraphicsImportSetGWorld(gi, m_pmap, nil); + GraphicsImportDraw(gi); +// Well, this is a hack. The graphics importer sets the alpha channel of the pixelmap to 0x00 +// for imported images without alpha channel but this would cause agg to draw an invisible image. + // set alpha channel to 0xff + unsigned char * buf = m_buf; + for (unsigned int size = 0; size < m_img_size; size += 4) + { + *buf = 0xff; + buf += 4; + } + } + } + return err == noErr; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_qt(const char *filename) const + { + FSSpec fss; + OSErr err; + + // get file specification to application directory + err = HGetVol(nil, &fss.vRefNum, &fss.parID); + if (err == noErr) + { + GraphicsExportComponent ge; + CopyCStringToPascal(filename, fss.name); + // I decided to use PNG as output image file type. + // There are a number of other available formats. + // Should I check the file suffix to choose the image file format? + err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypePNG, &ge); + if (err == noErr) + { + err = GraphicsExportSetInputGWorld(ge, m_pmap); + if (err == noErr) + { + err = GraphicsExportSetOutputFile (ge, &fss); + if (err == noErr) + { + GraphicsExportDoExport(ge, nil); + } + } + CloseComponent(ge); + } + } + + return err == noErr; + } + + //------------------------------------------------------------------------ + unsigned char* pixel_map::buf() + { + return m_buf; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::width() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + Rect bounds; + GetPixBounds (pm, &bounds); + return bounds.right - bounds.left; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::height() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + Rect bounds; + GetPixBounds (pm, &bounds); + return bounds.bottom - bounds.top; + } + + //------------------------------------------------------------------------ + int pixel_map::row_bytes() const + { + if(m_pmap == nil) return 0; + PixMapHandle pm = GetGWorldPixMap (m_pmap); + return calc_row_len(width(), GetPixDepth(pm)); + } + + + +} + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_platform_support.cpp new file mode 100644 index 00000000000..f518dbe1f27 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/mac/agg_platform_support.cpp @@ -0,0 +1,1053 @@ +//---------------------------------------------------------------------------- +// Anti-Grain Geometry - Version 2.4 +// Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) +// Copyright (C) 2003 Hansruedi Baer (MacOS support) +// +// 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 +// baer@karto.baug.eth.ch +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- +// +// Note: +// I tried to retain the original structure for the Win32 platform as far +// as possible. Currently, not all features are implemented but the examples +// should work properly. +// HB +//---------------------------------------------------------------------------- + +#include +#if defined(__MWERKS__) +#include "console.h" +#endif +#include +#include +#include "platform/agg_platform_support.h" +#include "platform/mac/agg_mac_pmap.h" +#include "util/agg_color_conv_rgb8.h" + + +namespace agg +{ + +pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData); +pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData); + + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + + void create_pmap(unsigned width, unsigned height, + rendering_buffer* wnd); + + void display_pmap(WindowRef window, const rendering_buffer* src); + bool load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst); + + bool save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src); + + unsigned translate(unsigned keycode); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + WindowRef m_window; + pixel_map m_pmap_window; + pixel_map m_pmap_img[platform_support::max_images]; + unsigned m_keymap[256]; + unsigned m_last_translated_key; + int m_cur_x; + int m_cur_y; + unsigned m_input_flags; + bool m_redraw_flag; + UnsignedWide m_sw_freq; + UnsignedWide m_sw_start; + }; + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_window(nil), + m_last_translated_key(0), + m_cur_x(0), + m_cur_y(0), + m_input_flags(0), + m_redraw_flag(true) + { + memset(m_keymap, 0, sizeof(m_keymap)); + + //Keyboard input is not yet fully supported nor tested + //m_keymap[VK_PAUSE] = key_pause; + m_keymap[kClearCharCode] = key_clear; + + //m_keymap[VK_NUMPAD0] = key_kp0; + //m_keymap[VK_NUMPAD1] = key_kp1; + //m_keymap[VK_NUMPAD2] = key_kp2; + //m_keymap[VK_NUMPAD3] = key_kp3; + //m_keymap[VK_NUMPAD4] = key_kp4; + //m_keymap[VK_NUMPAD5] = key_kp5; + //m_keymap[VK_NUMPAD6] = key_kp6; + //m_keymap[VK_NUMPAD7] = key_kp7; + //m_keymap[VK_NUMPAD8] = key_kp8; + //m_keymap[VK_NUMPAD9] = key_kp9; + //m_keymap[VK_DECIMAL] = key_kp_period; + //m_keymap[VK_DIVIDE] = key_kp_divide; + //m_keymap[VK_MULTIPLY] = key_kp_multiply; + //m_keymap[VK_SUBTRACT] = key_kp_minus; + //m_keymap[VK_ADD] = key_kp_plus; + + m_keymap[kUpArrowCharCode] = key_up; + m_keymap[kDownArrowCharCode] = key_down; + m_keymap[kRightArrowCharCode] = key_right; + m_keymap[kLeftArrowCharCode] = key_left; + //m_keymap[VK_INSERT] = key_insert; + m_keymap[kDeleteCharCode] = key_delete; + m_keymap[kHomeCharCode] = key_home; + m_keymap[kEndCharCode] = key_end; + m_keymap[kPageUpCharCode] = key_page_up; + m_keymap[kPageDownCharCode] = key_page_down; + + //m_keymap[VK_F1] = key_f1; + //m_keymap[VK_F2] = key_f2; + //m_keymap[VK_F3] = key_f3; + //m_keymap[VK_F4] = key_f4; + //m_keymap[VK_F5] = key_f5; + //m_keymap[VK_F6] = key_f6; + //m_keymap[VK_F7] = key_f7; + //m_keymap[VK_F8] = key_f8; + //m_keymap[VK_F9] = key_f9; + //m_keymap[VK_F10] = key_f10; + //m_keymap[VK_F11] = key_f11; + //m_keymap[VK_F12] = key_f12; + //m_keymap[VK_F13] = key_f13; + //m_keymap[VK_F14] = key_f14; + //m_keymap[VK_F15] = key_f15; + + //m_keymap[VK_NUMLOCK] = key_numlock; + //m_keymap[VK_CAPITAL] = key_capslock; + //m_keymap[VK_SCROLL] = key_scrollock; + + switch(m_format) + { + case pix_format_gray8: + m_sys_format = pix_format_gray8; + m_bpp = 8; + m_sys_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_sys_format = pix_format_rgb555; + m_bpp = 16; + m_sys_bpp = 16; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + m_sys_format = pix_format_rgb24; + m_bpp = 24; + m_sys_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + m_sys_format = pix_format_argb32; + m_bpp = 32; + m_sys_bpp = 32; + break; + } + ::Microseconds(&m_sw_freq); + ::Microseconds(&m_sw_start); + } + + + //------------------------------------------------------------------------ + void platform_specific::create_pmap(unsigned width, + unsigned height, + rendering_buffer* wnd) + { + m_pmap_window.create(width, height, org_e(m_bpp)); + wnd->attach(m_pmap_window.buf(), + m_pmap_window.width(), + m_pmap_window.height(), + m_flip_y ? + -m_pmap_window.row_bytes() : + m_pmap_window.row_bytes()); + } + + + //------------------------------------------------------------------------ + void platform_specific::display_pmap(WindowRef window, const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + m_pmap_window.draw(window); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_window.width(), + m_pmap_window.height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + + switch(m_format) + { + case pix_format_gray8: + return; + + case pix_format_rgb565: + color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_bgr24: + color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb24()); + break; + + case pix_format_abgr32: + color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32()); + break; + + case pix_format_bgra32: + color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32()); + break; + + case pix_format_rgba32: + color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32()); + break; + } + pmap_tmp.draw(window); + } + } + + + //------------------------------------------------------------------------ + bool platform_specific::save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + return m_pmap_img[idx].save_as_qt(fn); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + switch(m_format) + { + case pix_format_gray8: + return false; + + case pix_format_rgb565: + color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_rgb24: + color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_abgr32: + color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32()); + break; + + case pix_format_argb32: + color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32()); + break; + + case pix_format_rgba32: + color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32()); + break; + } + return pmap_tmp.save_as_qt(fn); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_specific::load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst) + { + pixel_map pmap_tmp; + if(!pmap_tmp.load_from_qt(fn)) return false; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + -pmap_tmp.row_bytes() : + pmap_tmp.row_bytes()); + + m_pmap_img[idx].create(pmap_tmp.width(), + pmap_tmp.height(), + org_e(m_bpp), + 0); + + dst->attach(m_pmap_img[idx].buf(), + m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + m_flip_y ? + -m_pmap_img[idx].row_bytes() : + m_pmap_img[idx].row_bytes()); + + switch(m_format) + { + case pix_format_gray8: + return false; + break; + + case pix_format_rgb555: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb555()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb565()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb565()); break; + } + break; + + case pix_format_rgb24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb24()); break; + } + break; + + case pix_format_bgr24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgr24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgr24()); break; + } + break; + + case pix_format_abgr32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_abgr32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_abgr32()); break; + } + break; + + case pix_format_argb32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_argb32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_argb32()); break; + } + break; + + case pix_format_bgra32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgra32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgra32()); break; + } + break; + + case pix_format_rgba32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgba32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgba32()); break; + } + break; + } + + return true; + } + + + + + + + + + //------------------------------------------------------------------------ + unsigned platform_specific::translate(unsigned keycode) + { + return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode]; + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_window) + { + SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, cap, kCFStringEncodingASCII, nil)); + } + } + + + + //------------------------------------------------------------------------ + static unsigned get_key_flags(UInt32 wflags) + { + unsigned flags = 0; + + if(wflags & shiftKey) flags |= kbd_shift; + if(wflags & controlKey) flags |= kbd_ctrl; + + return flags; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + SInt16 item; + Str255 p_msg; + + ::CopyCStringToPascal (msg, p_msg); + ::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\013AGG Message", p_msg, NULL, &item); + //::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\pAGG Message", p_msg, NULL, &item); + } + + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + ::Microseconds (&(m_specific->m_sw_start)); + } + + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + UnsignedWide stop; + ::Microseconds(&stop); + return double(stop.lo - + m_specific->m_sw_start.lo) * 1e6 / + double(m_specific->m_sw_freq.lo); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + if(m_specific->m_sys_format == pix_format_undefined) + { + return false; + } + + m_window_flags = flags; + + // application + EventTypeSpec eventType; + EventHandlerUPP handlerUPP; + + eventType.eventClass = kEventClassApplication; + eventType.eventKind = kEventAppQuit; + + handlerUPP = NewEventHandlerUPP(DoAppQuit); + + InstallApplicationEventHandler (handlerUPP, 1, &eventType, nil, nil); + + eventType.eventClass = kEventClassMouse; + eventType.eventKind = kEventMouseDown; + handlerUPP = NewEventHandlerUPP(DoMouseDown); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventMouseUp; + handlerUPP = NewEventHandlerUPP(DoMouseUp); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventMouseDragged; + handlerUPP = NewEventHandlerUPP(DoMouseDragged); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventClass = kEventClassKeyboard; + eventType.eventKind = kEventRawKeyDown; + handlerUPP = NewEventHandlerUPP(DoKeyDown); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventRawKeyUp; + handlerUPP = NewEventHandlerUPP(DoKeyUp); + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + eventType.eventKind = kEventRawKeyRepeat; + handlerUPP = NewEventHandlerUPP(DoKeyDown); // 'key repeat' is translated to 'key down' + InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil); + + WindowAttributes windowAttrs; + Rect bounds; + + // window + windowAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute; + SetRect (&bounds, 0, 0, width, height); + OffsetRect (&bounds, 100, 100); + CreateNewWindow (kDocumentWindowClass, windowAttrs, &bounds, &m_specific->m_window); + + if(m_specific->m_window == nil) + { + return false; + } + + // I assume the text is ASCII. + // Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need. + SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, m_caption, kCFStringEncodingASCII, nil)); + + eventType.eventClass = kEventClassWindow; + eventType.eventKind = kEventWindowClose; + + handlerUPP = NewEventHandlerUPP(DoWindowClose); + InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL); + + eventType.eventKind = kEventWindowDrawContent; + handlerUPP = NewEventHandlerUPP(DoWindowDrawContent); + InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL); + + // Periodic task + // Instead of an idle function I use the Carbon event timer. + // You may decide to change the wait value which is currently 50 milliseconds. + EventLoopRef mainLoop; + EventLoopTimerUPP timerUPP; + EventLoopTimerRef theTimer; + + mainLoop = GetMainEventLoop(); + timerUPP = NewEventLoopTimerUPP (DoPeriodicTask); + InstallEventLoopTimer (mainLoop, 0, 50 * kEventDurationMillisecond, timerUPP, this, &theTimer); + + m_specific->create_pmap(width, height, &m_rbuf_window); + m_initial_width = width; + m_initial_height = height; + on_init(); + on_resize(width, height); + m_specific->m_redraw_flag = true; + + ShowWindow (m_specific->m_window); + SetPortWindowPort (m_specific->m_window); + + return true; + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + + RunApplicationEventLoop (); + return true; + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); +#if defined(__MWERKS__) + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif + { + strcat(fn, ".bmp"); + } + return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); +#if defined(__MWERKS__) + if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0) +#else + if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0) +#endif + { + strcat(fn, ".bmp"); + } + return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->m_pmap_window.width(); + if(height == 0) height = m_specific->m_pmap_window.height(); + m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp)); + m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(), + m_specific->m_pmap_img[idx].width(), + m_specific->m_pmap_img[idx].height(), + m_flip_y ? + -m_specific->m_pmap_img[idx].row_bytes() : + m_specific->m_pmap_img[idx].row_bytes()); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + Rect bounds; + + m_specific->m_redraw_flag = true; + // on_ctrl_change (); + on_draw(); + + SetRect(&bounds, 0, 0, m_rbuf_window.width(), m_rbuf_window.height()); + InvalWindowRect(m_specific->m_window, &bounds); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + m_specific->display_pmap(m_specific->m_window, &m_rbuf_window); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + +//------------------------------------------------------------------------ +pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + userData; + + QuitApplicationEventLoop (); + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + userData; + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y); + if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + if(app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + Point wheresMyMouse; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse); + GlobalToLocal (&wheresMyMouse); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast(userData); + + app->m_specific->m_cur_x = wheresMyMouse.h; + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v; + } + else + { + app->m_specific->m_cur_y = wheresMyMouse.v; + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier); + + + if(app->m_ctrls.on_mouse_move( + app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + (app->m_specific->m_input_flags & mouse_left) != 0)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_mouse_move(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + char key_code; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast(userData); + + app->m_specific->m_last_translated_key = 0; + switch(modifier) + { + case controlKey: + app->m_specific->m_input_flags |= kbd_ctrl; + break; + + case shiftKey: + app->m_specific->m_input_flags |= kbd_shift; + break; + + default: + app->m_specific->translate(key_code); + break; + } + + if(app->m_specific->m_last_translated_key) + { + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(app->m_specific->m_last_translated_key) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + //On a Mac, screenshots are handled by the system. + case key_f2: + app->copy_window_to_img(agg::platform_support::max_images - 1); + app->save_img(agg::platform_support::max_images - 1, "screenshot"); + break; + } + + + if(app->m_ctrls.on_arrow_keys(left, right, down, up)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + char key_code; + UInt32 modifier; + + GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code); + GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier); + + platform_support * app = reinterpret_cast(userData); + + app->m_specific->m_last_translated_key = 0; + switch(modifier) + { + case controlKey: + app->m_specific->m_input_flags &= ~kbd_ctrl; + break; + + case shiftKey: + app->m_specific->m_input_flags &= ~kbd_shift; + break; + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData) +{ + platform_support * app = reinterpret_cast(userData); + + if(app) + { + if(app->m_specific->m_redraw_flag) + { + app->on_draw(); + app->m_specific->m_redraw_flag = false; + } + app->m_specific->display_pmap(app->m_specific->m_window, &app->rbuf_window()); + } + + return CallNextEventHandler (nextHandler, theEvent); +} + + +//------------------------------------------------------------------------ +pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData) +{ + platform_support * app = reinterpret_cast(userData); + + if(!app->wait_mode()) + app->on_idle(); +} + + +} + + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + +// Hm. Classic MacOS does not know command line input. +// CodeWarrior provides a way to mimic command line input. +// The function 'ccommand' can be used to get the command +// line arguments. +//---------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ +#if defined(__MWERKS__) + // argc = ccommand (&argv); +#endif + + // Check if we are launched by double-clicking under OSX + // Get rid of extra argument, this will confuse the standard argument parsing + // calls used in the examples to get the name of the image file to be used + if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { + argc = 1; + } + +launch: + return agg_main(argc, argv); +} \ No newline at end of file diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/sdl/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/sdl/agg_platform_support.cpp new file mode 100644 index 00000000000..28c6436baa1 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/sdl/agg_platform_support.cpp @@ -0,0 +1,708 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class platform_support. SDL version. +// +//---------------------------------------------------------------------------- + +#include +#include "platform/agg_platform_support.h" +#include "SDL.h" +#include "SDL_byteorder.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + ~platform_specific(); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + unsigned m_rmask; + unsigned m_gmask; + unsigned m_bmask; + unsigned m_amask; + bool m_update_flag; + bool m_resize_flag; + bool m_initialized; + SDL_Surface* m_surf_screen; + SDL_Surface* m_surf_window; + SDL_Surface* m_surf_img[platform_support::max_images]; + int m_cur_x; + int m_cur_y; + int m_sw_start; + }; + + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_update_flag(true), + m_resize_flag(true), + m_initialized(false), + m_surf_screen(0), + m_surf_window(0), + m_cur_x(0), + m_cur_y(0) + { + memset(m_surf_img, 0, sizeof(m_surf_img)); + + switch(m_format) + { + case pix_format_gray8: + m_bpp = 8; + break; + + case pix_format_rgb565: + m_rmask = 0xF800; + m_gmask = 0x7E0; + m_bmask = 0x1F; + m_amask = 0; + m_bpp = 16; + break; + + case pix_format_rgb555: + m_rmask = 0x7C00; + m_gmask = 0x3E0; + m_bmask = 0x1F; + m_amask = 0; + m_bpp = 16; + break; + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN + case pix_format_rgb24: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgr24: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgra32: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_abgr32: + m_rmask = 0xFF000000; + m_gmask = 0xFF0000; + m_bmask = 0xFF00; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_argb32: + m_rmask = 0xFF00; + m_gmask = 0xFF0000; + m_bmask = 0xFF000000; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_rgba32: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0xFF000000; + m_bpp = 32; + break; +#else //SDL_BIG_ENDIAN (PPC) + case pix_format_rgb24: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgr24: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0; + m_bpp = 24; + break; + + case pix_format_bgra32: + m_rmask = 0xFF00; + m_gmask = 0xFF0000; + m_bmask = 0xFF000000; + m_amask = 0xFF; + m_bpp = 32; + break; + + case pix_format_abgr32: + m_rmask = 0xFF; + m_gmask = 0xFF00; + m_bmask = 0xFF0000; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_argb32: + m_rmask = 0xFF0000; + m_gmask = 0xFF00; + m_bmask = 0xFF; + m_amask = 0xFF000000; + m_bpp = 32; + break; + + case pix_format_rgba32: + m_rmask = 0xFF000000; + m_gmask = 0xFF0000; + m_bmask = 0xFF00; + m_amask = 0xFF; + m_bpp = 32; + break; +#endif + } + } + + //------------------------------------------------------------------------ + platform_specific::~platform_specific() + { + int i; + for(i = platform_support::max_images - 1; i >= 0; --i) + { + if(m_surf_img[i]) SDL_FreeSurface(m_surf_img[i]); + } + if(m_surf_window) SDL_FreeSurface(m_surf_window); + if(m_surf_screen) SDL_FreeSurface(m_surf_screen); + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y) + { + SDL_Init(SDL_INIT_VIDEO); + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_initialized) + { + SDL_WM_SetCaption(cap, 0); + } + } + + + + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + m_window_flags = flags; + unsigned wflags = SDL_SWSURFACE; + + if(m_window_flags & window_hw_buffer) + { + wflags = SDL_HWSURFACE; + } + + if(m_window_flags & window_resize) + { + wflags |= SDL_RESIZABLE; + } + + if(m_specific->m_surf_screen) SDL_FreeSurface(m_specific->m_surf_screen); + + m_specific->m_surf_screen = SDL_SetVideoMode(width, height, m_bpp, wflags); + if(m_specific->m_surf_screen == 0) + { + fprintf(stderr, + "Unable to set %dx%d %d bpp video: %s\n", + width, + height, + m_bpp, + ::SDL_GetError()); + return false; + } + + SDL_WM_SetCaption(m_caption, 0); + + if(m_specific->m_surf_window) SDL_FreeSurface(m_specific->m_surf_window); + + m_specific->m_surf_window = + SDL_CreateRGBSurface(SDL_HWSURFACE, + m_specific->m_surf_screen->w, + m_specific->m_surf_screen->h, + m_specific->m_surf_screen->format->BitsPerPixel, + m_specific->m_rmask, + m_specific->m_gmask, + m_specific->m_bmask, + m_specific->m_amask); + + if(m_specific->m_surf_window == 0) + { + fprintf(stderr, + "Unable to create image buffer %dx%d %d bpp: %s\n", + width, + height, + m_bpp, + SDL_GetError()); + return false; + } + + m_rbuf_window.attach((unsigned char*)m_specific->m_surf_window->pixels, + m_specific->m_surf_window->w, + m_specific->m_surf_window->h, + m_flip_y ? -m_specific->m_surf_window->pitch : + m_specific->m_surf_window->pitch); + + if(!m_specific->m_initialized) + { + m_initial_width = width; + m_initial_height = height; + on_init(); + m_specific->m_initialized = true; + } + on_resize(m_rbuf_window.width(), m_rbuf_window.height()); + m_specific->m_update_flag = true; + return true; + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + SDL_BlitSurface(m_specific->m_surf_window, 0, m_specific->m_surf_screen, 0); + SDL_UpdateRect(m_specific->m_surf_screen, 0, 0, 0, 0); + } + + + //------------------------------------------------------------------------ + int platform_support::run() + { + SDL_Event event; + bool ev_flag = false; + + for(;;) + { + if(m_specific->m_update_flag) + { + on_draw(); + update_window(); + m_specific->m_update_flag = false; + } + + ev_flag = false; + if(m_wait_mode) + { + SDL_WaitEvent(&event); + ev_flag = true; + } + else + { + if(SDL_PollEvent(&event)) + { + ev_flag = true; + } + else + { + on_idle(); + } + } + + if(ev_flag) + { + if(event.type == SDL_QUIT) + { + break; + } + + int y; + unsigned flags = 0; + + switch (event.type) + { + case SDL_VIDEORESIZE: + if(!init(event.resize.w, event.resize.h, m_window_flags)) return false; + on_resize(m_rbuf_window.width(), m_rbuf_window.height()); + trans_affine_resizing(event.resize.w, event.resize.h); + m_specific->m_update_flag = true; + break; + + case SDL_KEYDOWN: + { + flags = 0; + if(event.key.keysym.mod & KMOD_SHIFT) flags |= kbd_shift; + if(event.key.keysym.mod & KMOD_CTRL) flags |= kbd_ctrl; + + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(event.key.keysym.sym) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + } + + if(m_ctrls.on_arrow_keys(left, right, down, up)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_key(m_specific->m_cur_x, + m_specific->m_cur_y, + event.key.keysym.sym, + flags); + } + } + break; + + case SDL_MOUSEMOTION: + y = m_flip_y ? + m_rbuf_window.height() - event.motion.y : + event.motion.y; + + m_specific->m_cur_x = event.motion.x; + m_specific->m_cur_y = y; + flags = 0; + if(event.motion.state & SDL_BUTTON_LMASK) flags |= mouse_left; + if(event.motion.state & SDL_BUTTON_RMASK) flags |= mouse_right; + + if(m_ctrls.on_mouse_move(m_specific->m_cur_x, + m_specific->m_cur_y, + (flags & mouse_left) != 0)) + { + on_ctrl_change(); + force_redraw(); + } + else + { + on_mouse_move(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + } + SDL_Event eventtrash; + while (SDL_PeepEvents(&eventtrash, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION))!=0){;} + break; + + case SDL_MOUSEBUTTONDOWN: + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; + + m_specific->m_cur_x = event.button.x; + m_specific->m_cur_y = y; + flags = 0; + switch(event.button.button) + { + case SDL_BUTTON_LEFT: + { + flags = mouse_left; + +if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y); + on_ctrl_change(); + force_redraw(); + } + else + { + if(m_ctrls.in_rect(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + if(m_ctrls.set_cur(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + } + else + { + on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + } + } + } + break; + case SDL_BUTTON_RIGHT: + flags = mouse_right; + on_mouse_button_down(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + break; + } //switch(event.button.button) + break; + + case SDL_MOUSEBUTTONUP: + y = m_flip_y + ? m_rbuf_window.height() - event.button.y + : event.button.y; + + m_specific->m_cur_x = event.button.x; + m_specific->m_cur_y = y; + flags = 0; + if(m_ctrls.on_mouse_button_up(m_specific->m_cur_x, + m_specific->m_cur_y)) + { + on_ctrl_change(); + force_redraw(); + } + on_mouse_button_up(m_specific->m_cur_x, + m_specific->m_cur_y, + flags); + break; + } + } + } + return 0; + } + + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]); + + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + { + strcat(fn, ".bmp"); + } + + SDL_Surface* tmp_surf = SDL_LoadBMP(fn); + if (tmp_surf == 0) + { + fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError()); + return false; + } + + SDL_PixelFormat format; + format.palette = 0; + format.BitsPerPixel = m_bpp; + format.BytesPerPixel = m_bpp >> 8; + format.Rmask = m_specific->m_rmask; + format.Gmask = m_specific->m_gmask; + format.Bmask = m_specific->m_bmask; + format.Amask = m_specific->m_amask; + format.Rshift = 0; + format.Gshift = 0; + format.Bshift = 0; + format.Ashift = 0; + format.Rloss = 0; + format.Gloss = 0; + format.Bloss = 0; + format.Aloss = 0; + format.colorkey = 0; + format.alpha = 0; + + m_specific->m_surf_img[idx] = + SDL_ConvertSurface(tmp_surf, + &format, + SDL_SWSURFACE); + + SDL_FreeSurface(tmp_surf); + + if(m_specific->m_surf_img[idx] == 0) return false; + + m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels, + m_specific->m_surf_img[idx]->w, + m_specific->m_surf_img[idx]->h, + m_flip_y ? -m_specific->m_surf_img[idx]->pitch : + m_specific->m_surf_img[idx]->pitch); + return true; + + } + return false; + } + + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images && m_specific->m_surf_img[idx]) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0) + { + strcat(fn, ".bmp"); + } + return SDL_SaveBMP(m_specific->m_surf_img[idx], fn) == 0; + } + return false; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + + if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]); + + m_specific->m_surf_img[idx] = + SDL_CreateRGBSurface(SDL_SWSURFACE, + width, + height, + m_specific->m_surf_screen->format->BitsPerPixel, + m_specific->m_rmask, + m_specific->m_gmask, + m_specific->m_bmask, + m_specific->m_amask); + if(m_specific->m_surf_img[idx] == 0) + { + fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError()); + return false; + } + + m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels, + m_specific->m_surf_img[idx]->w, + m_specific->m_surf_img[idx]->h, + m_flip_y ? -m_specific->m_surf_img[idx]->pitch : + m_specific->m_surf_img[idx]->pitch); + + return true; + } + + return false; + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + m_specific->m_sw_start = SDL_GetTicks(); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + int stop = SDL_GetTicks(); + return double(stop - m_specific->m_sw_start); + } + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + fprintf(stderr, "%s\n", msg); + } + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_update_flag = true; + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} + + +} + + +int agg_main(int argc, char* argv[]); + +int main(int argc, char* argv[]) +{ + return agg_main(argc, argv); +} + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_platform_support.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_platform_support.cpp new file mode 100644 index 00000000000..ea9123802f2 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_platform_support.cpp @@ -0,0 +1,1655 @@ +//---------------------------------------------------------------------------- +// 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 +//---------------------------------------------------------------------------- +// +// class platform_support +// +//---------------------------------------------------------------------------- + +#include +#include +#include "platform/agg_platform_support.h" +#include "platform/win32/agg_win32_bmp.h" +#include "util/agg_color_conv.h" +#include "util/agg_color_conv_rgb8.h" +#include "util/agg_color_conv_rgb16.h" +#include "agg_pixfmt_gray.h" +#include "agg_pixfmt_rgb.h" +#include "agg_pixfmt_rgba.h" + + +namespace agg +{ + + //------------------------------------------------------------------------ + HINSTANCE g_windows_instance = 0; + int g_windows_cmd_show = 0; + + + //------------------------------------------------------------------------ + class platform_specific + { + public: + platform_specific(pix_format_e format, bool flip_y); + + void create_pmap(unsigned width, unsigned height, + rendering_buffer* wnd); + + void display_pmap(HDC dc, const rendering_buffer* src); + bool load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst); + + bool save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src); + + unsigned translate(unsigned keycode); + + pix_format_e m_format; + pix_format_e m_sys_format; + bool m_flip_y; + unsigned m_bpp; + unsigned m_sys_bpp; + HWND m_hwnd; + pixel_map m_pmap_window; + pixel_map m_pmap_img[platform_support::max_images]; + unsigned m_keymap[256]; + unsigned m_last_translated_key; + int m_cur_x; + int m_cur_y; + unsigned m_input_flags; + bool m_redraw_flag; + HDC m_current_dc; + LARGE_INTEGER m_sw_freq; + LARGE_INTEGER m_sw_start; + }; + + + //------------------------------------------------------------------------ + platform_specific::platform_specific(pix_format_e format, bool flip_y) : + m_format(format), + m_sys_format(pix_format_undefined), + m_flip_y(flip_y), + m_bpp(0), + m_sys_bpp(0), + m_hwnd(0), + m_last_translated_key(0), + m_cur_x(0), + m_cur_y(0), + m_input_flags(0), + m_redraw_flag(true), + m_current_dc(0) + { + memset(m_keymap, 0, sizeof(m_keymap)); + + m_keymap[VK_PAUSE] = key_pause; + m_keymap[VK_CLEAR] = key_clear; + + m_keymap[VK_NUMPAD0] = key_kp0; + m_keymap[VK_NUMPAD1] = key_kp1; + m_keymap[VK_NUMPAD2] = key_kp2; + m_keymap[VK_NUMPAD3] = key_kp3; + m_keymap[VK_NUMPAD4] = key_kp4; + m_keymap[VK_NUMPAD5] = key_kp5; + m_keymap[VK_NUMPAD6] = key_kp6; + m_keymap[VK_NUMPAD7] = key_kp7; + m_keymap[VK_NUMPAD8] = key_kp8; + m_keymap[VK_NUMPAD9] = key_kp9; + m_keymap[VK_DECIMAL] = key_kp_period; + m_keymap[VK_DIVIDE] = key_kp_divide; + m_keymap[VK_MULTIPLY] = key_kp_multiply; + m_keymap[VK_SUBTRACT] = key_kp_minus; + m_keymap[VK_ADD] = key_kp_plus; + + m_keymap[VK_UP] = key_up; + m_keymap[VK_DOWN] = key_down; + m_keymap[VK_RIGHT] = key_right; + m_keymap[VK_LEFT] = key_left; + m_keymap[VK_INSERT] = key_insert; + m_keymap[VK_DELETE] = key_delete; + m_keymap[VK_HOME] = key_home; + m_keymap[VK_END] = key_end; + m_keymap[VK_PRIOR] = key_page_up; + m_keymap[VK_NEXT] = key_page_down; + + m_keymap[VK_F1] = key_f1; + m_keymap[VK_F2] = key_f2; + m_keymap[VK_F3] = key_f3; + m_keymap[VK_F4] = key_f4; + m_keymap[VK_F5] = key_f5; + m_keymap[VK_F6] = key_f6; + m_keymap[VK_F7] = key_f7; + m_keymap[VK_F8] = key_f8; + m_keymap[VK_F9] = key_f9; + m_keymap[VK_F10] = key_f10; + m_keymap[VK_F11] = key_f11; + m_keymap[VK_F12] = key_f12; + m_keymap[VK_F13] = key_f13; + m_keymap[VK_F14] = key_f14; + m_keymap[VK_F15] = key_f15; + + m_keymap[VK_NUMLOCK] = key_numlock; + m_keymap[VK_CAPITAL] = key_capslock; + m_keymap[VK_SCROLL] = key_scrollock; + + + switch(m_format) + { + case pix_format_bw: + m_sys_format = pix_format_bw; + m_bpp = 1; + m_sys_bpp = 1; + break; + + case pix_format_gray8: + case pix_format_sgray8: + m_sys_format = pix_format_sgray8; + m_bpp = 8; + m_sys_bpp = 8; + break; + + case pix_format_gray16: + m_sys_format = pix_format_sgray8; + m_bpp = 16; + m_sys_bpp = 8; + break; + + case pix_format_gray32: + m_sys_format = pix_format_sgray8; + m_bpp = 32; + m_sys_bpp = 8; + break; + + case pix_format_rgb565: + case pix_format_rgb555: + m_sys_format = pix_format_rgb555; + m_bpp = 16; + m_sys_bpp = 16; + break; + + case pix_format_rgbAAA: + case pix_format_bgrAAA: + case pix_format_rgbBBA: + case pix_format_bgrABB: + m_sys_format = pix_format_bgr24; + m_bpp = 32; + m_sys_bpp = 24; + break; + + case pix_format_rgb24: + case pix_format_bgr24: + case pix_format_srgb24: + case pix_format_sbgr24: + m_sys_format = pix_format_sbgr24; + m_bpp = 24; + m_sys_bpp = 24; + break; + + case pix_format_rgb48: + case pix_format_bgr48: + m_sys_format = pix_format_sbgr24; + m_bpp = 48; + m_sys_bpp = 24; + break; + + case pix_format_rgb96: + case pix_format_bgr96: + m_sys_format = pix_format_sbgr24; + m_bpp = 96; + m_sys_bpp = 24; + break; + + case pix_format_bgra32: + case pix_format_abgr32: + case pix_format_argb32: + case pix_format_rgba32: + case pix_format_sbgra32: + case pix_format_sabgr32: + case pix_format_sargb32: + case pix_format_srgba32: + m_sys_format = pix_format_sbgr24; + m_bpp = 32; + m_sys_bpp = 24; + break; + + case pix_format_bgra64: + case pix_format_abgr64: + case pix_format_argb64: + case pix_format_rgba64: + m_sys_format = pix_format_sbgr24; + m_bpp = 64; + m_sys_bpp = 24; + break; + + case pix_format_bgra128: + case pix_format_abgr128: + case pix_format_argb128: + case pix_format_rgba128: + m_sys_format = pix_format_sbgr24; + m_bpp = 128; + m_sys_bpp = 24; + break; + + } + ::QueryPerformanceFrequency(&m_sw_freq); + ::QueryPerformanceCounter(&m_sw_start); + } + + + //------------------------------------------------------------------------ + void platform_specific::create_pmap(unsigned width, + unsigned height, + rendering_buffer* wnd) + { + m_pmap_window.create(width, height, org_e(m_bpp)); + wnd->attach(m_pmap_window.buf(), + m_pmap_window.width(), + m_pmap_window.height(), + m_flip_y ? + m_pmap_window.stride() : + -m_pmap_window.stride()); + } + + + //------------------------------------------------------------------------ + static void convert_pmap(rendering_buffer* dst, + const rendering_buffer* src, + pix_format_e format) + { + switch(format) + { + case pix_format_gray8: + convert(dst, src); + break; + + case pix_format_gray16: + convert(dst, src); + break; + + case pix_format_gray32: + convert(dst, src); + break; + + case pix_format_rgb565: + color_conv(dst, src, color_conv_rgb565_to_rgb555()); + break; + + case pix_format_rgbAAA: + color_conv(dst, src, color_conv_rgbAAA_to_bgr24()); + break; + + case pix_format_bgrAAA: + color_conv(dst, src, color_conv_bgrAAA_to_bgr24()); + break; + + case pix_format_rgbBBA: + color_conv(dst, src, color_conv_rgbBBA_to_bgr24()); + break; + + case pix_format_bgrABB: + color_conv(dst, src, color_conv_bgrABB_to_bgr24()); + break; + + case pix_format_srgb24: + color_conv(dst, src, color_conv_rgb24_to_bgr24()); + break; + + case pix_format_rgb24: + convert(dst, src); + break; + + case pix_format_bgr24: + convert(dst, src); + break; + + case pix_format_rgb48: + convert(dst, src); + break; + + case pix_format_bgr48: + convert(dst, src); + break; + + case pix_format_bgra32: + convert(dst, src); + break; + + case pix_format_abgr32: + convert(dst, src); + break; + + case pix_format_argb32: + convert(dst, src); + break; + + case pix_format_rgba32: + convert(dst, src); + break; + + case pix_format_sbgra32: + convert(dst, src); + break; + + case pix_format_sabgr32: + convert(dst, src); + break; + + case pix_format_sargb32: + convert(dst, src); + break; + + case pix_format_srgba32: + convert(dst, src); + break; + + case pix_format_bgra64: + convert(dst, src); + break; + + case pix_format_abgr64: + convert(dst, src); + break; + + case pix_format_argb64: + convert(dst, src); + break; + + case pix_format_rgba64: + convert(dst, src); + break; + + case pix_format_rgb96: + convert(dst, src); + break; + + case pix_format_bgr96: + convert(dst, src); + break; + + case pix_format_bgra128: + convert(dst, src); + break; + + case pix_format_abgr128: + convert(dst, src); + break; + + case pix_format_argb128: + convert(dst, src); + break; + + case pix_format_rgba128: + convert(dst, src); + break; + } + } + + + //------------------------------------------------------------------------ + void platform_specific::display_pmap(HDC dc, const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + m_pmap_window.draw(dc); + } + else + { + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_window.width(), + m_pmap_window.height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + convert_pmap(&rbuf_tmp, src, m_format); + pmap_tmp.draw(dc); + } + } + + + + //------------------------------------------------------------------------ + bool platform_specific::save_pmap(const char* fn, unsigned idx, + const rendering_buffer* src) + { + if(m_sys_format == m_format) + { + return m_pmap_img[idx].save_as_bmp(fn); + } + + pixel_map pmap_tmp; + pmap_tmp.create(m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + org_e(m_sys_bpp)); + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + convert_pmap(&rbuf_tmp, src, m_format); + return pmap_tmp.save_as_bmp(fn); + } + + + + //------------------------------------------------------------------------ + bool platform_specific::load_pmap(const char* fn, unsigned idx, + rendering_buffer* dst) + { + pixel_map pmap_tmp; + if(!pmap_tmp.load_from_bmp(fn)) return false; + + rendering_buffer rbuf_tmp; + rbuf_tmp.attach(pmap_tmp.buf(), + pmap_tmp.width(), + pmap_tmp.height(), + m_flip_y ? + pmap_tmp.stride() : + -pmap_tmp.stride()); + + m_pmap_img[idx].create(pmap_tmp.width(), + pmap_tmp.height(), + org_e(m_bpp), + 0); + + dst->attach(m_pmap_img[idx].buf(), + m_pmap_img[idx].width(), + m_pmap_img[idx].height(), + m_flip_y ? + m_pmap_img[idx].stride() : + -m_pmap_img[idx].stride()); + + switch(m_format) + { + case pix_format_sgray8: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray8()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_gray8()); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray8()); break; + } + break; + + case pix_format_gray8: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_gray16: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray16()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray16()); break; + } + break; + + case pix_format_gray32: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_gray32()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_gray32()); break; + } + break; + + case pix_format_rgb555: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb555()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb555()); break; + } + break; + + case pix_format_rgb565: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb565()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb565()); break; + } + break; + + case pix_format_srgb24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgb24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb24()); break; + } + break; + + case pix_format_sbgr24: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgr24()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr24()); break; + } + break; + + case pix_format_rgb24: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgr24: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgb48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb48()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgb48()); break; + } + break; + + case pix_format_bgr48: + switch(pmap_tmp.bpp()) + { + //case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr48()); break; + case 24: convert(dst, &rbuf_tmp); break; + //case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgr48()); break; + } + break; + + case pix_format_sabgr32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_abgr32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_abgr32()); break; + } + break; + + case pix_format_sargb32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_argb32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_argb32()); break; + } + break; + + case pix_format_sbgra32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_bgra32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_bgra32()); break; + } + break; + + case pix_format_srgba32: + switch(pmap_tmp.bpp()) + { + case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break; + case 24: color_conv(dst, &rbuf_tmp, color_conv_bgr24_to_rgba32()); break; + case 32: color_conv(dst, &rbuf_tmp, color_conv_bgra32_to_rgba32()); break; + } + break; + + case pix_format_abgr32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba32: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_abgr64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba64: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgb96: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgr96: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_abgr128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_argb128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_bgra128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + + case pix_format_rgba128: + switch(pmap_tmp.bpp()) + { + case 24: convert(dst, &rbuf_tmp); break; + } + break; + } + + return true; + } + + + + + + + + + //------------------------------------------------------------------------ + unsigned platform_specific::translate(unsigned keycode) + { + return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode]; + } + + + + //------------------------------------------------------------------------ + platform_support::platform_support(pix_format_e format, bool flip_y) : + m_specific(new platform_specific(format, flip_y)), + m_format(format), + m_bpp(m_specific->m_bpp), + m_window_flags(0), + m_wait_mode(true), + m_flip_y(flip_y), + m_initial_width(10), + m_initial_height(10) + { + strcpy(m_caption, "Anti-Grain Geometry Application"); + } + + + //------------------------------------------------------------------------ + platform_support::~platform_support() + { + delete m_specific; + } + + + + //------------------------------------------------------------------------ + void platform_support::caption(const char* cap) + { + strcpy(m_caption, cap); + if(m_specific->m_hwnd) + { + SetWindowText(m_specific->m_hwnd, m_caption); + } + } + + //------------------------------------------------------------------------ + void platform_support::start_timer() + { + ::QueryPerformanceCounter(&(m_specific->m_sw_start)); + } + + //------------------------------------------------------------------------ + double platform_support::elapsed_time() const + { + LARGE_INTEGER stop; + ::QueryPerformanceCounter(&stop); + return double(stop.QuadPart - + m_specific->m_sw_start.QuadPart) * 1000.0 / + double(m_specific->m_sw_freq.QuadPart); + } + + + + //------------------------------------------------------------------------ + static unsigned get_key_flags(int wflags) + { + unsigned flags = 0; + if(wflags & MK_LBUTTON) flags |= mouse_left; + if(wflags & MK_RBUTTON) flags |= mouse_right; + if(wflags & MK_SHIFT) flags |= kbd_shift; + if(wflags & MK_CONTROL) flags |= kbd_ctrl; + return flags; + } + + + void* platform_support::raw_display_handler() + { + return m_specific->m_current_dc; + } + + + //------------------------------------------------------------------------ + LRESULT CALLBACK window_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + PAINTSTRUCT ps; + HDC paintDC; + + + void* user_data = reinterpret_cast(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); + platform_support* app = 0; + + if(user_data) + { + app = reinterpret_cast(user_data); + } + + if(app == 0) + { + if(msg == WM_DESTROY) + { + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProc(hWnd, msg, wParam, lParam); + } + + HDC dc = ::GetDC(app->m_specific->m_hwnd); + app->m_specific->m_current_dc = dc; + LRESULT ret = 0; + + switch(msg) + { + //-------------------------------------------------------------------- + case WM_CREATE: + break; + + //-------------------------------------------------------------------- + case WM_SIZE: + app->m_specific->create_pmap(LOWORD(lParam), + HIWORD(lParam), + &app->rbuf_window()); + + app->trans_affine_resizing(LOWORD(lParam), HIWORD(lParam)); + app->on_resize(LOWORD(lParam), HIWORD(lParam)); + app->force_redraw(); + break; + + //-------------------------------------------------------------------- + case WM_ERASEBKGND: + break; + + //-------------------------------------------------------------------- + case WM_LBUTTONDOWN: + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); + + app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y); + if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + if(app->m_ctrls.set_cur(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + } + else + { + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_LBUTTONUP: + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_left | get_key_flags(wParam); + + if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + + //-------------------------------------------------------------------- + case WM_RBUTTONDOWN: + ::SetCapture(app->m_specific->m_hwnd); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); + app->on_mouse_button_down(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_RBUTTONUP: + ::ReleaseCapture(); + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = mouse_right | get_key_flags(wParam); + app->on_mouse_button_up(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_MOUSEMOVE: + app->m_specific->m_cur_x = int16(LOWORD(lParam)); + if(app->flip_y()) + { + app->m_specific->m_cur_y = app->rbuf_window().height() - int16(HIWORD(lParam)); + } + else + { + app->m_specific->m_cur_y = int16(HIWORD(lParam)); + } + app->m_specific->m_input_flags = get_key_flags(wParam); + + + if(app->m_ctrls.on_mouse_move( + app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + (app->m_specific->m_input_flags & mouse_left) != 0)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + if(!app->m_ctrls.in_rect(app->m_specific->m_cur_x, + app->m_specific->m_cur_y)) + { + app->on_mouse_move(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_input_flags); + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + app->m_specific->m_last_translated_key = 0; + switch(wParam) + { + case VK_CONTROL: + app->m_specific->m_input_flags |= kbd_ctrl; + break; + + case VK_SHIFT: + app->m_specific->m_input_flags |= kbd_shift; + break; + + default: + app->m_specific->translate(wParam); + break; + } + + if(app->m_specific->m_last_translated_key) + { + bool left = false; + bool up = false; + bool right = false; + bool down = false; + + switch(app->m_specific->m_last_translated_key) + { + case key_left: + left = true; + break; + + case key_up: + up = true; + break; + + case key_right: + right = true; + break; + + case key_down: + down = true; + break; + + case key_f2: + app->copy_window_to_img(agg::platform_support::max_images - 1); + app->save_img(agg::platform_support::max_images - 1, "screenshot"); + break; + } + + if(app->window_flags() & window_process_all_keys) + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + else + { + if(app->m_ctrls.on_arrow_keys(left, right, down, up)) + { + app->on_ctrl_change(); + app->force_redraw(); + } + else + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + app->m_specific->m_last_translated_key, + app->m_specific->m_input_flags); + } + } + } +/* + if(!app->wait_mode()) + { + app->on_idle(); + } +*/ + break; + + //-------------------------------------------------------------------- + case WM_SYSKEYUP: + case WM_KEYUP: + app->m_specific->m_last_translated_key = 0; + switch(wParam) + { + case VK_CONTROL: + app->m_specific->m_input_flags &= ~kbd_ctrl; + break; + + case VK_SHIFT: + app->m_specific->m_input_flags &= ~kbd_shift; + break; + } + break; + + //-------------------------------------------------------------------- + case WM_CHAR: + case WM_SYSCHAR: + if(app->m_specific->m_last_translated_key == 0) + { + app->on_key(app->m_specific->m_cur_x, + app->m_specific->m_cur_y, + wParam, + app->m_specific->m_input_flags); + } + break; + + //-------------------------------------------------------------------- + case WM_PAINT: + paintDC = ::BeginPaint(hWnd, &ps); + app->m_specific->m_current_dc = paintDC; + if(app->m_specific->m_redraw_flag) + { + app->on_draw(); + app->m_specific->m_redraw_flag = false; + } + app->m_specific->display_pmap(paintDC, &app->rbuf_window()); + app->on_post_draw(paintDC); + app->m_specific->m_current_dc = 0; + ::EndPaint(hWnd, &ps); + break; + + //-------------------------------------------------------------------- + case WM_COMMAND: + break; + + //-------------------------------------------------------------------- + case WM_DESTROY: + ::PostQuitMessage(0); + break; + + //-------------------------------------------------------------------- + default: + ret = ::DefWindowProc(hWnd, msg, wParam, lParam); + break; + } + app->m_specific->m_current_dc = 0; + ::ReleaseDC(app->m_specific->m_hwnd, dc); + return ret; + } + + + //------------------------------------------------------------------------ + void platform_support::message(const char* msg) + { + ::MessageBox(m_specific->m_hwnd, msg, "AGG Message", MB_OK); + } + + + //------------------------------------------------------------------------ + bool platform_support::init(unsigned width, unsigned height, unsigned flags) + { + if(m_specific->m_sys_format == pix_format_undefined) + { + return false; + } + + m_window_flags = flags; + + int wflags = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; + + WNDCLASS wc; + wc.lpszClassName = "AGGAppClass"; + wc.lpfnWndProc = window_proc; + wc.style = wflags; + wc.hInstance = g_windows_instance; + wc.hIcon = LoadIcon(0, IDI_APPLICATION); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wc.lpszMenuName = "AGGAppMenu"; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + ::RegisterClass(&wc); + + wflags = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; + + if(m_window_flags & window_resize) + { + wflags |= WS_THICKFRAME | WS_MAXIMIZEBOX; + } + + m_specific->m_hwnd = ::CreateWindow("AGGAppClass", + m_caption, + wflags, + 100, + 100, + width, + height, + 0, + 0, + g_windows_instance, + 0); + + if(m_specific->m_hwnd == 0) + { + return false; + } + + + RECT rct; + ::GetClientRect(m_specific->m_hwnd, &rct); + + ::MoveWindow(m_specific->m_hwnd, // handle to window + 100, // horizontal position + 100, // vertical position + width + (width - (rct.right - rct.left)), + height + (height - (rct.bottom - rct.top)), + FALSE); + + ::SetWindowLongPtr(m_specific->m_hwnd, GWLP_USERDATA, (LONG)this); + m_specific->create_pmap(width, height, &m_rbuf_window); + m_initial_width = width; + m_initial_height = height; + on_init(); + m_specific->m_redraw_flag = true; + ::ShowWindow(m_specific->m_hwnd, g_windows_cmd_show); + return true; + } + + + + //------------------------------------------------------------------------ + int platform_support::run() + { + MSG msg; + + for(;;) + { + if(m_wait_mode) + { + if(!::GetMessage(&msg, 0, 0, 0)) + { + break; + } + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + else + { + if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + ::TranslateMessage(&msg); + if(msg.message == WM_QUIT) + { + break; + } + ::DispatchMessage(&msg); + } + else + { + on_idle(); + } + } + } + return (int)msg.wParam; + } + + + //------------------------------------------------------------------------ + const char* platform_support::img_ext() const { return ".bmp"; } + + + //------------------------------------------------------------------------ + const char* platform_support::full_file_name(const char* file_name) + { + return file_name; + } + + //------------------------------------------------------------------------ + bool platform_support::load_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || _stricmp(fn + len - 4, ".BMP") != 0) + { + strcat(fn, ".bmp"); + } + return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::save_img(unsigned idx, const char* file) + { + if(idx < max_images) + { + char fn[1024]; + strcpy(fn, file); + int len = strlen(fn); + if(len < 4 || _stricmp(fn + len - 4, ".BMP") != 0) + { + strcat(fn, ".bmp"); + } + return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]); + } + return true; + } + + + + //------------------------------------------------------------------------ + bool platform_support::create_img(unsigned idx, unsigned width, unsigned height) + { + if(idx < max_images) + { + if(width == 0) width = m_specific->m_pmap_window.width(); + if(height == 0) height = m_specific->m_pmap_window.height(); + m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp)); + m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(), + m_specific->m_pmap_img[idx].width(), + m_specific->m_pmap_img[idx].height(), + m_flip_y ? + m_specific->m_pmap_img[idx].stride() : + -m_specific->m_pmap_img[idx].stride()); + return true; + } + return false; + } + + + //------------------------------------------------------------------------ + void platform_support::force_redraw() + { + m_specific->m_redraw_flag = true; + ::InvalidateRect(m_specific->m_hwnd, 0, FALSE); + } + + + + //------------------------------------------------------------------------ + void platform_support::update_window() + { + HDC dc = ::GetDC(m_specific->m_hwnd); + m_specific->display_pmap(dc, &m_rbuf_window); + ::ReleaseDC(m_specific->m_hwnd, dc); + } + + + //------------------------------------------------------------------------ + void platform_support::on_init() {} + void platform_support::on_resize(int sx, int sy) {} + void platform_support::on_idle() {} + void platform_support::on_mouse_move(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {} + void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {} + void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {} + void platform_support::on_ctrl_change() {} + void platform_support::on_draw() {} + void platform_support::on_post_draw(void* raw_handler) {} +} + + + + +namespace agg +{ + // That's ridiculous. I have to parse the command line by myself + // because Windows doesn't provide a method of getting the command + // line arguments in a form of argc, argv. Of course, there's + // CommandLineToArgv() but first, it returns Unicode that I don't + // need to deal with, but most of all, it's not compatible with Win98. + //----------------------------------------------------------------------- + class tokenizer + { + public: + enum sep_flag + { + single, + multiple, + whole_str + }; + + struct token + { + const char* ptr; + unsigned len; + }; + + public: + tokenizer(const char* sep, + const char* trim=0, + const char* quote="\"", + char mask_chr='\\', + sep_flag sf=multiple); + + void set_str(const char* str); + token next_token(); + + private: + int check_chr(const char *str, char chr); + + private: + const char* m_src_string; + int m_start; + const char* m_sep; + const char* m_trim; + const char* m_quote; + char m_mask_chr; + unsigned m_sep_len; + sep_flag m_sep_flag; + }; + + + + //----------------------------------------------------------------------- + inline void tokenizer::set_str(const char* str) + { + m_src_string = str; + m_start = 0; + } + + + //----------------------------------------------------------------------- + inline int tokenizer::check_chr(const char *str, char chr) + { + return int(strchr(str, chr)); + } + + + //----------------------------------------------------------------------- + tokenizer::tokenizer(const char* sep, + const char* trim, + const char* quote, + char mask_chr, + sep_flag sf) : + m_src_string(0), + m_start(0), + m_sep(sep), + m_trim(trim), + m_quote(quote), + m_mask_chr(mask_chr), + m_sep_len(sep ? strlen(sep) : 0), + m_sep_flag(sep ? sf : single) + { + } + + + //----------------------------------------------------------------------- + tokenizer::token tokenizer::next_token() + { + unsigned count = 0; + char quote_chr = 0; + token tok; + + tok.ptr = 0; + tok.len = 0; + if(m_src_string == 0 || m_start == -1) return tok; + + const char *pstr = m_src_string + m_start; + + if(*pstr == 0) + { + m_start = -1; + return tok; + } + + int sep_len = 1; + if(m_sep_flag == whole_str) sep_len = m_sep_len; + + if(m_sep_flag == multiple) + { + //Pass all the separator symbols at the begin of the string + while(*pstr && check_chr(m_sep, *pstr)) + { + ++pstr; + ++m_start; + } + } + + if(*pstr == 0) + { + m_start = -1; + return tok; + } + + for(count = 0;; ++count) + { + char c = *pstr; + int found = 0; + + //We are outside of qotation: find one of separator symbols + if(quote_chr == 0) + { + if(sep_len == 1) + { + found = check_chr(m_sep, c); + } + else + { + found = strncmp(m_sep, pstr, m_sep_len) == 0; + } + } + + ++pstr; + + if(c == 0 || found) + { + if(m_trim) + { + while(count && + check_chr(m_trim, m_src_string[m_start])) + { + ++m_start; + --count; + } + + while(count && + check_chr(m_trim, m_src_string[m_start + count - 1])) + { + --count; + } + } + + tok.ptr = m_src_string + m_start; + tok.len = count; + + //Next time it will be the next separator character + //But we must check, whether it is NOT the end of the string. + m_start += count; + if(c) + { + m_start += sep_len; + if(m_sep_flag == multiple) + { + //Pass all the separator symbols + //after the end of the string + while(check_chr(m_sep, m_src_string[m_start])) + { + ++m_start; + } + } + } + break; + } + + //Switch quote. If it is not a quote yet, try to check any of + //quote symbols. Otherwise quote must be finished with quote_symb + if(quote_chr == 0) + { + if(check_chr(m_quote, c)) + { + quote_chr = c; + continue; + } + } + else + { + //We are inside quote: pass all the mask symbols + if(m_mask_chr && c == m_mask_chr) + { + if(*pstr) + { + ++count; + ++pstr; + } + continue; + } + if(c == quote_chr) + { + quote_chr = 0; + continue; + } + } + } + return tok; + } + + +} + + + +//---------------------------------------------------------------------------- +int agg_main(int argc, char* argv[]); + + + +//---------------------------------------------------------------------------- +int PASCAL WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpszCmdLine, + int nCmdShow) +{ + agg::g_windows_instance = hInstance; + agg::g_windows_cmd_show = nCmdShow; + + char* argv_str = new char [strlen(lpszCmdLine) + 3]; + char* argv_ptr = argv_str; + + char* argv[64]; + memset(argv, 0, sizeof(argv)); + + agg::tokenizer cmd_line(" ", "\"' ", "\"'", '\\', agg::tokenizer::multiple); + cmd_line.set_str(lpszCmdLine); + + int argc = 0; + argv[argc++] = argv_ptr; + *argv_ptr++ = 0; + + while(argc < 64) + { + agg::tokenizer::token tok = cmd_line.next_token(); + if(tok.ptr == 0) break; + if(tok.len) + { + memcpy(argv_ptr, tok.ptr, tok.len); + argv[argc++] = argv_ptr; + argv_ptr += tok.len; + *argv_ptr++ = 0; + } + } + + int ret = agg_main(argc, argv); + delete [] argv_str; + + return ret; +} + + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_win32_bmp.cpp b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_win32_bmp.cpp new file mode 100644 index 00000000000..8c3bdc83fd7 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/src/platform/win32/agg_win32_bmp.cpp @@ -0,0 +1,631 @@ +//---------------------------------------------------------------------------- +// +//---------------------------------------------------------------------------- +// Contact: mcseemagg@yahoo.com +//---------------------------------------------------------------------------- +// +// class pixel_map +// +//---------------------------------------------------------------------------- + +#include "platform/win32/agg_win32_bmp.h" +#include "agg_basics.h" + +namespace agg +{ + + //------------------------------------------------------------------------ + pixel_map::~pixel_map() + { + destroy(); + } + + + //------------------------------------------------------------------------ + pixel_map::pixel_map() : + m_bmp(0), + m_buf(0), + m_bpp(0), + m_is_internal(false), + m_img_size(0), + m_full_size(0) + + { + } + + + //------------------------------------------------------------------------ + void pixel_map::destroy() + { + if(m_bmp && m_is_internal) delete [] (unsigned char*)m_bmp; + m_bmp = 0; + m_is_internal = false; + m_buf = 0; + } + + + //------------------------------------------------------------------------ + void pixel_map::create(unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + create_from_bmp(create_bitmap_info(width, height, m_bpp)); + create_gray_scale_palette(m_bmp); + m_is_internal = true; + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + } + + + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section(HDC h_dc, + unsigned width, + unsigned height, + org_e org, + unsigned clear_val) + { + destroy(); + if(width == 0) width = 1; + if(height == 0) height = 1; + m_bpp = org; + HBITMAP h_bitmap = create_dib_section_from_args(h_dc, width, height, m_bpp); + create_gray_scale_palette(m_bmp); + m_is_internal = true; + if(clear_val <= 255) + { + memset(m_buf, clear_val, m_img_size); + } + return h_bitmap; + } + + + + //------------------------------------------------------------------------ + void pixel_map::clear(unsigned clear_val) + { + if(m_buf) memset(m_buf, clear_val, m_img_size); + } + + + //------------------------------------------------------------------------ + void pixel_map::attach_to_bmp(BITMAPINFO *bmp) + { + if(bmp) + { + destroy(); + create_from_bmp(bmp); + m_is_internal = false; + } + } + + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_full_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + + return sizeof(BITMAPINFOHEADER) + + sizeof(RGBQUAD) * calc_palette_size(bmp) + + bmp->bmiHeader.biSizeImage; + } + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_header_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * calc_palette_size(bmp); + } + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_palette_size(unsigned clr_used, unsigned bits_per_pixel) + { + int palette_size = 0; + + if(bits_per_pixel <= 8) + { + palette_size = clr_used; + if(palette_size == 0) + { + palette_size = 1 << bits_per_pixel; + } + } + return palette_size; + } + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_palette_size(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return calc_palette_size(bmp->bmiHeader.biClrUsed, bmp->bmiHeader.biBitCount); + } + + + //static + //------------------------------------------------------------------------ + unsigned char * pixel_map::calc_img_ptr(BITMAPINFO *bmp) + { + if(bmp == 0) return 0; + return ((unsigned char*)bmp) + calc_header_size(bmp); + } + + //static + //------------------------------------------------------------------------ + BITMAPINFO* pixel_map::create_bitmap_info(unsigned width, + unsigned height, + unsigned bits_per_pixel) + { + unsigned line_len = calc_row_len(width, bits_per_pixel); + unsigned img_size = line_len * height; + unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD); + unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size + img_size; + + BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size]; + + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = width; + bmp->bmiHeader.biHeight = height; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel; + bmp->bmiHeader.biCompression = 0; + bmp->bmiHeader.biSizeImage = img_size; + bmp->bmiHeader.biXPelsPerMeter = 0; + bmp->bmiHeader.biYPelsPerMeter = 0; + bmp->bmiHeader.biClrUsed = 0; + bmp->bmiHeader.biClrImportant = 0; + + return bmp; + } + + + //static + //------------------------------------------------------------------------ + void pixel_map::create_gray_scale_palette(BITMAPINFO *bmp) + { + if(bmp == 0) return; + + unsigned rgb_size = calc_palette_size(bmp); + RGBQUAD *rgb = (RGBQUAD*)(((unsigned char*)bmp) + sizeof(BITMAPINFOHEADER)); + unsigned brightness; + unsigned i; + + for(i = 0; i < rgb_size; i++) + { + brightness = (255 * i) / (rgb_size - 1); + rgb->rgbBlue = + rgb->rgbGreen = + rgb->rgbRed = (unsigned char)brightness; + rgb->rgbReserved = 0; + rgb++; + } + } + + + + //static + //------------------------------------------------------------------------ + unsigned pixel_map::calc_row_len(unsigned width, unsigned bits_per_pixel) + { + unsigned n = width; + unsigned k; + + switch(bits_per_pixel) + { + case 1: k = n; + n = n >> 3; + if(k & 7) n++; + break; + + case 4: k = n; + n = n >> 1; + if(k & 3) n++; + break; + + case 8: + break; + + case 16: n *= 2; + break; + + case 24: n *= 3; + break; + + case 32: n *= 4; + break; + + case 48: n *= 6; + break; + + case 64: n *= 8; + break; + + case 96: n *= 12; + break; + + case 128: n *= 16; + break; + + default: n = 0; + break; + } + return ((n + 3) >> 2) << 2; + } + + + + + + //------------------------------------------------------------------------ + void pixel_map::draw(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const + { + if(m_bmp == 0 || m_buf == 0) return; + + unsigned bmp_x = 0; + unsigned bmp_y = 0; + unsigned bmp_width = m_bmp->bmiHeader.biWidth; + unsigned bmp_height = m_bmp->bmiHeader.biHeight; + unsigned dvc_x = 0; + unsigned dvc_y = 0; + unsigned dvc_width = m_bmp->bmiHeader.biWidth; + unsigned dvc_height = m_bmp->bmiHeader.biHeight; + + if(bmp_rect) + { + bmp_x = bmp_rect->left; + bmp_y = bmp_rect->top; + bmp_width = bmp_rect->right - bmp_rect->left; + bmp_height = bmp_rect->bottom - bmp_rect->top; + } + + dvc_x = bmp_x; + dvc_y = bmp_y; + dvc_width = bmp_width; + dvc_height = bmp_height; + + if(device_rect) + { + dvc_x = device_rect->left; + dvc_y = device_rect->top; + dvc_width = device_rect->right - device_rect->left; + dvc_height = device_rect->bottom - device_rect->top; + } + + if(dvc_width != bmp_width || dvc_height != bmp_height) + { + ::SetStretchBltMode(h_dc, COLORONCOLOR); + ::StretchDIBits( + h_dc, // handle of device context + dvc_x, // x-coordinate of upper-left corner of source rect. + dvc_y, // y-coordinate of upper-left corner of source rect. + dvc_width, // width of source rectangle + dvc_height, // height of source rectangle + bmp_x, + bmp_y, // x, y -coordinates of upper-left corner of dest. rect. + bmp_width, // width of destination rectangle + bmp_height, // height of destination rectangle + m_buf, // address of bitmap bits + m_bmp, // address of bitmap data + DIB_RGB_COLORS, // usage + SRCCOPY // raster operation code + ); + } + else + { + ::SetDIBitsToDevice( + h_dc, // handle to device context + dvc_x, // x-coordinate of upper-left corner of + dvc_y, // y-coordinate of upper-left corner of + dvc_width, // source rectangle width + dvc_height, // source rectangle height + bmp_x, // x-coordinate of lower-left corner of + bmp_y, // y-coordinate of lower-left corner of + 0, // first scan line in array + bmp_height, // number of scan lines + m_buf, // address of array with DIB bits + m_bmp, // address of structure with bitmap info. + DIB_RGB_COLORS // RGB or palette indexes + ); + } + } + + + //------------------------------------------------------------------------ + void pixel_map::draw(HDC h_dc, int x, int y, double scale) const + { + if(m_bmp == 0 || m_buf == 0) return; + + unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale); + unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale); + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + draw(h_dc, &rect); + } + + + + + //------------------------------------------------------------------------ + void pixel_map::blend(HDC h_dc, const RECT *device_rect, const RECT *bmp_rect) const + { +#if !defined(AGG_BMP_ALPHA_BLEND) + draw(h_dc, device_rect, bmp_rect); + return; +#else + if(m_bpp != 32) + { + draw(h_dc, device_rect, bmp_rect); + return; + } + + if(m_bmp == 0 || m_buf == 0) return; + + unsigned bmp_x = 0; + unsigned bmp_y = 0; + unsigned bmp_width = m_bmp->bmiHeader.biWidth; + unsigned bmp_height = m_bmp->bmiHeader.biHeight; + unsigned dvc_x = 0; + unsigned dvc_y = 0; + unsigned dvc_width = m_bmp->bmiHeader.biWidth; + unsigned dvc_height = m_bmp->bmiHeader.biHeight; + + if(bmp_rect) + { + bmp_x = bmp_rect->left; + bmp_y = bmp_rect->top; + bmp_width = bmp_rect->right - bmp_rect->left; + bmp_height = bmp_rect->bottom - bmp_rect->top; + } + + dvc_x = bmp_x; + dvc_y = bmp_y; + dvc_width = bmp_width; + dvc_height = bmp_height; + + if(device_rect) + { + dvc_x = device_rect->left; + dvc_y = device_rect->top; + dvc_width = device_rect->right - device_rect->left; + dvc_height = device_rect->bottom - device_rect->top; + } + + HDC mem_dc = ::CreateCompatibleDC(h_dc); + void* buf = 0; + HBITMAP bmp = ::CreateDIBSection( + mem_dc, + m_bmp, + DIB_RGB_COLORS, + &buf, + 0, + 0 + ); + memcpy(buf, m_buf, m_bmp->bmiHeader.biSizeImage); + + HBITMAP temp = (HBITMAP)::SelectObject(mem_dc, bmp); + + BLENDFUNCTION blend; + blend.BlendOp = AC_SRC_OVER; + blend.BlendFlags = 0; + +#if defined(AC_SRC_ALPHA) + blend.AlphaFormat = AC_SRC_ALPHA; +//#elif defined(AC_SRC_NO_PREMULT_ALPHA) +// blend.AlphaFormat = AC_SRC_NO_PREMULT_ALPHA; +#else +#error "No appropriate constant for alpha format. Check version of wingdi.h, There must be AC_SRC_ALPHA or AC_SRC_NO_PREMULT_ALPHA" +#endif + + blend.SourceConstantAlpha = 255; + ::AlphaBlend( + h_dc, + dvc_x, + dvc_y, + dvc_width, + dvc_height, + mem_dc, + bmp_x, + bmp_y, + bmp_width, + bmp_height, + blend + ); + + ::SelectObject(mem_dc, temp); + ::DeleteObject(bmp); + ::DeleteObject(mem_dc); +#endif //defined(AGG_BMP_ALPHA_BLEND) + } + + + //------------------------------------------------------------------------ + void pixel_map::blend(HDC h_dc, int x, int y, double scale) const + { + if(m_bmp == 0 || m_buf == 0) return; + unsigned width = unsigned(m_bmp->bmiHeader.biWidth * scale); + unsigned height = unsigned(m_bmp->bmiHeader.biHeight * scale); + RECT rect; + rect.left = x; + rect.top = y; + rect.right = x + width; + rect.bottom = y + height; + blend(h_dc, &rect); + } + + + //------------------------------------------------------------------------ + bool pixel_map::load_from_bmp(FILE *fd) + { + BITMAPFILEHEADER bmf; + BITMAPINFO *bmi = 0; + unsigned bmp_size; + + fread(&bmf, sizeof(bmf), 1, fd); + if(bmf.bfType != 0x4D42) goto bmperr; + + bmp_size = bmf.bfSize - sizeof(BITMAPFILEHEADER); + + bmi = (BITMAPINFO*) new unsigned char [bmp_size]; + if(fread(bmi, 1, bmp_size, fd) != bmp_size) goto bmperr; + destroy(); + m_bpp = bmi->bmiHeader.biBitCount; + create_from_bmp(bmi); + m_is_internal = 1; + return true; + + bmperr: + if(bmi) delete [] (unsigned char*) bmi; + return false; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::load_from_bmp(const char *filename) + { + FILE *fd = fopen(filename, "rb"); + bool ret = false; + if(fd) + { + ret = load_from_bmp(fd); + fclose(fd); + } + return ret; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_bmp(FILE *fd) const + { + if(m_bmp == 0) return 0; + + BITMAPFILEHEADER bmf; + + bmf.bfType = 0x4D42; + bmf.bfOffBits = calc_header_size(m_bmp) + sizeof(bmf); + bmf.bfSize = bmf.bfOffBits + m_img_size; + bmf.bfReserved1 = 0; + bmf.bfReserved2 = 0; + + fwrite(&bmf, sizeof(bmf), 1, fd); + fwrite(m_bmp, m_full_size, 1, fd); + return true; + } + + + + //------------------------------------------------------------------------ + bool pixel_map::save_as_bmp(const char *filename) const + { + FILE *fd = fopen(filename, "wb"); + bool ret = false; + if(fd) + { + ret = save_as_bmp(fd); + fclose(fd); + } + return ret; + } + + + //------------------------------------------------------------------------ + unsigned char* pixel_map::buf() + { + return m_buf; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::width() const + { + return m_bmp->bmiHeader.biWidth; + } + + //------------------------------------------------------------------------ + unsigned pixel_map::height() const + { + return m_bmp->bmiHeader.biHeight; + } + + //------------------------------------------------------------------------ + int pixel_map::stride() const + { + return calc_row_len(m_bmp->bmiHeader.biWidth, + m_bmp->bmiHeader.biBitCount); + } + + + //private + //------------------------------------------------------------------------ + void pixel_map::create_from_bmp(BITMAPINFO *bmp) + { + if(bmp) + { + m_img_size = calc_row_len(bmp->bmiHeader.biWidth, + bmp->bmiHeader.biBitCount) * + bmp->bmiHeader.biHeight; + + m_full_size = calc_full_size(bmp); + m_bmp = bmp; + m_buf = calc_img_ptr(bmp); + } + } + + + //private + //------------------------------------------------------------------------ + HBITMAP pixel_map::create_dib_section_from_args(HDC h_dc, + unsigned width, + unsigned height, + unsigned bits_per_pixel) + { + unsigned line_len = calc_row_len(width, bits_per_pixel); + unsigned img_size = line_len * height; + unsigned rgb_size = calc_palette_size(0, bits_per_pixel) * sizeof(RGBQUAD); + unsigned full_size = sizeof(BITMAPINFOHEADER) + rgb_size; + + BITMAPINFO *bmp = (BITMAPINFO *) new unsigned char[full_size]; + + bmp->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmp->bmiHeader.biWidth = width; + bmp->bmiHeader.biHeight = height; + bmp->bmiHeader.biPlanes = 1; + bmp->bmiHeader.biBitCount = (unsigned short)bits_per_pixel; + bmp->bmiHeader.biCompression = 0; + bmp->bmiHeader.biSizeImage = img_size; + bmp->bmiHeader.biXPelsPerMeter = 0; + bmp->bmiHeader.biYPelsPerMeter = 0; + bmp->bmiHeader.biClrUsed = 0; + bmp->bmiHeader.biClrImportant = 0; + + void* img_ptr = 0; + HBITMAP h_bitmap = ::CreateDIBSection(h_dc, bmp, DIB_RGB_COLORS, &img_ptr, NULL, 0); + + if(img_ptr) + { + m_img_size = calc_row_len(width, bits_per_pixel) * height; + m_full_size = 0; + m_bmp = bmp; + m_buf = (unsigned char *) img_ptr; + } + + return h_bitmap; + } +} + + + diff --git a/contrib/python/matplotlib/py2/extern/agg24-svn/ya.make b/contrib/python/matplotlib/py2/extern/agg24-svn/ya.make new file mode 100644 index 00000000000..c2ae9ed70fb --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/agg24-svn/ya.make @@ -0,0 +1,24 @@ +LIBRARY() + +VERSION(2.2.5) + +LICENSE(PSF-2.0) + +ADDINCL( + contrib/python/matplotlib/py2/extern/agg24-svn/include +) + +NO_COMPILER_WARNINGS() + +SRCS( + src/agg_bezier_arc.cpp + src/agg_curves.cpp + src/agg_image_filters.cpp + src/agg_trans_affine.cpp + src/agg_vcgen_contour.cpp + src/agg_vcgen_dash.cpp + src/agg_vcgen_stroke.cpp + src/agg_vpgen_segmentator.cpp +) + +END() diff --git a/contrib/python/matplotlib/py2/extern/ttconv/pprdrv.h b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv.h new file mode 100644 index 00000000000..39e81fee7f0 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv.h @@ -0,0 +1,113 @@ +/* -*- mode: c++; c-basic-offset: 4 -*- */ + +/* + * Modified for use within matplotlib + * 5 July 2007 + * Michael Droettboom + */ + +/* +** ~ppr/src/include/pprdrv.h +** Copyright 1995, Trinity College Computing Center. +** Written by David Chappell. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** This file last revised 5 December 1995. +*/ + +#include +#include + +/* + * Encapsulates all of the output to write to an arbitrary output + * function. This both removes the hardcoding of output to go to stdout + * and makes output thread-safe. Michael Droettboom [06-07-07] + */ +class TTStreamWriter +{ + private: + // Private copy and assignment + TTStreamWriter& operator=(const TTStreamWriter& other); + TTStreamWriter(const TTStreamWriter& other); + + public: + TTStreamWriter() { } + virtual ~TTStreamWriter() { } + + virtual void write(const char*) = 0; + + virtual void printf(const char* format, ...); + virtual void put_char(int val); + virtual void puts(const char* a); + virtual void putline(const char* a); +}; + +class TTDictionaryCallback +{ +private: + // Private copy and assignment + TTDictionaryCallback& operator=(const TTStreamWriter& other); + TTDictionaryCallback(const TTStreamWriter& other); + +public: + TTDictionaryCallback() { } + virtual ~TTDictionaryCallback() { } + + virtual void add_pair(const char* key, const char* value) = 0; +}; + +void replace_newlines_with_spaces(char* a); + +/* + * A simple class for all ttconv exceptions. + */ +class TTException +{ + const char* message; + TTException& operator=(const TTStreamWriter& other); + TTException(const TTStreamWriter& other); + +public: + TTException(const char* message_) : message(message_) { } + const char* getMessage() + { + return message; + } +}; + +/* +** No debug code will be included if this +** is not defined: +*/ +/* #define DEBUG 1 */ + +/* +** Uncomment the defines for the debugging +** code you want to have included. +*/ +#ifdef DEBUG +#define DEBUG_TRUETYPE /* truetype fonts, conversion to Postscript */ +#endif + +/* Do not change anything below this line. */ + +enum font_type_enum +{ + PS_TYPE_3 = 3, + PS_TYPE_42 = 42, + PS_TYPE_42_3_HYBRID = 43, + PDF_TYPE_3 = -3 +}; + +/* routines in pprdrv_tt.c */ +void insert_ttfont(const char *filename, TTStreamWriter& stream, font_type_enum target_type, std::vector& glyph_ids); + +void get_pdf_charprocs(const char *filename, std::vector& glyph_ids, TTDictionaryCallback& dict); + +/* end of file */ diff --git a/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt.cpp b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt.cpp new file mode 100644 index 00000000000..abe209856ed --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt.cpp @@ -0,0 +1,1484 @@ +/* -*- mode: c++; c-basic-offset: 4 -*- */ + +/* + * Modified for use within matplotlib + * 5 July 2007 + * Michael Droettboom + */ + +/* +** ~ppr/src/pprdrv/pprdrv_tt.c +** Copyright 1995, Trinity College Computing Center. +** Written by David Chappell. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** TrueType font support. These functions allow PPR to generate +** PostScript fonts from Microsoft compatible TrueType font files. +** +** Last revised 19 December 1995. +*/ + +#include +#include +#include +#include "pprdrv.h" +#include "truetype.h" +#include +#ifdef _POSIX_C_SOURCE +# undef _POSIX_C_SOURCE +#endif +#ifndef _AIX +#ifdef _XOPEN_SOURCE +# undef _XOPEN_SOURCE +#endif +#endif +#include + +/*========================================================================== +** Convert the indicated Truetype font file to a type 42 or type 3 +** PostScript font and insert it in the output stream. +** +** All the routines from here to the end of file file are involved +** in this process. +==========================================================================*/ + +/*--------------------------------------- +** Endian conversion routines. +** These routines take a BYTE pointer +** and return a value formed by reading +** bytes starting at that point. +** +** These routines read the big-endian +** values which are used in TrueType +** font files. +---------------------------------------*/ + +/* +** Get an Unsigned 32 bit number. +*/ +ULONG getULONG(BYTE *p) +{ + int x; + ULONG val=0; + + for (x=0; x<4; x++) + { + val *= 0x100; + val += p[x]; + } + + return val; +} /* end of ftohULONG() */ + +/* +** Get an unsigned 16 bit number. +*/ +USHORT getUSHORT(BYTE *p) +{ + int x; + USHORT val=0; + + for (x=0; x<2; x++) + { + val *= 0x100; + val += p[x]; + } + + return val; +} /* end of getUSHORT() */ + +/* +** Get a 32 bit fixed point (16.16) number. +** A special structure is used to return the value. +*/ +Fixed getFixed(BYTE *s) +{ + Fixed val={0,0}; + + val.whole = ((s[0] * 256) + s[1]); + val.fraction = ((s[2] * 256) + s[3]); + + return val; +} /* end of getFixed() */ + +/*----------------------------------------------------------------------- +** Load a TrueType font table into memory and return a pointer to it. +** The font's "file" and "offset_table" fields must be set before this +** routine is called. +** +** This first argument is a TrueType font structure, the second +** argument is the name of the table to retrieve. A table name +** is always 4 characters, though the last characters may be +** padding spaces. +-----------------------------------------------------------------------*/ +BYTE *GetTable(struct TTFONT *font, const char *name) +{ + BYTE *ptr; + ULONG x; + +#ifdef DEBUG_TRUETYPE + debug("GetTable(file,font,\"%s\")",name); +#endif + + /* We must search the table directory. */ + ptr = font->offset_table + 12; + x=0; + while (true) + { + if ( strncmp((const char*)ptr,name,4) == 0 ) + { + ULONG offset,length; + BYTE *table; + + offset = getULONG( ptr + 8 ); + length = getULONG( ptr + 12 ); + table = (BYTE*)calloc( sizeof(BYTE), length + 2 ); + + try + { +#ifdef DEBUG_TRUETYPE + debug("Loading table \"%s\" from offset %d, %d bytes",name,offset,length); +#endif + + if ( fseek( font->file, (long)offset, SEEK_SET ) ) + { + throw TTException("TrueType font may be corrupt (reason 3)"); + } + + if ( fread(table,sizeof(BYTE),length,font->file) != (sizeof(BYTE) * length)) + { + throw TTException("TrueType font may be corrupt (reason 4)"); + } + } + catch (TTException& ) + { + free(table); + throw; + } + /* Always NUL-terminate; add two in case of UTF16 strings. */ + table[length] = '\0'; + table[length + 1] = '\0'; + return table; + } + + x++; + ptr += 16; + if (x == font->numTables) + { + throw TTException("TrueType font is missing table"); + } + } + +} /* end of GetTable() */ + +static void utf16be_to_ascii(char *dst, char *src, size_t length) { + ++src; + for (; *src != 0 && length; dst++, src += 2, --length) { + *dst = *src; + } +} + +/*-------------------------------------------------------------------- +** Load the 'name' table, get information from it, +** and store that information in the font structure. +** +** The 'name' table contains information such as the name of +** the font, and it's PostScript name. +--------------------------------------------------------------------*/ +void Read_name(struct TTFONT *font) +{ + BYTE *table_ptr,*ptr2; + int numrecords; /* Number of strings in this table */ + BYTE *strings; /* pointer to start of string storage */ + int x; + int platform; /* Current platform id */ + int nameid; /* name id, */ + int offset,length; /* offset and length of string. */ + +#ifdef DEBUG_TRUETYPE + debug("Read_name()"); +#endif + + table_ptr = NULL; + + /* Set default values to avoid future references to undefined + * pointers. Allocate each of PostName, FullName, FamilyName, + * Version, and Style separately so they can be freed safely. */ + for (char **ptr = &(font->PostName); ptr != NULL; ) + { + *ptr = (char*) calloc(sizeof(char), strlen("unknown")+1); + strcpy(*ptr, "unknown"); + if (ptr == &(font->PostName)) ptr = &(font->FullName); + else if (ptr == &(font->FullName)) ptr = &(font->FamilyName); + else if (ptr == &(font->FamilyName)) ptr = &(font->Version); + else if (ptr == &(font->Version)) ptr = &(font->Style); + else ptr = NULL; + } + font->Copyright = font->Trademark = (char*)NULL; + + table_ptr = GetTable(font, "name"); /* pointer to table */ + try + { + numrecords = getUSHORT( table_ptr + 2 ); /* number of names */ + strings = table_ptr + getUSHORT( table_ptr + 4 ); /* start of string storage */ + + ptr2 = table_ptr + 6; + for (x=0; x < numrecords; x++,ptr2+=12) + { + platform = getUSHORT(ptr2); + nameid = getUSHORT(ptr2+6); + length = getUSHORT(ptr2+8); + offset = getUSHORT(ptr2+10); + +#ifdef DEBUG_TRUETYPE + debug("platform %d, encoding %d, language 0x%x, name %d, offset %d, length %d", + platform,encoding,language,nameid,offset,length); +#endif + + /* Copyright notice */ + if ( platform == 1 && nameid == 0 ) + { + font->Copyright = (char*)calloc(sizeof(char),length+1); + strncpy(font->Copyright,(const char*)strings+offset,length); + font->Copyright[length]='\0'; + replace_newlines_with_spaces(font->Copyright); + +#ifdef DEBUG_TRUETYPE + debug("font->Copyright=\"%s\"",font->Copyright); +#endif + continue; + } + + + /* Font Family name */ + if ( platform == 1 && nameid == 1 ) + { + free(font->FamilyName); + font->FamilyName = (char*)calloc(sizeof(char),length+1); + strncpy(font->FamilyName,(const char*)strings+offset,length); + font->FamilyName[length]='\0'; + replace_newlines_with_spaces(font->FamilyName); + +#ifdef DEBUG_TRUETYPE + debug("font->FamilyName=\"%s\"",font->FamilyName); +#endif + continue; + } + + + /* Font Family name */ + if ( platform == 1 && nameid == 2 ) + { + free(font->Style); + font->Style = (char*)calloc(sizeof(char),length+1); + strncpy(font->Style,(const char*)strings+offset,length); + font->Style[length]='\0'; + replace_newlines_with_spaces(font->Style); + +#ifdef DEBUG_TRUETYPE + debug("font->Style=\"%s\"",font->Style); +#endif + continue; + } + + + /* Full Font name */ + if ( platform == 1 && nameid == 4 ) + { + free(font->FullName); + font->FullName = (char*)calloc(sizeof(char),length+1); + strncpy(font->FullName,(const char*)strings+offset,length); + font->FullName[length]='\0'; + replace_newlines_with_spaces(font->FullName); + +#ifdef DEBUG_TRUETYPE + debug("font->FullName=\"%s\"",font->FullName); +#endif + continue; + } + + + /* Version string */ + if ( platform == 1 && nameid == 5 ) + { + free(font->Version); + font->Version = (char*)calloc(sizeof(char),length+1); + strncpy(font->Version,(const char*)strings+offset,length); + font->Version[length]='\0'; + replace_newlines_with_spaces(font->Version); + +#ifdef DEBUG_TRUETYPE + debug("font->Version=\"%s\"",font->Version); +#endif + continue; + } + + + /* PostScript name */ + if ( platform == 1 && nameid == 6 ) + { + free(font->PostName); + font->PostName = (char*)calloc(sizeof(char),length+1); + strncpy(font->PostName,(const char*)strings+offset,length); + font->PostName[length]='\0'; + replace_newlines_with_spaces(font->PostName); + +#ifdef DEBUG_TRUETYPE + debug("font->PostName=\"%s\"",font->PostName); +#endif + continue; + } + + /* Microsoft-format PostScript name */ + if ( platform == 3 && nameid == 6 ) + { + free(font->PostName); + font->PostName = (char*)calloc(sizeof(char),length+1); + utf16be_to_ascii(font->PostName, (char *)strings+offset, length); + font->PostName[length/2]='\0'; + replace_newlines_with_spaces(font->PostName); + +#ifdef DEBUG_TRUETYPE + debug("font->PostName=\"%s\"",font->PostName); +#endif + continue; + } + + + /* Trademark string */ + if ( platform == 1 && nameid == 7 ) + { + font->Trademark = (char*)calloc(sizeof(char),length+1); + strncpy(font->Trademark,(const char*)strings+offset,length); + font->Trademark[length]='\0'; + replace_newlines_with_spaces(font->Trademark); + +#ifdef DEBUG_TRUETYPE + debug("font->Trademark=\"%s\"",font->Trademark); +#endif + continue; + } + } + } + catch (TTException& ) + { + free(table_ptr); + throw; + } + + free(table_ptr); +} /* end of Read_name() */ + +/*--------------------------------------------------------------------- +** Write the header for a PostScript font. +---------------------------------------------------------------------*/ +void ttfont_header(TTStreamWriter& stream, struct TTFONT *font) +{ + int VMMin; + int VMMax; + + /* + ** To show that it is a TrueType font in PostScript format, + ** we will begin the file with a specific string. + ** This string also indicates the version of the TrueType + ** specification on which the font is based and the + ** font manufacturer's revision number for the font. + */ + if ( font->target_type == PS_TYPE_42 || + font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.printf("%%!PS-TrueTypeFont-%d.%d-%d.%d\n", + font->TTVersion.whole, font->TTVersion.fraction, + font->MfrRevision.whole, font->MfrRevision.fraction); + } + + /* If it is not a Type 42 font, we will use a different format. */ + else + { + stream.putline("%!PS-Adobe-3.0 Resource-Font"); + } /* See RBIIp 641 */ + + /* We will make the title the name of the font. */ + stream.printf("%%%%Title: %s\n",font->FullName); + + /* If there is a Copyright notice, put it here too. */ + if ( font->Copyright != (char*)NULL ) + { + stream.printf("%%%%Copyright: %s\n",font->Copyright); + } + + /* We created this file. */ + if ( font->target_type == PS_TYPE_42 ) + { + stream.putline("%%Creator: Converted from TrueType to type 42 by PPR"); + } + else if (font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.putline("%%Creator: Converted from TypeType to type 42/type 3 hybrid by PPR"); + } + else + { + stream.putline("%%Creator: Converted from TrueType to type 3 by PPR"); + } + + /* If VM usage information is available, print it. */ + if ( font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID) + { + VMMin = (int)getULONG( font->post_table + 16 ); + VMMax = (int)getULONG( font->post_table + 20 ); + if ( VMMin > 0 && VMMax > 0 ) + stream.printf("%%%%VMUsage: %d %d\n",VMMin,VMMax); + } + + /* Start the dictionary which will eventually */ + /* become the font. */ + if (font->target_type == PS_TYPE_42) + { + stream.putline("15 dict begin"); + } + else + { + stream.putline("25 dict begin"); + + /* Type 3 fonts will need some subroutines here. */ + stream.putline("/_d{bind def}bind def"); + stream.putline("/_m{moveto}_d"); + stream.putline("/_l{lineto}_d"); + stream.putline("/_cl{closepath eofill}_d"); + stream.putline("/_c{curveto}_d"); + stream.putline("/_sc{7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse}_d"); + stream.putline("/_e{exec}_d"); + } + + stream.printf("/FontName /%s def\n",font->PostName); + stream.putline("/PaintType 0 def"); + + if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.putline("/FontMatrix[1 0 0 1 0 0]def"); + } + else + { + stream.putline("/FontMatrix[.001 0 0 .001 0 0]def"); + } + + stream.printf("/FontBBox[%d %d %d %d]def\n",font->llx-1,font->lly-1,font->urx,font->ury); + if (font->target_type == PS_TYPE_42 || font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.printf("/FontType 42 def\n", font->target_type ); + } + else + { + stream.printf("/FontType 3 def\n", font->target_type ); + } +} /* end of ttfont_header() */ + +/*------------------------------------------------------------- +** Define the encoding array for this font. +** Since we don't really want to deal with converting all of +** the possible font encodings in the wild to a standard PS +** one, we just explicitly create one for each font. +-------------------------------------------------------------*/ +void ttfont_encoding(TTStreamWriter& stream, struct TTFONT *font, std::vector& glyph_ids, font_type_enum target_type) +{ + if (target_type == PS_TYPE_3 || target_type == PS_TYPE_42_3_HYBRID) + { + stream.printf("/Encoding [ "); + + for (std::vector::const_iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) + { + const char* name = ttfont_CharStrings_getname(font, *i); + stream.printf("/%s ", name); + } + + stream.printf("] def\n"); + } + else + { + stream.putline("/Encoding StandardEncoding def"); + } +} /* end of ttfont_encoding() */ + +/*----------------------------------------------------------- +** Create the optional "FontInfo" sub-dictionary. +-----------------------------------------------------------*/ +void ttfont_FontInfo(TTStreamWriter& stream, struct TTFONT *font) +{ + Fixed ItalicAngle; + + /* We create a sub dictionary named "FontInfo" where we */ + /* store information which though it is not used by the */ + /* interpreter, is useful to some programs which will */ + /* be printing with the font. */ + stream.putline("/FontInfo 10 dict dup begin"); + + /* These names come from the TrueType font's "name" table. */ + stream.printf("/FamilyName (%s) def\n",font->FamilyName); + stream.printf("/FullName (%s) def\n",font->FullName); + + if ( font->Copyright != (char*)NULL || font->Trademark != (char*)NULL ) + { + stream.printf("/Notice (%s", + font->Copyright != (char*)NULL ? font->Copyright : ""); + stream.printf("%s%s) def\n", + font->Trademark != (char*)NULL ? " " : "", + font->Trademark != (char*)NULL ? font->Trademark : ""); + } + + /* This information is not quite correct. */ + stream.printf("/Weight (%s) def\n",font->Style); + + /* Some fonts have this as "version". */ + stream.printf("/Version (%s) def\n",font->Version); + + /* Some information from the "post" table. */ + ItalicAngle = getFixed( font->post_table + 4 ); + stream.printf("/ItalicAngle %d.%d def\n",ItalicAngle.whole,ItalicAngle.fraction); + stream.printf("/isFixedPitch %s def\n", getULONG( font->post_table + 12 ) ? "true" : "false" ); + stream.printf("/UnderlinePosition %d def\n", (int)getFWord( font->post_table + 8 ) ); + stream.printf("/UnderlineThickness %d def\n", (int)getFWord( font->post_table + 10 ) ); + stream.putline("end readonly def"); +} /* end of ttfont_FontInfo() */ + +/*------------------------------------------------------------------- +** sfnts routines +** These routines generate the PostScript "sfnts" array which +** contains one or more strings which contain a reduced version +** of the TrueType font. +** +** A number of functions are required to accomplish this rather +** complicated task. +-------------------------------------------------------------------*/ +int string_len; +int line_len; +bool in_string; + +/* +** This is called once at the start. +*/ +void sfnts_start(TTStreamWriter& stream) +{ + stream.puts("/sfnts[<"); + in_string=true; + string_len=0; + line_len=8; +} /* end of sfnts_start() */ + +/* +** Write a BYTE as a hexadecimal value as part of the sfnts array. +*/ +void sfnts_pputBYTE(TTStreamWriter& stream, BYTE n) +{ + static const char hexdigits[]="0123456789ABCDEF"; + + if (!in_string) + { + stream.put_char('<'); + string_len=0; + line_len++; + in_string=true; + } + + stream.put_char( hexdigits[ n / 16 ] ); + stream.put_char( hexdigits[ n % 16 ] ); + string_len++; + line_len+=2; + + if (line_len > 70) + { + stream.put_char('\n'); + line_len=0; + } + +} /* end of sfnts_pputBYTE() */ + +/* +** Write a USHORT as a hexadecimal value as part of the sfnts array. +*/ +void sfnts_pputUSHORT(TTStreamWriter& stream, USHORT n) +{ + sfnts_pputBYTE(stream, n / 256); + sfnts_pputBYTE(stream, n % 256); +} /* end of sfnts_pputUSHORT() */ + +/* +** Write a ULONG as part of the sfnts array. +*/ +void sfnts_pputULONG(TTStreamWriter& stream, ULONG n) +{ + int x1,x2,x3; + + x1 = n % 256; + n /= 256; + x2 = n % 256; + n /= 256; + x3 = n % 256; + n /= 256; + + sfnts_pputBYTE(stream, n); + sfnts_pputBYTE(stream, x3); + sfnts_pputBYTE(stream, x2); + sfnts_pputBYTE(stream, x1); +} /* end of sfnts_pputULONG() */ + +/* +** This is called whenever it is +** necessary to end a string in the sfnts array. +** +** (The array must be broken into strings which are +** no longer than 64K characters.) +*/ +void sfnts_end_string(TTStreamWriter& stream) +{ + if (in_string) + { + string_len=0; /* fool sfnts_pputBYTE() */ + +#ifdef DEBUG_TRUETYPE_INLINE + puts("\n% dummy byte:\n"); +#endif + + sfnts_pputBYTE(stream, 0); /* extra byte for pre-2013 compatibility */ + stream.put_char('>'); + line_len++; + } + in_string=false; +} /* end of sfnts_end_string() */ + +/* +** This is called at the start of each new table. +** The argement is the length in bytes of the table +** which will follow. If the new table will not fit +** in the current string, a new one is started. +*/ +void sfnts_new_table(TTStreamWriter& stream, ULONG length) +{ + if ( (string_len + length) > 65528 ) + sfnts_end_string(stream); +} /* end of sfnts_new_table() */ + +/* +** We may have to break up the 'glyf' table. That is the reason +** why we provide this special routine to copy it into the sfnts +** array. +*/ +void sfnts_glyf_table(TTStreamWriter& stream, struct TTFONT *font, ULONG oldoffset, ULONG correct_total_length) +{ + ULONG off; + ULONG length; + int c; + ULONG total=0; /* running total of bytes written to table */ + int x; + bool loca_is_local=false; + +#ifdef DEBUG_TRUETYPE + debug("sfnts_glyf_table(font,%d)", (int)correct_total_length); +#endif + + if (font->loca_table == NULL) + { + font->loca_table = GetTable(font,"loca"); + loca_is_local = true; + } + + /* Seek to proper position in the file. */ + fseek( font->file, oldoffset, SEEK_SET ); + + /* Copy the glyphs one by one */ + for (x=0; x < font->numGlyphs; x++) + { + /* Read the glyph offset from the index-to-location table. */ + if (font->indexToLocFormat == 0) + { + off = getUSHORT( font->loca_table + (x * 2) ); + off *= 2; + length = getUSHORT( font->loca_table + ((x+1) * 2) ); + length *= 2; + length -= off; + } + else + { + off = getULONG( font->loca_table + (x * 4) ); + length = getULONG( font->loca_table + ((x+1) * 4) ); + length -= off; + } + +#ifdef DEBUG_TRUETYPE + debug("glyph length=%d",(int)length); +#endif + + /* Start new string if necessary. */ + sfnts_new_table( stream, (int)length ); + + /* + ** Make sure the glyph is padded out to a + ** two byte boundary. + */ + if ( length % 2 ) { + throw TTException("TrueType font contains a 'glyf' table without 2 byte padding"); + } + + /* Copy the bytes of the glyph. */ + while ( length-- ) + { + if ( (c = fgetc(font->file)) == EOF ) { + throw TTException("TrueType font may be corrupt (reason 6)"); + } + + sfnts_pputBYTE(stream, c); + total++; /* add to running total */ + } + + } + + if (loca_is_local) + { + free(font->loca_table); + font->loca_table = NULL; + } + + /* Pad out to full length from table directory */ + while ( total < correct_total_length ) + { + sfnts_pputBYTE(stream, 0); + total++; + } + +} /* end of sfnts_glyf_table() */ + +/* +** Here is the routine which ties it all together. +** +** Create the array called "sfnts" which +** holds the actual TrueType data. +*/ +void ttfont_sfnts(TTStreamWriter& stream, struct TTFONT *font) +{ + static const char *table_names[] = /* The names of all tables */ + { + /* which it is worth while */ + "cvt ", /* to include in a Type 42 */ + "fpgm", /* PostScript font. */ + "glyf", + "head", + "hhea", + "hmtx", + "loca", + "maxp", + "prep" + } ; + + struct /* The location of each of */ + { + ULONG oldoffset; /* the above tables. */ + ULONG newoffset; + ULONG length; + ULONG checksum; + } tables[9]; + + BYTE *ptr; /* A pointer into the origional table directory. */ + ULONG x,y; /* General use loop countes. */ + int c; /* Input character. */ + int diff; + ULONG nextoffset; + int count; /* How many `important' tables did we find? */ + + ptr = font->offset_table + 12; + nextoffset=0; + count=0; + + /* + ** Find the tables we want and store there vital + ** statistics in tables[]. + */ + ULONG num_tables_read = 0; /* Number of tables read from the directory */ + for (x = 0; x < 9; x++) { + do { + if (num_tables_read < font->numTables) { + /* There are still tables to read from ptr */ + diff = strncmp((char*)ptr, table_names[x], 4); + + if (diff > 0) { /* If we are past it. */ + tables[x].length = 0; + diff = 0; + } else if (diff < 0) { /* If we haven't hit it yet. */ + ptr += 16; + num_tables_read++; + } else if (diff == 0) { /* Here it is! */ + tables[x].newoffset = nextoffset; + tables[x].checksum = getULONG( ptr + 4 ); + tables[x].oldoffset = getULONG( ptr + 8 ); + tables[x].length = getULONG( ptr + 12 ); + nextoffset += ( ((tables[x].length + 3) / 4) * 4 ); + count++; + ptr += 16; + num_tables_read++; + } + } else { + /* We've read the whole table directory already */ + /* Some tables couldn't be found */ + tables[x].length = 0; + break; /* Proceed to next tables[x] */ + } + } while (diff != 0); + + } /* end of for loop which passes over the table directory */ + + /* Begin the sfnts array. */ + sfnts_start(stream); + + /* Generate the offset table header */ + /* Start by copying the TrueType version number. */ + ptr = font->offset_table; + for (x=0; x < 4; x++) + { + sfnts_pputBYTE( stream, *(ptr++) ); + } + + /* Now, generate those silly numTables numbers. */ + sfnts_pputUSHORT(stream, count); /* number of tables */ + + int search_range = 1; + int entry_sel = 0; + + while (search_range <= count) { + search_range <<= 1; + entry_sel++; + } + entry_sel = entry_sel > 0 ? entry_sel - 1 : 0; + search_range = (search_range >> 1) * 16; + int range_shift = count * 16 - search_range; + + sfnts_pputUSHORT(stream, search_range); /* searchRange */ + sfnts_pputUSHORT(stream, entry_sel); /* entrySelector */ + sfnts_pputUSHORT(stream, range_shift); /* rangeShift */ + +#ifdef DEBUG_TRUETYPE + debug("only %d tables selected",count); +#endif + + /* Now, emmit the table directory. */ + for (x=0; x < 9; x++) + { + if ( tables[x].length == 0 ) /* Skip missing tables */ + { + continue; + } + + /* Name */ + sfnts_pputBYTE( stream, table_names[x][0] ); + sfnts_pputBYTE( stream, table_names[x][1] ); + sfnts_pputBYTE( stream, table_names[x][2] ); + sfnts_pputBYTE( stream, table_names[x][3] ); + + /* Checksum */ + sfnts_pputULONG( stream, tables[x].checksum ); + + /* Offset */ + sfnts_pputULONG( stream, tables[x].newoffset + 12 + (count * 16) ); + + /* Length */ + sfnts_pputULONG( stream, tables[x].length ); + } + + /* Now, send the tables */ + for (x=0; x < 9; x++) + { + if ( tables[x].length == 0 ) /* skip tables that aren't there */ + { + continue; + } + +#ifdef DEBUG_TRUETYPE + debug("emmiting table '%s'",table_names[x]); +#endif + + /* 'glyf' table gets special treatment */ + if ( strcmp(table_names[x],"glyf")==0 ) + { + sfnts_glyf_table(stream,font,tables[x].oldoffset,tables[x].length); + } + else /* Other tables may not exceed */ + { + /* 65535 bytes in length. */ + if ( tables[x].length > 65535 ) + { + throw TTException("TrueType font has a table which is too long"); + } + + /* Start new string if necessary. */ + sfnts_new_table(stream, tables[x].length); + + /* Seek to proper position in the file. */ + fseek( font->file, tables[x].oldoffset, SEEK_SET ); + + /* Copy the bytes of the table. */ + for ( y=0; y < tables[x].length; y++ ) + { + if ( (c = fgetc(font->file)) == EOF ) + { + throw TTException("TrueType font may be corrupt (reason 7)"); + } + + sfnts_pputBYTE(stream, c); + } + } + + /* Padd it out to a four byte boundary. */ + y=tables[x].length; + while ( (y % 4) != 0 ) + { + sfnts_pputBYTE(stream, 0); + y++; +#ifdef DEBUG_TRUETYPE_INLINE + puts("\n% pad byte:\n"); +#endif + } + + } /* End of loop for all tables */ + + /* Close the array. */ + sfnts_end_string(stream); + stream.putline("]def"); +} /* end of ttfont_sfnts() */ + +/*-------------------------------------------------------------- +** Create the CharStrings dictionary which will translate +** PostScript character names to TrueType font character +** indexes. +** +** If we are creating a type 3 instead of a type 42 font, +** this array will instead convert PostScript character names +** to executable proceedures. +--------------------------------------------------------------*/ +const char *Apple_CharStrings[]= +{ + ".notdef",".null","nonmarkingreturn","space","exclam","quotedbl","numbersign", + "dollar","percent","ampersand","quotesingle","parenleft","parenright", + "asterisk","plus", "comma","hyphen","period","slash","zero","one","two", + "three","four","five","six","seven","eight","nine","colon","semicolon", + "less","equal","greater","question","at","A","B","C","D","E","F","G","H","I", + "J","K", "L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z", + "bracketleft","backslash","bracketright","asciicircum","underscore","grave", + "a","b","c","d","e","f","g","h","i","j","k", "l","m","n","o","p","q","r","s", + "t","u","v","w","x","y","z","braceleft","bar","braceright","asciitilde", + "Adieresis","Aring","Ccedilla","Eacute","Ntilde","Odieresis","Udieresis", + "aacute","agrave","acircumflex","adieresis","atilde","aring","ccedilla", + "eacute","egrave","ecircumflex","edieresis","iacute","igrave","icircumflex", + "idieresis","ntilde","oacute","ograve","ocircumflex","odieresis","otilde", + "uacute","ugrave","ucircumflex","udieresis","dagger","degree","cent", + "sterling","section","bullet","paragraph","germandbls","registered", + "copyright","trademark","acute","dieresis","notequal","AE","Oslash", + "infinity","plusminus","lessequal","greaterequal","yen","mu","partialdiff", + "summation","product","pi","integral","ordfeminine","ordmasculine","Omega", + "ae","oslash","questiondown","exclamdown","logicalnot","radical","florin", + "approxequal","Delta","guillemotleft","guillemotright","ellipsis", + "nobreakspace","Agrave","Atilde","Otilde","OE","oe","endash","emdash", + "quotedblleft","quotedblright","quoteleft","quoteright","divide","lozenge", + "ydieresis","Ydieresis","fraction","currency","guilsinglleft","guilsinglright", + "fi","fl","daggerdbl","periodcentered","quotesinglbase","quotedblbase", + "perthousand","Acircumflex","Ecircumflex","Aacute","Edieresis","Egrave", + "Iacute","Icircumflex","Idieresis","Igrave","Oacute","Ocircumflex","apple", + "Ograve","Uacute","Ucircumflex","Ugrave","dotlessi","circumflex","tilde", + "macron","breve","dotaccent","ring","cedilla","hungarumlaut","ogonek","caron", + "Lslash","lslash","Scaron","scaron","Zcaron","zcaron","brokenbar","Eth","eth", + "Yacute","yacute","Thorn","thorn","minus","multiply","onesuperior", + "twosuperior","threesuperior","onehalf","onequarter","threequarters","franc", + "Gbreve","gbreve","Idot","Scedilla","scedilla","Cacute","cacute","Ccaron", + "ccaron","dmacron","markingspace","capslock","shift","propeller","enter", + "markingtabrtol","markingtabltor","control","markingdeleteltor", + "markingdeletertol","option","escape","parbreakltor","parbreakrtol", + "newpage","checkmark","linebreakltor","linebreakrtol","markingnobreakspace", + "diamond","appleoutline" +}; + +/* +** This routine is called by the one below. +** It is also called from pprdrv_tt2.c +*/ +const char *ttfont_CharStrings_getname(struct TTFONT *font, int charindex) +{ + int GlyphIndex; + static char temp[80]; + char *ptr; + ULONG len; + + Fixed post_format; + + /* The 'post' table format number. */ + post_format = getFixed( font->post_table ); + + if ( post_format.whole != 2 || post_format.fraction != 0 ) + { + /* We don't have a glyph name table, so generate a name. + This generated name must match exactly the name that is + generated by FT2Font in get_glyph_name */ + PyOS_snprintf(temp, 80, "uni%08x", charindex); + return temp; + } + + GlyphIndex = (int)getUSHORT( font->post_table + 34 + (charindex * 2) ); + + if ( GlyphIndex <= 257 ) /* If a standard Apple name, */ + { + return Apple_CharStrings[GlyphIndex]; + } + else /* Otherwise, use one */ + { + /* of the pascal strings. */ + GlyphIndex -= 258; + + /* Set pointer to start of Pascal strings. */ + ptr = (char*)(font->post_table + 34 + (font->numGlyphs * 2)); + + len = (ULONG)*(ptr++); /* Step thru the strings */ + while (GlyphIndex--) /* until we get to the one */ + { + /* that we want. */ + ptr += len; + len = (ULONG)*(ptr++); + } + + if ( len >= sizeof(temp) ) + { + throw TTException("TrueType font file contains a very long PostScript name"); + } + + strncpy(temp,ptr,len); /* Copy the pascal string into */ + temp[len]='\0'; /* a buffer and make it ASCIIz. */ + + return temp; + } +} /* end of ttfont_CharStrings_getname() */ + +/* +** This is the central routine of this section. +*/ +void ttfont_CharStrings(TTStreamWriter& stream, struct TTFONT *font, std::vector& glyph_ids) +{ + Fixed post_format; + + /* The 'post' table format number. */ + post_format = getFixed( font->post_table ); + + /* Emmit the start of the PostScript code to define the dictionary. */ + stream.printf("/CharStrings %d dict dup begin\n", glyph_ids.size()+1); + /* Section 5.8.2 table 5.7 of the PS Language Ref says a CharStrings dictionary must contain an entry for .notdef */ + stream.printf("/.notdef 0 def\n"); + + /* Emmit one key-value pair for each glyph. */ + for (std::vector::const_iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) + { + if ((font->target_type == PS_TYPE_42 || + font->target_type == PS_TYPE_42_3_HYBRID) + && *i < 256) /* type 42 */ + { + stream.printf("/%s %d def\n",ttfont_CharStrings_getname(font, *i), *i); + } + else /* type 3 */ + { + stream.printf("/%s{",ttfont_CharStrings_getname(font, *i)); + + tt_type3_charproc(stream, font, *i); + + stream.putline("}_d"); /* "} bind def" */ + } + } + + stream.putline("end readonly def"); +} /* end of ttfont_CharStrings() */ + +/*---------------------------------------------------------------- +** Emmit the code to finish up the dictionary and turn +** it into a font. +----------------------------------------------------------------*/ +void ttfont_trailer(TTStreamWriter& stream, struct TTFONT *font) +{ + /* If we are generating a type 3 font, we need to provide */ + /* a BuildGlyph and BuildChar proceedures. */ + if (font->target_type == PS_TYPE_3 || + font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.put_char('\n'); + + stream.putline("/BuildGlyph"); + stream.putline(" {exch begin"); /* start font dictionary */ + stream.putline(" CharStrings exch"); + stream.putline(" 2 copy known not{pop /.notdef}if"); + stream.putline(" true 3 1 roll get exec"); + stream.putline(" end}_d"); + + stream.put_char('\n'); + + /* This proceedure is for compatibility with */ + /* level 1 interpreters. */ + stream.putline("/BuildChar {"); + stream.putline(" 1 index /Encoding get exch get"); + stream.putline(" 1 index /BuildGlyph get exec"); + stream.putline("}_d"); + + stream.put_char('\n'); + } + + /* If we are generating a type 42 font, we need to check to see */ + /* if this PostScript interpreter understands type 42 fonts. If */ + /* it doesn't, we will hope that the Apple TrueType rasterizer */ + /* has been loaded and we will adjust the font accordingly. */ + /* I found out how to do this by examining a TrueType font */ + /* generated by a Macintosh. That is where the TrueType interpreter */ + /* setup instructions and part of BuildGlyph came from. */ + if (font->target_type == PS_TYPE_42 || + font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.put_char('\n'); + + /* If we have no "resourcestatus" command, or FontType 42 */ + /* is unknown, leave "true" on the stack. */ + stream.putline("systemdict/resourcestatus known"); + stream.putline(" {42 /FontType resourcestatus"); + stream.putline(" {pop pop false}{true}ifelse}"); + stream.putline(" {true}ifelse"); + + /* If true, execute code to produce an error message if */ + /* we can't find Apple's TrueDict in VM. */ + stream.putline("{/TrueDict where{pop}{(%%[ Error: no TrueType rasterizer ]%%)= flush}ifelse"); + + /* Since we are expected to use Apple's TrueDict TrueType */ + /* reasterizer, change the font type to 3. */ + stream.putline("/FontType 3 def"); + + /* Define a string to hold the state of the Apple */ + /* TrueType interpreter. */ + stream.putline(" /TrueState 271 string def"); + + /* It looks like we get information about the resolution */ + /* of the printer and store it in the TrueState string. */ + stream.putline(" TrueDict begin sfnts save"); + stream.putline(" 72 0 matrix defaultmatrix dtransform dup"); + stream.putline(" mul exch dup mul add sqrt cvi 0 72 matrix"); + stream.putline(" defaultmatrix dtransform dup mul exch dup"); + stream.putline(" mul add sqrt cvi 3 -1 roll restore"); + stream.putline(" TrueState initer end"); + + /* This BuildGlyph procedure will look the name up in the */ + /* CharStrings array, and then check to see if what it gets */ + /* is a procedure. If it is, it executes it, otherwise, it */ + /* lets the TrueType rasterizer loose on it. */ + + /* When this proceedure is executed the stack contains */ + /* the font dictionary and the character name. We */ + /* exchange arguments and move the dictionary to the */ + /* dictionary stack. */ + stream.putline(" /BuildGlyph{exch begin"); + /* stack: charname */ + + /* Put two copies of CharStrings on the stack and consume */ + /* one testing to see if the charname is defined in it, */ + /* leave the answer on the stack. */ + stream.putline(" CharStrings dup 2 index known"); + /* stack: charname CharStrings bool */ + + /* Exchange the CharStrings dictionary and the charname, */ + /* but if the answer was false, replace the character name */ + /* with ".notdef". */ + stream.putline(" {exch}{exch pop /.notdef}ifelse"); + /* stack: CharStrings charname */ + + /* Get the value from the CharStrings dictionary and see */ + /* if it is executable. */ + stream.putline(" get dup xcheck"); + /* stack: CharStrings_entry */ + + /* If is a proceedure. Execute according to RBIIp 277-278. */ + stream.putline(" {currentdict systemdict begin begin exec end end}"); + + /* Is a TrueType character index, let the rasterizer at it. */ + stream.putline(" {TrueDict begin /bander load cvlit exch TrueState render end}"); + + stream.putline(" ifelse"); + + /* Pop the font's dictionary off the stack. */ + stream.putline(" end}bind def"); + + /* This is the level 1 compatibility BuildChar procedure. */ + /* See RBIIp 281. */ + stream.putline(" /BuildChar{"); + stream.putline(" 1 index /Encoding get exch get"); + stream.putline(" 1 index /BuildGlyph get exec"); + stream.putline(" }bind def"); + + /* Here we close the condition which is true */ + /* if the printer has no built-in TrueType */ + /* rasterizer. */ + stream.putline("}if"); + stream.put_char('\n'); + } /* end of if Type 42 not understood. */ + + stream.putline("FontName currentdict end definefont pop"); + /* stream.putline("%%EOF"); */ +} /* end of ttfont_trailer() */ + +/*------------------------------------------------------------------ +** This is the externally callable routine which inserts the font. +------------------------------------------------------------------*/ + +void read_font(const char *filename, font_type_enum target_type, std::vector& glyph_ids, TTFONT& font) +{ + BYTE *ptr; + + /* Decide what type of PostScript font we will be generating. */ + font.target_type = target_type; + + if (font.target_type == PS_TYPE_42) + { + bool has_low = false; + bool has_high = false; + + for (std::vector::const_iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) + { + if (*i > 255) + { + has_high = true; + if (has_low) break; + } + else + { + has_low = true; + if (has_high) break; + } + } + + if (has_high && has_low) + { + font.target_type = PS_TYPE_42_3_HYBRID; + } + else if (has_high && !has_low) + { + font.target_type = PS_TYPE_3; + } + } + + /* Save the file name for error messages. */ + font.filename=filename; + + /* Open the font file */ + if ( (font.file = fopen(filename,"rb")) == (FILE*)NULL ) + { + throw TTException("Failed to open TrueType font"); + } + + /* Allocate space for the unvarying part of the offset table. */ + assert(font.offset_table == NULL); + font.offset_table = (BYTE*)calloc( 12, sizeof(BYTE) ); + + /* Read the first part of the offset table. */ + if ( fread( font.offset_table, sizeof(BYTE), 12, font.file ) != 12 ) + { + throw TTException("TrueType font may be corrupt (reason 1)"); + } + + /* Determine how many directory entries there are. */ + font.numTables = getUSHORT( font.offset_table + 4 ); +#ifdef DEBUG_TRUETYPE + debug("numTables=%d",(int)font.numTables); +#endif + + /* Expand the memory block to hold the whole thing. */ + font.offset_table = (BYTE*)realloc( font.offset_table, sizeof(BYTE) * (12 + font.numTables * 16) ); + + /* Read the rest of the table directory. */ + if ( fread( font.offset_table + 12, sizeof(BYTE), (font.numTables*16), font.file ) != (font.numTables*16) ) + { + throw TTException("TrueType font may be corrupt (reason 2)"); + } + + /* Extract information from the "Offset" table. */ + font.TTVersion = getFixed( font.offset_table ); + + /* Load the "head" table and extract information from it. */ + ptr = GetTable(&font, "head"); + try + { + font.MfrRevision = getFixed( ptr + 4 ); /* font revision number */ + font.unitsPerEm = getUSHORT( ptr + 18 ); + font.HUPM = font.unitsPerEm / 2; +#ifdef DEBUG_TRUETYPE + debug("unitsPerEm=%d",(int)font.unitsPerEm); +#endif + font.llx = topost2( getFWord( ptr + 36 ) ); /* bounding box info */ + font.lly = topost2( getFWord( ptr + 38 ) ); + font.urx = topost2( getFWord( ptr + 40 ) ); + font.ury = topost2( getFWord( ptr + 42 ) ); + font.indexToLocFormat = getSHORT( ptr + 50 ); /* size of 'loca' data */ + if (font.indexToLocFormat != 0 && font.indexToLocFormat != 1) + { + throw TTException("TrueType font is unusable because indexToLocFormat != 0"); + } + if ( getSHORT(ptr+52) != 0 ) + { + throw TTException("TrueType font is unusable because glyphDataFormat != 0"); + } + } + catch (TTException& ) + { + free(ptr); + throw; + } + free(ptr); + + /* Load information from the "name" table. */ + Read_name(&font); + + /* We need to have the PostScript table around. */ + assert(font.post_table == NULL); + font.post_table = GetTable(&font, "post"); + font.numGlyphs = getUSHORT( font.post_table + 32 ); + + /* If we are generating a Type 3 font, we will need to */ + /* have the 'loca' and 'glyf' tables arround while */ + /* we are generating the CharStrings. */ + if (font.target_type == PS_TYPE_3 || font.target_type == PDF_TYPE_3 || + font.target_type == PS_TYPE_42_3_HYBRID) + { + BYTE *ptr; /* We need only one value */ + ptr = GetTable(&font, "hhea"); + font.numberOfHMetrics = getUSHORT(ptr + 34); + free(ptr); + + assert(font.loca_table == NULL); + font.loca_table = GetTable(&font,"loca"); + assert(font.glyf_table == NULL); + font.glyf_table = GetTable(&font,"glyf"); + assert(font.hmtx_table == NULL); + font.hmtx_table = GetTable(&font,"hmtx"); + } + + if (glyph_ids.size() == 0) + { + glyph_ids.clear(); + glyph_ids.reserve(font.numGlyphs); + for (int x = 0; x < font.numGlyphs; ++x) + { + glyph_ids.push_back(x); + } + } + else if (font.target_type == PS_TYPE_3 || + font.target_type == PS_TYPE_42_3_HYBRID) + { + ttfont_add_glyph_dependencies(&font, glyph_ids); + } + +} /* end of insert_ttfont() */ + +void insert_ttfont(const char *filename, TTStreamWriter& stream, + font_type_enum target_type, std::vector& glyph_ids) +{ + struct TTFONT font; + + read_font(filename, target_type, glyph_ids, font); + + /* Write the header for the PostScript font. */ + ttfont_header(stream, &font); + + /* Define the encoding. */ + ttfont_encoding(stream, &font, glyph_ids, target_type); + + /* Insert FontInfo dictionary. */ + ttfont_FontInfo(stream, &font); + + /* If we are generating a type 42 font, */ + /* emmit the sfnts array. */ + if (font.target_type == PS_TYPE_42 || + font.target_type == PS_TYPE_42_3_HYBRID) + { + ttfont_sfnts(stream, &font); + } + + /* Emmit the CharStrings array. */ + ttfont_CharStrings(stream, &font, glyph_ids); + + /* Send the font trailer. */ + ttfont_trailer(stream, &font); + +} /* end of insert_ttfont() */ + +class StringStreamWriter : public TTStreamWriter +{ + std::ostringstream oss; + +public: + void write(const char* a) + { + oss << a; + } + + std::string str() + { + return oss.str(); + } +}; + +void get_pdf_charprocs(const char *filename, std::vector& glyph_ids, TTDictionaryCallback& dict) +{ + struct TTFONT font; + + read_font(filename, PDF_TYPE_3, glyph_ids, font); + + for (std::vector::const_iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) + { + StringStreamWriter writer; + tt_type3_charproc(writer, &font, *i); + const char* name = ttfont_CharStrings_getname(&font, *i); + dict.add_pair(name, writer.str().c_str()); + } +} + +TTFONT::TTFONT() : + file(NULL), + PostName(NULL), + FullName(NULL), + FamilyName(NULL), + Style(NULL), + Copyright(NULL), + Version(NULL), + Trademark(NULL), + offset_table(NULL), + post_table(NULL), + loca_table(NULL), + glyf_table(NULL), + hmtx_table(NULL) +{ + +} + +TTFONT::~TTFONT() +{ + if (file) + { + fclose(file); + } + free(PostName); + free(FullName); + free(FamilyName); + free(Style); + free(Copyright); + free(Version); + free(Trademark); + free(offset_table); + free(post_table); + free(loca_table); + free(glyf_table); + free(hmtx_table); +} + +/* end of file */ diff --git a/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt2.cpp b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt2.cpp new file mode 100644 index 00000000000..058bc005348 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/pprdrv_tt2.cpp @@ -0,0 +1,736 @@ +/* -*- mode: c++; c-basic-offset: 4 -*- */ + +/* + * Modified for use within matplotlib + * 5 July 2007 + * Michael Droettboom + */ + +/* +** ~ppr/src/pprdrv/pprdrv_tt2.c +** Copyright 1995, Trinity College Computing Center. +** Written by David Chappell. +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** TrueType font support. These functions allow PPR to generate +** PostScript fonts from Microsoft compatible TrueType font files. +** +** The functions in this file do most of the work to convert a +** TrueType font to a type 3 PostScript font. +** +** Most of the material in this file is derived from a program called +** "ttf2ps" which L. S. Ng posted to the usenet news group +** "comp.sources.postscript". The author did not provide a copyright +** notice or indicate any restrictions on use. +** +** Last revised 11 July 1995. +*/ + +#include +#include +#include +#include +#include "pprdrv.h" +#include "truetype.h" +#include +#include +#include + +class GlyphToType3 +{ +private: + GlyphToType3& operator=(const GlyphToType3& other); + GlyphToType3(const GlyphToType3& other); + + /* The PostScript bounding box. */ + int llx,lly,urx,ury; + int advance_width; + + /* Variables to hold the character data. */ + int *epts_ctr; /* array of contour endpoints */ + int num_pts, num_ctr; /* number of points, number of coutours */ + FWord *xcoor, *ycoor; /* arrays of x and y coordinates */ + BYTE *tt_flags; /* array of TrueType flags */ + + int stack_depth; /* A book-keeping variable for keeping track of the depth of the PS stack */ + + bool pdf_mode; + + void load_char(TTFONT* font, BYTE *glyph); + void stack(TTStreamWriter& stream, int new_elem); + void stack_end(TTStreamWriter& stream); + void PSConvert(TTStreamWriter& stream); + void PSCurveto(TTStreamWriter& stream, + FWord x0, FWord y0, + FWord x1, FWord y1, + FWord x2, FWord y2); + void PSMoveto(TTStreamWriter& stream, int x, int y); + void PSLineto(TTStreamWriter& stream, int x, int y); + void do_composite(TTStreamWriter& stream, struct TTFONT *font, BYTE *glyph); + +public: + GlyphToType3(TTStreamWriter& stream, struct TTFONT *font, int charindex, bool embedded = false); + ~GlyphToType3(); +}; + +// Each point on a TrueType contour is either on the path or off it (a +// control point); here's a simple representation for building such +// contours. Added by Jouni Seppänen 2012-05-27. +enum Flag { ON_PATH, OFF_PATH }; +struct FlaggedPoint +{ + enum Flag flag; + FWord x; + FWord y; + FlaggedPoint(Flag flag_, FWord x_, FWord y_): flag(flag_), x(x_), y(y_) {}; +}; + +double area(FWord *x, FWord *y, int n); +#define sqr(x) ((x)*(x)) + +#define NOMOREINCTR -1 +#define NOMOREOUTCTR -1 + +/* +** This routine is used to break the character +** procedure up into a number of smaller +** procedures. This is necessary so as not to +** overflow the stack on certain level 1 interpreters. +** +** Prepare to push another item onto the stack, +** starting a new proceedure if necessary. +** +** Not all the stack depth calculations in this routine +** are perfectly accurate, but they do the job. +*/ +void GlyphToType3::stack(TTStreamWriter& stream, int new_elem) +{ + if ( !pdf_mode && num_pts > 25 ) /* Only do something of we will */ + { + /* have a log of points. */ + if (stack_depth == 0) + { + stream.put_char('{'); + stack_depth=1; + } + + stack_depth += new_elem; /* Account for what we propose to add */ + + if (stack_depth > 100) + { + stream.puts("}_e{"); + stack_depth = 3 + new_elem; /* A rough estimate */ + } + } +} /* end of stack() */ + +void GlyphToType3::stack_end(TTStreamWriter& stream) /* called at end */ +{ + if ( !pdf_mode && stack_depth ) + { + stream.puts("}_e"); + stack_depth=0; + } +} /* end of stack_end() */ + +/* +** We call this routine to emmit the PostScript code +** for the character we have loaded with load_char(). +*/ +void GlyphToType3::PSConvert(TTStreamWriter& stream) +{ + int j, k; + + /* Step thru the contours. + * j = index to xcoor, ycoor, tt_flags (point data) + * k = index to epts_ctr (which points belong to the same contour) */ + for(j = k = 0; k < num_ctr; k++) + { + // A TrueType contour consists of on-path and off-path points. + // Two consecutive on-path points are to be joined with a + // line; off-path points between on-path points indicate a + // quadratic spline, where the off-path point is the control + // point. Two consecutive off-path points have an implicit + // on-path point midway between them. + std::list points; + + // Represent flags and x/y coordinates as a C++ list + for (; j <= epts_ctr[k]; j++) + { + if (!(tt_flags[j] & 1)) { + points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j])); + } else { + points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j])); + } + } + + if (points.size() == 0) { + // Don't try to access the last element of an empty list + continue; + } + + // For any two consecutive off-path points, insert the implied + // on-path point. + FlaggedPoint prev = points.back(); + for (std::list::iterator it = points.begin(); + it != points.end(); + it++) + { + if (prev.flag == OFF_PATH && it->flag == OFF_PATH) + { + points.insert(it, + FlaggedPoint(ON_PATH, + (prev.x + it->x) / 2, + (prev.y + it->y) / 2)); + } + prev = *it; + } + // Handle the wrap-around: insert a point either at the beginning + // or at the end that has the same coordinates as the opposite point. + // This also ensures that the initial point is ON_PATH. + if (points.front().flag == OFF_PATH) + { + assert(points.back().flag == ON_PATH); + points.insert(points.begin(), points.back()); + } + else + { + assert(points.front().flag == ON_PATH); + points.push_back(points.front()); + } + + // The first point + stack(stream, 3); + PSMoveto(stream, points.front().x, points.front().y); + + // Step through the remaining points + std::list::const_iterator it = points.begin(); + for (it++; it != points.end(); /* incremented inside */) + { + const FlaggedPoint& point = *it; + if (point.flag == ON_PATH) + { + stack(stream, 3); + PSLineto(stream, point.x, point.y); + it++; + } else { + std::list::const_iterator prev = it, next = it; + prev--; + next++; + assert(prev->flag == ON_PATH); + assert(next->flag == ON_PATH); + stack(stream, 7); + PSCurveto(stream, + prev->x, prev->y, + point.x, point.y, + next->x, next->y); + it++; + it++; + } + } + } + + /* Now, we can fill the whole thing. */ + stack(stream, 1); + stream.puts( pdf_mode ? "f" : "_cl" ); +} /* end of PSConvert() */ + +void GlyphToType3::PSMoveto(TTStreamWriter& stream, int x, int y) +{ + stream.printf(pdf_mode ? "%d %d m\n" : "%d %d _m\n", + x, y); +} + +void GlyphToType3::PSLineto(TTStreamWriter& stream, int x, int y) +{ + stream.printf(pdf_mode ? "%d %d l\n" : "%d %d _l\n", + x, y); +} + +/* +** Emit a PostScript "curveto" command, assuming the current point +** is (x0, y0), the control point of a quadratic spline is (x1, y1), +** and the endpoint is (x2, y2). Note that this requires a conversion, +** since PostScript splines are cubic. +*/ +void GlyphToType3::PSCurveto(TTStreamWriter& stream, + FWord x0, FWord y0, + FWord x1, FWord y1, + FWord x2, FWord y2) +{ + double sx[3], sy[3], cx[3], cy[3]; + + sx[0] = x0; + sy[0] = y0; + sx[1] = x1; + sy[1] = y1; + sx[2] = x2; + sy[2] = y2; + cx[0] = (2*sx[1]+sx[0])/3; + cy[0] = (2*sy[1]+sy[0])/3; + cx[1] = (sx[2]+2*sx[1])/3; + cy[1] = (sy[2]+2*sy[1])/3; + cx[2] = sx[2]; + cy[2] = sy[2]; + stream.printf("%d %d %d %d %d %d %s\n", + (int)cx[0], (int)cy[0], (int)cx[1], (int)cy[1], + (int)cx[2], (int)cy[2], pdf_mode ? "c" : "_c"); +} + +/* +** Deallocate the structures which stored +** the data for the last simple glyph. +*/ +GlyphToType3::~GlyphToType3() +{ + free(tt_flags); /* The flags array */ + free(xcoor); /* The X coordinates */ + free(ycoor); /* The Y coordinates */ + free(epts_ctr); /* The array of contour endpoints */ +} + +/* +** Load the simple glyph data pointed to by glyph. +** The pointer "glyph" should point 10 bytes into +** the glyph data. +*/ +void GlyphToType3::load_char(TTFONT* font, BYTE *glyph) +{ + int x; + BYTE c, ct; + + /* Read the contour endpoints list. */ + epts_ctr = (int *)calloc(num_ctr,sizeof(int)); + for (x = 0; x < num_ctr; x++) + { + epts_ctr[x] = getUSHORT(glyph); + glyph += 2; + } + + /* From the endpoint of the last contour, we can */ + /* determine the number of points. */ + num_pts = epts_ctr[num_ctr-1]+1; +#ifdef DEBUG_TRUETYPE + debug("num_pts=%d",num_pts); + stream.printf("%% num_pts=%d\n",num_pts); +#endif + + /* Skip the instructions. */ + x = getUSHORT(glyph); + glyph += 2; + glyph += x; + + /* Allocate space to hold the data. */ + tt_flags = (BYTE *)calloc(num_pts,sizeof(BYTE)); + xcoor = (FWord *)calloc(num_pts,sizeof(FWord)); + ycoor = (FWord *)calloc(num_pts,sizeof(FWord)); + + /* Read the flags array, uncompressing it as we go. */ + /* There is danger of overflow here. */ + for (x = 0; x < num_pts; ) + { + tt_flags[x++] = c = *(glyph++); + + if (c&8) /* If next byte is repeat count, */ + { + ct = *(glyph++); + + if ( (x + ct) > num_pts ) + { + throw TTException("Error in TT flags"); + } + + while (ct--) + { + tt_flags[x++] = c; + } + } + } + + /* Read the x coordinates */ + for (x = 0; x < num_pts; x++) + { + if (tt_flags[x] & 2) /* one byte value with */ + { + /* external sign */ + c = *(glyph++); + xcoor[x] = (tt_flags[x] & 0x10) ? c : (-1 * (int)c); + } + else if (tt_flags[x] & 0x10) /* repeat last */ + { + xcoor[x] = 0; + } + else /* two byte signed value */ + { + xcoor[x] = getFWord(glyph); + glyph+=2; + } + } + + /* Read the y coordinates */ + for (x = 0; x < num_pts; x++) + { + if (tt_flags[x] & 4) /* one byte value with */ + { + /* external sign */ + c = *(glyph++); + ycoor[x] = (tt_flags[x] & 0x20) ? c : (-1 * (int)c); + } + else if (tt_flags[x] & 0x20) /* repeat last value */ + { + ycoor[x] = 0; + } + else /* two byte signed value */ + { + ycoor[x] = getUSHORT(glyph); + glyph+=2; + } + } + + /* Convert delta values to absolute values. */ + for (x = 1; x < num_pts; x++) + { + xcoor[x] += xcoor[x-1]; + ycoor[x] += ycoor[x-1]; + } + + for (x=0; x < num_pts; x++) + { + xcoor[x] = topost(xcoor[x]); + ycoor[x] = topost(ycoor[x]); + } + +} /* end of load_char() */ + +/* +** Emmit PostScript code for a composite character. +*/ +void GlyphToType3::do_composite(TTStreamWriter& stream, struct TTFONT *font, BYTE *glyph) +{ + USHORT flags; + USHORT glyphIndex; + int arg1; + int arg2; + + /* Once around this loop for each component. */ + do + { + flags = getUSHORT(glyph); /* read the flags word */ + glyph += 2; + + glyphIndex = getUSHORT(glyph); /* read the glyphindex word */ + glyph += 2; + + if (flags & ARG_1_AND_2_ARE_WORDS) + { + /* The tt spec. seems to say these are signed. */ + arg1 = getSHORT(glyph); + glyph += 2; + arg2 = getSHORT(glyph); + glyph += 2; + } + else /* The tt spec. does not clearly indicate */ + { + /* whether these values are signed or not. */ + arg1 = *(signed char *)(glyph++); + arg2 = *(signed char *)(glyph++); + } + + if (flags & WE_HAVE_A_SCALE) + { + glyph += 2; + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + glyph += 4; + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + glyph += 8; + } + else + { + } + + /* Debugging */ +#ifdef DEBUG_TRUETYPE + stream.printf("%% flags=%d, arg1=%d, arg2=%d\n", + (int)flags,arg1,arg2); +#endif + + if (pdf_mode) + { + if ( flags & ARGS_ARE_XY_VALUES ) + { + /* We should have been able to use 'Do' to reference the + subglyph here. However, that doesn't seem to work with + xpdf or gs (only acrobat), so instead, this just includes + the subglyph here inline. */ + stream.printf("q 1 0 0 1 %d %d cm\n", topost(arg1), topost(arg2)); + } + else + { + stream.printf("%% unimplemented shift, arg1=%d, arg2=%d\n",arg1,arg2); + } + GlyphToType3(stream, font, glyphIndex, true); + if ( flags & ARGS_ARE_XY_VALUES ) + { + stream.printf("\nQ\n"); + } + } + else + { + /* If we have an (X,Y) shif and it is non-zero, */ + /* translate the coordinate system. */ + if ( flags & ARGS_ARE_XY_VALUES ) + { + if ( arg1 != 0 || arg2 != 0 ) + stream.printf("gsave %d %d translate\n", topost(arg1), topost(arg2) ); + } + else + { + stream.printf("%% unimplemented shift, arg1=%d, arg2=%d\n",arg1,arg2); + } + + /* Invoke the CharStrings procedure to print the component. */ + stream.printf("false CharStrings /%s get exec\n", + ttfont_CharStrings_getname(font,glyphIndex)); + + /* If we translated the coordinate system, */ + /* put it back the way it was. */ + if ( flags & ARGS_ARE_XY_VALUES && (arg1 != 0 || arg2 != 0) ) + { + stream.puts("grestore "); + } + } + + } + while (flags & MORE_COMPONENTS); + +} /* end of do_composite() */ + +/* +** Return a pointer to a specific glyph's data. +*/ +BYTE *find_glyph_data(struct TTFONT *font, int charindex) +{ + ULONG off; + ULONG length; + + /* Read the glyph offset from the index to location table. */ + if (font->indexToLocFormat == 0) + { + off = getUSHORT( font->loca_table + (charindex * 2) ); + off *= 2; + length = getUSHORT( font->loca_table + ((charindex+1) * 2) ); + length *= 2; + length -= off; + } + else + { + off = getULONG( font->loca_table + (charindex * 4) ); + length = getULONG( font->loca_table + ((charindex+1) * 4) ); + length -= off; + } + + if (length > 0) + { + return font->glyf_table + off; + } + else + { + return (BYTE*)NULL; + } + +} /* end of find_glyph_data() */ + +GlyphToType3::GlyphToType3(TTStreamWriter& stream, struct TTFONT *font, int charindex, bool embedded /* = false */) +{ + BYTE *glyph; + + tt_flags = NULL; + xcoor = NULL; + ycoor = NULL; + epts_ctr = NULL; + stack_depth = 0; + pdf_mode = font->target_type < 0; + + /* Get a pointer to the data. */ + glyph = find_glyph_data( font, charindex ); + + /* If the character is blank, it has no bounding box, */ + /* otherwise read the bounding box. */ + if ( glyph == (BYTE*)NULL ) + { + llx=lly=urx=ury=0; /* A blank char has an all zero BoundingBox */ + num_ctr=0; /* Set this for later if()s */ + } + else + { + /* Read the number of contours. */ + num_ctr = getSHORT(glyph); + + /* Read PostScript bounding box. */ + llx = getFWord(glyph + 2); + lly = getFWord(glyph + 4); + urx = getFWord(glyph + 6); + ury = getFWord(glyph + 8); + + /* Advance the pointer. */ + glyph += 10; + } + + /* If it is a simple character, load its data. */ + if (num_ctr > 0) + { + load_char(font, glyph); + } + else + { + num_pts=0; + } + + /* Consult the horizontal metrics table to determine */ + /* the character width. */ + if ( charindex < font->numberOfHMetrics ) + { + advance_width = getuFWord( font->hmtx_table + (charindex * 4) ); + } + else + { + advance_width = getuFWord( font->hmtx_table + ((font->numberOfHMetrics-1) * 4) ); + } + + /* Execute setcachedevice in order to inform the font machinery */ + /* of the character bounding box and advance width. */ + stack(stream, 7); + if (pdf_mode) + { + if (!embedded) { + stream.printf("%d 0 %d %d %d %d d1\n", + topost(advance_width), + topost(llx), topost(lly), topost(urx), topost(ury) ); + } + } + else if (font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.printf("pop gsave .001 .001 scale %d 0 %d %d %d %d setcachedevice\n", + topost(advance_width), + topost(llx), topost(lly), topost(urx), topost(ury) ); + } + else + { + stream.printf("%d 0 %d %d %d %d _sc\n", + topost(advance_width), + topost(llx), topost(lly), topost(urx), topost(ury) ); + } + + /* If it is a simple glyph, convert it, */ + /* otherwise, close the stack business. */ + if ( num_ctr > 0 ) /* simple */ + { + PSConvert(stream); + } + else if ( num_ctr < 0 ) /* composite */ + { + do_composite(stream, font, glyph); + } + + if (font->target_type == PS_TYPE_42_3_HYBRID) + { + stream.printf("\ngrestore\n"); + } + + stack_end(stream); +} + +/* +** This is the routine which is called from pprdrv_tt.c. +*/ +void tt_type3_charproc(TTStreamWriter& stream, struct TTFONT *font, int charindex) +{ + GlyphToType3 glyph(stream, font, charindex); +} /* end of tt_type3_charproc() */ + +/* +** Some of the given glyph ids may refer to composite glyphs. +** This function adds all of the dependencies of those composite +** glyphs to the glyph id vector. Michael Droettboom [06-07-07] +*/ +void ttfont_add_glyph_dependencies(struct TTFONT *font, std::vector& glyph_ids) +{ + std::sort(glyph_ids.begin(), glyph_ids.end()); + + std::stack glyph_stack; + for (std::vector::iterator i = glyph_ids.begin(); + i != glyph_ids.end(); ++i) + { + glyph_stack.push(*i); + } + + while (glyph_stack.size()) + { + int gind = glyph_stack.top(); + glyph_stack.pop(); + + BYTE* glyph = find_glyph_data( font, gind ); + if (glyph != (BYTE*)NULL) + { + + int num_ctr = getSHORT(glyph); + if (num_ctr <= 0) // This is a composite glyph + { + + glyph += 10; + USHORT flags = 0; + + do + { + flags = getUSHORT(glyph); + glyph += 2; + gind = (int)getUSHORT(glyph); + glyph += 2; + + std::vector::iterator insertion = + std::lower_bound(glyph_ids.begin(), glyph_ids.end(), gind); + if (insertion == glyph_ids.end() || *insertion != gind) + { + glyph_ids.insert(insertion, gind); + glyph_stack.push(gind); + } + + if (flags & ARG_1_AND_2_ARE_WORDS) + { + glyph += 4; + } + else + { + glyph += 2; + } + + if (flags & WE_HAVE_A_SCALE) + { + glyph += 2; + } + else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) + { + glyph += 4; + } + else if (flags & WE_HAVE_A_TWO_BY_TWO) + { + glyph += 8; + } + } + while (flags & MORE_COMPONENTS); + } + } + } +} + +/* end of file */ diff --git a/contrib/python/matplotlib/py2/extern/ttconv/truetype.h b/contrib/python/matplotlib/py2/extern/ttconv/truetype.h new file mode 100644 index 00000000000..86be14fe370 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/truetype.h @@ -0,0 +1,129 @@ +/* -*- mode: c; c-basic-offset: 4 -*- */ + +/* + * Modified for use within matplotlib + * 5 July 2007 + * Michael Droettboom + */ + +#include + +/* +** ~ppr/src/include/typetype.h +** +** Permission to use, copy, modify, and distribute this software and its +** documentation for any purpose and without fee is hereby granted, provided +** that the above copyright notice appear in all copies and that both that +** copyright notice and this permission notice appear in supporting +** documentation. This software is provided "as is" without express or +** implied warranty. +** +** This include file is shared by the source files +** "pprdrv/pprdrv_tt.c" and "pprdrv/pprdrv_tt2.c". +** +** Last modified 19 April 1995. +*/ + +/* Types used in TrueType font files. */ +#define BYTE unsigned char +#define USHORT unsigned short int +#define SHORT short signed int +#define ULONG unsigned int +#define FIXED long signed int +#define FWord short signed int +#define uFWord short unsigned int + +/* This structure stores a 16.16 bit fixed */ +/* point number. */ +typedef struct + { + short int whole; + unsigned short int fraction; + } Fixed; + +/* This structure tells what we have found out about */ +/* the current font. */ +struct TTFONT + { + // A quick-and-dirty way to create a minimum level of exception safety + // Added by Michael Droettboom + TTFONT(); + ~TTFONT(); + + const char *filename; /* Name of TT file */ + FILE *file; /* the open TT file */ + font_type_enum target_type; /* 42 or 3 for PS, or -3 for PDF */ + + ULONG numTables; /* number of tables present */ + char *PostName; /* Font's PostScript name */ + char *FullName; /* Font's full name */ + char *FamilyName; /* Font's family name */ + char *Style; /* Font's style string */ + char *Copyright; /* Font's copyright string */ + char *Version; /* Font's version string */ + char *Trademark; /* Font's trademark string */ + int llx,lly,urx,ury; /* bounding box */ + + Fixed TTVersion; /* Truetype version number from offset table */ + Fixed MfrRevision; /* Revision number of this font */ + + BYTE *offset_table; /* Offset table in memory */ + BYTE *post_table; /* 'post' table in memory */ + + BYTE *loca_table; /* 'loca' table in memory */ + BYTE *glyf_table; /* 'glyf' table in memory */ + BYTE *hmtx_table; /* 'hmtx' table in memory */ + + USHORT numberOfHMetrics; + int unitsPerEm; /* unitsPerEm converted to int */ + int HUPM; /* half of above */ + + int numGlyphs; /* from 'post' table */ + + int indexToLocFormat; /* short or long offsets */ +}; + +ULONG getULONG(BYTE *p); +USHORT getUSHORT(BYTE *p); +Fixed getFixed(BYTE *p); + +/* +** Get an funits word. +** since it is 16 bits long, we can +** use getUSHORT() to do the real work. +*/ +#define getFWord(x) (FWord)getUSHORT(x) +#define getuFWord(x) (uFWord)getUSHORT(x) + +/* +** We can get a SHORT by making USHORT signed. +*/ +#define getSHORT(x) (SHORT)getUSHORT(x) + +/* This is the one routine in pprdrv_tt.c that is */ +/* called from pprdrv_tt.c. */ +const char *ttfont_CharStrings_getname(struct TTFONT *font, int charindex); + +void tt_type3_charproc(TTStreamWriter& stream, struct TTFONT *font, int charindex); + +/* Added 06-07-07 Michael Droettboom */ +void ttfont_add_glyph_dependencies(struct TTFONT *font, std::vector& glypy_ids); + +/* This routine converts a number in the font's character coordinate */ +/* system to a number in a 1000 unit character system. */ +#define topost(x) (int)( ((int)(x) * 1000 + font->HUPM) / font->unitsPerEm ) +#define topost2(x) (int)( ((int)(x) * 1000 + font.HUPM) / font.unitsPerEm ) + +/* Composite glyph values. */ +#define ARG_1_AND_2_ARE_WORDS 1 +#define ARGS_ARE_XY_VALUES 2 +#define ROUND_XY_TO_GRID 4 +#define WE_HAVE_A_SCALE 8 +/* RESERVED 16 */ +#define MORE_COMPONENTS 32 +#define WE_HAVE_AN_X_AND_Y_SCALE 64 +#define WE_HAVE_A_TWO_BY_TWO 128 +#define WE_HAVE_INSTRUCTIONS 256 +#define USE_MY_METRICS 512 + +/* end of file */ diff --git a/contrib/python/matplotlib/py2/extern/ttconv/ttutil.cpp b/contrib/python/matplotlib/py2/extern/ttconv/ttutil.cpp new file mode 100644 index 00000000000..85e7e23c4f0 --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/ttutil.cpp @@ -0,0 +1,82 @@ +/* -*- mode: c++; c-basic-offset: 4 -*- */ + +/* + * Modified for use within matplotlib + * 5 July 2007 + * Michael Droettboom + */ + +/* Very simple interface to the ppr TT routines */ +/* (c) Frank Siegert 1996 */ + +#include +#include +#include +#include "pprdrv.h" + +#if DEBUG_TRUETYPE +void debug(const char *format, ... ) +{ + va_list arg_list; + va_start(arg_list, format); + + printf(format, arg_list); + + va_end(arg_list); +} +#endif + +#define PRINTF_BUFFER_SIZE 512 +void TTStreamWriter::printf(const char* format, ...) +{ + va_list arg_list; + va_start(arg_list, format); + char buffer[PRINTF_BUFFER_SIZE]; + +#if defined(WIN32) || defined(_MSC_VER) + int size = _vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list); +#else + int size = vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list); +#endif + if (size >= PRINTF_BUFFER_SIZE) { + char* buffer2 = (char*)malloc(size); +#if defined(WIN32) || defined(_MSC_VER) + _vsnprintf(buffer2, size, format, arg_list); +#else + vsnprintf(buffer2, size, format, arg_list); +#endif + free(buffer2); + } else { + this->write(buffer); + } + + va_end(arg_list); +} + +void TTStreamWriter::put_char(int val) +{ + char c[2]; + c[0] = (char)val; + c[1] = 0; + this->write(c); +} + +void TTStreamWriter::puts(const char *a) +{ + this->write(a); +} + +void TTStreamWriter::putline(const char *a) +{ + this->write(a); + this->write("\n"); +} + +void replace_newlines_with_spaces(char *a) { + char* i = a; + while (*i != 0) { + if (*i == '\r' || *i == '\n') + *i = ' '; + i++; + } +} diff --git a/contrib/python/matplotlib/py2/extern/ttconv/ya.make b/contrib/python/matplotlib/py2/extern/ttconv/ya.make new file mode 100644 index 00000000000..c36ec960b9c --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ttconv/ya.make @@ -0,0 +1,15 @@ +PY23_LIBRARY() + +VERSION(2.2.5) + +LICENSE(PSF-2.0) + +NO_WSHADOW() + +SRCS( + pprdrv_tt.cpp + pprdrv_tt2.cpp + ttutil.cpp +) + +END() diff --git a/contrib/python/matplotlib/py2/extern/ya.make b/contrib/python/matplotlib/py2/extern/ya.make new file mode 100644 index 00000000000..ef8acb58eaa --- /dev/null +++ b/contrib/python/matplotlib/py2/extern/ya.make @@ -0,0 +1,4 @@ +RECURSE( + agg24-svn + ttconv +) diff --git a/contrib/python/matplotlib/py2/matplotlib/__init__.py b/contrib/python/matplotlib/py2/matplotlib/__init__.py new file mode 100644 index 00000000000..506f634d4d6 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/__init__.py @@ -0,0 +1,1928 @@ +""" +This is an object-oriented plotting library. + +A procedural interface is provided by the companion pyplot module, +which may be imported directly, e.g.:: + + import matplotlib.pyplot as plt + +or using ipython:: + + ipython + +at your terminal, followed by:: + + In [1]: %matplotlib + In [2]: import matplotlib.pyplot as plt + +at the ipython shell prompt. + +For the most part, direct use of the object-oriented library is +encouraged when programming; pyplot is primarily for working +interactively. The +exceptions are the pyplot commands :func:`~matplotlib.pyplot.figure`, +:func:`~matplotlib.pyplot.subplot`, +:func:`~matplotlib.pyplot.subplots`, and +:func:`~pyplot.savefig`, which can greatly simplify scripting. + +Modules include: + + :mod:`matplotlib.axes` + defines the :class:`~matplotlib.axes.Axes` class. Most pylab + commands are wrappers for :class:`~matplotlib.axes.Axes` + methods. The axes module is the highest level of OO access to + the library. + + :mod:`matplotlib.figure` + defines the :class:`~matplotlib.figure.Figure` class. + + :mod:`matplotlib.artist` + defines the :class:`~matplotlib.artist.Artist` base class for + all classes that draw things. + + :mod:`matplotlib.lines` + defines the :class:`~matplotlib.lines.Line2D` class for + drawing lines and markers + + :mod:`matplotlib.patches` + defines classes for drawing polygons + + :mod:`matplotlib.text` + defines the :class:`~matplotlib.text.Text`, + :class:`~matplotlib.text.TextWithDash`, and + :class:`~matplotlib.text.Annotate` classes + + :mod:`matplotlib.image` + defines the :class:`~matplotlib.image.AxesImage` and + :class:`~matplotlib.image.FigureImage` classes + + :mod:`matplotlib.collections` + classes for efficient drawing of groups of lines or polygons + + :mod:`matplotlib.colors` + classes for interpreting color specifications and for making + colormaps + + :mod:`matplotlib.cm` + colormaps and the :class:`~matplotlib.image.ScalarMappable` + mixin class for providing color mapping functionality to other + classes + + :mod:`matplotlib.ticker` + classes for calculating tick mark locations and for formatting + tick labels + + :mod:`matplotlib.backends` + a subpackage with modules for various gui libraries and output + formats + +The base matplotlib namespace includes: + + :data:`~matplotlib.rcParams` + a global dictionary of default configuration settings. It is + initialized by code which may be overridden by a matplotlibrc + file. + + :func:`~matplotlib.rc` + a function for setting groups of rcParams values + + :func:`~matplotlib.use` + a function for setting the matplotlib backend. If used, this + function must be called immediately after importing matplotlib + for the first time. In particular, it must be called + **before** importing pylab (if pylab is imported). + +matplotlib was initially written by John D. Hunter (1968-2012) and is now +developed and maintained by a host of others. + +Occasionally the internal documentation (python docstrings) will refer +to MATLAB®, a registered trademark of The MathWorks, Inc. + +""" +from __future__ import absolute_import, division, print_function + +import six + +import atexit +try: + from collections.abc import MutableMapping +except ImportError: + from collections import MutableMapping +import contextlib +import distutils.version +import functools +import io +import inspect +import itertools +import locale +import logging +import os +import re +import shutil +import stat +import sys +import tempfile +import warnings + +# cbook must import matplotlib only within function +# definitions, so it is safe to import from it here. +from . import cbook +from matplotlib.cbook import ( + _backports, mplDeprecation, dedent, get_label, sanitize_sequence) +from matplotlib.compat import subprocess +from matplotlib.rcsetup import defaultParams, validate_backend, cycler + +import numpy +from six.moves.urllib.request import urlopen +from six.moves import reload_module as reload + +# Get the version from the _version.py versioneer file. For a git checkout, +# this is computed based on the number of commits since the last tag. +from ._version import get_versions +__version__ = str(get_versions()['version']) +del get_versions + +_log = logging.getLogger(__name__) + +__version__numpy__ = str('1.7.1') # minimum required numpy version + +__bibtex__ = r"""@Article{Hunter:2007, + Author = {Hunter, J. D.}, + Title = {Matplotlib: A 2D graphics environment}, + Journal = {Computing In Science \& Engineering}, + Volume = {9}, + Number = {3}, + Pages = {90--95}, + abstract = {Matplotlib is a 2D graphics package used for Python + for application development, interactive scripting, and + publication-quality image generation across user + interfaces and operating systems.}, + publisher = {IEEE COMPUTER SOC}, + year = 2007 +}""" + + +_python27 = (sys.version_info.major == 2 and sys.version_info.minor >= 7) +_python34 = (sys.version_info.major == 3 and sys.version_info.minor >= 4) +if not (_python27 or _python34): + raise ImportError("Matplotlib requires Python 2.7 or 3.4 or later") + +if _python27: + _log.addHandler(logging.NullHandler()) + + +def compare_versions(a, b): + "return True if a is greater than or equal to b" + if a: + if six.PY3: + if isinstance(a, bytes): + a = a.decode('ascii') + if isinstance(b, bytes): + b = b.decode('ascii') + a = distutils.version.LooseVersion(a) + b = distutils.version.LooseVersion(b) + return a >= b + else: + return False + + +try: + import dateutil +except ImportError: + raise ImportError("Matplotlib requires dateutil") + + +if not compare_versions(six.__version__, '1.10'): + raise ImportError( + "Matplotlib requires six>=1.10; you have %s" % six.__version__) + + +try: + import pyparsing +except ImportError: + raise ImportError("Matplotlib requires pyparsing") +else: + if not compare_versions(pyparsing.__version__, '2.0.1'): + raise ImportError( + "Matplotlib requires pyparsing>=2.0.1; you have %s" + % pyparsing.__version__) + + +if not compare_versions(numpy.__version__, __version__numpy__): + raise ImportError( + "Matplotlib requires numpy>=%s; you have %s" % ( + __version__numpy__, numpy.__version__)) + + +if not hasattr(sys, 'argv'): # for modpython + sys.argv = [str('modpython')] + + +def _is_writable_dir(p): + """ + p is a string pointing to a putative writable dir -- return True p + is such a string, else False + """ + return os.access(p, os.W_OK) and os.path.isdir(p) + +_verbose_msg = """\ +matplotlib.verbose is deprecated; +Command line argument --verbose-LEVEL is deprecated. +This functionality is now provided by the standard +python logging library. To get more (or less) logging output: + import logging + logger = logging.getLogger('matplotlib') + logger.set_level(logging.INFO)""" + + +def _set_logger_verbose_level(level_str='silent', file_str='sys.stdout'): + """ + Use a --verbose-LEVEL level to set the logging level: + + """ + levelmap = {'silent': logging.WARNING, 'helpful': logging.INFO, + 'debug': logging.DEBUG, 'debug-annoying': logging.DEBUG, + 'info': logging.INFO, 'warning': logging.WARNING} + # Check that current state of logger isn't already more verbose + # than the requested level. If it is more verbose, then leave more + # verbose. + newlev = levelmap[level_str] + oldlev = _log.getEffectiveLevel() + if newlev < oldlev: + _log.setLevel(newlev) + std = { + 'sys.stdout': sys.stdout, + 'sys.stderr': sys.stderr, + } + if file_str in std: + fileo = std[file_str] + else: + fileo = sys.stdout + try: + fileo = open(file_str, 'w') + # if this fails, we will just write to stdout + except IOError: + warnings.warn('could not open log file "{0}"' + 'for writing. Check your ' + 'matplotlibrc'.format(file_str)) + console = logging.StreamHandler(fileo) + console.setLevel(newlev) + _log.addHandler(console) + + +def _parse_commandline(): + """ + Check for --verbose-LEVEL type command line arguments and + set logging level appropriately. + """ + + levels = ('silent', 'helpful', 'debug', 'debug-annoying', + 'info', 'warning') + + for arg in sys.argv[1:]: + if arg.startswith('--verbose-'): + level_str = arg[10:] + # If it doesn't match one of ours, then don't even + # bother noting it, we are just a 3rd-party library + # to somebody else's script. + if level_str in levels: + _set_logger_verbose_level(level_str) + +_parse_commandline() + + +class Verbose(object): + """ + A class to handle reporting. Set the fileo attribute to any file + instance to handle the output. Default is sys.stdout + """ + levels = ('silent', 'helpful', 'debug', 'debug-annoying') + vald = {level: i for i, level in enumerate(levels)} + + # parse the verbosity from the command line; flags look like + # --verbose-silent or --verbose-helpful + _commandLineVerbose = None + + for arg in sys.argv[1:]: + if not arg.startswith('--verbose-'): + continue + level_str = arg[10:] + # If it doesn't match one of ours, then don't even + # bother noting it, we are just a 3rd-party library + # to somebody else's script. + if level_str in levels: + _commandLineVerbose = level_str + + @cbook.deprecated("2.2", message=_verbose_msg) + def __init__(self): + self.set_level('silent') + self.fileo = sys.stdout + + @cbook.deprecated("2.2", message=_verbose_msg) + def set_level(self, level): + 'set the verbosity to one of the Verbose.levels strings' + + if self._commandLineVerbose is not None: + level = self._commandLineVerbose + if level not in self.levels: + warnings.warn('matplotlib: unrecognized --verbose-* string "%s".' + ' Legal values are %s' % (level, self.levels)) + else: + self.level = level + + @cbook.deprecated("2.2", message=_verbose_msg) + def set_fileo(self, fname): + std = { + 'sys.stdout': sys.stdout, + 'sys.stderr': sys.stderr, + } + if fname in std: + self.fileo = std[fname] + else: + try: + fileo = open(fname, 'w') + except IOError: + raise ValueError('Verbose object could not open log file "{0}"' + ' for writing.\nCheck your matplotlibrc ' + 'verbose.fileo setting'.format(fname)) + else: + self.fileo = fileo + + @cbook.deprecated("2.2", message=_verbose_msg) + def report(self, s, level='helpful'): + """ + print message s to self.fileo if self.level>=level. Return + value indicates whether a message was issued + + """ + if self.ge(level): + print(s, file=self.fileo) + return True + return False + + @cbook.deprecated("2.2", message=_verbose_msg) + def wrap(self, fmt, func, level='helpful', always=True): + """ + return a callable function that wraps func and reports it + output through the verbose handler if current verbosity level + is higher than level + + if always is True, the report will occur on every function + call; otherwise only on the first time the function is called + """ + assert callable(func) + + def wrapper(*args, **kwargs): + ret = func(*args, **kwargs) + + if (always or not wrapper._spoke): + spoke = self.report(fmt % ret, level) + if not wrapper._spoke: + wrapper._spoke = spoke + return ret + wrapper._spoke = False + wrapper.__doc__ = func.__doc__ + return wrapper + + @cbook.deprecated("2.2", message=_verbose_msg) + def ge(self, level): + 'return true if self.level is >= level' + return self.vald[self.level] >= self.vald[level] + + +with warnings.catch_warnings(): + warnings.simplefilter("ignore") + verbose = Verbose() + + +def _wrap(fmt, func, level=logging.DEBUG, always=True): + """ + return a callable function that wraps func and reports its + output through logger + + if always is True, the report will occur on every function + call; otherwise only on the first time the function is called + """ + assert callable(func) + + def wrapper(*args, **kwargs): + ret = func(*args, **kwargs) + + if (always or not wrapper._spoke): + _log.log(level, fmt % ret) + spoke = True + if not wrapper._spoke: + wrapper._spoke = spoke + return ret + wrapper._spoke = False + wrapper.__doc__ = func.__doc__ + return wrapper + + +def checkdep_dvipng(): + try: + s = subprocess.Popen([str('dvipng'), '-version'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + line = stdout.decode('ascii').split('\n')[1] + v = line.split()[-1] + return v + except (IndexError, ValueError, OSError): + return None + + +def checkdep_ghostscript(): + if checkdep_ghostscript.executable is None: + if sys.platform == 'win32': + # mgs is the name in miktex + gs_execs = ['gswin32c', 'gswin64c', 'mgs', 'gs'] + else: + gs_execs = ['gs'] + for gs_exec in gs_execs: + try: + s = subprocess.Popen( + [str(gs_exec), '--version'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + if s.returncode == 0: + v = stdout[:-1].decode('ascii') + checkdep_ghostscript.executable = gs_exec + checkdep_ghostscript.version = v + except (IndexError, ValueError, OSError): + pass + return checkdep_ghostscript.executable, checkdep_ghostscript.version +checkdep_ghostscript.executable = None +checkdep_ghostscript.version = None + + +# Deprecated, as it is unneeded and some distributions (e.g. MiKTeX 2.9.6350) +# do not actually report the TeX version. +@cbook.deprecated("2.1") +def checkdep_tex(): + try: + s = subprocess.Popen([str('tex'), '-version'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + line = stdout.decode('ascii').split('\n')[0] + pattern = r'3\.1\d+' + match = re.search(pattern, line) + v = match.group(0) + return v + except (IndexError, ValueError, AttributeError, OSError): + return None + + +def checkdep_pdftops(): + try: + s = subprocess.Popen([str('pdftops'), '-v'], stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + lines = stderr.decode('ascii').split('\n') + for line in lines: + if 'version' in line: + v = line.split()[-1] + return v + except (IndexError, ValueError, UnboundLocalError, OSError): + return None + + +def checkdep_inkscape(): + if checkdep_inkscape.version is None: + try: + s = subprocess.Popen([str('inkscape'), '-V'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + lines = stdout.decode('ascii').split('\n') + for line in lines: + if 'Inkscape' in line: + v = line.split()[1] + break + checkdep_inkscape.version = v + except (IndexError, ValueError, UnboundLocalError, OSError): + pass + return checkdep_inkscape.version +checkdep_inkscape.version = None + + +@cbook.deprecated("2.1") +def checkdep_xmllint(): + try: + s = subprocess.Popen([str('xmllint'), '--version'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = s.communicate() + lines = stderr.decode('ascii').split('\n') + for line in lines: + if 'version' in line: + v = line.split()[-1] + break + return v + except (IndexError, ValueError, UnboundLocalError, OSError): + return None + + +def checkdep_ps_distiller(s): + if not s: + return False + + flag = True + gs_req = '8.60' + gs_exec, gs_v = checkdep_ghostscript() + if not compare_versions(gs_v, gs_req): + flag = False + warnings.warn(('matplotlibrc ps.usedistiller option can not be used ' + 'unless ghostscript-%s or later is installed on your ' + 'system') % gs_req) + + if s == 'xpdf': + pdftops_req = '3.0' + pdftops_req_alt = '0.9' # poppler version numbers, ugh + pdftops_v = checkdep_pdftops() + if compare_versions(pdftops_v, pdftops_req): + pass + elif (compare_versions(pdftops_v, pdftops_req_alt) and not + compare_versions(pdftops_v, '1.0')): + pass + else: + flag = False + warnings.warn(('matplotlibrc ps.usedistiller can not be set to ' + 'xpdf unless xpdf-%s or later is installed on ' + 'your system') % pdftops_req) + + if flag: + return s + else: + return False + + +def checkdep_usetex(s): + if not s: + return False + + gs_req = '8.60' + dvipng_req = '1.6' + flag = True + + if _backports.which("tex") is None: + flag = False + warnings.warn('matplotlibrc text.usetex option can not be used unless ' + 'TeX is installed on your system') + + dvipng_v = checkdep_dvipng() + if not compare_versions(dvipng_v, dvipng_req): + flag = False + warnings.warn('matplotlibrc text.usetex can not be used with *Agg ' + 'backend unless dvipng-%s or later is installed on ' + 'your system' % dvipng_req) + + gs_exec, gs_v = checkdep_ghostscript() + if not compare_versions(gs_v, gs_req): + flag = False + warnings.warn('matplotlibrc text.usetex can not be used unless ' + 'ghostscript-%s or later is installed on your system' + % gs_req) + + return flag + + +def _get_home(): + """Find user's home directory if possible. + Otherwise, returns None. + + :see: + http://mail.python.org/pipermail/python-list/2005-February/325395.html + """ + if six.PY2 and sys.platform == 'win32': + path = os.path.expanduser(b"~").decode(sys.getfilesystemencoding()) + else: + path = os.path.expanduser("~") + if os.path.isdir(path): + return path + for evar in ('HOME', 'USERPROFILE', 'TMP'): + path = os.environ.get(evar) + if path is not None and os.path.isdir(path): + return path + return None + + +def _create_tmp_config_dir(): + """ + If the config directory can not be created, create a temporary + directory. + """ + configdir = os.environ['MPLCONFIGDIR'] = ( + tempfile.mkdtemp(prefix='matplotlib-')) + atexit.register(shutil.rmtree, configdir) + return configdir + + +get_home = _wrap('$HOME=%s', _get_home, always=False) + + +def _get_xdg_config_dir(): + """ + Returns the XDG configuration directory, according to the `XDG + base directory spec + `_. + """ + path = os.environ.get('XDG_CONFIG_HOME') + if path is None: + path = get_home() + if path is not None: + path = os.path.join(path, '.config') + return path + + +def _get_xdg_cache_dir(): + """ + Returns the XDG cache directory, according to the `XDG + base directory spec + `_. + """ + path = os.environ.get('XDG_CACHE_HOME') + if path is None: + path = get_home() + if path is not None: + path = os.path.join(path, '.cache') + return path + + +def _get_config_or_cache_dir(xdg_base): + from matplotlib.cbook import mkdirs + + configdir = os.environ.get('MPLCONFIGDIR') + if configdir is not None: + configdir = os.path.abspath(configdir) + if not os.path.exists(configdir): + mkdirs(configdir) + + if not _is_writable_dir(configdir): + return _create_tmp_config_dir() + return configdir + + p = None + h = get_home() + if h is not None: + p = os.path.join(h, '.matplotlib') + if sys.platform.startswith(('linux', 'freebsd')): + p = None + if xdg_base is not None: + p = os.path.join(xdg_base, 'matplotlib') + + if p is not None: + if os.path.exists(p): + if _is_writable_dir(p): + return p + else: + try: + mkdirs(p) + except OSError: + pass + else: + return p + + return _create_tmp_config_dir() + + +def _get_configdir(): + """ + Return the string representing the configuration directory. + + The directory is chosen as follows: + + 1. If the MPLCONFIGDIR environment variable is supplied, choose that. + + 2a. On Linux, follow the XDG specification and look first in + `$XDG_CONFIG_HOME`, if defined, or `$HOME/.config`. + + 2b. On other platforms, choose `$HOME/.matplotlib`. + + 3. If the chosen directory exists and is writable, use that as the + configuration directory. + 4. If possible, create a temporary directory, and use it as the + configuration directory. + 5. A writable directory could not be found or created; return None. + """ + return _get_config_or_cache_dir(_get_xdg_config_dir()) + +get_configdir = _wrap('CONFIGDIR=%s', _get_configdir, always=False) + + +def _get_cachedir(): + """ + Return the location of the cache directory. + + The procedure used to find the directory is the same as for + _get_config_dir, except using `$XDG_CACHE_HOME`/`~/.cache` instead. + """ + return _get_config_or_cache_dir(_get_xdg_cache_dir()) + +get_cachedir = _wrap('CACHEDIR=%s', _get_cachedir, always=False) + + +def _decode_filesystem_path(path): + if not isinstance(path, str): + return path.decode(sys.getfilesystemencoding()) + else: + return path + + +def _get_internal_mpl_data(): + import tempfile + import hashlib + import errno + + def mpl_archive(): + import __res + res_name = '/mpl-data/mpl-data.tar.gz' + return __res.find(res_name) + + def extract_to(data, path): + import tarfile + string = six.BytesIO(data) + tar = tarfile.open(fileobj=string) + try: + tar.extractall(path) + finally: + tar.close() + + data = mpl_archive() + if not data: + return None + + mpl_path = os.path.join(tempfile.gettempdir(), 'mpl-data_{}_{}'.format(hashlib.md5(data).hexdigest(), os.geteuid())) + if os.path.exists(mpl_path): + return mpl_path + + tmp_dir = tempfile.mkdtemp(prefix='mpl-temp', dir=tempfile.gettempdir()) + extract_to(data, tmp_dir) + + try: + os.rename(tmp_dir, mpl_path) + except OSError as e: + if e.errno not in [errno.EEXIST, errno.ENOTEMPTY]: + raise + + return mpl_path + + +def _get_data_path(): + 'get the path to matplotlib data' + + if 'MATPLOTLIBDATA' in os.environ: + path = os.environ['MATPLOTLIBDATA'] + if not os.path.isdir(path): + raise RuntimeError('Path in environment MATPLOTLIBDATA not a ' + 'directory') + return path + + _file = _decode_filesystem_path(__file__) + path = os.sep.join([os.path.dirname(_file), 'mpl-data']) + if os.path.isdir(path): + return path + + # setuptools' namespace_packages may highjack this init file + # so need to try something known to be in matplotlib, not basemap + import matplotlib.afm + _file = _decode_filesystem_path(matplotlib.afm.__file__) + path = os.sep.join([os.path.dirname(_file), 'mpl-data']) + if os.path.isdir(path): + return path + + # py2exe zips pure python, so still need special check + if getattr(sys, 'frozen', None): + exe_path = os.path.dirname(_decode_filesystem_path(sys.executable)) + path = os.path.join(exe_path, 'mpl-data') + if os.path.isdir(path): + return path + + # Try again assuming we need to step up one more directory + path = os.path.join(os.path.split(exe_path)[0], 'mpl-data') + if os.path.isdir(path): + return path + + # Try again assuming sys.path[0] is a dir not a exe + path = os.path.join(sys.path[0], 'mpl-data') + if os.path.isdir(path): + return path + + path = _get_internal_mpl_data() + if path: + return path + + raise RuntimeError('Could not find the matplotlib data files') + + +def _get_data_path_cached(): + if defaultParams['datapath'][0] is None: + defaultParams['datapath'][0] = _get_data_path() + return defaultParams['datapath'][0] + +get_data_path = _wrap('matplotlib data path %s', _get_data_path_cached, + always=False) + + +def get_py2exe_datafiles(): + datapath = get_data_path() + _, tail = os.path.split(datapath) + d = {} + for root, _, files in os.walk(datapath): + # Need to explicitly remove cocoa_agg files or py2exe complains + # NOTE I don't know why, but do as previous version + if 'Matplotlib.nib' in files: + files.remove('Matplotlib.nib') + files = [os.path.join(root, filename) for filename in files] + root = root.replace(tail, 'mpl-data') + root = root[root.index('mpl-data'):] + d[root] = files + return list(d.items()) + + +def matplotlib_fname(): + """ + Get the location of the config file. + + The file location is determined in the following order + + - `$PWD/matplotlibrc` + + - `$MATPLOTLIBRC` if it is a file (or a named pipe, which can be created + e.g. by process substitution) + + - `$MATPLOTLIBRC/matplotlibrc` + + - `$MPLCONFIGDIR/matplotlibrc` + + - On Linux, + + - `$XDG_CONFIG_HOME/matplotlib/matplotlibrc` (if + $XDG_CONFIG_HOME is defined) + + - or `$HOME/.config/matplotlib/matplotlibrc` (if + $XDG_CONFIG_HOME is not defined) + + - On other platforms, + + - `$HOME/.matplotlib/matplotlibrc` if `$HOME` is defined. + + - Lastly, it looks in `$MATPLOTLIBDATA/matplotlibrc` for a + system-defined copy. + """ + + def gen_candidates(): + yield os.path.join(six.moves.getcwd(), 'matplotlibrc') + try: + matplotlibrc = os.environ['MATPLOTLIBRC'] + except KeyError: + pass + else: + yield matplotlibrc + yield os.path.join(matplotlibrc, 'matplotlibrc') + yield os.path.join(_get_configdir(), 'matplotlibrc') + yield os.path.join(get_data_path(), 'matplotlibrc') + + for fname in gen_candidates(): + if os.path.exists(fname): + st_mode = os.stat(fname).st_mode + if stat.S_ISREG(st_mode) or stat.S_ISFIFO(st_mode): + break + # Return first candidate that is a file, or last candidate if none is + # valid (in that case, a warning is raised at startup by `rc_params`). + return fname + + +# names of keys to deprecate +# the values are a tuple of (new_name, f_old_2_new, f_new_2_old) +# the inverse function may be `None` +_deprecated_map = {} + +_deprecated_ignore_map = {'nbagg.transparent': 'figure.facecolor'} + +_obsolete_set = {'plugins.directory', 'text.dvipnghack'} + +# The following may use a value of None to suppress the warning. +# do NOT include in _all_deprecated +_deprecated_set = {'axes.hold', + 'backend.qt4', + 'backend.qt5'} + +_all_deprecated = set(itertools.chain( + _deprecated_ignore_map, _deprecated_map, _obsolete_set)) + + +class RcParams(MutableMapping, dict): + + """ + A dictionary object including validation + + validating functions are defined and associated with rc parameters in + :mod:`matplotlib.rcsetup` + """ + + validate = dict((key, converter) for key, (default, converter) in + six.iteritems(defaultParams) + if key not in _all_deprecated) + msg_depr = "%s is deprecated and replaced with %s; please use the latter." + msg_depr_set = ("%s is deprecated. Please remove it from your " + "matplotlibrc and/or style files.") + msg_depr_ignore = "%s is deprecated and ignored. Use %s instead." + msg_obsolete = ("%s is obsolete. Please remove it from your matplotlibrc " + "and/or style files.") + msg_backend_obsolete = ("The {} rcParam was deprecated in version 2.2. In" + " order to force the use of a specific Qt binding," + " either import that binding first, or set the " + "QT_API environment variable.") + + # validate values on the way in + def __init__(self, *args, **kwargs): + self.update(*args, **kwargs) + + def __setitem__(self, key, val): + try: + if key in _deprecated_map: + alt_key, alt_val, inverse_alt = _deprecated_map[key] + warnings.warn(self.msg_depr % (key, alt_key), + mplDeprecation) + key = alt_key + val = alt_val(val) + elif key in _deprecated_set and val is not None: + if key.startswith('backend'): + warnings.warn(self.msg_backend_obsolete.format(key), + mplDeprecation) + else: + warnings.warn(self.msg_depr_set % key, + mplDeprecation) + elif key in _deprecated_ignore_map: + alt = _deprecated_ignore_map[key] + warnings.warn(self.msg_depr_ignore % (key, alt), + mplDeprecation) + return + elif key in _obsolete_set: + warnings.warn(self.msg_obsolete % (key, ), + mplDeprecation) + return + try: + cval = self.validate[key](val) + except ValueError as ve: + raise ValueError("Key %s: %s" % (key, str(ve))) + dict.__setitem__(self, key, cval) + except KeyError: + raise KeyError( + '%s is not a valid rc parameter. See rcParams.keys() for a ' + 'list of valid parameters.' % (key,)) + + def __getitem__(self, key): + inverse_alt = None + if key in _deprecated_map: + alt_key, alt_val, inverse_alt = _deprecated_map[key] + warnings.warn(self.msg_depr % (key, alt_key), + mplDeprecation) + key = alt_key + + elif key in _deprecated_ignore_map: + alt = _deprecated_ignore_map[key] + warnings.warn(self.msg_depr_ignore % (key, alt), + mplDeprecation) + key = alt + + elif key in _obsolete_set: + warnings.warn(self.msg_obsolete % (key, ), + mplDeprecation) + return None + + val = dict.__getitem__(self, key) + if inverse_alt is not None: + return inverse_alt(val) + else: + return val + + def __repr__(self): + import pprint + class_name = self.__class__.__name__ + indent = len(class_name) + 1 + repr_split = pprint.pformat(dict(self), indent=1, + width=80 - indent).split('\n') + repr_indented = ('\n' + ' ' * indent).join(repr_split) + return '{0}({1})'.format(class_name, repr_indented) + + def __str__(self): + return '\n'.join('{0}: {1}'.format(k, v) + for k, v in sorted(self.items())) + + def __iter__(self): + """ + Yield sorted list of keys. + """ + for k in sorted(dict.__iter__(self)): + yield k + + def find_all(self, pattern): + """ + Return the subset of this RcParams dictionary whose keys match, + using :func:`re.search`, the given ``pattern``. + + .. note:: + + Changes to the returned dictionary are *not* propagated to + the parent RcParams dictionary. + + """ + pattern_re = re.compile(pattern) + return RcParams((key, value) + for key, value in self.items() + if pattern_re.search(key)) + + +def rc_params(fail_on_error=False): + """Return a :class:`matplotlib.RcParams` instance from the + default matplotlib rc file. + """ + fname = matplotlib_fname() + if not os.path.exists(fname): + # this should never happen, default in mpl-data should always be found + message = 'could not find rc file; returning defaults' + ret = RcParams([(key, default) for key, (default, _) in + six.iteritems(defaultParams) + if key not in _all_deprecated]) + warnings.warn(message) + return ret + + return rc_params_from_file(fname, fail_on_error) + + +URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\') + + +def is_url(filename): + """Return True if string is an http, ftp, or file URL path.""" + return URL_REGEX.match(filename) is not None + + +def _url_lines(f): + # Compatibility for urlopen in python 3, which yields bytes. + for line in f: + yield line.decode('utf8') + + +@contextlib.contextmanager +def _open_file_or_url(fname): + if is_url(fname): + f = urlopen(fname) + yield _url_lines(f) + f.close() + else: + fname = os.path.expanduser(fname) + encoding = locale.getpreferredencoding(do_setlocale=False) + if encoding is None: + encoding = "utf-8" + with io.open(fname, encoding=encoding) as f: + yield f + + +_error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"' + + +def _rc_params_in_file(fname, fail_on_error=False): + """Return :class:`matplotlib.RcParams` from the contents of the given file. + + Unlike `rc_params_from_file`, the configuration class only contains the + parameters specified in the file (i.e. default values are not filled in). + """ + cnt = 0 + rc_temp = {} + with _open_file_or_url(fname) as fd: + try: + for line in fd: + cnt += 1 + strippedline = line.split('#', 1)[0].strip() + if not strippedline: + continue + tup = strippedline.split(':', 1) + if len(tup) != 2: + error_details = _error_details_fmt % (cnt, line, fname) + warnings.warn('Illegal %s' % error_details) + continue + key, val = tup + key = key.strip() + val = val.strip() + if key in rc_temp: + warnings.warn('Duplicate key in file "%s", line #%d' % + (fname, cnt)) + rc_temp[key] = (val, line, cnt) + except UnicodeDecodeError: + warnings.warn( + ('Cannot decode configuration file %s with ' + 'encoding %s, check LANG and LC_* variables') + % (fname, locale.getpreferredencoding(do_setlocale=False) or + 'utf-8 (default)')) + raise + + config = RcParams() + + for key in ('verbose.level', 'verbose.fileo'): + if key in rc_temp: + val, line, cnt = rc_temp.pop(key) + if fail_on_error: + config[key] = val # try to convert to proper type or raise + else: + try: + config[key] = val # try to convert to proper type or skip + except Exception as msg: + error_details = _error_details_fmt % (cnt, line, fname) + warnings.warn('Bad val "%s" on %s\n\t%s' % + (val, error_details, msg)) + + for key, (val, line, cnt) in six.iteritems(rc_temp): + if key in defaultParams: + if fail_on_error: + config[key] = val # try to convert to proper type or raise + else: + try: + config[key] = val # try to convert to proper type or skip + except Exception as msg: + error_details = _error_details_fmt % (cnt, line, fname) + warnings.warn('Bad val "%s" on %s\n\t%s' % + (val, error_details, msg)) + elif key in _deprecated_ignore_map: + warnings.warn('%s is deprecated. Update your matplotlibrc to use ' + '%s instead.' % (key, _deprecated_ignore_map[key]), + mplDeprecation) + + else: + print(""" +Bad key "%s" on line %d in +%s. +You probably need to get an updated matplotlibrc file from +http://github.com/matplotlib/matplotlib/blob/master/matplotlibrc.template +or from the matplotlib source distribution""" % (key, cnt, fname), + file=sys.stderr) + + return config + + +def rc_params_from_file(fname, fail_on_error=False, use_default_template=True): + """Return :class:`matplotlib.RcParams` from the contents of the given file. + + Parameters + ---------- + fname : str + Name of file parsed for matplotlib settings. + fail_on_error : bool + If True, raise an error when the parser fails to convert a parameter. + use_default_template : bool + If True, initialize with default parameters before updating with those + in the given file. If False, the configuration class only contains the + parameters specified in the file. (Useful for updating dicts.) + """ + config_from_file = _rc_params_in_file(fname, fail_on_error) + + if not use_default_template: + return config_from_file + + iter_params = six.iteritems(defaultParams) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", mplDeprecation) + config = RcParams([(key, default) for key, (default, _) in iter_params + if key not in _all_deprecated]) + config.update(config_from_file) + + if config['datapath'] is None: + config['datapath'] = get_data_path() + + if "".join(config['text.latex.preamble']): + _log.info(""" +***************************************************************** +You have the following UNSUPPORTED LaTeX preamble customizations: +%s +Please do not ask for support with these customizations active. +***************************************************************** +""", '\n'.join(config['text.latex.preamble'])) + _log.debug('loaded rc file %s', fname) + + return config + + +# this is the instance used by the matplotlib classes +rcParams = rc_params() + +if rcParams['examples.directory']: + # paths that are intended to be relative to matplotlib_fname() + # are allowed for the examples.directory parameter. + # However, we will need to fully qualify the path because + # Sphinx requires absolute paths. + if not os.path.isabs(rcParams['examples.directory']): + _basedir, _fname = os.path.split(matplotlib_fname()) + # Sometimes matplotlib_fname() can return relative paths, + # Also, using realpath() guarantees that Sphinx will use + # the same path that matplotlib sees (in case of weird symlinks). + _basedir = os.path.realpath(_basedir) + _fullpath = os.path.join(_basedir, rcParams['examples.directory']) + rcParams['examples.directory'] = _fullpath + +rcParamsOrig = rcParams.copy() + +with warnings.catch_warnings(): + warnings.simplefilter("ignore", mplDeprecation) + rcParamsDefault = RcParams([(key, default) for key, (default, converter) in + six.iteritems(defaultParams) + if key not in _all_deprecated]) + +rcParams['ps.usedistiller'] = checkdep_ps_distiller( + rcParams['ps.usedistiller']) + +rcParams['text.usetex'] = checkdep_usetex(rcParams['text.usetex']) + +if rcParams['axes.formatter.use_locale']: + locale.setlocale(locale.LC_ALL, '') + + +def rc(group, **kwargs): + """ + Set the current rc params. Group is the grouping for the rc, e.g., + for ``lines.linewidth`` the group is ``lines``, for + ``axes.facecolor``, the group is ``axes``, and so on. Group may + also be a list or tuple of group names, e.g., (*xtick*, *ytick*). + *kwargs* is a dictionary attribute name/value pairs, e.g.,:: + + rc('lines', linewidth=2, color='r') + + sets the current rc params and is equivalent to:: + + rcParams['lines.linewidth'] = 2 + rcParams['lines.color'] = 'r' + + The following aliases are available to save typing for interactive + users: + + ===== ================= + Alias Property + ===== ================= + 'lw' 'linewidth' + 'ls' 'linestyle' + 'c' 'color' + 'fc' 'facecolor' + 'ec' 'edgecolor' + 'mew' 'markeredgewidth' + 'aa' 'antialiased' + ===== ================= + + Thus you could abbreviate the above rc command as:: + + rc('lines', lw=2, c='r') + + + Note you can use python's kwargs dictionary facility to store + dictionaries of default parameters. e.g., you can customize the + font rc as follows:: + + font = {'family' : 'monospace', + 'weight' : 'bold', + 'size' : 'larger'} + + rc('font', **font) # pass in the font dict as kwargs + + This enables you to easily switch between several configurations. Use + ``matplotlib.style.use('default')`` or :func:`~matplotlib.rcdefaults` to + restore the default rc params after changes. + """ + + aliases = { + 'lw': 'linewidth', + 'ls': 'linestyle', + 'c': 'color', + 'fc': 'facecolor', + 'ec': 'edgecolor', + 'mew': 'markeredgewidth', + 'aa': 'antialiased', + } + + if isinstance(group, six.string_types): + group = (group,) + for g in group: + for k, v in six.iteritems(kwargs): + name = aliases.get(k) or k + key = '%s.%s' % (g, name) + try: + rcParams[key] = v + except KeyError: + raise KeyError(('Unrecognized key "%s" for group "%s" and ' + 'name "%s"') % (key, g, name)) + + +def rcdefaults(): + """Restore the rc params from Matplotlib's internal defaults. + + See Also + -------- + rc_file_defaults : + Restore the rc params from the rc file originally loaded by Matplotlib. + matplotlib.style.use : + Use a specific style file. Call ``style.use('default')`` to restore + the default style. + """ + rcParams.clear() + rcParams.update(rcParamsDefault) + + +def rc_file_defaults(): + """Restore the rc params from the original rc file loaded by Matplotlib. + """ + rcParams.update(rcParamsOrig) + + +def rc_file(fname): + """ + Update rc params from file. + """ + rcParams.update(rc_params_from_file(fname)) + + +class rc_context(object): + """ + Return a context manager for managing rc settings. + + This allows one to do:: + + with mpl.rc_context(fname='screen.rc'): + plt.plot(x, a) + with mpl.rc_context(fname='print.rc'): + plt.plot(x, b) + plt.plot(x, c) + + The 'a' vs 'x' and 'c' vs 'x' plots would have settings from + 'screen.rc', while the 'b' vs 'x' plot would have settings from + 'print.rc'. + + A dictionary can also be passed to the context manager:: + + with mpl.rc_context(rc={'text.usetex': True}, fname='screen.rc'): + plt.plot(x, a) + + The 'rc' dictionary takes precedence over the settings loaded from + 'fname'. Passing a dictionary only is also valid. For example a + common usage is:: + + with mpl.rc_context(rc={'interactive': False}): + fig, ax = plt.subplots() + ax.plot(range(3), range(3)) + fig.savefig('A.png', format='png') + plt.close(fig) + """ + # While it may seem natural to implement rc_context using + # contextlib.contextmanager, that would entail always calling the finally: + # clause of the contextmanager (which restores the original rcs) including + # during garbage collection; as a result, something like `plt.xkcd(); + # gc.collect()` would result in the style being lost (as `xkcd()` is + # implemented on top of rc_context, and nothing is holding onto context + # manager except possibly circular references. + + def __init__(self, rc=None, fname=None): + self._orig = rcParams.copy() + try: + if fname: + rc_file(fname) + if rc: + rcParams.update(rc) + except Exception: + # If anything goes wrong, revert to the original rcs. + dict.update(rcParams, self._orig) + raise + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, exc_tb): + # No need to revalidate the original values. + dict.update(rcParams, self._orig) + + +_use_error_msg = """ +This call to matplotlib.use() has no effect because the backend has already +been chosen; matplotlib.use() must be called *before* pylab, matplotlib.pyplot, +or matplotlib.backends is imported for the first time. + +The backend was *originally* set to {backend!r} by the following code: +{tb} +""" + + +def use(arg, warn=True, force=False): + """ + Set the matplotlib backend to one of the known backends. + + The argument is case-insensitive. *warn* specifies whether a + warning should be issued if a backend has already been set up. + *force* is an **experimental** flag that tells matplotlib to + attempt to initialize a new backend by reloading the backend + module. + + .. note:: + + This function must be called *before* importing pyplot for + the first time; or, if you are not using pyplot, it must be called + before importing matplotlib.backends. If warn is True, a warning + is issued if you try and call this after pylab or pyplot have been + loaded. In certain black magic use cases, e.g. + :func:`pyplot.switch_backend`, we are doing the reloading necessary to + make the backend switch work (in some cases, e.g., pure image + backends) so one can set warn=False to suppress the warnings. + + To find out which backend is currently set, see + :func:`matplotlib.get_backend`. + + """ + # Lets determine the proper backend name first + if arg.startswith('module://'): + name = arg + else: + # Lowercase only non-module backend names (modules are case-sensitive) + arg = arg.lower() + name = validate_backend(arg) + + # Check if we've already set up a backend + if 'matplotlib.backends' in sys.modules: + # Warn only if called with a different name + if (rcParams['backend'] != name) and warn: + import matplotlib.backends + warnings.warn( + _use_error_msg.format( + backend=rcParams['backend'], + tb=matplotlib.backends._backend_loading_tb), + stacklevel=2) + + # Unless we've been told to force it, just return + if not force: + return + need_reload = True + else: + need_reload = False + + # Store the backend name + rcParams['backend'] = name + + # If needed we reload here because a lot of setup code is triggered on + # module import. See backends/__init__.py for more detail. + if need_reload: + reload(sys.modules['matplotlib.backends']) + + +try: + use(os.environ['MPLBACKEND']) +except KeyError: + pass + + +def get_backend(): + """Return the name of the current backend.""" + return rcParams['backend'] + + +def interactive(b): + """ + Set interactive mode to boolean b. + + If b is True, then draw after every plotting command, e.g., after xlabel + """ + rcParams['interactive'] = b + + +def is_interactive(): + 'Return true if plot mode is interactive' + return rcParams['interactive'] + + +def tk_window_focus(): + """Return true if focus maintenance under TkAgg on win32 is on. + This currently works only for python.exe and IPython.exe. + Both IDLE and Pythonwin.exe fail badly when tk_window_focus is on.""" + if rcParams['backend'] != 'TkAgg': + return False + return rcParams['tk.window_focus'] + + +default_test_modules = [ + 'matplotlib.tests', + 'matplotlib.sphinxext.tests', + 'mpl_toolkits.tests', +] + + +def _init_tests(): + try: + import faulthandler + except ImportError: + pass + else: + # CPython's faulthandler since v3.6 handles exceptions on Windows + # https://bugs.python.org/issue23848 but until v3.6.4 it was + # printing non-fatal exceptions https://bugs.python.org/issue30557 + import platform + if not (sys.platform == 'win32' and + (3, 6) < sys.version_info < (3, 6, 4) and + platform.python_implementation() == 'CPython'): + faulthandler.enable() + + # The version of FreeType to install locally for running the + # tests. This must match the value in `setupext.py` + LOCAL_FREETYPE_VERSION = '2.6.1' + + from matplotlib import ft2font + if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or + ft2font.__freetype_build_type__ != 'local'): + warnings.warn( + "Matplotlib is not built with the correct FreeType version to run " + "tests. Set local_freetype=True in setup.cfg and rebuild. " + "Expect many image comparison failures below. " + "Expected freetype version {0}. " + "Found freetype version {1}. " + "Freetype build type is {2}local".format( + LOCAL_FREETYPE_VERSION, + ft2font.__freetype_version__, + "" if ft2font.__freetype_build_type__ == 'local' else "not " + ) + ) + + try: + import pytest + try: + from unittest import mock + except ImportError: + import mock + except ImportError: + print("matplotlib.test requires pytest and mock to run.") + raise + + +def test(verbosity=None, coverage=False, switch_backend_warn=True, + recursionlimit=0, **kwargs): + """run the matplotlib test suite""" + _init_tests() + if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')): + raise ImportError("Matplotlib test data is not installed") + + old_backend = get_backend() + old_recursionlimit = sys.getrecursionlimit() + try: + use('agg') + if recursionlimit: + sys.setrecursionlimit(recursionlimit) + import pytest + + args = kwargs.pop('argv', []) + provide_default_modules = True + use_pyargs = True + for arg in args: + if any(arg.startswith(module_path) + for module_path in default_test_modules): + provide_default_modules = False + break + if os.path.exists(arg): + provide_default_modules = False + use_pyargs = False + break + if use_pyargs: + args += ['--pyargs'] + if provide_default_modules: + args += default_test_modules + + if coverage: + args += ['--cov'] + + if verbosity: + args += ['-' + 'v' * verbosity] + + retcode = pytest.main(args, **kwargs) + finally: + if old_backend.lower() != 'agg': + use(old_backend, warn=switch_backend_warn) + if recursionlimit: + sys.setrecursionlimit(old_recursionlimit) + + return retcode + + +test.__test__ = False # pytest: this function is not a test + + +def _replacer(data, key): + """Either returns data[key] or passes data back. Also + converts input data to a sequence as needed. + """ + # if key isn't a string don't bother + if not isinstance(key, six.string_types): + return (key) + # try to use __getitem__ + try: + return sanitize_sequence(data[key]) + # key does not exist, silently fall back to key + except KeyError: + return key + + +_DATA_DOC_APPENDIX = """ + +.. note:: + In addition to the above described arguments, this function can take a + **data** keyword argument. If such a **data** argument is given, the + following arguments are replaced by **data[]**: + + {replaced} +""" + + +def _add_data_doc(docstring, replace_names, replace_all_args): + """Add documentation for a *data* field to the given docstring. + + Parameters + ---------- + docstring : str + The input docstring. + replace_names : list of strings or None + The list of parameter names which arguments should be replaced by + `data[name]`. If None, all arguments are replaced if they are + included in `data`. + replace_all_args : bool + If True, all arguments in *args get replaced, even if they are not + in replace_names. + + Returns + ------- + The augmented docstring. + """ + if docstring is None: + docstring = '' + else: + docstring = dedent(docstring) + _repl = "" + if replace_names is None: + _repl = "* All positional and all keyword arguments." + else: + if len(replace_names) != 0: + _repl = "* All arguments with the following names: '{names}'." + if replace_all_args: + _repl += "\n * All positional arguments." + _repl = _repl.format(names="', '".join(sorted(replace_names))) + return docstring + _DATA_DOC_APPENDIX.format(replaced=_repl) + + +def _preprocess_data(replace_names=None, replace_all_args=False, + label_namer=None, positional_parameter_names=None): + """ + A decorator to add a 'data' kwarg to any a function. The signature + of the input function must include the ax argument at the first position :: + + def foo(ax, *args, **kwargs) + + so this is suitable for use with Axes methods. + + Parameters + ---------- + replace_names : list of strings, optional, default: None + The list of parameter names which arguments should be replaced by + `data[name]`. If None, all arguments are replaced if they are + included in `data`. + replace_all_args : bool, default: False + If True, all arguments in *args get replaced, even if they are not + in replace_names. + label_namer : string, optional, default: None + The name of the parameter which argument should be used as label, if + label is not set. If None, the label keyword argument is not set. + positional_parameter_names : list of strings or callable, optional + The full list of positional parameter names (excluding an explicit + `ax`/'self' argument at the first place and including all possible + positional parameter in `*args`), in the right order. Can also include + all other keyword parameter. Only needed if the wrapped function does + contain `*args` and (replace_names is not None or replace_all_args is + False). If it is a callable, it will be called with the actual + tuple of *args and the data and should return a list like + above. + NOTE: callables should only be used when the names and order of *args + can only be determined at runtime. Please use list of names + when the order and names of *args is clear before runtime! + + .. note:: decorator also converts MappingView input data to list. + """ + if replace_names is not None: + replace_names = set(replace_names) + + def param(func): + new_sig = None + # signature is since 3.3 and wrapped since 3.2, but we support 3.4+. + python_has_signature = python_has_wrapped = six.PY3 + + # if in a legacy version of python and IPython is already imported + # try to use their back-ported signature + if not python_has_signature and 'IPython' in sys.modules: + try: + import IPython.utils.signatures + signature = IPython.utils.signatures.signature + Parameter = IPython.utils.signatures.Parameter + except ImportError: + pass + else: + python_has_signature = True + else: + if python_has_signature: + signature = inspect.signature + Parameter = inspect.Parameter + + if not python_has_signature: + arg_spec = inspect.getargspec(func) + _arg_names = arg_spec.args + _has_varargs = arg_spec.varargs is not None + _has_varkwargs = arg_spec.keywords is not None + else: + sig = signature(func) + _has_varargs = False + _has_varkwargs = False + _arg_names = [] + params = list(sig.parameters.values()) + for p in params: + if p.kind is Parameter.VAR_POSITIONAL: + _has_varargs = True + elif p.kind is Parameter.VAR_KEYWORD: + _has_varkwargs = True + else: + _arg_names.append(p.name) + data_param = Parameter('data', + Parameter.KEYWORD_ONLY, + default=None) + if _has_varkwargs: + params.insert(-1, data_param) + else: + params.append(data_param) + new_sig = sig.replace(parameters=params) + # Import-time check: do we have enough information to replace *args? + arg_names_at_runtime = False + # there can't be any positional arguments behind *args and no + # positional args can end up in **kwargs, so only *varargs make + # problems. + # http://stupidpythonideas.blogspot.de/2013/08/arguments-and-parameters.html + if not _has_varargs: + # all args are "named", so no problem + # remove the first "ax" / self arg + arg_names = _arg_names[1:] + else: + # Here we have "unnamed" variables and we need a way to determine + # whether to replace a arg or not + if replace_names is None: + # all argnames should be replaced + arg_names = None + elif len(replace_names) == 0: + # No argnames should be replaced + arg_names = [] + elif len(_arg_names) > 1 and (positional_parameter_names is None): + # we got no manual parameter names but more than an 'ax' ... + if len(replace_names - set(_arg_names[1:])) == 0: + # all to be replaced arguments are in the list + arg_names = _arg_names[1:] + else: + raise AssertionError( + "Got unknown 'replace_names' and wrapped function " + "{!r} uses '*args', need 'positional_parameter_names'" + .format(func.__name__)) + else: + if positional_parameter_names is not None: + if callable(positional_parameter_names): + # determined by the function at runtime + arg_names_at_runtime = True + # so that we don't compute the label_pos at import time + arg_names = [] + else: + arg_names = positional_parameter_names + else: + if replace_all_args: + arg_names = [] + else: + raise AssertionError( + "Got 'replace_names' and wrapped function {!r} " + "uses *args, need 'positional_parameter_names' or " + "'replace_all_args'".format(func.__name__)) + + # compute the possible label_namer and label position in positional + # arguments + label_pos = 9999 # bigger than all "possible" argument lists + label_namer_pos = 9999 # bigger than all "possible" argument lists + if (label_namer and # we actually want a label here ... + arg_names and # and we can determine a label in *args ... + (label_namer in arg_names)): # and it is in *args + label_namer_pos = arg_names.index(label_namer) + if "label" in arg_names: + label_pos = arg_names.index("label") + + # Check the case we know a label_namer but we can't find it the + # arg_names... Unfortunately the label_namer can be in **kwargs, + # which we can't detect here and which results in a non-set label + # which might surprise the user :-( + if label_namer and not arg_names_at_runtime and not _has_varkwargs: + if not arg_names: + raise AssertionError( + "label_namer {!r} can't be found as the parameter without " + "'positional_parameter_names'".format(label_namer)) + elif label_namer not in arg_names: + raise AssertionError( + "label_namer {!r} can't be found in the parameter names " + "(known argnames: %s).".format(label_namer, arg_names)) + else: + # this is the case when the name is in arg_names + pass + + @functools.wraps(func) + def inner(ax, *args, **kwargs): + # this is needed because we want to change these values if + # arg_names_at_runtime==True, but python does not allow assigning + # to a variable in a outer scope. So use some new local ones and + # set them to the already computed values. + _label_pos = label_pos + _label_namer_pos = label_namer_pos + _arg_names = arg_names + + label = None + + data = kwargs.pop('data', None) + + if data is None: # data validation + args = tuple(sanitize_sequence(a) for a in args) + else: + if arg_names_at_runtime: + # update the information about replace names and + # label position + _arg_names = positional_parameter_names(args, data) + if (label_namer and # we actually want a label here ... + _arg_names and # and we can find a label in *args + (label_namer in _arg_names)): # and it is in *args + _label_namer_pos = _arg_names.index(label_namer) + if "label" in _arg_names: + _label_pos = arg_names.index("label") + + # save the current label_namer value so that it can be used as + # a label + if _label_namer_pos < len(args): + label = args[_label_namer_pos] + else: + label = kwargs.get(label_namer, None) + # ensure a string, as label can't be anything else + if not isinstance(label, six.string_types): + label = None + + if (replace_names is None) or (replace_all_args is True): + # all should be replaced + args = tuple(_replacer(data, a) for + j, a in enumerate(args)) + else: + # An arg is replaced if the arg_name of that position is + # in replace_names ... + if len(_arg_names) < len(args): + raise RuntimeError( + "Got more args than function expects") + args = tuple(_replacer(data, a) + if _arg_names[j] in replace_names else a + for j, a in enumerate(args)) + + if replace_names is None: + # replace all kwargs ... + kwargs = dict((k, _replacer(data, v)) + for k, v in six.iteritems(kwargs)) + else: + # ... or only if a kwarg of that name is in replace_names + kwargs = dict((k, _replacer(data, v) + if k in replace_names else v) + for k, v in six.iteritems(kwargs)) + + # replace the label if this func "wants" a label arg and the user + # didn't set one. Note: if the user puts in "label=None", it does + # *NOT* get replaced! + user_supplied_label = ( + (len(args) >= _label_pos) or # label is included in args + ('label' in kwargs) # ... or in kwargs + ) + if (label_namer and not user_supplied_label): + if _label_namer_pos < len(args): + kwargs['label'] = get_label(args[_label_namer_pos], label) + elif label_namer in kwargs: + kwargs['label'] = get_label(kwargs[label_namer], label) + else: + warnings.warn( + "Tried to set a label via parameter %r in func %r but " + "couldn't find such an argument.\n" + "(This is a programming error, please report to " + "the Matplotlib list!)" % (label_namer, func.__name__), + RuntimeWarning, stacklevel=2) + return func(ax, *args, **kwargs) + + inner.__doc__ = _add_data_doc(inner.__doc__, + replace_names, replace_all_args) + if not python_has_wrapped: + inner.__wrapped__ = func + if new_sig is not None: + inner.__signature__ = new_sig + return inner + + return param + +_log.debug('matplotlib version %s', __version__) +_log.debug('interactive is %s', is_interactive()) +_log.debug('platform is %s', sys.platform) +_log.debug('loaded modules: %s', list(sys.modules)) diff --git a/contrib/python/matplotlib/py2/matplotlib/_animation_data.py b/contrib/python/matplotlib/py2/matplotlib/_animation_data.py new file mode 100644 index 00000000000..4c3f2c75b65 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_animation_data.py @@ -0,0 +1,210 @@ +# Javascript template for HTMLWriter +JS_INCLUDE = """ + + +""" + + +# HTML template for HTMLWriter +DISPLAY_TEMPLATE = """ +
+ +
+ +
+ + + + + + + + + +
+ Once + Loop + Reflect +
+
+ + + +""" + +INCLUDED_FRAMES = """ + for (var i=0; i<{Nframes}; i++){{ + frames[i] = "{frame_dir}/frame" + ("0000000" + i).slice(-7) + + ".{frame_format}"; + }} +""" diff --git a/contrib/python/matplotlib/py2/matplotlib/_cm.py b/contrib/python/matplotlib/py2/matplotlib/_cm.py new file mode 100644 index 00000000000..a32229cb63b --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_cm.py @@ -0,0 +1,1445 @@ +""" +Nothing here but dictionaries for generating LinearSegmentedColormaps, +and a dictionary of these dictionaries. + +Documentation for each is in pyplot.colormaps(). Please update this +with the purpose and type of your colormap if you add data for one here. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import numpy as np + +_binary_data = { + 'red': ((0., 1., 1.), (1., 0., 0.)), + 'green': ((0., 1., 1.), (1., 0., 0.)), + 'blue': ((0., 1., 1.), (1., 0., 0.)) + } + +_autumn_data = {'red': ((0., 1.0, 1.0), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), (1.0, 0., 0.))} + +_bone_data = {'red': ((0., 0., 0.), + (0.746032, 0.652778, 0.652778), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.365079, 0.319444, 0.319444), + (0.746032, 0.777778, 0.777778), + (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), + (0.365079, 0.444444, 0.444444), + (1.0, 1.0, 1.0))} + +_cool_data = {'red': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'green': ((0., 1., 1.), (1.0, 0., 0.)), + 'blue': ((0., 1., 1.), (1.0, 1., 1.))} + +_copper_data = {'red': ((0., 0., 0.), + (0.809524, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (1.0, 0.7812, 0.7812)), + 'blue': ((0., 0., 0.), + (1.0, 0.4975, 0.4975))} + +_flag_data = { + 'red': lambda x: 0.75 * np.sin((x * 31.5 + 0.25) * np.pi) + 0.5, + 'green': lambda x: np.sin(x * 31.5 * np.pi), + 'blue': lambda x: 0.75 * np.sin((x * 31.5 - 0.25) * np.pi) + 0.5, +} + +_prism_data = { + 'red': lambda x: 0.75 * np.sin((x * 20.9 + 0.25) * np.pi) + 0.67, + 'green': lambda x: 0.75 * np.sin((x * 20.9 - 0.25) * np.pi) + 0.33, + 'blue': lambda x: -1.1 * np.sin((x * 20.9) * np.pi), +} + + +def cubehelix(gamma=1.0, s=0.5, r=-1.5, h=1.0): + """Return custom data dictionary of (r,g,b) conversion functions, which + can be used with :func:`register_cmap`, for the cubehelix color scheme. + + Unlike most other color schemes cubehelix was designed by D.A. Green to + be monotonically increasing in terms of perceived brightness. + Also, when printed on a black and white postscript printer, the scheme + results in a greyscale with monotonically increasing brightness. + This color scheme is named cubehelix because the r,g,b values produced + can be visualised as a squashed helix around the diagonal in the + r,g,b color cube. + + For a unit color cube (i.e. 3-D coordinates for r,g,b each in the + range 0 to 1) the color scheme starts at (r,g,b) = (0,0,0), i.e. black, + and finishes at (r,g,b) = (1,1,1), i.e. white. For some fraction *x*, + between 0 and 1, the color is the corresponding grey value at that + fraction along the black to white diagonal (x,x,x) plus a color + element. This color element is calculated in a plane of constant + perceived intensity and controlled by the following parameters. + + Optional keyword arguments: + + ========= ======================================================= + Keyword Description + ========= ======================================================= + gamma gamma factor to emphasise either low intensity values + (gamma < 1), or high intensity values (gamma > 1); + defaults to 1.0. + s the start color; defaults to 0.5 (i.e. purple). + r the number of r,g,b rotations in color that are made + from the start to the end of the color scheme; defaults + to -1.5 (i.e. -> B -> G -> R -> B). + h the hue parameter which controls how saturated the + colors are. If this parameter is zero then the color + scheme is purely a greyscale; defaults to 1.0. + ========= ======================================================= + + """ + + def get_color_function(p0, p1): + + def color(x): + # Apply gamma factor to emphasise low or high intensity values + xg = x ** gamma + + # Calculate amplitude and angle of deviation from the black + # to white diagonal in the plane of constant + # perceived intensity. + a = h * xg * (1 - xg) / 2 + + phi = 2 * np.pi * (s / 3 + r * x) + + return xg + a * (p0 * np.cos(phi) + p1 * np.sin(phi)) + return color + + return { + 'red': get_color_function(-0.14861, 1.78277), + 'green': get_color_function(-0.29227, -0.90649), + 'blue': get_color_function(1.97294, 0.0), + } + +_cubehelix_data = cubehelix() + +_bwr_data = ((0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0)) +_brg_data = ((0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)) + +# Gnuplot palette functions +gfunc = { + 0: lambda x: 0, + 1: lambda x: 0.5, + 2: lambda x: 1, + 3: lambda x: x, + 4: lambda x: x ** 2, + 5: lambda x: x ** 3, + 6: lambda x: x ** 4, + 7: lambda x: np.sqrt(x), + 8: lambda x: np.sqrt(np.sqrt(x)), + 9: lambda x: np.sin(x * np.pi / 2), + 10: lambda x: np.cos(x * np.pi / 2), + 11: lambda x: np.abs(x - 0.5), + 12: lambda x: (2 * x - 1) ** 2, + 13: lambda x: np.sin(x * np.pi), + 14: lambda x: np.abs(np.cos(x * np.pi)), + 15: lambda x: np.sin(x * 2 * np.pi), + 16: lambda x: np.cos(x * 2 * np.pi), + 17: lambda x: np.abs(np.sin(x * 2 * np.pi)), + 18: lambda x: np.abs(np.cos(x * 2 * np.pi)), + 19: lambda x: np.abs(np.sin(x * 4 * np.pi)), + 20: lambda x: np.abs(np.cos(x * 4 * np.pi)), + 21: lambda x: 3 * x, + 22: lambda x: 3 * x - 1, + 23: lambda x: 3 * x - 2, + 24: lambda x: np.abs(3 * x - 1), + 25: lambda x: np.abs(3 * x - 2), + 26: lambda x: (3 * x - 1) / 2, + 27: lambda x: (3 * x - 2) / 2, + 28: lambda x: np.abs((3 * x - 1) / 2), + 29: lambda x: np.abs((3 * x - 2) / 2), + 30: lambda x: x / 0.32 - 0.78125, + 31: lambda x: 2 * x - 0.84, + 32: lambda x: gfunc32(x), + 33: lambda x: np.abs(2 * x - 0.5), + 34: lambda x: 2 * x, + 35: lambda x: 2 * x - 0.5, + 36: lambda x: 2 * x - 1. +} + + +def gfunc32(x): + ret = np.zeros(len(x)) + m = (x < 0.25) + ret[m] = 4 * x[m] + m = (x >= 0.25) & (x < 0.92) + ret[m] = -2 * x[m] + 1.84 + m = (x >= 0.92) + ret[m] = x[m] / 0.08 - 11.5 + return ret + +_gnuplot_data = { + 'red': gfunc[7], + 'green': gfunc[5], + 'blue': gfunc[15], +} + +_gnuplot2_data = { + 'red': gfunc[30], + 'green': gfunc[31], + 'blue': gfunc[32], +} + +_ocean_data = { + 'red': gfunc[23], + 'green': gfunc[28], + 'blue': gfunc[3], +} + +_afmhot_data = { + 'red': gfunc[34], + 'green': gfunc[35], + 'blue': gfunc[36], +} + +_rainbow_data = { + 'red': gfunc[33], + 'green': gfunc[13], + 'blue': gfunc[10], +} + +_seismic_data = ( + (0.0, 0.0, 0.3), (0.0, 0.0, 1.0), + (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), + (0.5, 0.0, 0.0)) + +_terrain_data = ( + (0.00, (0.2, 0.2, 0.6)), + (0.15, (0.0, 0.6, 1.0)), + (0.25, (0.0, 0.8, 0.4)), + (0.50, (1.0, 1.0, 0.6)), + (0.75, (0.5, 0.36, 0.33)), + (1.00, (1.0, 1.0, 1.0))) + +_gray_data = {'red': ((0., 0, 0), (1., 1, 1)), + 'green': ((0., 0, 0), (1., 1, 1)), + 'blue': ((0., 0, 0), (1., 1, 1))} + +_hot_data = {'red': ((0., 0.0416, 0.0416), + (0.365079, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.365079, 0.000000, 0.000000), + (0.746032, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), + (0.746032, 0.000000, 0.000000), + (1.0, 1.0, 1.0))} + +_hsv_data = {'red': ((0., 1., 1.), + (0.158730, 1.000000, 1.000000), + (0.174603, 0.968750, 0.968750), + (0.333333, 0.031250, 0.031250), + (0.349206, 0.000000, 0.000000), + (0.666667, 0.000000, 0.000000), + (0.682540, 0.031250, 0.031250), + (0.841270, 0.968750, 0.968750), + (0.857143, 1.000000, 1.000000), + (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), + (0.158730, 0.937500, 0.937500), + (0.174603, 1.000000, 1.000000), + (0.507937, 1.000000, 1.000000), + (0.666667, 0.062500, 0.062500), + (0.682540, 0.000000, 0.000000), + (1.0, 0., 0.)), + 'blue': ((0., 0., 0.), + (0.333333, 0.000000, 0.000000), + (0.349206, 0.062500, 0.062500), + (0.507937, 1.000000, 1.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.937500, 0.937500), + (1.0, 0.09375, 0.09375))} + +_jet_data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), + (1, 0.5, 0.5)), + 'green': ((0., 0, 0), (0.125, 0, 0), (0.375, 1, 1), (0.64, 1, 1), + (0.91, 0, 0), (1, 0, 0)), + 'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), + (0.65, 0, 0), (1, 0, 0))} + +_pink_data = {'red': ((0., 0.1178, 0.1178), (0.015873, 0.195857, 0.195857), + (0.031746, 0.250661, 0.250661), + (0.047619, 0.295468, 0.295468), + (0.063492, 0.334324, 0.334324), + (0.079365, 0.369112, 0.369112), + (0.095238, 0.400892, 0.400892), + (0.111111, 0.430331, 0.430331), + (0.126984, 0.457882, 0.457882), + (0.142857, 0.483867, 0.483867), + (0.158730, 0.508525, 0.508525), + (0.174603, 0.532042, 0.532042), + (0.190476, 0.554563, 0.554563), + (0.206349, 0.576204, 0.576204), + (0.222222, 0.597061, 0.597061), + (0.238095, 0.617213, 0.617213), + (0.253968, 0.636729, 0.636729), + (0.269841, 0.655663, 0.655663), + (0.285714, 0.674066, 0.674066), + (0.301587, 0.691980, 0.691980), + (0.317460, 0.709441, 0.709441), + (0.333333, 0.726483, 0.726483), + (0.349206, 0.743134, 0.743134), + (0.365079, 0.759421, 0.759421), + (0.380952, 0.766356, 0.766356), + (0.396825, 0.773229, 0.773229), + (0.412698, 0.780042, 0.780042), + (0.428571, 0.786796, 0.786796), + (0.444444, 0.793492, 0.793492), + (0.460317, 0.800132, 0.800132), + (0.476190, 0.806718, 0.806718), + (0.492063, 0.813250, 0.813250), + (0.507937, 0.819730, 0.819730), + (0.523810, 0.826160, 0.826160), + (0.539683, 0.832539, 0.832539), + (0.555556, 0.838870, 0.838870), + (0.571429, 0.845154, 0.845154), + (0.587302, 0.851392, 0.851392), + (0.603175, 0.857584, 0.857584), + (0.619048, 0.863731, 0.863731), + (0.634921, 0.869835, 0.869835), + (0.650794, 0.875897, 0.875897), + (0.666667, 0.881917, 0.881917), + (0.682540, 0.887896, 0.887896), + (0.698413, 0.893835, 0.893835), + (0.714286, 0.899735, 0.899735), + (0.730159, 0.905597, 0.905597), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.517549, 0.517549), + (0.396825, 0.540674, 0.540674), + (0.412698, 0.562849, 0.562849), + (0.428571, 0.584183, 0.584183), + (0.444444, 0.604765, 0.604765), + (0.460317, 0.624669, 0.624669), + (0.476190, 0.643958, 0.643958), + (0.492063, 0.662687, 0.662687), + (0.507937, 0.680900, 0.680900), + (0.523810, 0.698638, 0.698638), + (0.539683, 0.715937, 0.715937), + (0.555556, 0.732828, 0.732828), + (0.571429, 0.749338, 0.749338), + (0.587302, 0.765493, 0.765493), + (0.603175, 0.781313, 0.781313), + (0.619048, 0.796819, 0.796819), + (0.634921, 0.812029, 0.812029), + (0.650794, 0.826960, 0.826960), + (0.666667, 0.841625, 0.841625), + (0.682540, 0.856040, 0.856040), + (0.698413, 0.870216, 0.870216), + (0.714286, 0.884164, 0.884164), + (0.730159, 0.897896, 0.897896), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)), + 'blue': ((0., 0., 0.), (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.503953, 0.503953), + (0.396825, 0.514344, 0.514344), + (0.412698, 0.524531, 0.524531), + (0.428571, 0.534522, 0.534522), + (0.444444, 0.544331, 0.544331), + (0.460317, 0.553966, 0.553966), + (0.476190, 0.563436, 0.563436), + (0.492063, 0.572750, 0.572750), + (0.507937, 0.581914, 0.581914), + (0.523810, 0.590937, 0.590937), + (0.539683, 0.599824, 0.599824), + (0.555556, 0.608581, 0.608581), + (0.571429, 0.617213, 0.617213), + (0.587302, 0.625727, 0.625727), + (0.603175, 0.634126, 0.634126), + (0.619048, 0.642416, 0.642416), + (0.634921, 0.650600, 0.650600), + (0.650794, 0.658682, 0.658682), + (0.666667, 0.666667, 0.666667), + (0.682540, 0.674556, 0.674556), + (0.698413, 0.682355, 0.682355), + (0.714286, 0.690066, 0.690066), + (0.730159, 0.697691, 0.697691), + (0.746032, 0.705234, 0.705234), + (0.761905, 0.727166, 0.727166), + (0.777778, 0.748455, 0.748455), + (0.793651, 0.769156, 0.769156), + (0.809524, 0.789314, 0.789314), + (0.825397, 0.808969, 0.808969), + (0.841270, 0.828159, 0.828159), + (0.857143, 0.846913, 0.846913), + (0.873016, 0.865261, 0.865261), + (0.888889, 0.883229, 0.883229), + (0.904762, 0.900837, 0.900837), + (0.920635, 0.918109, 0.918109), + (0.936508, 0.935061, 0.935061), + (0.952381, 0.951711, 0.951711), + (0.968254, 0.968075, 0.968075), + (0.984127, 0.984167, 0.984167), (1.0, 1.0, 1.0))} + +_spring_data = {'red': ((0., 1., 1.), (1.0, 1.0, 1.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 1., 1.), (1.0, 0.0, 0.0))} + + +_summer_data = {'red': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'green': ((0., 0.5, 0.5), (1.0, 1.0, 1.0)), + 'blue': ((0., 0.4, 0.4), (1.0, 0.4, 0.4))} + + +_winter_data = {'red': ((0., 0., 0.), (1.0, 0.0, 0.0)), + 'green': ((0., 0., 0.), (1.0, 1.0, 1.0)), + 'blue': ((0., 1., 1.), (1.0, 0.5, 0.5))} + +_nipy_spectral_data = { + 'red': [(0.0, 0.0, 0.0), (0.05, 0.4667, 0.4667), + (0.10, 0.5333, 0.5333), (0.15, 0.0, 0.0), + (0.20, 0.0, 0.0), (0.25, 0.0, 0.0), + (0.30, 0.0, 0.0), (0.35, 0.0, 0.0), + (0.40, 0.0, 0.0), (0.45, 0.0, 0.0), + (0.50, 0.0, 0.0), (0.55, 0.0, 0.0), + (0.60, 0.0, 0.0), (0.65, 0.7333, 0.7333), + (0.70, 0.9333, 0.9333), (0.75, 1.0, 1.0), + (0.80, 1.0, 1.0), (0.85, 1.0, 1.0), + (0.90, 0.8667, 0.8667), (0.95, 0.80, 0.80), + (1.0, 0.80, 0.80)], + 'green': [(0.0, 0.0, 0.0), (0.05, 0.0, 0.0), + (0.10, 0.0, 0.0), (0.15, 0.0, 0.0), + (0.20, 0.0, 0.0), (0.25, 0.4667, 0.4667), + (0.30, 0.6000, 0.6000), (0.35, 0.6667, 0.6667), + (0.40, 0.6667, 0.6667), (0.45, 0.6000, 0.6000), + (0.50, 0.7333, 0.7333), (0.55, 0.8667, 0.8667), + (0.60, 1.0, 1.0), (0.65, 1.0, 1.0), + (0.70, 0.9333, 0.9333), (0.75, 0.8000, 0.8000), + (0.80, 0.6000, 0.6000), (0.85, 0.0, 0.0), + (0.90, 0.0, 0.0), (0.95, 0.0, 0.0), + (1.0, 0.80, 0.80)], + 'blue': [(0.0, 0.0, 0.0), (0.05, 0.5333, 0.5333), + (0.10, 0.6000, 0.6000), (0.15, 0.6667, 0.6667), + (0.20, 0.8667, 0.8667), (0.25, 0.8667, 0.8667), + (0.30, 0.8667, 0.8667), (0.35, 0.6667, 0.6667), + (0.40, 0.5333, 0.5333), (0.45, 0.0, 0.0), + (0.5, 0.0, 0.0), (0.55, 0.0, 0.0), + (0.60, 0.0, 0.0), (0.65, 0.0, 0.0), + (0.70, 0.0, 0.0), (0.75, 0.0, 0.0), + (0.80, 0.0, 0.0), (0.85, 0.0, 0.0), + (0.90, 0.0, 0.0), (0.95, 0.0, 0.0), + (1.0, 0.80, 0.80)], +} + + +# 34 colormaps based on color specifications and designs +# developed by Cynthia Brewer (http://colorbrewer.org). +# The ColorBrewer palettes have been included under the terms +# of an Apache-stype license (for details, see the file +# LICENSE_COLORBREWER in the license directory of the matplotlib +# source distribution). + +# RGB values taken from Brewer's Excel sheet, divided by 255 + +_Blues_data = ( + (0.96862745098039216, 0.98431372549019602, 1.0 ), + (0.87058823529411766, 0.92156862745098034, 0.96862745098039216), + (0.77647058823529413, 0.85882352941176465, 0.93725490196078431), + (0.61960784313725492, 0.792156862745098 , 0.88235294117647056), + (0.41960784313725491, 0.68235294117647061, 0.83921568627450982), + (0.25882352941176473, 0.5725490196078431 , 0.77647058823529413), + (0.12941176470588237, 0.44313725490196076, 0.70980392156862748), + (0.03137254901960784, 0.31764705882352939, 0.61176470588235299), + (0.03137254901960784, 0.18823529411764706, 0.41960784313725491) + ) + +_BrBG_data = ( + (0.32941176470588235, 0.18823529411764706, 0.0196078431372549 ), + (0.5490196078431373 , 0.31764705882352939, 0.0392156862745098 ), + (0.74901960784313726, 0.50588235294117645, 0.17647058823529413), + (0.87450980392156863, 0.76078431372549016, 0.49019607843137253), + (0.96470588235294119, 0.90980392156862744, 0.76470588235294112), + (0.96078431372549022, 0.96078431372549022, 0.96078431372549022), + (0.7803921568627451 , 0.91764705882352937, 0.89803921568627454), + (0.50196078431372548, 0.80392156862745101, 0.75686274509803919), + (0.20784313725490197, 0.59215686274509804, 0.5607843137254902 ), + (0.00392156862745098, 0.4 , 0.36862745098039218), + (0.0 , 0.23529411764705882, 0.18823529411764706) + ) + +_BuGn_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.99215686274509807), + (0.89803921568627454, 0.96078431372549022, 0.97647058823529409), + (0.8 , 0.92549019607843142, 0.90196078431372551), + (0.6 , 0.84705882352941175, 0.78823529411764703), + (0.4 , 0.76078431372549016, 0.64313725490196083), + (0.25490196078431371, 0.68235294117647061, 0.46274509803921571), + (0.13725490196078433, 0.54509803921568623, 0.27058823529411763), + (0.0 , 0.42745098039215684, 0.17254901960784313), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_BuPu_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.99215686274509807), + (0.8784313725490196 , 0.92549019607843142, 0.95686274509803926), + (0.74901960784313726, 0.82745098039215681, 0.90196078431372551), + (0.61960784313725492, 0.73725490196078436, 0.85490196078431369), + (0.5490196078431373 , 0.58823529411764708, 0.77647058823529413), + (0.5490196078431373 , 0.41960784313725491, 0.69411764705882351), + (0.53333333333333333, 0.25490196078431371, 0.61568627450980395), + (0.50588235294117645, 0.05882352941176471, 0.48627450980392156), + (0.30196078431372547, 0.0 , 0.29411764705882354) + ) + +_GnBu_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.94117647058823528), + (0.8784313725490196 , 0.95294117647058818, 0.85882352941176465), + (0.8 , 0.92156862745098034, 0.77254901960784317), + (0.6588235294117647 , 0.8666666666666667 , 0.70980392156862748), + (0.4823529411764706 , 0.8 , 0.7686274509803922 ), + (0.30588235294117649, 0.70196078431372544, 0.82745098039215681), + (0.16862745098039217, 0.5490196078431373 , 0.74509803921568629), + (0.03137254901960784, 0.40784313725490196, 0.67450980392156867), + (0.03137254901960784, 0.25098039215686274, 0.50588235294117645) + ) + +_Greens_data = ( + (0.96862745098039216, 0.9882352941176471 , 0.96078431372549022), + (0.89803921568627454, 0.96078431372549022, 0.8784313725490196 ), + (0.7803921568627451 , 0.9137254901960784 , 0.75294117647058822), + (0.63137254901960782, 0.85098039215686272, 0.60784313725490191), + (0.45490196078431372, 0.7686274509803922 , 0.46274509803921571), + (0.25490196078431371, 0.6705882352941176 , 0.36470588235294116), + (0.13725490196078433, 0.54509803921568623, 0.27058823529411763), + (0.0 , 0.42745098039215684, 0.17254901960784313), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_Greys_data = ( + (1.0 , 1.0 , 1.0 ), + (0.94117647058823528, 0.94117647058823528, 0.94117647058823528), + (0.85098039215686272, 0.85098039215686272, 0.85098039215686272), + (0.74117647058823533, 0.74117647058823533, 0.74117647058823533), + (0.58823529411764708, 0.58823529411764708, 0.58823529411764708), + (0.45098039215686275, 0.45098039215686275, 0.45098039215686275), + (0.32156862745098042, 0.32156862745098042, 0.32156862745098042), + (0.14509803921568629, 0.14509803921568629, 0.14509803921568629), + (0.0 , 0.0 , 0.0 ) + ) + +_Oranges_data = ( + (1.0 , 0.96078431372549022, 0.92156862745098034), + (0.99607843137254903, 0.90196078431372551, 0.80784313725490198), + (0.99215686274509807, 0.81568627450980391, 0.63529411764705879), + (0.99215686274509807, 0.68235294117647061, 0.41960784313725491), + (0.99215686274509807, 0.55294117647058827, 0.23529411764705882), + (0.94509803921568625, 0.41176470588235292, 0.07450980392156863), + (0.85098039215686272, 0.28235294117647058, 0.00392156862745098), + (0.65098039215686276, 0.21176470588235294, 0.01176470588235294), + (0.49803921568627452, 0.15294117647058825, 0.01568627450980392) + ) + +_OrRd_data = ( + (1.0 , 0.96862745098039216, 0.92549019607843142), + (0.99607843137254903, 0.90980392156862744, 0.78431372549019607), + (0.99215686274509807, 0.83137254901960789, 0.61960784313725492), + (0.99215686274509807, 0.73333333333333328, 0.51764705882352946), + (0.9882352941176471 , 0.55294117647058827, 0.34901960784313724), + (0.93725490196078431, 0.396078431372549 , 0.28235294117647058), + (0.84313725490196079, 0.18823529411764706, 0.12156862745098039), + (0.70196078431372544, 0.0 , 0.0 ), + (0.49803921568627452, 0.0 , 0.0 ) + ) + +_PiYG_data = ( + (0.55686274509803924, 0.00392156862745098, 0.32156862745098042), + (0.77254901960784317, 0.10588235294117647, 0.49019607843137253), + (0.87058823529411766, 0.46666666666666667, 0.68235294117647061), + (0.94509803921568625, 0.71372549019607845, 0.85490196078431369), + (0.99215686274509807, 0.8784313725490196 , 0.93725490196078431), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.90196078431372551, 0.96078431372549022, 0.81568627450980391), + (0.72156862745098038, 0.88235294117647056, 0.52549019607843139), + (0.49803921568627452, 0.73725490196078436, 0.25490196078431371), + (0.30196078431372547, 0.5725490196078431 , 0.12941176470588237), + (0.15294117647058825, 0.39215686274509803, 0.09803921568627451) + ) + +_PRGn_data = ( + (0.25098039215686274, 0.0 , 0.29411764705882354), + (0.46274509803921571, 0.16470588235294117, 0.51372549019607838), + (0.6 , 0.4392156862745098 , 0.6705882352941176 ), + (0.76078431372549016, 0.6470588235294118 , 0.81176470588235294), + (0.90588235294117647, 0.83137254901960789, 0.90980392156862744), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.85098039215686272, 0.94117647058823528, 0.82745098039215681), + (0.65098039215686276, 0.85882352941176465, 0.62745098039215685), + (0.35294117647058826, 0.68235294117647061, 0.38039215686274508), + (0.10588235294117647, 0.47058823529411764, 0.21568627450980393), + (0.0 , 0.26666666666666666, 0.10588235294117647) + ) + +_PuBu_data = ( + (1.0 , 0.96862745098039216, 0.98431372549019602), + (0.92549019607843142, 0.90588235294117647, 0.94901960784313721), + (0.81568627450980391, 0.81960784313725488, 0.90196078431372551), + (0.65098039215686276, 0.74117647058823533, 0.85882352941176465), + (0.45490196078431372, 0.66274509803921566, 0.81176470588235294), + (0.21176470588235294, 0.56470588235294117, 0.75294117647058822), + (0.0196078431372549 , 0.4392156862745098 , 0.69019607843137254), + (0.01568627450980392, 0.35294117647058826, 0.55294117647058827), + (0.00784313725490196, 0.2196078431372549 , 0.34509803921568627) + ) + +_PuBuGn_data = ( + (1.0 , 0.96862745098039216, 0.98431372549019602), + (0.92549019607843142, 0.88627450980392153, 0.94117647058823528), + (0.81568627450980391, 0.81960784313725488, 0.90196078431372551), + (0.65098039215686276, 0.74117647058823533, 0.85882352941176465), + (0.40392156862745099, 0.66274509803921566, 0.81176470588235294), + (0.21176470588235294, 0.56470588235294117, 0.75294117647058822), + (0.00784313725490196, 0.50588235294117645, 0.54117647058823526), + (0.00392156862745098, 0.42352941176470588, 0.34901960784313724), + (0.00392156862745098, 0.27450980392156865, 0.21176470588235294) + ) + +_PuOr_data = ( + (0.49803921568627452, 0.23137254901960785, 0.03137254901960784), + (0.70196078431372544, 0.34509803921568627, 0.02352941176470588), + (0.8784313725490196 , 0.50980392156862742, 0.07843137254901961), + (0.99215686274509807, 0.72156862745098038, 0.38823529411764707), + (0.99607843137254903, 0.8784313725490196 , 0.71372549019607845), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.84705882352941175, 0.85490196078431369, 0.92156862745098034), + (0.69803921568627447, 0.6705882352941176 , 0.82352941176470584), + (0.50196078431372548, 0.45098039215686275, 0.67450980392156867), + (0.32941176470588235, 0.15294117647058825, 0.53333333333333333), + (0.17647058823529413, 0.0 , 0.29411764705882354) + ) + +_PuRd_data = ( + (0.96862745098039216, 0.95686274509803926, 0.97647058823529409), + (0.90588235294117647, 0.88235294117647056, 0.93725490196078431), + (0.83137254901960789, 0.72549019607843135, 0.85490196078431369), + (0.78823529411764703, 0.58039215686274515, 0.7803921568627451 ), + (0.87450980392156863, 0.396078431372549 , 0.69019607843137254), + (0.90588235294117647, 0.16078431372549021, 0.54117647058823526), + (0.80784313725490198, 0.07058823529411765, 0.33725490196078434), + (0.59607843137254901, 0.0 , 0.2627450980392157 ), + (0.40392156862745099, 0.0 , 0.12156862745098039) + ) + +_Purples_data = ( + (0.9882352941176471 , 0.98431372549019602, 0.99215686274509807), + (0.93725490196078431, 0.92941176470588238, 0.96078431372549022), + (0.85490196078431369, 0.85490196078431369, 0.92156862745098034), + (0.73725490196078436, 0.74117647058823533, 0.86274509803921573), + (0.61960784313725492, 0.60392156862745094, 0.78431372549019607), + (0.50196078431372548, 0.49019607843137253, 0.72941176470588232), + (0.41568627450980394, 0.31764705882352939, 0.63921568627450975), + (0.32941176470588235, 0.15294117647058825, 0.5607843137254902 ), + (0.24705882352941178, 0.0 , 0.49019607843137253) + ) + +_RdBu_data = ( + (0.40392156862745099, 0.0 , 0.12156862745098039), + (0.69803921568627447, 0.09411764705882353, 0.16862745098039217), + (0.83921568627450982, 0.37647058823529411, 0.30196078431372547), + (0.95686274509803926, 0.6470588235294118 , 0.50980392156862742), + (0.99215686274509807, 0.85882352941176465, 0.7803921568627451 ), + (0.96862745098039216, 0.96862745098039216, 0.96862745098039216), + (0.81960784313725488, 0.89803921568627454, 0.94117647058823528), + (0.5725490196078431 , 0.77254901960784317, 0.87058823529411766), + (0.2627450980392157 , 0.57647058823529407, 0.76470588235294112), + (0.12941176470588237, 0.4 , 0.67450980392156867), + (0.0196078431372549 , 0.18823529411764706, 0.38039215686274508) + ) + +_RdGy_data = ( + (0.40392156862745099, 0.0 , 0.12156862745098039), + (0.69803921568627447, 0.09411764705882353, 0.16862745098039217), + (0.83921568627450982, 0.37647058823529411, 0.30196078431372547), + (0.95686274509803926, 0.6470588235294118 , 0.50980392156862742), + (0.99215686274509807, 0.85882352941176465, 0.7803921568627451 ), + (1.0 , 1.0 , 1.0 ), + (0.8784313725490196 , 0.8784313725490196 , 0.8784313725490196 ), + (0.72941176470588232, 0.72941176470588232, 0.72941176470588232), + (0.52941176470588236, 0.52941176470588236, 0.52941176470588236), + (0.30196078431372547, 0.30196078431372547, 0.30196078431372547), + (0.10196078431372549, 0.10196078431372549, 0.10196078431372549) + ) + +_RdPu_data = ( + (1.0 , 0.96862745098039216, 0.95294117647058818), + (0.99215686274509807, 0.8784313725490196 , 0.86666666666666667), + (0.9882352941176471 , 0.77254901960784317, 0.75294117647058822), + (0.98039215686274506, 0.62352941176470589, 0.70980392156862748), + (0.96862745098039216, 0.40784313725490196, 0.63137254901960782), + (0.86666666666666667, 0.20392156862745098, 0.59215686274509804), + (0.68235294117647061, 0.00392156862745098, 0.49411764705882355), + (0.47843137254901963, 0.00392156862745098, 0.46666666666666667), + (0.28627450980392155, 0.0 , 0.41568627450980394) + ) + +_RdYlBu_data = ( + (0.6470588235294118 , 0.0 , 0.14901960784313725), + (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.56470588235294117), + (1.0 , 1.0 , 0.74901960784313726), + (0.8784313725490196 , 0.95294117647058818 , 0.97254901960784312), + (0.6705882352941176 , 0.85098039215686272 , 0.9137254901960784 ), + (0.45490196078431372, 0.67843137254901964 , 0.81960784313725488), + (0.27058823529411763, 0.45882352941176469 , 0.70588235294117652), + (0.19215686274509805, 0.21176470588235294 , 0.58431372549019611) + ) + +_RdYlGn_data = ( + (0.6470588235294118 , 0.0 , 0.14901960784313725), + (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.54509803921568623), + (1.0 , 1.0 , 0.74901960784313726), + (0.85098039215686272, 0.93725490196078431 , 0.54509803921568623), + (0.65098039215686276, 0.85098039215686272 , 0.41568627450980394), + (0.4 , 0.74117647058823533 , 0.38823529411764707), + (0.10196078431372549, 0.59607843137254901 , 0.31372549019607843), + (0.0 , 0.40784313725490196 , 0.21568627450980393) + ) + +_Reds_data = ( + (1.0 , 0.96078431372549022 , 0.94117647058823528), + (0.99607843137254903, 0.8784313725490196 , 0.82352941176470584), + (0.9882352941176471 , 0.73333333333333328 , 0.63137254901960782), + (0.9882352941176471 , 0.5725490196078431 , 0.44705882352941179), + (0.98431372549019602, 0.41568627450980394 , 0.29019607843137257), + (0.93725490196078431, 0.23137254901960785 , 0.17254901960784313), + (0.79607843137254897, 0.094117647058823528, 0.11372549019607843), + (0.6470588235294118 , 0.058823529411764705, 0.08235294117647058), + (0.40392156862745099, 0.0 , 0.05098039215686274) + ) + +_Spectral_data = ( + (0.61960784313725492, 0.003921568627450980, 0.25882352941176473), + (0.83529411764705885, 0.24313725490196078 , 0.30980392156862746), + (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ), + (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508), + (0.99607843137254903, 0.8784313725490196 , 0.54509803921568623), + (1.0 , 1.0 , 0.74901960784313726), + (0.90196078431372551, 0.96078431372549022 , 0.59607843137254901), + (0.6705882352941176 , 0.8666666666666667 , 0.64313725490196083), + (0.4 , 0.76078431372549016 , 0.6470588235294118 ), + (0.19607843137254902, 0.53333333333333333 , 0.74117647058823533), + (0.36862745098039218, 0.30980392156862746 , 0.63529411764705879) + ) + +_YlGn_data = ( + (1.0 , 1.0 , 0.89803921568627454), + (0.96862745098039216, 0.9882352941176471 , 0.72549019607843135), + (0.85098039215686272, 0.94117647058823528 , 0.63921568627450975), + (0.67843137254901964, 0.8666666666666667 , 0.55686274509803924), + (0.47058823529411764, 0.77647058823529413 , 0.47450980392156861), + (0.25490196078431371, 0.6705882352941176 , 0.36470588235294116), + (0.13725490196078433, 0.51764705882352946 , 0.2627450980392157 ), + (0.0 , 0.40784313725490196 , 0.21568627450980393), + (0.0 , 0.27058823529411763 , 0.16078431372549021) + ) + +_YlGnBu_data = ( + (1.0 , 1.0 , 0.85098039215686272), + (0.92941176470588238, 0.97254901960784312 , 0.69411764705882351), + (0.7803921568627451 , 0.9137254901960784 , 0.70588235294117652), + (0.49803921568627452, 0.80392156862745101 , 0.73333333333333328), + (0.25490196078431371, 0.71372549019607845 , 0.7686274509803922 ), + (0.11372549019607843, 0.56862745098039214 , 0.75294117647058822), + (0.13333333333333333, 0.36862745098039218 , 0.6588235294117647 ), + (0.14509803921568629, 0.20392156862745098 , 0.58039215686274515), + (0.03137254901960784, 0.11372549019607843 , 0.34509803921568627) + ) + +_YlOrBr_data = ( + (1.0 , 1.0 , 0.89803921568627454), + (1.0 , 0.96862745098039216 , 0.73725490196078436), + (0.99607843137254903, 0.8901960784313725 , 0.56862745098039214), + (0.99607843137254903, 0.7686274509803922 , 0.30980392156862746), + (0.99607843137254903, 0.6 , 0.16078431372549021), + (0.92549019607843142, 0.4392156862745098 , 0.07843137254901961), + (0.8 , 0.29803921568627451 , 0.00784313725490196), + (0.6 , 0.20392156862745098 , 0.01568627450980392), + (0.4 , 0.14509803921568629 , 0.02352941176470588) + ) + +_YlOrRd_data = ( + (1.0 , 1.0 , 0.8 ), + (1.0 , 0.92941176470588238 , 0.62745098039215685), + (0.99607843137254903, 0.85098039215686272 , 0.46274509803921571), + (0.99607843137254903, 0.69803921568627447 , 0.29803921568627451), + (0.99215686274509807, 0.55294117647058827 , 0.23529411764705882), + (0.9882352941176471 , 0.30588235294117649 , 0.16470588235294117), + (0.8901960784313725 , 0.10196078431372549 , 0.10980392156862745), + (0.74117647058823533, 0.0 , 0.14901960784313725), + (0.50196078431372548, 0.0 , 0.14901960784313725) + ) + + +# ColorBrewer's qualitative maps, implemented using ListedColormap +# for use with mpl.colors.NoNorm + +_Accent_data = ( + (0.49803921568627452, 0.78823529411764703, 0.49803921568627452), + (0.74509803921568629, 0.68235294117647061, 0.83137254901960789), + (0.99215686274509807, 0.75294117647058822, 0.52549019607843139), + (1.0, 1.0, 0.6 ), + (0.2196078431372549, 0.42352941176470588, 0.69019607843137254), + (0.94117647058823528, 0.00784313725490196, 0.49803921568627452), + (0.74901960784313726, 0.35686274509803922, 0.09019607843137254), + (0.4, 0.4, 0.4 ), + ) + +_Dark2_data = ( + (0.10588235294117647, 0.61960784313725492, 0.46666666666666667), + (0.85098039215686272, 0.37254901960784315, 0.00784313725490196), + (0.45882352941176469, 0.4392156862745098, 0.70196078431372544), + (0.90588235294117647, 0.16078431372549021, 0.54117647058823526), + (0.4, 0.65098039215686276, 0.11764705882352941), + (0.90196078431372551, 0.6705882352941176, 0.00784313725490196), + (0.65098039215686276, 0.46274509803921571, 0.11372549019607843), + (0.4, 0.4, 0.4 ), + ) + +_Paired_data = ( + (0.65098039215686276, 0.80784313725490198, 0.8901960784313725 ), + (0.12156862745098039, 0.47058823529411764, 0.70588235294117652), + (0.69803921568627447, 0.87450980392156863, 0.54117647058823526), + (0.2, 0.62745098039215685, 0.17254901960784313), + (0.98431372549019602, 0.60392156862745094, 0.6 ), + (0.8901960784313725, 0.10196078431372549, 0.10980392156862745), + (0.99215686274509807, 0.74901960784313726, 0.43529411764705883), + (1.0, 0.49803921568627452, 0.0 ), + (0.792156862745098, 0.69803921568627447, 0.83921568627450982), + (0.41568627450980394, 0.23921568627450981, 0.60392156862745094), + (1.0, 1.0, 0.6 ), + (0.69411764705882351, 0.34901960784313724, 0.15686274509803921), + ) + +_Pastel1_data = ( + (0.98431372549019602, 0.70588235294117652, 0.68235294117647061), + (0.70196078431372544, 0.80392156862745101, 0.8901960784313725 ), + (0.8, 0.92156862745098034, 0.77254901960784317), + (0.87058823529411766, 0.79607843137254897, 0.89411764705882357), + (0.99607843137254903, 0.85098039215686272, 0.65098039215686276), + (1.0, 1.0, 0.8 ), + (0.89803921568627454, 0.84705882352941175, 0.74117647058823533), + (0.99215686274509807, 0.85490196078431369, 0.92549019607843142), + (0.94901960784313721, 0.94901960784313721, 0.94901960784313721), + ) + +_Pastel2_data = ( + (0.70196078431372544, 0.88627450980392153, 0.80392156862745101), + (0.99215686274509807, 0.80392156862745101, 0.67450980392156867), + (0.79607843137254897, 0.83529411764705885, 0.90980392156862744), + (0.95686274509803926, 0.792156862745098, 0.89411764705882357), + (0.90196078431372551, 0.96078431372549022, 0.78823529411764703), + (1.0, 0.94901960784313721, 0.68235294117647061), + (0.94509803921568625, 0.88627450980392153, 0.8 ), + (0.8, 0.8, 0.8 ), + ) + +_Set1_data = ( + (0.89411764705882357, 0.10196078431372549, 0.10980392156862745), + (0.21568627450980393, 0.49411764705882355, 0.72156862745098038), + (0.30196078431372547, 0.68627450980392157, 0.29019607843137257), + (0.59607843137254901, 0.30588235294117649, 0.63921568627450975), + (1.0, 0.49803921568627452, 0.0 ), + (1.0, 1.0, 0.2 ), + (0.65098039215686276, 0.33725490196078434, 0.15686274509803921), + (0.96862745098039216, 0.50588235294117645, 0.74901960784313726), + (0.6, 0.6, 0.6), + ) + +_Set2_data = ( + (0.4, 0.76078431372549016, 0.6470588235294118 ), + (0.9882352941176471, 0.55294117647058827, 0.3843137254901961 ), + (0.55294117647058827, 0.62745098039215685, 0.79607843137254897), + (0.90588235294117647, 0.54117647058823526, 0.76470588235294112), + (0.65098039215686276, 0.84705882352941175, 0.32941176470588235), + (1.0, 0.85098039215686272, 0.18431372549019609), + (0.89803921568627454, 0.7686274509803922, 0.58039215686274515), + (0.70196078431372544, 0.70196078431372544, 0.70196078431372544), + ) + +_Set3_data = ( + (0.55294117647058827, 0.82745098039215681, 0.7803921568627451 ), + (1.0, 1.0, 0.70196078431372544), + (0.74509803921568629, 0.72941176470588232, 0.85490196078431369), + (0.98431372549019602, 0.50196078431372548, 0.44705882352941179), + (0.50196078431372548, 0.69411764705882351, 0.82745098039215681), + (0.99215686274509807, 0.70588235294117652, 0.3843137254901961 ), + (0.70196078431372544, 0.87058823529411766, 0.41176470588235292), + (0.9882352941176471, 0.80392156862745101, 0.89803921568627454), + (0.85098039215686272, 0.85098039215686272, 0.85098039215686272), + (0.73725490196078436, 0.50196078431372548, 0.74117647058823533), + (0.8, 0.92156862745098034, 0.77254901960784317), + (1.0, 0.92941176470588238, 0.43529411764705883), + ) + + +# The next 7 palettes are from the Yorick scientific visalisation package, +# an evolution of the GIST package, both by David H. Munro. +# They are released under a BSD-like license (see LICENSE_YORICK in +# the license directory of the matplotlib source distribution). +# +# Most palette functions have been reduced to simple function descriptions +# by Reinier Heeres, since the rgb components were mostly straight lines. +# gist_earth_data and gist_ncar_data were simplified by a script and some +# manual effort. + +_gist_earth_data = \ +{'red': ( +(0.0, 0.0, 0.0000), +(0.2824, 0.1882, 0.1882), +(0.4588, 0.2714, 0.2714), +(0.5490, 0.4719, 0.4719), +(0.6980, 0.7176, 0.7176), +(0.7882, 0.7553, 0.7553), +(1.0000, 0.9922, 0.9922), +), 'green': ( +(0.0, 0.0, 0.0000), +(0.0275, 0.0000, 0.0000), +(0.1098, 0.1893, 0.1893), +(0.1647, 0.3035, 0.3035), +(0.2078, 0.3841, 0.3841), +(0.2824, 0.5020, 0.5020), +(0.5216, 0.6397, 0.6397), +(0.6980, 0.7171, 0.7171), +(0.7882, 0.6392, 0.6392), +(0.7922, 0.6413, 0.6413), +(0.8000, 0.6447, 0.6447), +(0.8078, 0.6481, 0.6481), +(0.8157, 0.6549, 0.6549), +(0.8667, 0.6991, 0.6991), +(0.8745, 0.7103, 0.7103), +(0.8824, 0.7216, 0.7216), +(0.8902, 0.7323, 0.7323), +(0.8980, 0.7430, 0.7430), +(0.9412, 0.8275, 0.8275), +(0.9569, 0.8635, 0.8635), +(0.9647, 0.8816, 0.8816), +(0.9961, 0.9733, 0.9733), +(1.0000, 0.9843, 0.9843), +), 'blue': ( +(0.0, 0.0, 0.0000), +(0.0039, 0.1684, 0.1684), +(0.0078, 0.2212, 0.2212), +(0.0275, 0.4329, 0.4329), +(0.0314, 0.4549, 0.4549), +(0.2824, 0.5004, 0.5004), +(0.4667, 0.2748, 0.2748), +(0.5451, 0.3205, 0.3205), +(0.7843, 0.3961, 0.3961), +(0.8941, 0.6651, 0.6651), +(1.0000, 0.9843, 0.9843), +)} + +_gist_gray_data = { + 'red': gfunc[3], + 'green': gfunc[3], + 'blue': gfunc[3], +} + +_gist_heat_data = { + 'red': lambda x: 1.5 * x, + 'green': lambda x: 2 * x - 1, + 'blue': lambda x: 4 * x - 3, +} + +_gist_ncar_data = \ +{'red': ( +(0.0, 0.0, 0.0000), +(0.3098, 0.0000, 0.0000), +(0.3725, 0.3993, 0.3993), +(0.4235, 0.5003, 0.5003), +(0.5333, 1.0000, 1.0000), +(0.7922, 1.0000, 1.0000), +(0.8471, 0.6218, 0.6218), +(0.8980, 0.9235, 0.9235), +(1.0000, 0.9961, 0.9961), +), 'green': ( +(0.0, 0.0, 0.0000), +(0.0510, 0.3722, 0.3722), +(0.1059, 0.0000, 0.0000), +(0.1569, 0.7202, 0.7202), +(0.1608, 0.7537, 0.7537), +(0.1647, 0.7752, 0.7752), +(0.2157, 1.0000, 1.0000), +(0.2588, 0.9804, 0.9804), +(0.2706, 0.9804, 0.9804), +(0.3176, 1.0000, 1.0000), +(0.3686, 0.8081, 0.8081), +(0.4275, 1.0000, 1.0000), +(0.5216, 1.0000, 1.0000), +(0.6314, 0.7292, 0.7292), +(0.6863, 0.2796, 0.2796), +(0.7451, 0.0000, 0.0000), +(0.7922, 0.0000, 0.0000), +(0.8431, 0.1753, 0.1753), +(0.8980, 0.5000, 0.5000), +(1.0000, 0.9725, 0.9725), +), 'blue': ( +(0.0, 0.5020, 0.5020), +(0.0510, 0.0222, 0.0222), +(0.1098, 1.0000, 1.0000), +(0.2039, 1.0000, 1.0000), +(0.2627, 0.6145, 0.6145), +(0.3216, 0.0000, 0.0000), +(0.4157, 0.0000, 0.0000), +(0.4745, 0.2342, 0.2342), +(0.5333, 0.0000, 0.0000), +(0.5804, 0.0000, 0.0000), +(0.6314, 0.0549, 0.0549), +(0.6902, 0.0000, 0.0000), +(0.7373, 0.0000, 0.0000), +(0.7922, 0.9738, 0.9738), +(0.8000, 1.0000, 1.0000), +(0.8431, 1.0000, 1.0000), +(0.8980, 0.9341, 0.9341), +(1.0000, 0.9961, 0.9961), +)} + +_gist_rainbow_data = ( + (0.000, (1.00, 0.00, 0.16)), + (0.030, (1.00, 0.00, 0.00)), + (0.215, (1.00, 1.00, 0.00)), + (0.400, (0.00, 1.00, 0.00)), + (0.586, (0.00, 1.00, 1.00)), + (0.770, (0.00, 0.00, 1.00)), + (0.954, (1.00, 0.00, 1.00)), + (1.000, (1.00, 0.00, 0.75)) +) + +_gist_stern_data = { + 'red': ( + (0.000, 0.000, 0.000), (0.0547, 1.000, 1.000), + (0.250, 0.027, 0.250), # (0.2500, 0.250, 0.250), + (1.000, 1.000, 1.000)), + 'green': ((0, 0, 0), (1, 1, 1)), + 'blue': ( + (0.000, 0.000, 0.000), (0.500, 1.000, 1.000), + (0.735, 0.000, 0.000), (1.000, 1.000, 1.000)) +} + +_gist_yarg_data = { + 'red': lambda x: 1 - x, + 'green': lambda x: 1 - x, + 'blue': lambda x: 1 - x, +} + +# This bipolar color map was generated from CoolWarmFloat33.csv of +# "Diverging Color Maps for Scientific Visualization" by Kenneth Moreland. +# +_coolwarm_data = { + 'red': [ + (0.0, 0.2298057, 0.2298057), + (0.03125, 0.26623388, 0.26623388), + (0.0625, 0.30386891, 0.30386891), + (0.09375, 0.342804478, 0.342804478), + (0.125, 0.38301334, 0.38301334), + (0.15625, 0.424369608, 0.424369608), + (0.1875, 0.46666708, 0.46666708), + (0.21875, 0.509635204, 0.509635204), + (0.25, 0.552953156, 0.552953156), + (0.28125, 0.596262162, 0.596262162), + (0.3125, 0.639176211, 0.639176211), + (0.34375, 0.681291281, 0.681291281), + (0.375, 0.722193294, 0.722193294), + (0.40625, 0.761464949, 0.761464949), + (0.4375, 0.798691636, 0.798691636), + (0.46875, 0.833466556, 0.833466556), + (0.5, 0.865395197, 0.865395197), + (0.53125, 0.897787179, 0.897787179), + (0.5625, 0.924127593, 0.924127593), + (0.59375, 0.944468518, 0.944468518), + (0.625, 0.958852946, 0.958852946), + (0.65625, 0.96732803, 0.96732803), + (0.6875, 0.969954137, 0.969954137), + (0.71875, 0.966811177, 0.966811177), + (0.75, 0.958003065, 0.958003065), + (0.78125, 0.943660866, 0.943660866), + (0.8125, 0.923944917, 0.923944917), + (0.84375, 0.89904617, 0.89904617), + (0.875, 0.869186849, 0.869186849), + (0.90625, 0.834620542, 0.834620542), + (0.9375, 0.795631745, 0.795631745), + (0.96875, 0.752534934, 0.752534934), + (1.0, 0.705673158, 0.705673158)], + 'green': [ + (0.0, 0.298717966, 0.298717966), + (0.03125, 0.353094838, 0.353094838), + (0.0625, 0.406535296, 0.406535296), + (0.09375, 0.458757618, 0.458757618), + (0.125, 0.50941904, 0.50941904), + (0.15625, 0.558148092, 0.558148092), + (0.1875, 0.604562568, 0.604562568), + (0.21875, 0.648280772, 0.648280772), + (0.25, 0.688929332, 0.688929332), + (0.28125, 0.726149107, 0.726149107), + (0.3125, 0.759599947, 0.759599947), + (0.34375, 0.788964712, 0.788964712), + (0.375, 0.813952739, 0.813952739), + (0.40625, 0.834302879, 0.834302879), + (0.4375, 0.849786142, 0.849786142), + (0.46875, 0.860207984, 0.860207984), + (0.5, 0.86541021, 0.86541021), + (0.53125, 0.848937047, 0.848937047), + (0.5625, 0.827384882, 0.827384882), + (0.59375, 0.800927443, 0.800927443), + (0.625, 0.769767752, 0.769767752), + (0.65625, 0.734132809, 0.734132809), + (0.6875, 0.694266682, 0.694266682), + (0.71875, 0.650421156, 0.650421156), + (0.75, 0.602842431, 0.602842431), + (0.78125, 0.551750968, 0.551750968), + (0.8125, 0.49730856, 0.49730856), + (0.84375, 0.439559467, 0.439559467), + (0.875, 0.378313092, 0.378313092), + (0.90625, 0.312874446, 0.312874446), + (0.9375, 0.24128379, 0.24128379), + (0.96875, 0.157246067, 0.157246067), + (1.0, 0.01555616, 0.01555616)], + 'blue': [ + (0.0, 0.753683153, 0.753683153), + (0.03125, 0.801466763, 0.801466763), + (0.0625, 0.84495867, 0.84495867), + (0.09375, 0.883725899, 0.883725899), + (0.125, 0.917387822, 0.917387822), + (0.15625, 0.945619588, 0.945619588), + (0.1875, 0.968154911, 0.968154911), + (0.21875, 0.98478814, 0.98478814), + (0.25, 0.995375608, 0.995375608), + (0.28125, 0.999836203, 0.999836203), + (0.3125, 0.998151185, 0.998151185), + (0.34375, 0.990363227, 0.990363227), + (0.375, 0.976574709, 0.976574709), + (0.40625, 0.956945269, 0.956945269), + (0.4375, 0.931688648, 0.931688648), + (0.46875, 0.901068838, 0.901068838), + (0.5, 0.865395561, 0.865395561), + (0.53125, 0.820880546, 0.820880546), + (0.5625, 0.774508472, 0.774508472), + (0.59375, 0.726736146, 0.726736146), + (0.625, 0.678007945, 0.678007945), + (0.65625, 0.628751763, 0.628751763), + (0.6875, 0.579375448, 0.579375448), + (0.71875, 0.530263762, 0.530263762), + (0.75, 0.481775914, 0.481775914), + (0.78125, 0.434243684, 0.434243684), + (0.8125, 0.387970225, 0.387970225), + (0.84375, 0.343229596, 0.343229596), + (0.875, 0.300267182, 0.300267182), + (0.90625, 0.259301199, 0.259301199), + (0.9375, 0.220525627, 0.220525627), + (0.96875, 0.184115123, 0.184115123), + (1.0, 0.150232812, 0.150232812)] + } + +# Implementation of Carey Rappaport's CMRmap. +# See `A Color Map for Effective Black-and-White Rendering of Color-Scale +# Images' by Carey Rappaport +# http://www.mathworks.com/matlabcentral/fileexchange/2662-cmrmap-m +_CMRmap_data = {'red': ((0.000, 0.00, 0.00), + (0.125, 0.15, 0.15), + (0.250, 0.30, 0.30), + (0.375, 0.60, 0.60), + (0.500, 1.00, 1.00), + (0.625, 0.90, 0.90), + (0.750, 0.90, 0.90), + (0.875, 0.90, 0.90), + (1.000, 1.00, 1.00)), + 'green': ((0.000, 0.00, 0.00), + (0.125, 0.15, 0.15), + (0.250, 0.15, 0.15), + (0.375, 0.20, 0.20), + (0.500, 0.25, 0.25), + (0.625, 0.50, 0.50), + (0.750, 0.75, 0.75), + (0.875, 0.90, 0.90), + (1.000, 1.00, 1.00)), + 'blue': ((0.000, 0.00, 0.00), + (0.125, 0.50, 0.50), + (0.250, 0.75, 0.75), + (0.375, 0.50, 0.50), + (0.500, 0.15, 0.15), + (0.625, 0.00, 0.00), + (0.750, 0.10, 0.10), + (0.875, 0.50, 0.50), + (1.000, 1.00, 1.00))} + + +# An MIT licensed, colorblind-friendly heatmap from Wistia: +# https://github.com/wistia/heatmap-palette +# http://wistia.com/blog/heatmaps-for-colorblindness +# +# >>> import matplotlib.colors as c +# >>> colors = ["#e4ff7a", "#ffe81a", "#ffbd00", "#ffa000", "#fc7f00"] +# >>> cm = c.LinearSegmentedColormap.from_list('wistia', colors) +# >>> _wistia_data = cm._segmentdata +# >>> del _wistia_data['alpha'] +# +_wistia_data = { + 'red': [(0.0, 0.8941176470588236, 0.8941176470588236), + (0.25, 1.0, 1.0), + (0.5, 1.0, 1.0), + (0.75, 1.0, 1.0), + (1.0, 0.9882352941176471, 0.9882352941176471)], + 'green': [(0.0, 1.0, 1.0), + (0.25, 0.9098039215686274, 0.9098039215686274), + (0.5, 0.7411764705882353, 0.7411764705882353), + (0.75, 0.6274509803921569, 0.6274509803921569), + (1.0, 0.4980392156862745, 0.4980392156862745)], + 'blue': [(0.0, 0.47843137254901963, 0.47843137254901963), + (0.25, 0.10196078431372549, 0.10196078431372549), + (0.5, 0.0, 0.0), + (0.75, 0.0, 0.0), + (1.0, 0.0, 0.0)], +} + + +# Categorical palettes from Vega: +# https://github.com/vega/vega/wiki/Scales +# (divided by 255) +# + +_tab10_data = ( + (0.12156862745098039, 0.4666666666666667, 0.7058823529411765 ), # 1f77b4 + (1.0, 0.4980392156862745, 0.054901960784313725), # ff7f0e + (0.17254901960784313, 0.6274509803921569, 0.17254901960784313 ), # 2ca02c + (0.8392156862745098, 0.15294117647058825, 0.1568627450980392 ), # d62728 + (0.5803921568627451, 0.403921568627451, 0.7411764705882353 ), # 9467bd + (0.5490196078431373, 0.33725490196078434, 0.29411764705882354 ), # 8c564b + (0.8901960784313725, 0.4666666666666667, 0.7607843137254902 ), # e377c2 + (0.4980392156862745, 0.4980392156862745, 0.4980392156862745 ), # 7f7f7f + (0.7372549019607844, 0.7411764705882353, 0.13333333333333333 ), # bcbd22 + (0.09019607843137255, 0.7450980392156863, 0.8117647058823529), # 17becf +) + +_tab20_data = ( + (0.12156862745098039, 0.4666666666666667, 0.7058823529411765 ), # 1f77b4 + (0.6823529411764706, 0.7803921568627451, 0.9098039215686274 ), # aec7e8 + (1.0, 0.4980392156862745, 0.054901960784313725), # ff7f0e + (1.0, 0.7333333333333333, 0.47058823529411764 ), # ffbb78 + (0.17254901960784313, 0.6274509803921569, 0.17254901960784313 ), # 2ca02c + (0.596078431372549, 0.8745098039215686, 0.5411764705882353 ), # 98df8a + (0.8392156862745098, 0.15294117647058825, 0.1568627450980392 ), # d62728 + (1.0, 0.596078431372549, 0.5882352941176471 ), # ff9896 + (0.5803921568627451, 0.403921568627451, 0.7411764705882353 ), # 9467bd + (0.7725490196078432, 0.6901960784313725, 0.8352941176470589 ), # c5b0d5 + (0.5490196078431373, 0.33725490196078434, 0.29411764705882354 ), # 8c564b + (0.7686274509803922, 0.611764705882353, 0.5803921568627451 ), # c49c94 + (0.8901960784313725, 0.4666666666666667, 0.7607843137254902 ), # e377c2 + (0.9686274509803922, 0.7137254901960784, 0.8235294117647058 ), # f7b6d2 + (0.4980392156862745, 0.4980392156862745, 0.4980392156862745 ), # 7f7f7f + (0.7803921568627451, 0.7803921568627451, 0.7803921568627451 ), # c7c7c7 + (0.7372549019607844, 0.7411764705882353, 0.13333333333333333 ), # bcbd22 + (0.8588235294117647, 0.8588235294117647, 0.5529411764705883 ), # dbdb8d + (0.09019607843137255, 0.7450980392156863, 0.8117647058823529 ), # 17becf + (0.6196078431372549, 0.8549019607843137, 0.8980392156862745), # 9edae5 +) + +_tab20b_data = ( + (0.2235294117647059, 0.23137254901960785, 0.4745098039215686 ), # 393b79 + (0.3215686274509804, 0.32941176470588235, 0.6392156862745098 ), # 5254a3 + (0.4196078431372549, 0.43137254901960786, 0.8117647058823529 ), # 6b6ecf + (0.611764705882353, 0.6196078431372549, 0.8705882352941177 ), # 9c9ede + (0.38823529411764707, 0.4745098039215686, 0.2235294117647059 ), # 637939 + (0.5490196078431373, 0.6352941176470588, 0.3215686274509804 ), # 8ca252 + (0.7098039215686275, 0.8117647058823529, 0.4196078431372549 ), # b5cf6b + (0.807843137254902, 0.8588235294117647, 0.611764705882353 ), # cedb9c + (0.5490196078431373, 0.42745098039215684, 0.19215686274509805), # 8c6d31 + (0.7411764705882353, 0.6196078431372549, 0.2235294117647059 ), # bd9e39 + (0.9058823529411765, 0.7294117647058823, 0.3215686274509804 ), # e7ba52 + (0.9058823529411765, 0.796078431372549, 0.5803921568627451 ), # e7cb94 + (0.5176470588235295, 0.23529411764705882, 0.2235294117647059 ), # 843c39 + (0.6784313725490196, 0.28627450980392155, 0.2901960784313726 ), # ad494a + (0.8392156862745098, 0.3803921568627451, 0.4196078431372549 ), # d6616b + (0.9058823529411765, 0.5882352941176471, 0.611764705882353 ), # e7969c + (0.4823529411764706, 0.2549019607843137, 0.45098039215686275), # 7b4173 + (0.6470588235294118, 0.3176470588235294, 0.5803921568627451 ), # a55194 + (0.807843137254902, 0.42745098039215684, 0.7411764705882353 ), # ce6dbd + (0.8705882352941177, 0.6196078431372549, 0.8392156862745098 ), # de9ed6 +) + +_tab20c_data = ( + (0.19215686274509805, 0.5098039215686274, 0.7411764705882353 ), # 3182bd + (0.4196078431372549, 0.6823529411764706, 0.8392156862745098 ), # 6baed6 + (0.6196078431372549, 0.792156862745098, 0.8823529411764706 ), # 9ecae1 + (0.7764705882352941, 0.8588235294117647, 0.9372549019607843 ), # c6dbef + (0.9019607843137255, 0.3333333333333333, 0.050980392156862744), # e6550d + (0.9921568627450981, 0.5529411764705883, 0.23529411764705882 ), # fd8d3c + (0.9921568627450981, 0.6823529411764706, 0.4196078431372549 ), # fdae6b + (0.9921568627450981, 0.8156862745098039, 0.6352941176470588 ), # fdd0a2 + (0.19215686274509805, 0.6392156862745098, 0.32941176470588235 ), # 31a354 + (0.4549019607843137, 0.7686274509803922, 0.4627450980392157 ), # 74c476 + (0.6313725490196078, 0.8509803921568627, 0.6078431372549019 ), # a1d99b + (0.7803921568627451, 0.9137254901960784, 0.7529411764705882 ), # c7e9c0 + (0.4588235294117647, 0.4196078431372549, 0.6941176470588235 ), # 756bb1 + (0.6196078431372549, 0.6039215686274509, 0.7843137254901961 ), # 9e9ac8 + (0.7372549019607844, 0.7411764705882353, 0.8627450980392157 ), # bcbddc + (0.8549019607843137, 0.8549019607843137, 0.9215686274509803 ), # dadaeb + (0.38823529411764707, 0.38823529411764707, 0.38823529411764707 ), # 636363 + (0.5882352941176471, 0.5882352941176471, 0.5882352941176471 ), # 969696 + (0.7411764705882353, 0.7411764705882353, 0.7411764705882353 ), # bdbdbd + (0.8509803921568627, 0.8509803921568627, 0.8509803921568627 ), # d9d9d9 +) + + +datad = { + 'Blues': _Blues_data, + 'BrBG': _BrBG_data, + 'BuGn': _BuGn_data, + 'BuPu': _BuPu_data, + 'CMRmap': _CMRmap_data, + 'GnBu': _GnBu_data, + 'Greens': _Greens_data, + 'Greys': _Greys_data, + 'OrRd': _OrRd_data, + 'Oranges': _Oranges_data, + 'PRGn': _PRGn_data, + 'PiYG': _PiYG_data, + 'PuBu': _PuBu_data, + 'PuBuGn': _PuBuGn_data, + 'PuOr': _PuOr_data, + 'PuRd': _PuRd_data, + 'Purples': _Purples_data, + 'RdBu': _RdBu_data, + 'RdGy': _RdGy_data, + 'RdPu': _RdPu_data, + 'RdYlBu': _RdYlBu_data, + 'RdYlGn': _RdYlGn_data, + 'Reds': _Reds_data, + 'Spectral': _Spectral_data, + 'Wistia': _wistia_data, + 'YlGn': _YlGn_data, + 'YlGnBu': _YlGnBu_data, + 'YlOrBr': _YlOrBr_data, + 'YlOrRd': _YlOrRd_data, + 'afmhot': _afmhot_data, + 'autumn': _autumn_data, + 'binary': _binary_data, + 'bone': _bone_data, + 'brg': _brg_data, + 'bwr': _bwr_data, + 'cool': _cool_data, + 'coolwarm': _coolwarm_data, + 'copper': _copper_data, + 'cubehelix': _cubehelix_data, + 'flag': _flag_data, + 'gist_earth': _gist_earth_data, + 'gist_gray': _gist_gray_data, + 'gist_heat': _gist_heat_data, + 'gist_ncar': _gist_ncar_data, + 'gist_rainbow': _gist_rainbow_data, + 'gist_stern': _gist_stern_data, + 'gist_yarg': _gist_yarg_data, + 'gnuplot': _gnuplot_data, + 'gnuplot2': _gnuplot2_data, + 'gray': _gray_data, + 'hot': _hot_data, + 'hsv': _hsv_data, + 'jet': _jet_data, + 'nipy_spectral': _nipy_spectral_data, + 'ocean': _ocean_data, + 'pink': _pink_data, + 'prism': _prism_data, + 'rainbow': _rainbow_data, + 'seismic': _seismic_data, + 'spring': _spring_data, + 'summer': _summer_data, + 'terrain': _terrain_data, + 'winter': _winter_data, + # Qualitative + 'Accent': {'listed': _Accent_data}, + 'Dark2': {'listed': _Dark2_data}, + 'Paired': {'listed': _Paired_data}, + 'Pastel1': {'listed': _Pastel1_data}, + 'Pastel2': {'listed': _Pastel2_data}, + 'Set1': {'listed': _Set1_data}, + 'Set2': {'listed': _Set2_data}, + 'Set3': {'listed': _Set3_data}, + 'tab10': {'listed': _tab10_data}, + 'tab20': {'listed': _tab20_data}, + 'tab20b': {'listed': _tab20b_data}, + 'tab20c': {'listed': _tab20c_data}, +} diff --git a/contrib/python/matplotlib/py2/matplotlib/_cm_listed.py b/contrib/python/matplotlib/py2/matplotlib/_cm_listed.py new file mode 100644 index 00000000000..c4a4e13e4d7 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_cm_listed.py @@ -0,0 +1,1298 @@ +from .colors import ListedColormap + +_magma_data = [[0.001462, 0.000466, 0.013866], + [0.002258, 0.001295, 0.018331], + [0.003279, 0.002305, 0.023708], + [0.004512, 0.003490, 0.029965], + [0.005950, 0.004843, 0.037130], + [0.007588, 0.006356, 0.044973], + [0.009426, 0.008022, 0.052844], + [0.011465, 0.009828, 0.060750], + [0.013708, 0.011771, 0.068667], + [0.016156, 0.013840, 0.076603], + [0.018815, 0.016026, 0.084584], + [0.021692, 0.018320, 0.092610], + [0.024792, 0.020715, 0.100676], + [0.028123, 0.023201, 0.108787], + [0.031696, 0.025765, 0.116965], + [0.035520, 0.028397, 0.125209], + [0.039608, 0.031090, 0.133515], + [0.043830, 0.033830, 0.141886], + [0.048062, 0.036607, 0.150327], + [0.052320, 0.039407, 0.158841], + [0.056615, 0.042160, 0.167446], + [0.060949, 0.044794, 0.176129], + [0.065330, 0.047318, 0.184892], + [0.069764, 0.049726, 0.193735], + [0.074257, 0.052017, 0.202660], + [0.078815, 0.054184, 0.211667], + [0.083446, 0.056225, 0.220755], + [0.088155, 0.058133, 0.229922], + [0.092949, 0.059904, 0.239164], + [0.097833, 0.061531, 0.248477], + [0.102815, 0.063010, 0.257854], + [0.107899, 0.064335, 0.267289], + [0.113094, 0.065492, 0.276784], + [0.118405, 0.066479, 0.286321], + [0.123833, 0.067295, 0.295879], + [0.129380, 0.067935, 0.305443], + [0.135053, 0.068391, 0.315000], + [0.140858, 0.068654, 0.324538], + [0.146785, 0.068738, 0.334011], + [0.152839, 0.068637, 0.343404], + [0.159018, 0.068354, 0.352688], + [0.165308, 0.067911, 0.361816], + [0.171713, 0.067305, 0.370771], + [0.178212, 0.066576, 0.379497], + [0.184801, 0.065732, 0.387973], + [0.191460, 0.064818, 0.396152], + [0.198177, 0.063862, 0.404009], + [0.204935, 0.062907, 0.411514], + [0.211718, 0.061992, 0.418647], + [0.218512, 0.061158, 0.425392], + [0.225302, 0.060445, 0.431742], + [0.232077, 0.059889, 0.437695], + [0.238826, 0.059517, 0.443256], + [0.245543, 0.059352, 0.448436], + [0.252220, 0.059415, 0.453248], + [0.258857, 0.059706, 0.457710], + [0.265447, 0.060237, 0.461840], + [0.271994, 0.060994, 0.465660], + [0.278493, 0.061978, 0.469190], + [0.284951, 0.063168, 0.472451], + [0.291366, 0.064553, 0.475462], + [0.297740, 0.066117, 0.478243], + [0.304081, 0.067835, 0.480812], + [0.310382, 0.069702, 0.483186], + [0.316654, 0.071690, 0.485380], + [0.322899, 0.073782, 0.487408], + [0.329114, 0.075972, 0.489287], + [0.335308, 0.078236, 0.491024], + [0.341482, 0.080564, 0.492631], + [0.347636, 0.082946, 0.494121], + [0.353773, 0.085373, 0.495501], + [0.359898, 0.087831, 0.496778], + [0.366012, 0.090314, 0.497960], + [0.372116, 0.092816, 0.499053], + [0.378211, 0.095332, 0.500067], + [0.384299, 0.097855, 0.501002], + [0.390384, 0.100379, 0.501864], + [0.396467, 0.102902, 0.502658], + [0.402548, 0.105420, 0.503386], + [0.408629, 0.107930, 0.504052], + [0.414709, 0.110431, 0.504662], + [0.420791, 0.112920, 0.505215], + [0.426877, 0.115395, 0.505714], + [0.432967, 0.117855, 0.506160], + [0.439062, 0.120298, 0.506555], + [0.445163, 0.122724, 0.506901], + [0.451271, 0.125132, 0.507198], + [0.457386, 0.127522, 0.507448], + [0.463508, 0.129893, 0.507652], + [0.469640, 0.132245, 0.507809], + [0.475780, 0.134577, 0.507921], + [0.481929, 0.136891, 0.507989], + [0.488088, 0.139186, 0.508011], + [0.494258, 0.141462, 0.507988], + [0.500438, 0.143719, 0.507920], + [0.506629, 0.145958, 0.507806], + [0.512831, 0.148179, 0.507648], + [0.519045, 0.150383, 0.507443], + [0.525270, 0.152569, 0.507192], + [0.531507, 0.154739, 0.506895], + [0.537755, 0.156894, 0.506551], + [0.544015, 0.159033, 0.506159], + [0.550287, 0.161158, 0.505719], + [0.556571, 0.163269, 0.505230], + [0.562866, 0.165368, 0.504692], + [0.569172, 0.167454, 0.504105], + [0.575490, 0.169530, 0.503466], + [0.581819, 0.171596, 0.502777], + [0.588158, 0.173652, 0.502035], + [0.594508, 0.175701, 0.501241], + [0.600868, 0.177743, 0.500394], + [0.607238, 0.179779, 0.499492], + [0.613617, 0.181811, 0.498536], + [0.620005, 0.183840, 0.497524], + [0.626401, 0.185867, 0.496456], + [0.632805, 0.187893, 0.495332], + [0.639216, 0.189921, 0.494150], + [0.645633, 0.191952, 0.492910], + [0.652056, 0.193986, 0.491611], + [0.658483, 0.196027, 0.490253], + [0.664915, 0.198075, 0.488836], + [0.671349, 0.200133, 0.487358], + [0.677786, 0.202203, 0.485819], + [0.684224, 0.204286, 0.484219], + [0.690661, 0.206384, 0.482558], + [0.697098, 0.208501, 0.480835], + [0.703532, 0.210638, 0.479049], + [0.709962, 0.212797, 0.477201], + [0.716387, 0.214982, 0.475290], + [0.722805, 0.217194, 0.473316], + [0.729216, 0.219437, 0.471279], + [0.735616, 0.221713, 0.469180], + [0.742004, 0.224025, 0.467018], + [0.748378, 0.226377, 0.464794], + [0.754737, 0.228772, 0.462509], + [0.761077, 0.231214, 0.460162], + [0.767398, 0.233705, 0.457755], + [0.773695, 0.236249, 0.455289], + [0.779968, 0.238851, 0.452765], + [0.786212, 0.241514, 0.450184], + [0.792427, 0.244242, 0.447543], + [0.798608, 0.247040, 0.444848], + [0.804752, 0.249911, 0.442102], + [0.810855, 0.252861, 0.439305], + [0.816914, 0.255895, 0.436461], + [0.822926, 0.259016, 0.433573], + [0.828886, 0.262229, 0.430644], + [0.834791, 0.265540, 0.427671], + [0.840636, 0.268953, 0.424666], + [0.846416, 0.272473, 0.421631], + [0.852126, 0.276106, 0.418573], + [0.857763, 0.279857, 0.415496], + [0.863320, 0.283729, 0.412403], + [0.868793, 0.287728, 0.409303], + [0.874176, 0.291859, 0.406205], + [0.879464, 0.296125, 0.403118], + [0.884651, 0.300530, 0.400047], + [0.889731, 0.305079, 0.397002], + [0.894700, 0.309773, 0.393995], + [0.899552, 0.314616, 0.391037], + [0.904281, 0.319610, 0.388137], + [0.908884, 0.324755, 0.385308], + [0.913354, 0.330052, 0.382563], + [0.917689, 0.335500, 0.379915], + [0.921884, 0.341098, 0.377376], + [0.925937, 0.346844, 0.374959], + [0.929845, 0.352734, 0.372677], + [0.933606, 0.358764, 0.370541], + [0.937221, 0.364929, 0.368567], + [0.940687, 0.371224, 0.366762], + [0.944006, 0.377643, 0.365136], + [0.947180, 0.384178, 0.363701], + [0.950210, 0.390820, 0.362468], + [0.953099, 0.397563, 0.361438], + [0.955849, 0.404400, 0.360619], + [0.958464, 0.411324, 0.360014], + [0.960949, 0.418323, 0.359630], + [0.963310, 0.425390, 0.359469], + [0.965549, 0.432519, 0.359529], + [0.967671, 0.439703, 0.359810], + [0.969680, 0.446936, 0.360311], + [0.971582, 0.454210, 0.361030], + [0.973381, 0.461520, 0.361965], + [0.975082, 0.468861, 0.363111], + [0.976690, 0.476226, 0.364466], + [0.978210, 0.483612, 0.366025], + [0.979645, 0.491014, 0.367783], + [0.981000, 0.498428, 0.369734], + [0.982279, 0.505851, 0.371874], + [0.983485, 0.513280, 0.374198], + [0.984622, 0.520713, 0.376698], + [0.985693, 0.528148, 0.379371], + [0.986700, 0.535582, 0.382210], + [0.987646, 0.543015, 0.385210], + [0.988533, 0.550446, 0.388365], + [0.989363, 0.557873, 0.391671], + [0.990138, 0.565296, 0.395122], + [0.990871, 0.572706, 0.398714], + [0.991558, 0.580107, 0.402441], + [0.992196, 0.587502, 0.406299], + [0.992785, 0.594891, 0.410283], + [0.993326, 0.602275, 0.414390], + [0.993834, 0.609644, 0.418613], + [0.994309, 0.616999, 0.422950], + [0.994738, 0.624350, 0.427397], + [0.995122, 0.631696, 0.431951], + [0.995480, 0.639027, 0.436607], + [0.995810, 0.646344, 0.441361], + [0.996096, 0.653659, 0.446213], + [0.996341, 0.660969, 0.451160], + [0.996580, 0.668256, 0.456192], + [0.996775, 0.675541, 0.461314], + [0.996925, 0.682828, 0.466526], + [0.997077, 0.690088, 0.471811], + [0.997186, 0.697349, 0.477182], + [0.997254, 0.704611, 0.482635], + [0.997325, 0.711848, 0.488154], + [0.997351, 0.719089, 0.493755], + [0.997351, 0.726324, 0.499428], + [0.997341, 0.733545, 0.505167], + [0.997285, 0.740772, 0.510983], + [0.997228, 0.747981, 0.516859], + [0.997138, 0.755190, 0.522806], + [0.997019, 0.762398, 0.528821], + [0.996898, 0.769591, 0.534892], + [0.996727, 0.776795, 0.541039], + [0.996571, 0.783977, 0.547233], + [0.996369, 0.791167, 0.553499], + [0.996162, 0.798348, 0.559820], + [0.995932, 0.805527, 0.566202], + [0.995680, 0.812706, 0.572645], + [0.995424, 0.819875, 0.579140], + [0.995131, 0.827052, 0.585701], + [0.994851, 0.834213, 0.592307], + [0.994524, 0.841387, 0.598983], + [0.994222, 0.848540, 0.605696], + [0.993866, 0.855711, 0.612482], + [0.993545, 0.862859, 0.619299], + [0.993170, 0.870024, 0.626189], + [0.992831, 0.877168, 0.633109], + [0.992440, 0.884330, 0.640099], + [0.992089, 0.891470, 0.647116], + [0.991688, 0.898627, 0.654202], + [0.991332, 0.905763, 0.661309], + [0.990930, 0.912915, 0.668481], + [0.990570, 0.920049, 0.675675], + [0.990175, 0.927196, 0.682926], + [0.989815, 0.934329, 0.690198], + [0.989434, 0.941470, 0.697519], + [0.989077, 0.948604, 0.704863], + [0.988717, 0.955742, 0.712242], + [0.988367, 0.962878, 0.719649], + [0.988033, 0.970012, 0.727077], + [0.987691, 0.977154, 0.734536], + [0.987387, 0.984288, 0.742002], + [0.987053, 0.991438, 0.749504]] + +_inferno_data = [[0.001462, 0.000466, 0.013866], + [0.002267, 0.001270, 0.018570], + [0.003299, 0.002249, 0.024239], + [0.004547, 0.003392, 0.030909], + [0.006006, 0.004692, 0.038558], + [0.007676, 0.006136, 0.046836], + [0.009561, 0.007713, 0.055143], + [0.011663, 0.009417, 0.063460], + [0.013995, 0.011225, 0.071862], + [0.016561, 0.013136, 0.080282], + [0.019373, 0.015133, 0.088767], + [0.022447, 0.017199, 0.097327], + [0.025793, 0.019331, 0.105930], + [0.029432, 0.021503, 0.114621], + [0.033385, 0.023702, 0.123397], + [0.037668, 0.025921, 0.132232], + [0.042253, 0.028139, 0.141141], + [0.046915, 0.030324, 0.150164], + [0.051644, 0.032474, 0.159254], + [0.056449, 0.034569, 0.168414], + [0.061340, 0.036590, 0.177642], + [0.066331, 0.038504, 0.186962], + [0.071429, 0.040294, 0.196354], + [0.076637, 0.041905, 0.205799], + [0.081962, 0.043328, 0.215289], + [0.087411, 0.044556, 0.224813], + [0.092990, 0.045583, 0.234358], + [0.098702, 0.046402, 0.243904], + [0.104551, 0.047008, 0.253430], + [0.110536, 0.047399, 0.262912], + [0.116656, 0.047574, 0.272321], + [0.122908, 0.047536, 0.281624], + [0.129285, 0.047293, 0.290788], + [0.135778, 0.046856, 0.299776], + [0.142378, 0.046242, 0.308553], + [0.149073, 0.045468, 0.317085], + [0.155850, 0.044559, 0.325338], + [0.162689, 0.043554, 0.333277], + [0.169575, 0.042489, 0.340874], + [0.176493, 0.041402, 0.348111], + [0.183429, 0.040329, 0.354971], + [0.190367, 0.039309, 0.361447], + [0.197297, 0.038400, 0.367535], + [0.204209, 0.037632, 0.373238], + [0.211095, 0.037030, 0.378563], + [0.217949, 0.036615, 0.383522], + [0.224763, 0.036405, 0.388129], + [0.231538, 0.036405, 0.392400], + [0.238273, 0.036621, 0.396353], + [0.244967, 0.037055, 0.400007], + [0.251620, 0.037705, 0.403378], + [0.258234, 0.038571, 0.406485], + [0.264810, 0.039647, 0.409345], + [0.271347, 0.040922, 0.411976], + [0.277850, 0.042353, 0.414392], + [0.284321, 0.043933, 0.416608], + [0.290763, 0.045644, 0.418637], + [0.297178, 0.047470, 0.420491], + [0.303568, 0.049396, 0.422182], + [0.309935, 0.051407, 0.423721], + [0.316282, 0.053490, 0.425116], + [0.322610, 0.055634, 0.426377], + [0.328921, 0.057827, 0.427511], + [0.335217, 0.060060, 0.428524], + [0.341500, 0.062325, 0.429425], + [0.347771, 0.064616, 0.430217], + [0.354032, 0.066925, 0.430906], + [0.360284, 0.069247, 0.431497], + [0.366529, 0.071579, 0.431994], + [0.372768, 0.073915, 0.432400], + [0.379001, 0.076253, 0.432719], + [0.385228, 0.078591, 0.432955], + [0.391453, 0.080927, 0.433109], + [0.397674, 0.083257, 0.433183], + [0.403894, 0.085580, 0.433179], + [0.410113, 0.087896, 0.433098], + [0.416331, 0.090203, 0.432943], + [0.422549, 0.092501, 0.432714], + [0.428768, 0.094790, 0.432412], + [0.434987, 0.097069, 0.432039], + [0.441207, 0.099338, 0.431594], + [0.447428, 0.101597, 0.431080], + [0.453651, 0.103848, 0.430498], + [0.459875, 0.106089, 0.429846], + [0.466100, 0.108322, 0.429125], + [0.472328, 0.110547, 0.428334], + [0.478558, 0.112764, 0.427475], + [0.484789, 0.114974, 0.426548], + [0.491022, 0.117179, 0.425552], + [0.497257, 0.119379, 0.424488], + [0.503493, 0.121575, 0.423356], + [0.509730, 0.123769, 0.422156], + [0.515967, 0.125960, 0.420887], + [0.522206, 0.128150, 0.419549], + [0.528444, 0.130341, 0.418142], + [0.534683, 0.132534, 0.416667], + [0.540920, 0.134729, 0.415123], + [0.547157, 0.136929, 0.413511], + [0.553392, 0.139134, 0.411829], + [0.559624, 0.141346, 0.410078], + [0.565854, 0.143567, 0.408258], + [0.572081, 0.145797, 0.406369], + [0.578304, 0.148039, 0.404411], + [0.584521, 0.150294, 0.402385], + [0.590734, 0.152563, 0.400290], + [0.596940, 0.154848, 0.398125], + [0.603139, 0.157151, 0.395891], + [0.609330, 0.159474, 0.393589], + [0.615513, 0.161817, 0.391219], + [0.621685, 0.164184, 0.388781], + [0.627847, 0.166575, 0.386276], + [0.633998, 0.168992, 0.383704], + [0.640135, 0.171438, 0.381065], + [0.646260, 0.173914, 0.378359], + [0.652369, 0.176421, 0.375586], + [0.658463, 0.178962, 0.372748], + [0.664540, 0.181539, 0.369846], + [0.670599, 0.184153, 0.366879], + [0.676638, 0.186807, 0.363849], + [0.682656, 0.189501, 0.360757], + [0.688653, 0.192239, 0.357603], + [0.694627, 0.195021, 0.354388], + [0.700576, 0.197851, 0.351113], + [0.706500, 0.200728, 0.347777], + [0.712396, 0.203656, 0.344383], + [0.718264, 0.206636, 0.340931], + [0.724103, 0.209670, 0.337424], + [0.729909, 0.212759, 0.333861], + [0.735683, 0.215906, 0.330245], + [0.741423, 0.219112, 0.326576], + [0.747127, 0.222378, 0.322856], + [0.752794, 0.225706, 0.319085], + [0.758422, 0.229097, 0.315266], + [0.764010, 0.232554, 0.311399], + [0.769556, 0.236077, 0.307485], + [0.775059, 0.239667, 0.303526], + [0.780517, 0.243327, 0.299523], + [0.785929, 0.247056, 0.295477], + [0.791293, 0.250856, 0.291390], + [0.796607, 0.254728, 0.287264], + [0.801871, 0.258674, 0.283099], + [0.807082, 0.262692, 0.278898], + [0.812239, 0.266786, 0.274661], + [0.817341, 0.270954, 0.270390], + [0.822386, 0.275197, 0.266085], + [0.827372, 0.279517, 0.261750], + [0.832299, 0.283913, 0.257383], + [0.837165, 0.288385, 0.252988], + [0.841969, 0.292933, 0.248564], + [0.846709, 0.297559, 0.244113], + [0.851384, 0.302260, 0.239636], + [0.855992, 0.307038, 0.235133], + [0.860533, 0.311892, 0.230606], + [0.865006, 0.316822, 0.226055], + [0.869409, 0.321827, 0.221482], + [0.873741, 0.326906, 0.216886], + [0.878001, 0.332060, 0.212268], + [0.882188, 0.337287, 0.207628], + [0.886302, 0.342586, 0.202968], + [0.890341, 0.347957, 0.198286], + [0.894305, 0.353399, 0.193584], + [0.898192, 0.358911, 0.188860], + [0.902003, 0.364492, 0.184116], + [0.905735, 0.370140, 0.179350], + [0.909390, 0.375856, 0.174563], + [0.912966, 0.381636, 0.169755], + [0.916462, 0.387481, 0.164924], + [0.919879, 0.393389, 0.160070], + [0.923215, 0.399359, 0.155193], + [0.926470, 0.405389, 0.150292], + [0.929644, 0.411479, 0.145367], + [0.932737, 0.417627, 0.140417], + [0.935747, 0.423831, 0.135440], + [0.938675, 0.430091, 0.130438], + [0.941521, 0.436405, 0.125409], + [0.944285, 0.442772, 0.120354], + [0.946965, 0.449191, 0.115272], + [0.949562, 0.455660, 0.110164], + [0.952075, 0.462178, 0.105031], + [0.954506, 0.468744, 0.099874], + [0.956852, 0.475356, 0.094695], + [0.959114, 0.482014, 0.089499], + [0.961293, 0.488716, 0.084289], + [0.963387, 0.495462, 0.079073], + [0.965397, 0.502249, 0.073859], + [0.967322, 0.509078, 0.068659], + [0.969163, 0.515946, 0.063488], + [0.970919, 0.522853, 0.058367], + [0.972590, 0.529798, 0.053324], + [0.974176, 0.536780, 0.048392], + [0.975677, 0.543798, 0.043618], + [0.977092, 0.550850, 0.039050], + [0.978422, 0.557937, 0.034931], + [0.979666, 0.565057, 0.031409], + [0.980824, 0.572209, 0.028508], + [0.981895, 0.579392, 0.026250], + [0.982881, 0.586606, 0.024661], + [0.983779, 0.593849, 0.023770], + [0.984591, 0.601122, 0.023606], + [0.985315, 0.608422, 0.024202], + [0.985952, 0.615750, 0.025592], + [0.986502, 0.623105, 0.027814], + [0.986964, 0.630485, 0.030908], + [0.987337, 0.637890, 0.034916], + [0.987622, 0.645320, 0.039886], + [0.987819, 0.652773, 0.045581], + [0.987926, 0.660250, 0.051750], + [0.987945, 0.667748, 0.058329], + [0.987874, 0.675267, 0.065257], + [0.987714, 0.682807, 0.072489], + [0.987464, 0.690366, 0.079990], + [0.987124, 0.697944, 0.087731], + [0.986694, 0.705540, 0.095694], + [0.986175, 0.713153, 0.103863], + [0.985566, 0.720782, 0.112229], + [0.984865, 0.728427, 0.120785], + [0.984075, 0.736087, 0.129527], + [0.983196, 0.743758, 0.138453], + [0.982228, 0.751442, 0.147565], + [0.981173, 0.759135, 0.156863], + [0.980032, 0.766837, 0.166353], + [0.978806, 0.774545, 0.176037], + [0.977497, 0.782258, 0.185923], + [0.976108, 0.789974, 0.196018], + [0.974638, 0.797692, 0.206332], + [0.973088, 0.805409, 0.216877], + [0.971468, 0.813122, 0.227658], + [0.969783, 0.820825, 0.238686], + [0.968041, 0.828515, 0.249972], + [0.966243, 0.836191, 0.261534], + [0.964394, 0.843848, 0.273391], + [0.962517, 0.851476, 0.285546], + [0.960626, 0.859069, 0.298010], + [0.958720, 0.866624, 0.310820], + [0.956834, 0.874129, 0.323974], + [0.954997, 0.881569, 0.337475], + [0.953215, 0.888942, 0.351369], + [0.951546, 0.896226, 0.365627], + [0.950018, 0.903409, 0.380271], + [0.948683, 0.910473, 0.395289], + [0.947594, 0.917399, 0.410665], + [0.946809, 0.924168, 0.426373], + [0.946392, 0.930761, 0.442367], + [0.946403, 0.937159, 0.458592], + [0.946903, 0.943348, 0.474970], + [0.947937, 0.949318, 0.491426], + [0.949545, 0.955063, 0.507860], + [0.951740, 0.960587, 0.524203], + [0.954529, 0.965896, 0.540361], + [0.957896, 0.971003, 0.556275], + [0.961812, 0.975924, 0.571925], + [0.966249, 0.980678, 0.587206], + [0.971162, 0.985282, 0.602154], + [0.976511, 0.989753, 0.616760], + [0.982257, 0.994109, 0.631017], + [0.988362, 0.998364, 0.644924]] + +_plasma_data = [[0.050383, 0.029803, 0.527975], + [0.063536, 0.028426, 0.533124], + [0.075353, 0.027206, 0.538007], + [0.086222, 0.026125, 0.542658], + [0.096379, 0.025165, 0.547103], + [0.105980, 0.024309, 0.551368], + [0.115124, 0.023556, 0.555468], + [0.123903, 0.022878, 0.559423], + [0.132381, 0.022258, 0.563250], + [0.140603, 0.021687, 0.566959], + [0.148607, 0.021154, 0.570562], + [0.156421, 0.020651, 0.574065], + [0.164070, 0.020171, 0.577478], + [0.171574, 0.019706, 0.580806], + [0.178950, 0.019252, 0.584054], + [0.186213, 0.018803, 0.587228], + [0.193374, 0.018354, 0.590330], + [0.200445, 0.017902, 0.593364], + [0.207435, 0.017442, 0.596333], + [0.214350, 0.016973, 0.599239], + [0.221197, 0.016497, 0.602083], + [0.227983, 0.016007, 0.604867], + [0.234715, 0.015502, 0.607592], + [0.241396, 0.014979, 0.610259], + [0.248032, 0.014439, 0.612868], + [0.254627, 0.013882, 0.615419], + [0.261183, 0.013308, 0.617911], + [0.267703, 0.012716, 0.620346], + [0.274191, 0.012109, 0.622722], + [0.280648, 0.011488, 0.625038], + [0.287076, 0.010855, 0.627295], + [0.293478, 0.010213, 0.629490], + [0.299855, 0.009561, 0.631624], + [0.306210, 0.008902, 0.633694], + [0.312543, 0.008239, 0.635700], + [0.318856, 0.007576, 0.637640], + [0.325150, 0.006915, 0.639512], + [0.331426, 0.006261, 0.641316], + [0.337683, 0.005618, 0.643049], + [0.343925, 0.004991, 0.644710], + [0.350150, 0.004382, 0.646298], + [0.356359, 0.003798, 0.647810], + [0.362553, 0.003243, 0.649245], + [0.368733, 0.002724, 0.650601], + [0.374897, 0.002245, 0.651876], + [0.381047, 0.001814, 0.653068], + [0.387183, 0.001434, 0.654177], + [0.393304, 0.001114, 0.655199], + [0.399411, 0.000859, 0.656133], + [0.405503, 0.000678, 0.656977], + [0.411580, 0.000577, 0.657730], + [0.417642, 0.000564, 0.658390], + [0.423689, 0.000646, 0.658956], + [0.429719, 0.000831, 0.659425], + [0.435734, 0.001127, 0.659797], + [0.441732, 0.001540, 0.660069], + [0.447714, 0.002080, 0.660240], + [0.453677, 0.002755, 0.660310], + [0.459623, 0.003574, 0.660277], + [0.465550, 0.004545, 0.660139], + [0.471457, 0.005678, 0.659897], + [0.477344, 0.006980, 0.659549], + [0.483210, 0.008460, 0.659095], + [0.489055, 0.010127, 0.658534], + [0.494877, 0.011990, 0.657865], + [0.500678, 0.014055, 0.657088], + [0.506454, 0.016333, 0.656202], + [0.512206, 0.018833, 0.655209], + [0.517933, 0.021563, 0.654109], + [0.523633, 0.024532, 0.652901], + [0.529306, 0.027747, 0.651586], + [0.534952, 0.031217, 0.650165], + [0.540570, 0.034950, 0.648640], + [0.546157, 0.038954, 0.647010], + [0.551715, 0.043136, 0.645277], + [0.557243, 0.047331, 0.643443], + [0.562738, 0.051545, 0.641509], + [0.568201, 0.055778, 0.639477], + [0.573632, 0.060028, 0.637349], + [0.579029, 0.064296, 0.635126], + [0.584391, 0.068579, 0.632812], + [0.589719, 0.072878, 0.630408], + [0.595011, 0.077190, 0.627917], + [0.600266, 0.081516, 0.625342], + [0.605485, 0.085854, 0.622686], + [0.610667, 0.090204, 0.619951], + [0.615812, 0.094564, 0.617140], + [0.620919, 0.098934, 0.614257], + [0.625987, 0.103312, 0.611305], + [0.631017, 0.107699, 0.608287], + [0.636008, 0.112092, 0.605205], + [0.640959, 0.116492, 0.602065], + [0.645872, 0.120898, 0.598867], + [0.650746, 0.125309, 0.595617], + [0.655580, 0.129725, 0.592317], + [0.660374, 0.134144, 0.588971], + [0.665129, 0.138566, 0.585582], + [0.669845, 0.142992, 0.582154], + [0.674522, 0.147419, 0.578688], + [0.679160, 0.151848, 0.575189], + [0.683758, 0.156278, 0.571660], + [0.688318, 0.160709, 0.568103], + [0.692840, 0.165141, 0.564522], + [0.697324, 0.169573, 0.560919], + [0.701769, 0.174005, 0.557296], + [0.706178, 0.178437, 0.553657], + [0.710549, 0.182868, 0.550004], + [0.714883, 0.187299, 0.546338], + [0.719181, 0.191729, 0.542663], + [0.723444, 0.196158, 0.538981], + [0.727670, 0.200586, 0.535293], + [0.731862, 0.205013, 0.531601], + [0.736019, 0.209439, 0.527908], + [0.740143, 0.213864, 0.524216], + [0.744232, 0.218288, 0.520524], + [0.748289, 0.222711, 0.516834], + [0.752312, 0.227133, 0.513149], + [0.756304, 0.231555, 0.509468], + [0.760264, 0.235976, 0.505794], + [0.764193, 0.240396, 0.502126], + [0.768090, 0.244817, 0.498465], + [0.771958, 0.249237, 0.494813], + [0.775796, 0.253658, 0.491171], + [0.779604, 0.258078, 0.487539], + [0.783383, 0.262500, 0.483918], + [0.787133, 0.266922, 0.480307], + [0.790855, 0.271345, 0.476706], + [0.794549, 0.275770, 0.473117], + [0.798216, 0.280197, 0.469538], + [0.801855, 0.284626, 0.465971], + [0.805467, 0.289057, 0.462415], + [0.809052, 0.293491, 0.458870], + [0.812612, 0.297928, 0.455338], + [0.816144, 0.302368, 0.451816], + [0.819651, 0.306812, 0.448306], + [0.823132, 0.311261, 0.444806], + [0.826588, 0.315714, 0.441316], + [0.830018, 0.320172, 0.437836], + [0.833422, 0.324635, 0.434366], + [0.836801, 0.329105, 0.430905], + [0.840155, 0.333580, 0.427455], + [0.843484, 0.338062, 0.424013], + [0.846788, 0.342551, 0.420579], + [0.850066, 0.347048, 0.417153], + [0.853319, 0.351553, 0.413734], + [0.856547, 0.356066, 0.410322], + [0.859750, 0.360588, 0.406917], + [0.862927, 0.365119, 0.403519], + [0.866078, 0.369660, 0.400126], + [0.869203, 0.374212, 0.396738], + [0.872303, 0.378774, 0.393355], + [0.875376, 0.383347, 0.389976], + [0.878423, 0.387932, 0.386600], + [0.881443, 0.392529, 0.383229], + [0.884436, 0.397139, 0.379860], + [0.887402, 0.401762, 0.376494], + [0.890340, 0.406398, 0.373130], + [0.893250, 0.411048, 0.369768], + [0.896131, 0.415712, 0.366407], + [0.898984, 0.420392, 0.363047], + [0.901807, 0.425087, 0.359688], + [0.904601, 0.429797, 0.356329], + [0.907365, 0.434524, 0.352970], + [0.910098, 0.439268, 0.349610], + [0.912800, 0.444029, 0.346251], + [0.915471, 0.448807, 0.342890], + [0.918109, 0.453603, 0.339529], + [0.920714, 0.458417, 0.336166], + [0.923287, 0.463251, 0.332801], + [0.925825, 0.468103, 0.329435], + [0.928329, 0.472975, 0.326067], + [0.930798, 0.477867, 0.322697], + [0.933232, 0.482780, 0.319325], + [0.935630, 0.487712, 0.315952], + [0.937990, 0.492667, 0.312575], + [0.940313, 0.497642, 0.309197], + [0.942598, 0.502639, 0.305816], + [0.944844, 0.507658, 0.302433], + [0.947051, 0.512699, 0.299049], + [0.949217, 0.517763, 0.295662], + [0.951344, 0.522850, 0.292275], + [0.953428, 0.527960, 0.288883], + [0.955470, 0.533093, 0.285490], + [0.957469, 0.538250, 0.282096], + [0.959424, 0.543431, 0.278701], + [0.961336, 0.548636, 0.275305], + [0.963203, 0.553865, 0.271909], + [0.965024, 0.559118, 0.268513], + [0.966798, 0.564396, 0.265118], + [0.968526, 0.569700, 0.261721], + [0.970205, 0.575028, 0.258325], + [0.971835, 0.580382, 0.254931], + [0.973416, 0.585761, 0.251540], + [0.974947, 0.591165, 0.248151], + [0.976428, 0.596595, 0.244767], + [0.977856, 0.602051, 0.241387], + [0.979233, 0.607532, 0.238013], + [0.980556, 0.613039, 0.234646], + [0.981826, 0.618572, 0.231287], + [0.983041, 0.624131, 0.227937], + [0.984199, 0.629718, 0.224595], + [0.985301, 0.635330, 0.221265], + [0.986345, 0.640969, 0.217948], + [0.987332, 0.646633, 0.214648], + [0.988260, 0.652325, 0.211364], + [0.989128, 0.658043, 0.208100], + [0.989935, 0.663787, 0.204859], + [0.990681, 0.669558, 0.201642], + [0.991365, 0.675355, 0.198453], + [0.991985, 0.681179, 0.195295], + [0.992541, 0.687030, 0.192170], + [0.993032, 0.692907, 0.189084], + [0.993456, 0.698810, 0.186041], + [0.993814, 0.704741, 0.183043], + [0.994103, 0.710698, 0.180097], + [0.994324, 0.716681, 0.177208], + [0.994474, 0.722691, 0.174381], + [0.994553, 0.728728, 0.171622], + [0.994561, 0.734791, 0.168938], + [0.994495, 0.740880, 0.166335], + [0.994355, 0.746995, 0.163821], + [0.994141, 0.753137, 0.161404], + [0.993851, 0.759304, 0.159092], + [0.993482, 0.765499, 0.156891], + [0.993033, 0.771720, 0.154808], + [0.992505, 0.777967, 0.152855], + [0.991897, 0.784239, 0.151042], + [0.991209, 0.790537, 0.149377], + [0.990439, 0.796859, 0.147870], + [0.989587, 0.803205, 0.146529], + [0.988648, 0.809579, 0.145357], + [0.987621, 0.815978, 0.144363], + [0.986509, 0.822401, 0.143557], + [0.985314, 0.828846, 0.142945], + [0.984031, 0.835315, 0.142528], + [0.982653, 0.841812, 0.142303], + [0.981190, 0.848329, 0.142279], + [0.979644, 0.854866, 0.142453], + [0.977995, 0.861432, 0.142808], + [0.976265, 0.868016, 0.143351], + [0.974443, 0.874622, 0.144061], + [0.972530, 0.881250, 0.144923], + [0.970533, 0.887896, 0.145919], + [0.968443, 0.894564, 0.147014], + [0.966271, 0.901249, 0.148180], + [0.964021, 0.907950, 0.149370], + [0.961681, 0.914672, 0.150520], + [0.959276, 0.921407, 0.151566], + [0.956808, 0.928152, 0.152409], + [0.954287, 0.934908, 0.152921], + [0.951726, 0.941671, 0.152925], + [0.949151, 0.948435, 0.152178], + [0.946602, 0.955190, 0.150328], + [0.944152, 0.961916, 0.146861], + [0.941896, 0.968590, 0.140956], + [0.940015, 0.975158, 0.131326]] + +_viridis_data = [[0.267004, 0.004874, 0.329415], + [0.268510, 0.009605, 0.335427], + [0.269944, 0.014625, 0.341379], + [0.271305, 0.019942, 0.347269], + [0.272594, 0.025563, 0.353093], + [0.273809, 0.031497, 0.358853], + [0.274952, 0.037752, 0.364543], + [0.276022, 0.044167, 0.370164], + [0.277018, 0.050344, 0.375715], + [0.277941, 0.056324, 0.381191], + [0.278791, 0.062145, 0.386592], + [0.279566, 0.067836, 0.391917], + [0.280267, 0.073417, 0.397163], + [0.280894, 0.078907, 0.402329], + [0.281446, 0.084320, 0.407414], + [0.281924, 0.089666, 0.412415], + [0.282327, 0.094955, 0.417331], + [0.282656, 0.100196, 0.422160], + [0.282910, 0.105393, 0.426902], + [0.283091, 0.110553, 0.431554], + [0.283197, 0.115680, 0.436115], + [0.283229, 0.120777, 0.440584], + [0.283187, 0.125848, 0.444960], + [0.283072, 0.130895, 0.449241], + [0.282884, 0.135920, 0.453427], + [0.282623, 0.140926, 0.457517], + [0.282290, 0.145912, 0.461510], + [0.281887, 0.150881, 0.465405], + [0.281412, 0.155834, 0.469201], + [0.280868, 0.160771, 0.472899], + [0.280255, 0.165693, 0.476498], + [0.279574, 0.170599, 0.479997], + [0.278826, 0.175490, 0.483397], + [0.278012, 0.180367, 0.486697], + [0.277134, 0.185228, 0.489898], + [0.276194, 0.190074, 0.493001], + [0.275191, 0.194905, 0.496005], + [0.274128, 0.199721, 0.498911], + [0.273006, 0.204520, 0.501721], + [0.271828, 0.209303, 0.504434], + [0.270595, 0.214069, 0.507052], + [0.269308, 0.218818, 0.509577], + [0.267968, 0.223549, 0.512008], + [0.266580, 0.228262, 0.514349], + [0.265145, 0.232956, 0.516599], + [0.263663, 0.237631, 0.518762], + [0.262138, 0.242286, 0.520837], + [0.260571, 0.246922, 0.522828], + [0.258965, 0.251537, 0.524736], + [0.257322, 0.256130, 0.526563], + [0.255645, 0.260703, 0.528312], + [0.253935, 0.265254, 0.529983], + [0.252194, 0.269783, 0.531579], + [0.250425, 0.274290, 0.533103], + [0.248629, 0.278775, 0.534556], + [0.246811, 0.283237, 0.535941], + [0.244972, 0.287675, 0.537260], + [0.243113, 0.292092, 0.538516], + [0.241237, 0.296485, 0.539709], + [0.239346, 0.300855, 0.540844], + [0.237441, 0.305202, 0.541921], + [0.235526, 0.309527, 0.542944], + [0.233603, 0.313828, 0.543914], + [0.231674, 0.318106, 0.544834], + [0.229739, 0.322361, 0.545706], + [0.227802, 0.326594, 0.546532], + [0.225863, 0.330805, 0.547314], + [0.223925, 0.334994, 0.548053], + [0.221989, 0.339161, 0.548752], + [0.220057, 0.343307, 0.549413], + [0.218130, 0.347432, 0.550038], + [0.216210, 0.351535, 0.550627], + [0.214298, 0.355619, 0.551184], + [0.212395, 0.359683, 0.551710], + [0.210503, 0.363727, 0.552206], + [0.208623, 0.367752, 0.552675], + [0.206756, 0.371758, 0.553117], + [0.204903, 0.375746, 0.553533], + [0.203063, 0.379716, 0.553925], + [0.201239, 0.383670, 0.554294], + [0.199430, 0.387607, 0.554642], + [0.197636, 0.391528, 0.554969], + [0.195860, 0.395433, 0.555276], + [0.194100, 0.399323, 0.555565], + [0.192357, 0.403199, 0.555836], + [0.190631, 0.407061, 0.556089], + [0.188923, 0.410910, 0.556326], + [0.187231, 0.414746, 0.556547], + [0.185556, 0.418570, 0.556753], + [0.183898, 0.422383, 0.556944], + [0.182256, 0.426184, 0.557120], + [0.180629, 0.429975, 0.557282], + [0.179019, 0.433756, 0.557430], + [0.177423, 0.437527, 0.557565], + [0.175841, 0.441290, 0.557685], + [0.174274, 0.445044, 0.557792], + [0.172719, 0.448791, 0.557885], + [0.171176, 0.452530, 0.557965], + [0.169646, 0.456262, 0.558030], + [0.168126, 0.459988, 0.558082], + [0.166617, 0.463708, 0.558119], + [0.165117, 0.467423, 0.558141], + [0.163625, 0.471133, 0.558148], + [0.162142, 0.474838, 0.558140], + [0.160665, 0.478540, 0.558115], + [0.159194, 0.482237, 0.558073], + [0.157729, 0.485932, 0.558013], + [0.156270, 0.489624, 0.557936], + [0.154815, 0.493313, 0.557840], + [0.153364, 0.497000, 0.557724], + [0.151918, 0.500685, 0.557587], + [0.150476, 0.504369, 0.557430], + [0.149039, 0.508051, 0.557250], + [0.147607, 0.511733, 0.557049], + [0.146180, 0.515413, 0.556823], + [0.144759, 0.519093, 0.556572], + [0.143343, 0.522773, 0.556295], + [0.141935, 0.526453, 0.555991], + [0.140536, 0.530132, 0.555659], + [0.139147, 0.533812, 0.555298], + [0.137770, 0.537492, 0.554906], + [0.136408, 0.541173, 0.554483], + [0.135066, 0.544853, 0.554029], + [0.133743, 0.548535, 0.553541], + [0.132444, 0.552216, 0.553018], + [0.131172, 0.555899, 0.552459], + [0.129933, 0.559582, 0.551864], + [0.128729, 0.563265, 0.551229], + [0.127568, 0.566949, 0.550556], + [0.126453, 0.570633, 0.549841], + [0.125394, 0.574318, 0.549086], + [0.124395, 0.578002, 0.548287], + [0.123463, 0.581687, 0.547445], + [0.122606, 0.585371, 0.546557], + [0.121831, 0.589055, 0.545623], + [0.121148, 0.592739, 0.544641], + [0.120565, 0.596422, 0.543611], + [0.120092, 0.600104, 0.542530], + [0.119738, 0.603785, 0.541400], + [0.119512, 0.607464, 0.540218], + [0.119423, 0.611141, 0.538982], + [0.119483, 0.614817, 0.537692], + [0.119699, 0.618490, 0.536347], + [0.120081, 0.622161, 0.534946], + [0.120638, 0.625828, 0.533488], + [0.121380, 0.629492, 0.531973], + [0.122312, 0.633153, 0.530398], + [0.123444, 0.636809, 0.528763], + [0.124780, 0.640461, 0.527068], + [0.126326, 0.644107, 0.525311], + [0.128087, 0.647749, 0.523491], + [0.130067, 0.651384, 0.521608], + [0.132268, 0.655014, 0.519661], + [0.134692, 0.658636, 0.517649], + [0.137339, 0.662252, 0.515571], + [0.140210, 0.665859, 0.513427], + [0.143303, 0.669459, 0.511215], + [0.146616, 0.673050, 0.508936], + [0.150148, 0.676631, 0.506589], + [0.153894, 0.680203, 0.504172], + [0.157851, 0.683765, 0.501686], + [0.162016, 0.687316, 0.499129], + [0.166383, 0.690856, 0.496502], + [0.170948, 0.694384, 0.493803], + [0.175707, 0.697900, 0.491033], + [0.180653, 0.701402, 0.488189], + [0.185783, 0.704891, 0.485273], + [0.191090, 0.708366, 0.482284], + [0.196571, 0.711827, 0.479221], + [0.202219, 0.715272, 0.476084], + [0.208030, 0.718701, 0.472873], + [0.214000, 0.722114, 0.469588], + [0.220124, 0.725509, 0.466226], + [0.226397, 0.728888, 0.462789], + [0.232815, 0.732247, 0.459277], + [0.239374, 0.735588, 0.455688], + [0.246070, 0.738910, 0.452024], + [0.252899, 0.742211, 0.448284], + [0.259857, 0.745492, 0.444467], + [0.266941, 0.748751, 0.440573], + [0.274149, 0.751988, 0.436601], + [0.281477, 0.755203, 0.432552], + [0.288921, 0.758394, 0.428426], + [0.296479, 0.761561, 0.424223], + [0.304148, 0.764704, 0.419943], + [0.311925, 0.767822, 0.415586], + [0.319809, 0.770914, 0.411152], + [0.327796, 0.773980, 0.406640], + [0.335885, 0.777018, 0.402049], + [0.344074, 0.780029, 0.397381], + [0.352360, 0.783011, 0.392636], + [0.360741, 0.785964, 0.387814], + [0.369214, 0.788888, 0.382914], + [0.377779, 0.791781, 0.377939], + [0.386433, 0.794644, 0.372886], + [0.395174, 0.797475, 0.367757], + [0.404001, 0.800275, 0.362552], + [0.412913, 0.803041, 0.357269], + [0.421908, 0.805774, 0.351910], + [0.430983, 0.808473, 0.346476], + [0.440137, 0.811138, 0.340967], + [0.449368, 0.813768, 0.335384], + [0.458674, 0.816363, 0.329727], + [0.468053, 0.818921, 0.323998], + [0.477504, 0.821444, 0.318195], + [0.487026, 0.823929, 0.312321], + [0.496615, 0.826376, 0.306377], + [0.506271, 0.828786, 0.300362], + [0.515992, 0.831158, 0.294279], + [0.525776, 0.833491, 0.288127], + [0.535621, 0.835785, 0.281908], + [0.545524, 0.838039, 0.275626], + [0.555484, 0.840254, 0.269281], + [0.565498, 0.842430, 0.262877], + [0.575563, 0.844566, 0.256415], + [0.585678, 0.846661, 0.249897], + [0.595839, 0.848717, 0.243329], + [0.606045, 0.850733, 0.236712], + [0.616293, 0.852709, 0.230052], + [0.626579, 0.854645, 0.223353], + [0.636902, 0.856542, 0.216620], + [0.647257, 0.858400, 0.209861], + [0.657642, 0.860219, 0.203082], + [0.668054, 0.861999, 0.196293], + [0.678489, 0.863742, 0.189503], + [0.688944, 0.865448, 0.182725], + [0.699415, 0.867117, 0.175971], + [0.709898, 0.868751, 0.169257], + [0.720391, 0.870350, 0.162603], + [0.730889, 0.871916, 0.156029], + [0.741388, 0.873449, 0.149561], + [0.751884, 0.874951, 0.143228], + [0.762373, 0.876424, 0.137064], + [0.772852, 0.877868, 0.131109], + [0.783315, 0.879285, 0.125405], + [0.793760, 0.880678, 0.120005], + [0.804182, 0.882046, 0.114965], + [0.814576, 0.883393, 0.110347], + [0.824940, 0.884720, 0.106217], + [0.835270, 0.886029, 0.102646], + [0.845561, 0.887322, 0.099702], + [0.855810, 0.888601, 0.097452], + [0.866013, 0.889868, 0.095953], + [0.876168, 0.891125, 0.095250], + [0.886271, 0.892374, 0.095374], + [0.896320, 0.893616, 0.096335], + [0.906311, 0.894855, 0.098125], + [0.916242, 0.896091, 0.100717], + [0.926106, 0.897330, 0.104071], + [0.935904, 0.898570, 0.108131], + [0.945636, 0.899815, 0.112838], + [0.955300, 0.901065, 0.118128], + [0.964894, 0.902323, 0.123941], + [0.974417, 0.903590, 0.130215], + [0.983868, 0.904867, 0.136897], + [0.993248, 0.906157, 0.143936]] + +_cividis_data = [[0.000000, 0.135112, 0.304751], + [0.000000, 0.138068, 0.311105], + [0.000000, 0.141013, 0.317579], + [0.000000, 0.143951, 0.323982], + [0.000000, 0.146877, 0.330479], + [0.000000, 0.149791, 0.337065], + [0.000000, 0.152673, 0.343704], + [0.000000, 0.155377, 0.350500], + [0.000000, 0.157932, 0.357521], + [0.000000, 0.160495, 0.364534], + [0.000000, 0.163058, 0.371608], + [0.000000, 0.165621, 0.378769], + [0.000000, 0.168204, 0.385902], + [0.000000, 0.170800, 0.393100], + [0.000000, 0.173420, 0.400353], + [0.000000, 0.176082, 0.407577], + [0.000000, 0.178802, 0.414764], + [0.000000, 0.181610, 0.421859], + [0.000000, 0.184550, 0.428802], + [0.000000, 0.186915, 0.435532], + [0.000000, 0.188769, 0.439563], + [0.000000, 0.190950, 0.441085], + [0.000000, 0.193366, 0.441561], + [0.003602, 0.195911, 0.441564], + [0.017852, 0.198528, 0.441248], + [0.032110, 0.201199, 0.440785], + [0.046205, 0.203903, 0.440196], + [0.058378, 0.206629, 0.439531], + [0.068968, 0.209372, 0.438863], + [0.078624, 0.212122, 0.438105], + [0.087465, 0.214879, 0.437342], + [0.095645, 0.217643, 0.436593], + [0.103401, 0.220406, 0.435790], + [0.110658, 0.223170, 0.435067], + [0.117612, 0.225935, 0.434308], + [0.124291, 0.228697, 0.433547], + [0.130669, 0.231458, 0.432840], + [0.136830, 0.234216, 0.432148], + [0.142852, 0.236972, 0.431404], + [0.148638, 0.239724, 0.430752], + [0.154261, 0.242475, 0.430120], + [0.159733, 0.245221, 0.429528], + [0.165113, 0.247965, 0.428908], + [0.170362, 0.250707, 0.428325], + [0.175490, 0.253444, 0.427790], + [0.180503, 0.256180, 0.427299], + [0.185453, 0.258914, 0.426788], + [0.190303, 0.261644, 0.426329], + [0.195057, 0.264372, 0.425924], + [0.199764, 0.267099, 0.425497], + [0.204385, 0.269823, 0.425126], + [0.208926, 0.272546, 0.424809], + [0.213431, 0.275266, 0.424480], + [0.217863, 0.277985, 0.424206], + [0.222264, 0.280702, 0.423914], + [0.226598, 0.283419, 0.423678], + [0.230871, 0.286134, 0.423498], + [0.235120, 0.288848, 0.423304], + [0.239312, 0.291562, 0.423167], + [0.243485, 0.294274, 0.423014], + [0.247605, 0.296986, 0.422917], + [0.251675, 0.299698, 0.422873], + [0.255731, 0.302409, 0.422814], + [0.259740, 0.305120, 0.422810], + [0.263738, 0.307831, 0.422789], + [0.267693, 0.310542, 0.422821], + [0.271639, 0.313253, 0.422837], + [0.275513, 0.315965, 0.422979], + [0.279411, 0.318677, 0.423031], + [0.283240, 0.321390, 0.423211], + [0.287065, 0.324103, 0.423373], + [0.290884, 0.326816, 0.423517], + [0.294669, 0.329531, 0.423716], + [0.298421, 0.332247, 0.423973], + [0.302169, 0.334963, 0.424213], + [0.305886, 0.337681, 0.424512], + [0.309601, 0.340399, 0.424790], + [0.313287, 0.343120, 0.425120], + [0.316941, 0.345842, 0.425512], + [0.320595, 0.348565, 0.425889], + [0.324250, 0.351289, 0.426250], + [0.327875, 0.354016, 0.426670], + [0.331474, 0.356744, 0.427144], + [0.335073, 0.359474, 0.427605], + [0.338673, 0.362206, 0.428053], + [0.342246, 0.364939, 0.428559], + [0.345793, 0.367676, 0.429127], + [0.349341, 0.370414, 0.429685], + [0.352892, 0.373153, 0.430226], + [0.356418, 0.375896, 0.430823], + [0.359916, 0.378641, 0.431501], + [0.363446, 0.381388, 0.432075], + [0.366923, 0.384139, 0.432796], + [0.370430, 0.386890, 0.433428], + [0.373884, 0.389646, 0.434209], + [0.377371, 0.392404, 0.434890], + [0.380830, 0.395164, 0.435653], + [0.384268, 0.397928, 0.436475], + [0.387705, 0.400694, 0.437305], + [0.391151, 0.403464, 0.438096], + [0.394568, 0.406236, 0.438986], + [0.397991, 0.409011, 0.439848], + [0.401418, 0.411790, 0.440708], + [0.404820, 0.414572, 0.441642], + [0.408226, 0.417357, 0.442570], + [0.411607, 0.420145, 0.443577], + [0.414992, 0.422937, 0.444578], + [0.418383, 0.425733, 0.445560], + [0.421748, 0.428531, 0.446640], + [0.425120, 0.431334, 0.447692], + [0.428462, 0.434140, 0.448864], + [0.431817, 0.436950, 0.449982], + [0.435168, 0.439763, 0.451134], + [0.438504, 0.442580, 0.452341], + [0.441810, 0.445402, 0.453659], + [0.445148, 0.448226, 0.454885], + [0.448447, 0.451053, 0.456264], + [0.451759, 0.453887, 0.457582], + [0.455072, 0.456718, 0.458976], + [0.458366, 0.459552, 0.460457], + [0.461616, 0.462405, 0.461969], + [0.464947, 0.465241, 0.463395], + [0.468254, 0.468083, 0.464908], + [0.471501, 0.470960, 0.466357], + [0.474812, 0.473832, 0.467681], + [0.478186, 0.476699, 0.468845], + [0.481622, 0.479573, 0.469767], + [0.485141, 0.482451, 0.470384], + [0.488697, 0.485318, 0.471008], + [0.492278, 0.488198, 0.471453], + [0.495913, 0.491076, 0.471751], + [0.499552, 0.493960, 0.472032], + [0.503185, 0.496851, 0.472305], + [0.506866, 0.499743, 0.472432], + [0.510540, 0.502643, 0.472550], + [0.514226, 0.505546, 0.472640], + [0.517920, 0.508454, 0.472707], + [0.521643, 0.511367, 0.472639], + [0.525348, 0.514285, 0.472660], + [0.529086, 0.517207, 0.472543], + [0.532829, 0.520135, 0.472401], + [0.536553, 0.523067, 0.472352], + [0.540307, 0.526005, 0.472163], + [0.544069, 0.528948, 0.471947], + [0.547840, 0.531895, 0.471704], + [0.551612, 0.534849, 0.471439], + [0.555393, 0.537807, 0.471147], + [0.559181, 0.540771, 0.470829], + [0.562972, 0.543741, 0.470488], + [0.566802, 0.546715, 0.469988], + [0.570607, 0.549695, 0.469593], + [0.574417, 0.552682, 0.469172], + [0.578236, 0.555673, 0.468724], + [0.582087, 0.558670, 0.468118], + [0.585916, 0.561674, 0.467618], + [0.589753, 0.564682, 0.467090], + [0.593622, 0.567697, 0.466401], + [0.597469, 0.570718, 0.465821], + [0.601354, 0.573743, 0.465074], + [0.605211, 0.576777, 0.464441], + [0.609105, 0.579816, 0.463638], + [0.612977, 0.582861, 0.462950], + [0.616852, 0.585913, 0.462237], + [0.620765, 0.588970, 0.461351], + [0.624654, 0.592034, 0.460583], + [0.628576, 0.595104, 0.459641], + [0.632506, 0.598180, 0.458668], + [0.636412, 0.601264, 0.457818], + [0.640352, 0.604354, 0.456791], + [0.644270, 0.607450, 0.455886], + [0.648222, 0.610553, 0.454801], + [0.652178, 0.613664, 0.453689], + [0.656114, 0.616780, 0.452702], + [0.660082, 0.619904, 0.451534], + [0.664055, 0.623034, 0.450338], + [0.668008, 0.626171, 0.449270], + [0.671991, 0.629316, 0.448018], + [0.675981, 0.632468, 0.446736], + [0.679979, 0.635626, 0.445424], + [0.683950, 0.638793, 0.444251], + [0.687957, 0.641966, 0.442886], + [0.691971, 0.645145, 0.441491], + [0.695985, 0.648334, 0.440072], + [0.700008, 0.651529, 0.438624], + [0.704037, 0.654731, 0.437147], + [0.708067, 0.657942, 0.435647], + [0.712105, 0.661160, 0.434117], + [0.716177, 0.664384, 0.432386], + [0.720222, 0.667618, 0.430805], + [0.724274, 0.670859, 0.429194], + [0.728334, 0.674107, 0.427554], + [0.732422, 0.677364, 0.425717], + [0.736488, 0.680629, 0.424028], + [0.740589, 0.683900, 0.422131], + [0.744664, 0.687181, 0.420393], + [0.748772, 0.690470, 0.418448], + [0.752886, 0.693766, 0.416472], + [0.756975, 0.697071, 0.414659], + [0.761096, 0.700384, 0.412638], + [0.765223, 0.703705, 0.410587], + [0.769353, 0.707035, 0.408516], + [0.773486, 0.710373, 0.406422], + [0.777651, 0.713719, 0.404112], + [0.781795, 0.717074, 0.401966], + [0.785965, 0.720438, 0.399613], + [0.790116, 0.723810, 0.397423], + [0.794298, 0.727190, 0.395016], + [0.798480, 0.730580, 0.392597], + [0.802667, 0.733978, 0.390153], + [0.806859, 0.737385, 0.387684], + [0.811054, 0.740801, 0.385198], + [0.815274, 0.744226, 0.382504], + [0.819499, 0.747659, 0.379785], + [0.823729, 0.751101, 0.377043], + [0.827959, 0.754553, 0.374292], + [0.832192, 0.758014, 0.371529], + [0.836429, 0.761483, 0.368747], + [0.840693, 0.764962, 0.365746], + [0.844957, 0.768450, 0.362741], + [0.849223, 0.771947, 0.359729], + [0.853515, 0.775454, 0.356500], + [0.857809, 0.778969, 0.353259], + [0.862105, 0.782494, 0.350011], + [0.866421, 0.786028, 0.346571], + [0.870717, 0.789572, 0.343333], + [0.875057, 0.793125, 0.339685], + [0.879378, 0.796687, 0.336241], + [0.883720, 0.800258, 0.332599], + [0.888081, 0.803839, 0.328770], + [0.892440, 0.807430, 0.324968], + [0.896818, 0.811030, 0.320982], + [0.901195, 0.814639, 0.317021], + [0.905589, 0.818257, 0.312889], + [0.910000, 0.821885, 0.308594], + [0.914407, 0.825522, 0.304348], + [0.918828, 0.829168, 0.299960], + [0.923279, 0.832822, 0.295244], + [0.927724, 0.836486, 0.290611], + [0.932180, 0.840159, 0.285880], + [0.936660, 0.843841, 0.280876], + [0.941147, 0.847530, 0.275815], + [0.945654, 0.851228, 0.270532], + [0.950178, 0.854933, 0.265085], + [0.954725, 0.858646, 0.259365], + [0.959284, 0.862365, 0.253563], + [0.963872, 0.866089, 0.247445], + [0.968469, 0.869819, 0.241310], + [0.973114, 0.873550, 0.234677], + [0.977780, 0.877281, 0.227954], + [0.982497, 0.881008, 0.220878], + [0.987293, 0.884718, 0.213336], + [0.992218, 0.888385, 0.205468], + [0.994847, 0.892954, 0.203445], + [0.995249, 0.898384, 0.207561], + [0.995503, 0.903866, 0.212370], + [0.995737, 0.909344, 0.217772]] + +cmaps = {} +for (name, data) in (('magma', _magma_data), + ('inferno', _inferno_data), + ('plasma', _plasma_data), + ('viridis', _viridis_data), + ('cividis', _cividis_data)): + + cmaps[name] = ListedColormap(data, name=name) + # generate reversed colormap + name = name + '_r' + cmaps[name] = ListedColormap(list(reversed(data)), name=name) diff --git a/contrib/python/matplotlib/py2/matplotlib/_color_data.py b/contrib/python/matplotlib/py2/matplotlib/_color_data.py new file mode 100644 index 00000000000..774e251d72b --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_color_data.py @@ -0,0 +1,1147 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) +from collections import OrderedDict +import six + + +BASE_COLORS = { + 'b': (0, 0, 1), + 'g': (0, 0.5, 0), + 'r': (1, 0, 0), + 'c': (0, 0.75, 0.75), + 'm': (0.75, 0, 0.75), + 'y': (0.75, 0.75, 0), + 'k': (0, 0, 0), + 'w': (1, 1, 1)} + + +# These colors are from Tableau +TABLEAU_COLORS = ( + ('blue', '#1f77b4'), + ('orange', '#ff7f0e'), + ('green', '#2ca02c'), + ('red', '#d62728'), + ('purple', '#9467bd'), + ('brown', '#8c564b'), + ('pink', '#e377c2'), + ('gray', '#7f7f7f'), + ('olive', '#bcbd22'), + ('cyan', '#17becf'), +) + +# Normalize name to "tab:" to avoid name collisions. +TABLEAU_COLORS = OrderedDict( + ('tab:' + name, value) for name, value in TABLEAU_COLORS) + +# This mapping of color names -> hex values is taken from +# a survey run by Randel Monroe see: +# http://blog.xkcd.com/2010/05/03/color-survey-results/ +# for more details. The results are hosted at +# https://xkcd.com/color/rgb.txt +# +# License: http://creativecommons.org/publicdomain/zero/1.0/ +XKCD_COLORS = { + 'cloudy blue': '#acc2d9', + 'dark pastel green': '#56ae57', + 'dust': '#b2996e', + 'electric lime': '#a8ff04', + 'fresh green': '#69d84f', + 'light eggplant': '#894585', + 'nasty green': '#70b23f', + 'really light blue': '#d4ffff', + 'tea': '#65ab7c', + 'warm purple': '#952e8f', + 'yellowish tan': '#fcfc81', + 'cement': '#a5a391', + 'dark grass green': '#388004', + 'dusty teal': '#4c9085', + 'grey teal': '#5e9b8a', + 'macaroni and cheese': '#efb435', + 'pinkish tan': '#d99b82', + 'spruce': '#0a5f38', + 'strong blue': '#0c06f7', + 'toxic green': '#61de2a', + 'windows blue': '#3778bf', + 'blue blue': '#2242c7', + 'blue with a hint of purple': '#533cc6', + 'booger': '#9bb53c', + 'bright sea green': '#05ffa6', + 'dark green blue': '#1f6357', + 'deep turquoise': '#017374', + 'green teal': '#0cb577', + 'strong pink': '#ff0789', + 'bland': '#afa88b', + 'deep aqua': '#08787f', + 'lavender pink': '#dd85d7', + 'light moss green': '#a6c875', + 'light seafoam green': '#a7ffb5', + 'olive yellow': '#c2b709', + 'pig pink': '#e78ea5', + 'deep lilac': '#966ebd', + 'desert': '#ccad60', + 'dusty lavender': '#ac86a8', + 'purpley grey': '#947e94', + 'purply': '#983fb2', + 'candy pink': '#ff63e9', + 'light pastel green': '#b2fba5', + 'boring green': '#63b365', + 'kiwi green': '#8ee53f', + 'light grey green': '#b7e1a1', + 'orange pink': '#ff6f52', + 'tea green': '#bdf8a3', + 'very light brown': '#d3b683', + 'egg shell': '#fffcc4', + 'eggplant purple': '#430541', + 'powder pink': '#ffb2d0', + 'reddish grey': '#997570', + 'baby shit brown': '#ad900d', + 'liliac': '#c48efd', + 'stormy blue': '#507b9c', + 'ugly brown': '#7d7103', + 'custard': '#fffd78', + 'darkish pink': '#da467d', + 'deep brown': '#410200', + 'greenish beige': '#c9d179', + 'manilla': '#fffa86', + 'off blue': '#5684ae', + 'battleship grey': '#6b7c85', + 'browny green': '#6f6c0a', + 'bruise': '#7e4071', + 'kelley green': '#009337', + 'sickly yellow': '#d0e429', + 'sunny yellow': '#fff917', + 'azul': '#1d5dec', + 'darkgreen': '#054907', + 'green/yellow': '#b5ce08', + 'lichen': '#8fb67b', + 'light light green': '#c8ffb0', + 'pale gold': '#fdde6c', + 'sun yellow': '#ffdf22', + 'tan green': '#a9be70', + 'burple': '#6832e3', + 'butterscotch': '#fdb147', + 'toupe': '#c7ac7d', + 'dark cream': '#fff39a', + 'indian red': '#850e04', + 'light lavendar': '#efc0fe', + 'poison green': '#40fd14', + 'baby puke green': '#b6c406', + 'bright yellow green': '#9dff00', + 'charcoal grey': '#3c4142', + 'squash': '#f2ab15', + 'cinnamon': '#ac4f06', + 'light pea green': '#c4fe82', + 'radioactive green': '#2cfa1f', + 'raw sienna': '#9a6200', + 'baby purple': '#ca9bf7', + 'cocoa': '#875f42', + 'light royal blue': '#3a2efe', + 'orangeish': '#fd8d49', + 'rust brown': '#8b3103', + 'sand brown': '#cba560', + 'swamp': '#698339', + 'tealish green': '#0cdc73', + 'burnt siena': '#b75203', + 'camo': '#7f8f4e', + 'dusk blue': '#26538d', + 'fern': '#63a950', + 'old rose': '#c87f89', + 'pale light green': '#b1fc99', + 'peachy pink': '#ff9a8a', + 'rosy pink': '#f6688e', + 'light bluish green': '#76fda8', + 'light bright green': '#53fe5c', + 'light neon green': '#4efd54', + 'light seafoam': '#a0febf', + 'tiffany blue': '#7bf2da', + 'washed out green': '#bcf5a6', + 'browny orange': '#ca6b02', + 'nice blue': '#107ab0', + 'sapphire': '#2138ab', + 'greyish teal': '#719f91', + 'orangey yellow': '#fdb915', + 'parchment': '#fefcaf', + 'straw': '#fcf679', + 'very dark brown': '#1d0200', + 'terracota': '#cb6843', + 'ugly blue': '#31668a', + 'clear blue': '#247afd', + 'creme': '#ffffb6', + 'foam green': '#90fda9', + 'grey/green': '#86a17d', + 'light gold': '#fddc5c', + 'seafoam blue': '#78d1b6', + 'topaz': '#13bbaf', + 'violet pink': '#fb5ffc', + 'wintergreen': '#20f986', + 'yellow tan': '#ffe36e', + 'dark fuchsia': '#9d0759', + 'indigo blue': '#3a18b1', + 'light yellowish green': '#c2ff89', + 'pale magenta': '#d767ad', + 'rich purple': '#720058', + 'sunflower yellow': '#ffda03', + 'green/blue': '#01c08d', + 'leather': '#ac7434', + 'racing green': '#014600', + 'vivid purple': '#9900fa', + 'dark royal blue': '#02066f', + 'hazel': '#8e7618', + 'muted pink': '#d1768f', + 'booger green': '#96b403', + 'canary': '#fdff63', + 'cool grey': '#95a3a6', + 'dark taupe': '#7f684e', + 'darkish purple': '#751973', + 'true green': '#089404', + 'coral pink': '#ff6163', + 'dark sage': '#598556', + 'dark slate blue': '#214761', + 'flat blue': '#3c73a8', + 'mushroom': '#ba9e88', + 'rich blue': '#021bf9', + 'dirty purple': '#734a65', + 'greenblue': '#23c48b', + 'icky green': '#8fae22', + 'light khaki': '#e6f2a2', + 'warm blue': '#4b57db', + 'dark hot pink': '#d90166', + 'deep sea blue': '#015482', + 'carmine': '#9d0216', + 'dark yellow green': '#728f02', + 'pale peach': '#ffe5ad', + 'plum purple': '#4e0550', + 'golden rod': '#f9bc08', + 'neon red': '#ff073a', + 'old pink': '#c77986', + 'very pale blue': '#d6fffe', + 'blood orange': '#fe4b03', + 'grapefruit': '#fd5956', + 'sand yellow': '#fce166', + 'clay brown': '#b2713d', + 'dark blue grey': '#1f3b4d', + 'flat green': '#699d4c', + 'light green blue': '#56fca2', + 'warm pink': '#fb5581', + 'dodger blue': '#3e82fc', + 'gross green': '#a0bf16', + 'ice': '#d6fffa', + 'metallic blue': '#4f738e', + 'pale salmon': '#ffb19a', + 'sap green': '#5c8b15', + 'algae': '#54ac68', + 'bluey grey': '#89a0b0', + 'greeny grey': '#7ea07a', + 'highlighter green': '#1bfc06', + 'light light blue': '#cafffb', + 'light mint': '#b6ffbb', + 'raw umber': '#a75e09', + 'vivid blue': '#152eff', + 'deep lavender': '#8d5eb7', + 'dull teal': '#5f9e8f', + 'light greenish blue': '#63f7b4', + 'mud green': '#606602', + 'pinky': '#fc86aa', + 'red wine': '#8c0034', + 'shit green': '#758000', + 'tan brown': '#ab7e4c', + 'darkblue': '#030764', + 'rosa': '#fe86a4', + 'lipstick': '#d5174e', + 'pale mauve': '#fed0fc', + 'claret': '#680018', + 'dandelion': '#fedf08', + 'orangered': '#fe420f', + 'poop green': '#6f7c00', + 'ruby': '#ca0147', + 'dark': '#1b2431', + 'greenish turquoise': '#00fbb0', + 'pastel red': '#db5856', + 'piss yellow': '#ddd618', + 'bright cyan': '#41fdfe', + 'dark coral': '#cf524e', + 'algae green': '#21c36f', + 'darkish red': '#a90308', + 'reddy brown': '#6e1005', + 'blush pink': '#fe828c', + 'camouflage green': '#4b6113', + 'lawn green': '#4da409', + 'putty': '#beae8a', + 'vibrant blue': '#0339f8', + 'dark sand': '#a88f59', + 'purple/blue': '#5d21d0', + 'saffron': '#feb209', + 'twilight': '#4e518b', + 'warm brown': '#964e02', + 'bluegrey': '#85a3b2', + 'bubble gum pink': '#ff69af', + 'duck egg blue': '#c3fbf4', + 'greenish cyan': '#2afeb7', + 'petrol': '#005f6a', + 'royal': '#0c1793', + 'butter': '#ffff81', + 'dusty orange': '#f0833a', + 'off yellow': '#f1f33f', + 'pale olive green': '#b1d27b', + 'orangish': '#fc824a', + 'leaf': '#71aa34', + 'light blue grey': '#b7c9e2', + 'dried blood': '#4b0101', + 'lightish purple': '#a552e6', + 'rusty red': '#af2f0d', + 'lavender blue': '#8b88f8', + 'light grass green': '#9af764', + 'light mint green': '#a6fbb2', + 'sunflower': '#ffc512', + 'velvet': '#750851', + 'brick orange': '#c14a09', + 'lightish red': '#fe2f4a', + 'pure blue': '#0203e2', + 'twilight blue': '#0a437a', + 'violet red': '#a50055', + 'yellowy brown': '#ae8b0c', + 'carnation': '#fd798f', + 'muddy yellow': '#bfac05', + 'dark seafoam green': '#3eaf76', + 'deep rose': '#c74767', + 'dusty red': '#b9484e', + 'grey/blue': '#647d8e', + 'lemon lime': '#bffe28', + 'purple/pink': '#d725de', + 'brown yellow': '#b29705', + 'purple brown': '#673a3f', + 'wisteria': '#a87dc2', + 'banana yellow': '#fafe4b', + 'lipstick red': '#c0022f', + 'water blue': '#0e87cc', + 'brown grey': '#8d8468', + 'vibrant purple': '#ad03de', + 'baby green': '#8cff9e', + 'barf green': '#94ac02', + 'eggshell blue': '#c4fff7', + 'sandy yellow': '#fdee73', + 'cool green': '#33b864', + 'pale': '#fff9d0', + 'blue/grey': '#758da3', + 'hot magenta': '#f504c9', + 'greyblue': '#77a1b5', + 'purpley': '#8756e4', + 'baby shit green': '#889717', + 'brownish pink': '#c27e79', + 'dark aquamarine': '#017371', + 'diarrhea': '#9f8303', + 'light mustard': '#f7d560', + 'pale sky blue': '#bdf6fe', + 'turtle green': '#75b84f', + 'bright olive': '#9cbb04', + 'dark grey blue': '#29465b', + 'greeny brown': '#696006', + 'lemon green': '#adf802', + 'light periwinkle': '#c1c6fc', + 'seaweed green': '#35ad6b', + 'sunshine yellow': '#fffd37', + 'ugly purple': '#a442a0', + 'medium pink': '#f36196', + 'puke brown': '#947706', + 'very light pink': '#fff4f2', + 'viridian': '#1e9167', + 'bile': '#b5c306', + 'faded yellow': '#feff7f', + 'very pale green': '#cffdbc', + 'vibrant green': '#0add08', + 'bright lime': '#87fd05', + 'spearmint': '#1ef876', + 'light aquamarine': '#7bfdc7', + 'light sage': '#bcecac', + 'yellowgreen': '#bbf90f', + 'baby poo': '#ab9004', + 'dark seafoam': '#1fb57a', + 'deep teal': '#00555a', + 'heather': '#a484ac', + 'rust orange': '#c45508', + 'dirty blue': '#3f829d', + 'fern green': '#548d44', + 'bright lilac': '#c95efb', + 'weird green': '#3ae57f', + 'peacock blue': '#016795', + 'avocado green': '#87a922', + 'faded orange': '#f0944d', + 'grape purple': '#5d1451', + 'hot green': '#25ff29', + 'lime yellow': '#d0fe1d', + 'mango': '#ffa62b', + 'shamrock': '#01b44c', + 'bubblegum': '#ff6cb5', + 'purplish brown': '#6b4247', + 'vomit yellow': '#c7c10c', + 'pale cyan': '#b7fffa', + 'key lime': '#aeff6e', + 'tomato red': '#ec2d01', + 'lightgreen': '#76ff7b', + 'merlot': '#730039', + 'night blue': '#040348', + 'purpleish pink': '#df4ec8', + 'apple': '#6ecb3c', + 'baby poop green': '#8f9805', + 'green apple': '#5edc1f', + 'heliotrope': '#d94ff5', + 'yellow/green': '#c8fd3d', + 'almost black': '#070d0d', + 'cool blue': '#4984b8', + 'leafy green': '#51b73b', + 'mustard brown': '#ac7e04', + 'dusk': '#4e5481', + 'dull brown': '#876e4b', + 'frog green': '#58bc08', + 'vivid green': '#2fef10', + 'bright light green': '#2dfe54', + 'fluro green': '#0aff02', + 'kiwi': '#9cef43', + 'seaweed': '#18d17b', + 'navy green': '#35530a', + 'ultramarine blue': '#1805db', + 'iris': '#6258c4', + 'pastel orange': '#ff964f', + 'yellowish orange': '#ffab0f', + 'perrywinkle': '#8f8ce7', + 'tealish': '#24bca8', + 'dark plum': '#3f012c', + 'pear': '#cbf85f', + 'pinkish orange': '#ff724c', + 'midnight purple': '#280137', + 'light urple': '#b36ff6', + 'dark mint': '#48c072', + 'greenish tan': '#bccb7a', + 'light burgundy': '#a8415b', + 'turquoise blue': '#06b1c4', + 'ugly pink': '#cd7584', + 'sandy': '#f1da7a', + 'electric pink': '#ff0490', + 'muted purple': '#805b87', + 'mid green': '#50a747', + 'greyish': '#a8a495', + 'neon yellow': '#cfff04', + 'banana': '#ffff7e', + 'carnation pink': '#ff7fa7', + 'tomato': '#ef4026', + 'sea': '#3c9992', + 'muddy brown': '#886806', + 'turquoise green': '#04f489', + 'buff': '#fef69e', + 'fawn': '#cfaf7b', + 'muted blue': '#3b719f', + 'pale rose': '#fdc1c5', + 'dark mint green': '#20c073', + 'amethyst': '#9b5fc0', + 'blue/green': '#0f9b8e', + 'chestnut': '#742802', + 'sick green': '#9db92c', + 'pea': '#a4bf20', + 'rusty orange': '#cd5909', + 'stone': '#ada587', + 'rose red': '#be013c', + 'pale aqua': '#b8ffeb', + 'deep orange': '#dc4d01', + 'earth': '#a2653e', + 'mossy green': '#638b27', + 'grassy green': '#419c03', + 'pale lime green': '#b1ff65', + 'light grey blue': '#9dbcd4', + 'pale grey': '#fdfdfe', + 'asparagus': '#77ab56', + 'blueberry': '#464196', + 'purple red': '#990147', + 'pale lime': '#befd73', + 'greenish teal': '#32bf84', + 'caramel': '#af6f09', + 'deep magenta': '#a0025c', + 'light peach': '#ffd8b1', + 'milk chocolate': '#7f4e1e', + 'ocher': '#bf9b0c', + 'off green': '#6ba353', + 'purply pink': '#f075e6', + 'lightblue': '#7bc8f6', + 'dusky blue': '#475f94', + 'golden': '#f5bf03', + 'light beige': '#fffeb6', + 'butter yellow': '#fffd74', + 'dusky purple': '#895b7b', + 'french blue': '#436bad', + 'ugly yellow': '#d0c101', + 'greeny yellow': '#c6f808', + 'orangish red': '#f43605', + 'shamrock green': '#02c14d', + 'orangish brown': '#b25f03', + 'tree green': '#2a7e19', + 'deep violet': '#490648', + 'gunmetal': '#536267', + 'blue/purple': '#5a06ef', + 'cherry': '#cf0234', + 'sandy brown': '#c4a661', + 'warm grey': '#978a84', + 'dark indigo': '#1f0954', + 'midnight': '#03012d', + 'bluey green': '#2bb179', + 'grey pink': '#c3909b', + 'soft purple': '#a66fb5', + 'blood': '#770001', + 'brown red': '#922b05', + 'medium grey': '#7d7f7c', + 'berry': '#990f4b', + 'poo': '#8f7303', + 'purpley pink': '#c83cb9', + 'light salmon': '#fea993', + 'snot': '#acbb0d', + 'easter purple': '#c071fe', + 'light yellow green': '#ccfd7f', + 'dark navy blue': '#00022e', + 'drab': '#828344', + 'light rose': '#ffc5cb', + 'rouge': '#ab1239', + 'purplish red': '#b0054b', + 'slime green': '#99cc04', + 'baby poop': '#937c00', + 'irish green': '#019529', + 'pink/purple': '#ef1de7', + 'dark navy': '#000435', + 'greeny blue': '#42b395', + 'light plum': '#9d5783', + 'pinkish grey': '#c8aca9', + 'dirty orange': '#c87606', + 'rust red': '#aa2704', + 'pale lilac': '#e4cbff', + 'orangey red': '#fa4224', + 'primary blue': '#0804f9', + 'kermit green': '#5cb200', + 'brownish purple': '#76424e', + 'murky green': '#6c7a0e', + 'wheat': '#fbdd7e', + 'very dark purple': '#2a0134', + 'bottle green': '#044a05', + 'watermelon': '#fd4659', + 'deep sky blue': '#0d75f8', + 'fire engine red': '#fe0002', + 'yellow ochre': '#cb9d06', + 'pumpkin orange': '#fb7d07', + 'pale olive': '#b9cc81', + 'light lilac': '#edc8ff', + 'lightish green': '#61e160', + 'carolina blue': '#8ab8fe', + 'mulberry': '#920a4e', + 'shocking pink': '#fe02a2', + 'auburn': '#9a3001', + 'bright lime green': '#65fe08', + 'celadon': '#befdb7', + 'pinkish brown': '#b17261', + 'poo brown': '#885f01', + 'bright sky blue': '#02ccfe', + 'celery': '#c1fd95', + 'dirt brown': '#836539', + 'strawberry': '#fb2943', + 'dark lime': '#84b701', + 'copper': '#b66325', + 'medium brown': '#7f5112', + 'muted green': '#5fa052', + "robin's egg": '#6dedfd', + 'bright aqua': '#0bf9ea', + 'bright lavender': '#c760ff', + 'ivory': '#ffffcb', + 'very light purple': '#f6cefc', + 'light navy': '#155084', + 'pink red': '#f5054f', + 'olive brown': '#645403', + 'poop brown': '#7a5901', + 'mustard green': '#a8b504', + 'ocean green': '#3d9973', + 'very dark blue': '#000133', + 'dusty green': '#76a973', + 'light navy blue': '#2e5a88', + 'minty green': '#0bf77d', + 'adobe': '#bd6c48', + 'barney': '#ac1db8', + 'jade green': '#2baf6a', + 'bright light blue': '#26f7fd', + 'light lime': '#aefd6c', + 'dark khaki': '#9b8f55', + 'orange yellow': '#ffad01', + 'ocre': '#c69c04', + 'maize': '#f4d054', + 'faded pink': '#de9dac', + 'british racing green': '#05480d', + 'sandstone': '#c9ae74', + 'mud brown': '#60460f', + 'light sea green': '#98f6b0', + 'robin egg blue': '#8af1fe', + 'aqua marine': '#2ee8bb', + 'dark sea green': '#11875d', + 'soft pink': '#fdb0c0', + 'orangey brown': '#b16002', + 'cherry red': '#f7022a', + 'burnt yellow': '#d5ab09', + 'brownish grey': '#86775f', + 'camel': '#c69f59', + 'purplish grey': '#7a687f', + 'marine': '#042e60', + 'greyish pink': '#c88d94', + 'pale turquoise': '#a5fbd5', + 'pastel yellow': '#fffe71', + 'bluey purple': '#6241c7', + 'canary yellow': '#fffe40', + 'faded red': '#d3494e', + 'sepia': '#985e2b', + 'coffee': '#a6814c', + 'bright magenta': '#ff08e8', + 'mocha': '#9d7651', + 'ecru': '#feffca', + 'purpleish': '#98568d', + 'cranberry': '#9e003a', + 'darkish green': '#287c37', + 'brown orange': '#b96902', + 'dusky rose': '#ba6873', + 'melon': '#ff7855', + 'sickly green': '#94b21c', + 'silver': '#c5c9c7', + 'purply blue': '#661aee', + 'purpleish blue': '#6140ef', + 'hospital green': '#9be5aa', + 'shit brown': '#7b5804', + 'mid blue': '#276ab3', + 'amber': '#feb308', + 'easter green': '#8cfd7e', + 'soft blue': '#6488ea', + 'cerulean blue': '#056eee', + 'golden brown': '#b27a01', + 'bright turquoise': '#0ffef9', + 'red pink': '#fa2a55', + 'red purple': '#820747', + 'greyish brown': '#7a6a4f', + 'vermillion': '#f4320c', + 'russet': '#a13905', + 'steel grey': '#6f828a', + 'lighter purple': '#a55af4', + 'bright violet': '#ad0afd', + 'prussian blue': '#004577', + 'slate green': '#658d6d', + 'dirty pink': '#ca7b80', + 'dark blue green': '#005249', + 'pine': '#2b5d34', + 'yellowy green': '#bff128', + 'dark gold': '#b59410', + 'bluish': '#2976bb', + 'darkish blue': '#014182', + 'dull red': '#bb3f3f', + 'pinky red': '#fc2647', + 'bronze': '#a87900', + 'pale teal': '#82cbb2', + 'military green': '#667c3e', + 'barbie pink': '#fe46a5', + 'bubblegum pink': '#fe83cc', + 'pea soup green': '#94a617', + 'dark mustard': '#a88905', + 'shit': '#7f5f00', + 'medium purple': '#9e43a2', + 'very dark green': '#062e03', + 'dirt': '#8a6e45', + 'dusky pink': '#cc7a8b', + 'red violet': '#9e0168', + 'lemon yellow': '#fdff38', + 'pistachio': '#c0fa8b', + 'dull yellow': '#eedc5b', + 'dark lime green': '#7ebd01', + 'denim blue': '#3b5b92', + 'teal blue': '#01889f', + 'lightish blue': '#3d7afd', + 'purpley blue': '#5f34e7', + 'light indigo': '#6d5acf', + 'swamp green': '#748500', + 'brown green': '#706c11', + 'dark maroon': '#3c0008', + 'hot purple': '#cb00f5', + 'dark forest green': '#002d04', + 'faded blue': '#658cbb', + 'drab green': '#749551', + 'light lime green': '#b9ff66', + 'snot green': '#9dc100', + 'yellowish': '#faee66', + 'light blue green': '#7efbb3', + 'bordeaux': '#7b002c', + 'light mauve': '#c292a1', + 'ocean': '#017b92', + 'marigold': '#fcc006', + 'muddy green': '#657432', + 'dull orange': '#d8863b', + 'steel': '#738595', + 'electric purple': '#aa23ff', + 'fluorescent green': '#08ff08', + 'yellowish brown': '#9b7a01', + 'blush': '#f29e8e', + 'soft green': '#6fc276', + 'bright orange': '#ff5b00', + 'lemon': '#fdff52', + 'purple grey': '#866f85', + 'acid green': '#8ffe09', + 'pale lavender': '#eecffe', + 'violet blue': '#510ac9', + 'light forest green': '#4f9153', + 'burnt red': '#9f2305', + 'khaki green': '#728639', + 'cerise': '#de0c62', + 'faded purple': '#916e99', + 'apricot': '#ffb16d', + 'dark olive green': '#3c4d03', + 'grey brown': '#7f7053', + 'green grey': '#77926f', + 'true blue': '#010fcc', + 'pale violet': '#ceaefa', + 'periwinkle blue': '#8f99fb', + 'light sky blue': '#c6fcff', + 'blurple': '#5539cc', + 'green brown': '#544e03', + 'bluegreen': '#017a79', + 'bright teal': '#01f9c6', + 'brownish yellow': '#c9b003', + 'pea soup': '#929901', + 'forest': '#0b5509', + 'barney purple': '#a00498', + 'ultramarine': '#2000b1', + 'purplish': '#94568c', + 'puke yellow': '#c2be0e', + 'bluish grey': '#748b97', + 'dark periwinkle': '#665fd1', + 'dark lilac': '#9c6da5', + 'reddish': '#c44240', + 'light maroon': '#a24857', + 'dusty purple': '#825f87', + 'terra cotta': '#c9643b', + 'avocado': '#90b134', + 'marine blue': '#01386a', + 'teal green': '#25a36f', + 'slate grey': '#59656d', + 'lighter green': '#75fd63', + 'electric green': '#21fc0d', + 'dusty blue': '#5a86ad', + 'golden yellow': '#fec615', + 'bright yellow': '#fffd01', + 'light lavender': '#dfc5fe', + 'umber': '#b26400', + 'poop': '#7f5e00', + 'dark peach': '#de7e5d', + 'jungle green': '#048243', + 'eggshell': '#ffffd4', + 'denim': '#3b638c', + 'yellow brown': '#b79400', + 'dull purple': '#84597e', + 'chocolate brown': '#411900', + 'wine red': '#7b0323', + 'neon blue': '#04d9ff', + 'dirty green': '#667e2c', + 'light tan': '#fbeeac', + 'ice blue': '#d7fffe', + 'cadet blue': '#4e7496', + 'dark mauve': '#874c62', + 'very light blue': '#d5ffff', + 'grey purple': '#826d8c', + 'pastel pink': '#ffbacd', + 'very light green': '#d1ffbd', + 'dark sky blue': '#448ee4', + 'evergreen': '#05472a', + 'dull pink': '#d5869d', + 'aubergine': '#3d0734', + 'mahogany': '#4a0100', + 'reddish orange': '#f8481c', + 'deep green': '#02590f', + 'vomit green': '#89a203', + 'purple pink': '#e03fd8', + 'dusty pink': '#d58a94', + 'faded green': '#7bb274', + 'camo green': '#526525', + 'pinky purple': '#c94cbe', + 'pink purple': '#db4bda', + 'brownish red': '#9e3623', + 'dark rose': '#b5485d', + 'mud': '#735c12', + 'brownish': '#9c6d57', + 'emerald green': '#028f1e', + 'pale brown': '#b1916e', + 'dull blue': '#49759c', + 'burnt umber': '#a0450e', + 'medium green': '#39ad48', + 'clay': '#b66a50', + 'light aqua': '#8cffdb', + 'light olive green': '#a4be5c', + 'brownish orange': '#cb7723', + 'dark aqua': '#05696b', + 'purplish pink': '#ce5dae', + 'dark salmon': '#c85a53', + 'greenish grey': '#96ae8d', + 'jade': '#1fa774', + 'ugly green': '#7a9703', + 'dark beige': '#ac9362', + 'emerald': '#01a049', + 'pale red': '#d9544d', + 'light magenta': '#fa5ff7', + 'sky': '#82cafc', + 'light cyan': '#acfffc', + 'yellow orange': '#fcb001', + 'reddish purple': '#910951', + 'reddish pink': '#fe2c54', + 'orchid': '#c875c4', + 'dirty yellow': '#cdc50a', + 'orange red': '#fd411e', + 'deep red': '#9a0200', + 'orange brown': '#be6400', + 'cobalt blue': '#030aa7', + 'neon pink': '#fe019a', + 'rose pink': '#f7879a', + 'greyish purple': '#887191', + 'raspberry': '#b00149', + 'aqua green': '#12e193', + 'salmon pink': '#fe7b7c', + 'tangerine': '#ff9408', + 'brownish green': '#6a6e09', + 'red brown': '#8b2e16', + 'greenish brown': '#696112', + 'pumpkin': '#e17701', + 'pine green': '#0a481e', + 'charcoal': '#343837', + 'baby pink': '#ffb7ce', + 'cornflower': '#6a79f7', + 'blue violet': '#5d06e9', + 'chocolate': '#3d1c02', + 'greyish green': '#82a67d', + 'scarlet': '#be0119', + 'green yellow': '#c9ff27', + 'dark olive': '#373e02', + 'sienna': '#a9561e', + 'pastel purple': '#caa0ff', + 'terracotta': '#ca6641', + 'aqua blue': '#02d8e9', + 'sage green': '#88b378', + 'blood red': '#980002', + 'deep pink': '#cb0162', + 'grass': '#5cac2d', + 'moss': '#769958', + 'pastel blue': '#a2bffe', + 'bluish green': '#10a674', + 'green blue': '#06b48b', + 'dark tan': '#af884a', + 'greenish blue': '#0b8b87', + 'pale orange': '#ffa756', + 'vomit': '#a2a415', + 'forrest green': '#154406', + 'dark lavender': '#856798', + 'dark violet': '#34013f', + 'purple blue': '#632de9', + 'dark cyan': '#0a888a', + 'olive drab': '#6f7632', + 'pinkish': '#d46a7e', + 'cobalt': '#1e488f', + 'neon purple': '#bc13fe', + 'light turquoise': '#7ef4cc', + 'apple green': '#76cd26', + 'dull green': '#74a662', + 'wine': '#80013f', + 'powder blue': '#b1d1fc', + 'off white': '#ffffe4', + 'electric blue': '#0652ff', + 'dark turquoise': '#045c5a', + 'blue purple': '#5729ce', + 'azure': '#069af3', + 'bright red': '#ff000d', + 'pinkish red': '#f10c45', + 'cornflower blue': '#5170d7', + 'light olive': '#acbf69', + 'grape': '#6c3461', + 'greyish blue': '#5e819d', + 'purplish blue': '#601ef9', + 'yellowish green': '#b0dd16', + 'greenish yellow': '#cdfd02', + 'medium blue': '#2c6fbb', + 'dusty rose': '#c0737a', + 'light violet': '#d6b4fc', + 'midnight blue': '#020035', + 'bluish purple': '#703be7', + 'red orange': '#fd3c06', + 'dark magenta': '#960056', + 'greenish': '#40a368', + 'ocean blue': '#03719c', + 'coral': '#fc5a50', + 'cream': '#ffffc2', + 'reddish brown': '#7f2b0a', + 'burnt sienna': '#b04e0f', + 'brick': '#a03623', + 'sage': '#87ae73', + 'grey green': '#789b73', + 'white': '#ffffff', + "robin's egg blue": '#98eff9', + 'moss green': '#658b38', + 'steel blue': '#5a7d9a', + 'eggplant': '#380835', + 'light yellow': '#fffe7a', + 'leaf green': '#5ca904', + 'light grey': '#d8dcd6', + 'puke': '#a5a502', + 'pinkish purple': '#d648d7', + 'sea blue': '#047495', + 'pale purple': '#b790d4', + 'slate blue': '#5b7c99', + 'blue grey': '#607c8e', + 'hunter green': '#0b4008', + 'fuchsia': '#ed0dd9', + 'crimson': '#8c000f', + 'pale yellow': '#ffff84', + 'ochre': '#bf9005', + 'mustard yellow': '#d2bd0a', + 'light red': '#ff474c', + 'cerulean': '#0485d1', + 'pale pink': '#ffcfdc', + 'deep blue': '#040273', + 'rust': '#a83c09', + 'light teal': '#90e4c1', + 'slate': '#516572', + 'goldenrod': '#fac205', + 'dark yellow': '#d5b60a', + 'dark grey': '#363737', + 'army green': '#4b5d16', + 'grey blue': '#6b8ba4', + 'seafoam': '#80f9ad', + 'puce': '#a57e52', + 'spring green': '#a9f971', + 'dark orange': '#c65102', + 'sand': '#e2ca76', + 'pastel green': '#b0ff9d', + 'mint': '#9ffeb0', + 'light orange': '#fdaa48', + 'bright pink': '#fe01b1', + 'chartreuse': '#c1f80a', + 'deep purple': '#36013f', + 'dark brown': '#341c02', + 'taupe': '#b9a281', + 'pea green': '#8eab12', + 'puke green': '#9aae07', + 'kelly green': '#02ab2e', + 'seafoam green': '#7af9ab', + 'blue green': '#137e6d', + 'khaki': '#aaa662', + 'burgundy': '#610023', + 'dark teal': '#014d4e', + 'brick red': '#8f1402', + 'royal purple': '#4b006e', + 'plum': '#580f41', + 'mint green': '#8fff9f', + 'gold': '#dbb40c', + 'baby blue': '#a2cffe', + 'yellow green': '#c0fb2d', + 'bright purple': '#be03fd', + 'dark red': '#840000', + 'pale blue': '#d0fefe', + 'grass green': '#3f9b0b', + 'navy': '#01153e', + 'aquamarine': '#04d8b2', + 'burnt orange': '#c04e01', + 'neon green': '#0cff0c', + 'bright blue': '#0165fc', + 'rose': '#cf6275', + 'light pink': '#ffd1df', + 'mustard': '#ceb301', + 'indigo': '#380282', + 'lime': '#aaff32', + 'sea green': '#53fca1', + 'periwinkle': '#8e82fe', + 'dark pink': '#cb416b', + 'olive green': '#677a04', + 'peach': '#ffb07c', + 'pale green': '#c7fdb5', + 'light brown': '#ad8150', + 'hot pink': '#ff028d', + 'black': '#000000', + 'lilac': '#cea2fd', + 'navy blue': '#001146', + 'royal blue': '#0504aa', + 'beige': '#e6daa6', + 'salmon': '#ff796c', + 'olive': '#6e750e', + 'maroon': '#650021', + 'bright green': '#01ff07', + 'dark purple': '#35063e', + 'mauve': '#ae7181', + 'forest green': '#06470c', + 'aqua': '#13eac9', + 'cyan': '#00ffff', + 'tan': '#d1b26f', + 'dark blue': '#00035b', + 'lavender': '#c79fef', + 'turquoise': '#06c2ac', + 'dark green': '#033500', + 'violet': '#9a0eea', + 'light purple': '#bf77f6', + 'lime green': '#89fe05', + 'grey': '#929591', + 'sky blue': '#75bbfd', + 'yellow': '#ffff14', + 'magenta': '#c20078', + 'light green': '#96f97b', + 'orange': '#f97306', + 'teal': '#029386', + 'light blue': '#95d0fc', + 'red': '#e50000', + 'brown': '#653700', + 'pink': '#ff81c0', + 'blue': '#0343df', + 'green': '#15b01a', + 'purple': '#7e1e9c'} + +# Normalize name to "xkcd:" to avoid name collisions. +XKCD_COLORS = {'xkcd:' + name: value for name, value in XKCD_COLORS.items()} + + +# https://drafts.csswg.org/css-color-4/#named-colors +CSS4_COLORS = { + 'aliceblue': '#F0F8FF', + 'antiquewhite': '#FAEBD7', + 'aqua': '#00FFFF', + 'aquamarine': '#7FFFD4', + 'azure': '#F0FFFF', + 'beige': '#F5F5DC', + 'bisque': '#FFE4C4', + 'black': '#000000', + 'blanchedalmond': '#FFEBCD', + 'blue': '#0000FF', + 'blueviolet': '#8A2BE2', + 'brown': '#A52A2A', + 'burlywood': '#DEB887', + 'cadetblue': '#5F9EA0', + 'chartreuse': '#7FFF00', + 'chocolate': '#D2691E', + 'coral': '#FF7F50', + 'cornflowerblue': '#6495ED', + 'cornsilk': '#FFF8DC', + 'crimson': '#DC143C', + 'cyan': '#00FFFF', + 'darkblue': '#00008B', + 'darkcyan': '#008B8B', + 'darkgoldenrod': '#B8860B', + 'darkgray': '#A9A9A9', + 'darkgreen': '#006400', + 'darkgrey': '#A9A9A9', + 'darkkhaki': '#BDB76B', + 'darkmagenta': '#8B008B', + 'darkolivegreen': '#556B2F', + 'darkorange': '#FF8C00', + 'darkorchid': '#9932CC', + 'darkred': '#8B0000', + 'darksalmon': '#E9967A', + 'darkseagreen': '#8FBC8F', + 'darkslateblue': '#483D8B', + 'darkslategray': '#2F4F4F', + 'darkslategrey': '#2F4F4F', + 'darkturquoise': '#00CED1', + 'darkviolet': '#9400D3', + 'deeppink': '#FF1493', + 'deepskyblue': '#00BFFF', + 'dimgray': '#696969', + 'dimgrey': '#696969', + 'dodgerblue': '#1E90FF', + 'firebrick': '#B22222', + 'floralwhite': '#FFFAF0', + 'forestgreen': '#228B22', + 'fuchsia': '#FF00FF', + 'gainsboro': '#DCDCDC', + 'ghostwhite': '#F8F8FF', + 'gold': '#FFD700', + 'goldenrod': '#DAA520', + 'gray': '#808080', + 'green': '#008000', + 'greenyellow': '#ADFF2F', + 'grey': '#808080', + 'honeydew': '#F0FFF0', + 'hotpink': '#FF69B4', + 'indianred': '#CD5C5C', + 'indigo': '#4B0082', + 'ivory': '#FFFFF0', + 'khaki': '#F0E68C', + 'lavender': '#E6E6FA', + 'lavenderblush': '#FFF0F5', + 'lawngreen': '#7CFC00', + 'lemonchiffon': '#FFFACD', + 'lightblue': '#ADD8E6', + 'lightcoral': '#F08080', + 'lightcyan': '#E0FFFF', + 'lightgoldenrodyellow': '#FAFAD2', + 'lightgray': '#D3D3D3', + 'lightgreen': '#90EE90', + 'lightgrey': '#D3D3D3', + 'lightpink': '#FFB6C1', + 'lightsalmon': '#FFA07A', + 'lightseagreen': '#20B2AA', + 'lightskyblue': '#87CEFA', + 'lightslategray': '#778899', + 'lightslategrey': '#778899', + 'lightsteelblue': '#B0C4DE', + 'lightyellow': '#FFFFE0', + 'lime': '#00FF00', + 'limegreen': '#32CD32', + 'linen': '#FAF0E6', + 'magenta': '#FF00FF', + 'maroon': '#800000', + 'mediumaquamarine': '#66CDAA', + 'mediumblue': '#0000CD', + 'mediumorchid': '#BA55D3', + 'mediumpurple': '#9370DB', + 'mediumseagreen': '#3CB371', + 'mediumslateblue': '#7B68EE', + 'mediumspringgreen': '#00FA9A', + 'mediumturquoise': '#48D1CC', + 'mediumvioletred': '#C71585', + 'midnightblue': '#191970', + 'mintcream': '#F5FFFA', + 'mistyrose': '#FFE4E1', + 'moccasin': '#FFE4B5', + 'navajowhite': '#FFDEAD', + 'navy': '#000080', + 'oldlace': '#FDF5E6', + 'olive': '#808000', + 'olivedrab': '#6B8E23', + 'orange': '#FFA500', + 'orangered': '#FF4500', + 'orchid': '#DA70D6', + 'palegoldenrod': '#EEE8AA', + 'palegreen': '#98FB98', + 'paleturquoise': '#AFEEEE', + 'palevioletred': '#DB7093', + 'papayawhip': '#FFEFD5', + 'peachpuff': '#FFDAB9', + 'peru': '#CD853F', + 'pink': '#FFC0CB', + 'plum': '#DDA0DD', + 'powderblue': '#B0E0E6', + 'purple': '#800080', + 'rebeccapurple': '#663399', + 'red': '#FF0000', + 'rosybrown': '#BC8F8F', + 'royalblue': '#4169E1', + 'saddlebrown': '#8B4513', + 'salmon': '#FA8072', + 'sandybrown': '#F4A460', + 'seagreen': '#2E8B57', + 'seashell': '#FFF5EE', + 'sienna': '#A0522D', + 'silver': '#C0C0C0', + 'skyblue': '#87CEEB', + 'slateblue': '#6A5ACD', + 'slategray': '#708090', + 'slategrey': '#708090', + 'snow': '#FFFAFA', + 'springgreen': '#00FF7F', + 'steelblue': '#4682B4', + 'tan': '#D2B48C', + 'teal': '#008080', + 'thistle': '#D8BFD8', + 'tomato': '#FF6347', + 'turquoise': '#40E0D0', + 'violet': '#EE82EE', + 'wheat': '#F5DEB3', + 'white': '#FFFFFF', + 'whitesmoke': '#F5F5F5', + 'yellow': '#FFFF00', + 'yellowgreen': '#9ACD32'} diff --git a/contrib/python/matplotlib/py2/matplotlib/_constrained_layout.py b/contrib/python/matplotlib/py2/matplotlib/_constrained_layout.py new file mode 100644 index 00000000000..b8325f5d636 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_constrained_layout.py @@ -0,0 +1,666 @@ +""" +This module provides the routine to adjust subplot layouts so that there are +no overlapping axes or axes decorations. All axes decorations are dealt with +(labels, ticks, titles, ticklabels) and some dependent artists are also dealt +with (colorbar, suptitle, legend). + +Layout is done via :meth:`~matplotlib.gridspec`, with one constraint per +gridspec, so it is possible to have overlapping axes if the gridspecs +overlap (i.e. using :meth:`~matplotlib.gridspec.GridSpecFromSubplotSpec`). +Axes placed using ``figure.subplots()`` or ``figure.add_subplots()`` will +participate in the layout. Axes manually placed via ``figure.add_axes()`` +will not. + +See Tutorial: :doc:`/tutorials/intermediate/constrainedlayout_guide` + +""" + +# Development Notes: + +# What gets a layoutbox: +# - figure +# - gridspec +# - subplotspec +# EITHER: +# - axes + pos for the axes (i.e. the total area taken by axis and +# the actual "position" argument that needs to be sent to +# ax.set_position.) +# - The axes layout box will also encomapss the legend, and that is +# how legends get included (axes legeneds, not figure legends) +# - colorbars are sibblings of the axes if they are single-axes +# colorbars +# OR: +# - a gridspec can be inside a subplotspec. +# - subplotspec +# EITHER: +# - axes... +# OR: +# - gridspec... with arbitrary nesting... +# - colorbars are siblings of the subplotspecs if they are multi-axes +# colorbars. +# - suptitle: +# - right now suptitles are just stacked atop everything else in figure. +# Could imagine suptitles being gridspec suptitles, but not implimented +# +# Todo: AnchoredOffsetbox connected to gridspecs or axes. This would +# be more general way to add extra-axes annotations. + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import numpy as np +import logging +import warnings + +from matplotlib.legend import Legend +import matplotlib.transforms as transforms +import matplotlib._layoutbox as layoutbox + +_log = logging.getLogger(__name__) + + +def get_axall_tightbbox(ax, renderer): + ''' + Get the tight_bbox of the axis ax, and any dependent decorations, like + a `Legend` instance. + ''' + + # main bbox of the axis.... + bbox = ax.get_tightbbox(renderer=renderer) + # now add the possibility of the legend... + for child in ax.get_children(): + if isinstance(child, Legend): + bboxn = child._legend_box.get_window_extent(renderer) + bbox = transforms.Bbox.union([bbox, bboxn]) + # add other children here.... + return bbox + + +def in_same_column(colnum0min, colnum0max, colnumCmin, colnumCmax): + if colnum0min >= colnumCmin and colnum0min <= colnumCmax: + return True + if colnum0max >= colnumCmin and colnum0max <= colnumCmax: + return True + return False + + +def in_same_row(rownum0min, rownum0max, rownumCmin, rownumCmax): + if rownum0min >= rownumCmin and rownum0min <= rownumCmax: + return True + if rownum0max >= rownumCmin and rownum0max <= rownumCmax: + return True + return False + + +###################################################### +def do_constrained_layout(fig, renderer, h_pad, w_pad, + hspace=None, wspace=None): + + """ + Do the constrained_layout. Called at draw time in + ``figure.constrained_layout()`` + + Parameters + ---------- + + + fig: Figure + is the ``figure`` instance to do the layout in. + + renderer: Renderer + the renderer to use. + + h_pad, w_pad : float + are in figure-normalized units, and are a padding around the axes + elements. + + hspace, wspace : float + are in fractions of the subplot sizes. + + """ + + ''' Steps: + + 1. get a list of unique gridspecs in this figure. Each gridspec will be + constrained separately. + 2. Check for gaps in the gridspecs. i.e. if not every axes slot in the + gridspec has been filled. If empty, add a ghost axis that is made so + that it cannot be seen (though visible=True). This is needed to make + a blank spot in the layout. + 3. Compare the tight_bbox of each axes to its `position`, and assume that + the difference is the space needed by the elements around the edge of + the axes (decorations) like the title, ticklabels, x-labels, etc. This + can include legends who overspill the axes boundaries. + 4. Constrain gridspec elements to line up: + a) if colnum0 neq colnumC, the two subplotspecs are stacked next to + each other, with the appropriate order. + b) if colnum0 == columnC line up the left or right side of the + _poslayoutbox (depending if it is the min or max num that is equal). + c) do the same for rows... + 5. The above doesn't constrain relative sizes of the _poslayoutboxes at + all, and indeed zero-size is a solution that the solver often finds more + convenient than expanding the sizes. Right now the solution is to compare + subplotspec sizes (i.e. drowsC and drows0) and constrain the larger + _poslayoutbox to be larger than the ratio of the sizes. i.e. if drows0 > + drowsC, then ax._poslayoutbox > axc._poslayoutbox * drowsC / drows0. This + works fine *if* the decorations are similar between the axes. If the + larger subplotspec has much larger axes decorations, then the constraint + above is incorrect. + + We need the greater than in the above, in general, rather than an equals + sign. Consider the case of the left column having 2 rows, and the right + column having 1 row. We want the top and bottom of the _poslayoutboxes to + line up. So that means if there are decorations on the left column axes + they will be smaller than half as large as the right hand axis. + + This can break down if the decoration size for the right hand axis (the + margins) is very large. There must be a math way to check for this case. + + ''' + + invTransFig = fig.transFigure.inverted().transform_bbox + + # list of unique gridspecs that contain child axes: + gss = set([]) + for ax in fig.axes: + if hasattr(ax, 'get_subplotspec'): + gs = ax.get_subplotspec().get_gridspec() + if gs._layoutbox is not None: + gss.add(gs) + if len(gss) == 0: + warnings.warn('There are no gridspecs with layoutboxes. ' + 'Possibly did not call parent GridSpec with the figure= ' + 'keyword') + + # check for unoccupied gridspec slots and make ghost axes for these + # slots... Do for each gs separately. This is a pretty big kludge + # but shoudn't have too much ill effect. The worst is that + # someone querrying the figure will wonder why there are more + # axes than they thought. + if fig._layoutbox.constrained_layout_called < 1: + for gs in gss: + nrows, ncols = gs.get_geometry() + hassubplotspec = np.zeros(nrows * ncols, dtype=bool) + axs = [] + for ax in fig.axes: + if (hasattr(ax, 'get_subplotspec') + and ax._layoutbox is not None + and ax.get_subplotspec().get_gridspec() == gs): + axs += [ax] + for ax in axs: + ss0 = ax.get_subplotspec() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + hassubplotspec[ss0.num1:(ss0.num2 + 1)] = True + for nn, hss in enumerate(hassubplotspec): + if not hss: + # this gridspec slot doesn't have an axis so we + # make a "ghost". + ax = fig.add_subplot(gs[nn]) + ax.set_frame_on(False) + ax.set_xticks([]) + ax.set_yticks([]) + ax.set_facecolor((1, 0, 0, 0)) + + # for each axes, make a margin between the *pos* layoutbox and the + # *axes* layoutbox be a minimum size that can accomodate the + # decorations on the axis. + for ax in fig.axes: + _log.debug(ax._layoutbox) + if ax._layoutbox is not None: + pos = ax.get_position(original=True) + tightbbox = get_axall_tightbbox(ax, renderer) + bbox = invTransFig(tightbbox) + # use stored h_pad if it exists + h_padt = ax._poslayoutbox.h_pad + if h_padt is None: + h_padt = h_pad + w_padt = ax._poslayoutbox.w_pad + if w_padt is None: + w_padt = w_pad + ax._poslayoutbox.edit_left_margin_min(-bbox.x0 + + pos.x0 + w_padt) + ax._poslayoutbox.edit_right_margin_min(bbox.x1 - + pos.x1 + w_padt) + ax._poslayoutbox.edit_bottom_margin_min( + -bbox.y0 + pos.y0 + h_padt) + ax._poslayoutbox.edit_top_margin_min(bbox.y1-pos.y1+h_padt) + _log.debug('left %f', (-bbox.x0 + pos.x0 + w_pad)) + _log.debug('right %f', (bbox.x1 - pos.x1 + w_pad)) + _log.debug('bottom %f', (-bbox.y0 + pos.y0 + h_padt)) + # Sometimes its possible for the solver to collapse + # rather than expand axes, so they all have zero height + # or width. This stops that... It *should* have been + # taken into account w/ pref_width... + if fig._layoutbox.constrained_layout_called < 1: + ax._poslayoutbox.constrain_height_min(20, strength='weak') + ax._poslayoutbox.constrain_width_min(20, strength='weak') + ax._layoutbox.constrain_height_min(20, strength='weak') + ax._layoutbox.constrain_width_min(20, strength='weak') + ax._poslayoutbox.constrain_top_margin(0, strength='weak') + ax._poslayoutbox.constrain_bottom_margin(0, + strength='weak') + ax._poslayoutbox.constrain_right_margin(0, strength='weak') + ax._poslayoutbox.constrain_left_margin(0, strength='weak') + + # do layout for suptitle. + if fig._suptitle is not None and fig._suptitle._layoutbox is not None: + sup = fig._suptitle + bbox = invTransFig(sup.get_window_extent(renderer=renderer)) + height = bbox.y1 - bbox.y0 + sup._layoutbox.edit_height(height+h_pad) + + # OK, the above lines up ax._poslayoutbox with ax._layoutbox + # now we need to + # 1) arrange the subplotspecs. We do it at this level because + # the subplotspecs are meant to contain other dependent axes + # like colorbars or legends. + # 2) line up the right and left side of the ax._poslayoutbox + # that have the same subplotspec maxes. + + if fig._layoutbox.constrained_layout_called < 1: + + # arrange the subplotspecs... This is all done relative to each + # other. Some subplotspecs conatain axes, and others contain gridspecs + # the ones that contain gridspecs are a set proportion of their + # parent gridspec. The ones that contain axes are not so constrained. + figlb = fig._layoutbox + for child in figlb.children: + if child._is_gridspec_layoutbox(): + # farm the gridspec layout out. + # + # This routine makes all the subplot spec containers + # have the correct arrangement. It just stacks the + # subplot layoutboxes in the correct order... + _arange_subplotspecs(child, hspace=hspace, wspace=wspace) + + # - Align right/left and bottom/top spines of appropriate subplots. + # - Compare size of subplotspec including height and width ratios + # and make sure that the axes spines are at least as large + # as they should be. + for gs in gss: + # for each gridspec... + nrows, ncols = gs.get_geometry() + width_ratios = gs.get_width_ratios() + height_ratios = gs.get_height_ratios() + if width_ratios is None: + width_ratios = np.ones(ncols) + if height_ratios is None: + height_ratios = np.ones(nrows) + + # get axes in this gridspec.... + axs = [] + for ax in fig.axes: + if (hasattr(ax, 'get_subplotspec') + and ax._layoutbox is not None): + if ax.get_subplotspec().get_gridspec() == gs: + axs += [ax] + rownummin = np.zeros(len(axs), dtype=np.int8) + rownummax = np.zeros(len(axs), dtype=np.int8) + colnummin = np.zeros(len(axs), dtype=np.int8) + colnummax = np.zeros(len(axs), dtype=np.int8) + width = np.zeros(len(axs)) + height = np.zeros(len(axs)) + + for n, ax in enumerate(axs): + ss0 = ax.get_subplotspec() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + rownummin[n], colnummin[n] = divmod(ss0.num1, ncols) + rownummax[n], colnummax[n] = divmod(ss0.num2, ncols) + width[n] = np.sum( + width_ratios[colnummin[n]:(colnummax[n] + 1)]) + height[n] = np.sum( + height_ratios[rownummin[n]:(rownummax[n] + 1)]) + + for nn, ax in enumerate(axs[:-1]): + ss0 = ax.get_subplotspec() + + # now compare ax to all the axs: + # + # If the subplotspecs have the same colnumXmax, then line + # up their right sides. If they have the same min, then + # line up their left sides (and vertical equivalents). + rownum0min, colnum0min = rownummin[nn], colnummin[nn] + rownum0max, colnum0max = rownummax[nn], colnummax[nn] + width0, height0 = width[nn], height[nn] + alignleft = False + alignright = False + alignbot = False + aligntop = False + alignheight = False + alignwidth = False + for mm in range(nn+1, len(axs)): + axc = axs[mm] + rownumCmin, colnumCmin = rownummin[mm], colnummin[mm] + rownumCmax, colnumCmax = rownummax[mm], colnummax[mm] + widthC, heightC = width[mm], height[mm] + # Horizontally align axes spines if they have the + # same min or max: + if not alignleft and colnum0min == colnumCmin: + # we want the _poslayoutboxes to line up on left + # side of the axes spines... + layoutbox.align([ax._poslayoutbox, + axc._poslayoutbox], + 'left') + alignleft = True + + if not alignright and colnum0max == colnumCmax: + # line up right sides of _poslayoutbox + layoutbox.align([ax._poslayoutbox, + axc._poslayoutbox], + 'right') + alignright = True + # Vertically align axes spines if they have the + # same min or max: + if not aligntop and rownum0min == rownumCmin: + # line up top of _poslayoutbox + _log.debug('rownum0min == rownumCmin') + layoutbox.align([ax._poslayoutbox, axc._poslayoutbox], + 'top') + aligntop = True + + if not alignbot and rownum0max == rownumCmax: + # line up bottom of _poslayoutbox + _log.debug('rownum0max == rownumCmax') + layoutbox.align([ax._poslayoutbox, axc._poslayoutbox], + 'bottom') + alignbot = True + ########### + # Now we make the widths and heights of position boxes + # similar. (i.e the spine locations) + # This allows vertically stacked subplots to have + # different sizes if they occupy different amounts + # of the gridspec: i.e. + # gs = gridspec.GridSpec(3,1) + # ax1 = gs[0,:] + # ax2 = gs[1:,:] + # then drows0 = 1, and drowsC = 2, and ax2 + # should be at least twice as large as ax1. + # But it can be more than twice as large because + # it needs less room for the labeling. + # + # For height, this only needs to be done if the + # subplots share a column. For width if they + # share a row. + + drowsC = (rownumCmax - rownumCmin + 1) + drows0 = (rownum0max - rownum0min + 1) + dcolsC = (colnumCmax - colnumCmin + 1) + dcols0 = (colnum0max - colnum0min + 1) + + if not alignheight and drows0 == drowsC: + ax._poslayoutbox.constrain_height( + axc._poslayoutbox.height * height0 / heightC) + alignheight = True + elif in_same_column(colnum0min, colnum0max, + colnumCmin, colnumCmax): + if height0 > heightC: + ax._poslayoutbox.constrain_height_min( + axc._poslayoutbox.height * height0 / heightC) + # these constraints stop the smaller axes from + # being allowed to go to zero height... + axc._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * heightC / + (height0*1.8)) + elif height0 < heightC: + axc._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * heightC / height0) + ax._poslayoutbox.constrain_height_min( + ax._poslayoutbox.height * height0 / + (heightC*1.8)) + # widths... + if not alignwidth and dcols0 == dcolsC: + ax._poslayoutbox.constrain_width( + axc._poslayoutbox.width * width0 / widthC) + alignwidth = True + elif in_same_row(rownum0min, rownum0max, + rownumCmin, rownumCmax): + if width0 > widthC: + ax._poslayoutbox.constrain_width_min( + axc._poslayoutbox.width * width0 / widthC) + axc._poslayoutbox.constrain_width_min( + ax._poslayoutbox.width * widthC / + (width0*1.8)) + elif width0 < widthC: + axc._poslayoutbox.constrain_width_min( + ax._poslayoutbox.width * widthC / width0) + ax._poslayoutbox.constrain_width_min( + axc._poslayoutbox.width * width0 / + (widthC*1.8)) + + fig._layoutbox.constrained_layout_called += 1 + fig._layoutbox.update_variables() + # Now set the position of the axes... + for ax in fig.axes: + if ax._layoutbox is not None: + newpos = ax._poslayoutbox.get_rect() + _log.debug('newpos %r', newpos) + # Now set the new position. + # ax.set_position will zero out the layout for + # this axis, allowing users to hard-code the position, + # so this does the same w/o zeroing layout. + ax._set_position(newpos, which='original') + + +def _arange_subplotspecs(gs, hspace=0, wspace=0): + """ + arange the subplotspec children of this gridspec, and then recursively + do the same of any gridspec children of those gridspecs... + """ + sschildren = [] + for child in gs.children: + if child._is_subplotspec_layoutbox(): + for child2 in child.children: + # check for gridspec children... + if child2._is_gridspec_layoutbox(): + _arange_subplotspecs(child2, hspace=hspace, wspace=wspace) + sschildren += [child] + # now arrange the subplots... + for child0 in sschildren: + ss0 = child0.artist + nrows, ncols = ss0.get_gridspec().get_geometry() + if ss0.num2 is None: + ss0.num2 = ss0.num1 + rowNum0min, colNum0min = divmod(ss0.num1, ncols) + rowNum0max, colNum0max = divmod(ss0.num2, ncols) + sschildren = sschildren[1:] + for childc in sschildren: + ssc = childc.artist + rowNumCmin, colNumCmin = divmod(ssc.num1, ncols) + if ssc.num2 is None: + ssc.num2 = ssc.num1 + rowNumCmax, colNumCmax = divmod(ssc.num2, ncols) + # OK, this tells us the relative layout of ax + # with axc + thepad = wspace / ncols + if colNum0max < colNumCmin: + layoutbox.hstack([ss0._layoutbox, ssc._layoutbox], + padding=thepad) + if colNumCmax < colNum0min: + layoutbox.hstack([ssc._layoutbox, ss0._layoutbox], + padding=thepad) + + #### + # vertical alignment + thepad = hspace / nrows + if rowNum0max < rowNumCmin: + layoutbox.vstack([ss0._layoutbox, + ssc._layoutbox], + padding=thepad) + if rowNumCmax < rowNum0min: + layoutbox.vstack([ssc._layoutbox, + ss0._layoutbox], + padding=thepad) + + +def layoutcolorbarsingle(ax, cax, shrink, aspect, location, pad=0.05): + """ + Do the layout for a colorbar, to not oeverly pollute colorbar.py + + `pad` is in fraction of the original axis size. + """ + axlb = ax._layoutbox + axpos = ax._poslayoutbox + axsslb = ax.get_subplotspec()._layoutbox + lb = layoutbox.LayoutBox( + parent=axsslb, + name=axsslb.name + '.cbar', + artist=cax) + + if location in ('left', 'right'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightwidth=False, + pos=True, + subplot=False, + artist=cax) + + if location == 'right': + # arrange to right of parent axis + layoutbox.hstack([axlb, lb], padding=pad * axlb.width, + strength='strong') + else: + layoutbox.hstack([lb, axlb], padding=pad * axlb.width) + # constrain the height and center... + layoutbox.match_heights([axpos, lbpos], [1, shrink]) + layoutbox.align([axpos, lbpos], 'v_center') + # set the width of the pos box + lbpos.constrain_width(shrink * axpos.height * (1/aspect), + strength='strong') + elif location in ('bottom', 'top'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightheight=True, + pos=True, + subplot=False, + artist=cax) + + if location == 'bottom': + layoutbox.vstack([axlb, lb], padding=pad * axlb.height) + else: + layoutbox.vstack([lb, axlb], padding=pad * axlb.height) + # constrain the height and center... + layoutbox.match_widths([axpos, lbpos], + [1, shrink], strength='strong') + layoutbox.align([axpos, lbpos], 'h_center') + # set the height of the pos box + lbpos.constrain_height(axpos.width * aspect * shrink, + strength='medium') + + return lb, lbpos + + +def layoutcolorbargridspec(parents, cax, shrink, aspect, location, pad=0.05): + """ + Do the layout for a colorbar, to not oeverly pollute colorbar.py + + `pad` is in fraction of the original axis size. + """ + + gs = parents[0].get_subplotspec().get_gridspec() + # parent layout box.... + gslb = gs._layoutbox + + lb = layoutbox.LayoutBox(parent=gslb.parent, + name=gslb.parent.name + '.cbar', + artist=cax) + if location in ('left', 'right'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightwidth=False, + pos=True, + subplot=False, + artist=cax) + + if location == 'right': + # arrange to right of the gridpec sibbling + layoutbox.hstack([gslb, lb], padding=pad * gslb.width, + strength='strong') + else: + layoutbox.hstack([lb, gslb], padding=pad * gslb.width) + # constrain the height and center... + # This isn't quite right. We'd like the colorbar + # pos to line up w/ the axes poss, not the size of the + # gs. + maxrow = -100000 + minrow = 1000000 + maxax = None + minax = None + + for ax in parents: + subspec = ax.get_subplotspec() + nrows, ncols = subspec.get_gridspec().get_geometry() + for num in [subspec.num1, subspec.num2]: + rownum1, colnum1 = divmod(subspec.num1, ncols) + if rownum1 > maxrow: + maxrow = rownum1 + maxax = ax + if rownum1 < minrow: + minrow = rownum1 + minax = ax + # invert the order so these are bottom to top: + maxposlb = minax._poslayoutbox + minposlb = maxax._poslayoutbox + # now we want the height of the colorbar pos to be + # set by the top and bottom of these poss + # bottom top + # b t + # h = (top-bottom)*shrink + # b = bottom + (top-bottom - h) / 2. + lbpos.constrain_height( + (maxposlb.top - minposlb.bottom) * + shrink, strength='strong') + lbpos.constrain_bottom( + (maxposlb.top - minposlb.bottom) * + (1 - shrink)/2 + minposlb.bottom, + strength='strong') + + # set the width of the pos box + lbpos.constrain_width(lbpos.height * (shrink / aspect), + strength='strong') + elif location in ('bottom', 'top'): + lbpos = layoutbox.LayoutBox( + parent=lb, + name=lb.name + '.pos', + tightheight=True, + pos=True, + subplot=False, + artist=cax) + + if location == 'bottom': + layoutbox.vstack([gslb, lb], padding=pad * gslb.width) + else: + layoutbox.vstack([lb, gslb], padding=pad * gslb.width) + + maxcol = -100000 + mincol = 1000000 + maxax = None + minax = None + + for ax in parents: + subspec = ax.get_subplotspec() + nrows, ncols = subspec.get_gridspec().get_geometry() + for num in [subspec.num1, subspec.num2]: + rownum1, colnum1 = divmod(subspec.num1, ncols) + if colnum1 > maxcol: + maxcol = colnum1 + maxax = ax + if rownum1 < mincol: + mincol = colnum1 + minax = ax + maxposlb = maxax._poslayoutbox + minposlb = minax._poslayoutbox + lbpos.constrain_width((maxposlb.right - minposlb.left) * + shrink) + lbpos.constrain_left( + (maxposlb.right - minposlb.left) * + (1-shrink)/2 + minposlb.left) + # set the height of the pos box + lbpos.constrain_height(lbpos.width * shrink * aspect, + strength='medium') + + return lb, lbpos diff --git a/contrib/python/matplotlib/py2/matplotlib/_layoutbox.py b/contrib/python/matplotlib/py2/matplotlib/_layoutbox.py new file mode 100644 index 00000000000..cb6f0315805 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_layoutbox.py @@ -0,0 +1,739 @@ +# -*- coding: utf-8 -*- +""" + +Conventions: + +"constrain_x" means to constrain the variable with either +another kiwisolver variable, or a float. i.e. `constrain_width(0.2)` +will set a constraint that the width has to be 0.2 and this constraint is +permanent - i.e. it will not be removed if it becomes obsolete. + +"edit_x" means to set x to a value (just a float), and that this value can +change. So `edit_width(0.2)` will set width to be 0.2, but `edit_width(0.3)` +will allow it to change to 0.3 later. Note that these values are still just +"suggestions" in `kiwisolver` parlance, and could be over-ridden by +other constrains. + +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import itertools +import kiwisolver as kiwi +import logging +import numpy as np +import warnings + +import matplotlib + +_log = logging.getLogger(__name__) + + +# renderers can be complicated +def get_renderer(fig): + if fig._cachedRenderer: + renderer = fig._cachedRenderer + else: + canvas = fig.canvas + if canvas and hasattr(canvas, "get_renderer"): + renderer = canvas.get_renderer() + else: + # not sure if this can happen + # seems to with PDF... + _log.info("constrained_layout : falling back to Agg renderer") + from matplotlib.backends.backend_agg import FigureCanvasAgg + canvas = FigureCanvasAgg(fig) + renderer = canvas.get_renderer() + + return renderer + + +class LayoutBox(object): + """ + Basic rectangle representation using kiwi solver variables + """ + + def __init__(self, parent=None, name='', tightwidth=False, + tightheight=False, artist=None, + lower_left=(0, 0), upper_right=(1, 1), pos=False, + subplot=False, h_pad=None, w_pad=None): + Variable = kiwi.Variable + self.parent = parent + self.name = name + sn = self.name + '_' + if parent is None: + self.solver = kiwi.Solver() + self.constrained_layout_called = 0 + else: + self.solver = parent.solver + self.constrained_layout_called = None + # parent wants to know about this child! + parent.add_child(self) + # keep track of artist associated w/ this layout. Can be none + self.artist = artist + # keep track if this box is supposed to be a pos that is constrained + # by the parent. + self.pos = pos + # keep track of whether we need to match this subplot up with others. + self.subplot = subplot + + # we need the str below for Py 2 which complains the string is unicode + self.top = Variable(str(sn + 'top')) + self.bottom = Variable(str(sn + 'bottom')) + self.left = Variable(str(sn + 'left')) + self.right = Variable(str(sn + 'right')) + + self.width = Variable(str(sn + 'width')) + self.height = Variable(str(sn + 'height')) + self.h_center = Variable(str(sn + 'h_center')) + self.v_center = Variable(str(sn + 'v_center')) + + self.min_width = Variable(str(sn + 'min_width')) + self.min_height = Variable(str(sn + 'min_height')) + self.pref_width = Variable(str(sn + 'pref_width')) + self.pref_height = Variable(str(sn + 'pref_height')) + # margis are only used for axes-position layout boxes. maybe should + # be a separate subclass: + self.left_margin = Variable(str(sn + 'left_margin')) + self.right_margin = Variable(str(sn + 'right_margin')) + self.bottom_margin = Variable(str(sn + 'bottom_margin')) + self.top_margin = Variable(str(sn + 'top_margin')) + # mins + self.left_margin_min = Variable(str(sn + 'left_margin_min')) + self.right_margin_min = Variable(str(sn + 'right_margin_min')) + self.bottom_margin_min = Variable(str(sn + 'bottom_margin_min')) + self.top_margin_min = Variable(str(sn + 'top_margin_min')) + + right, top = upper_right + left, bottom = lower_left + self.tightheight = tightheight + self.tightwidth = tightwidth + self.add_constraints() + self.children = [] + self.subplotspec = None + if self.pos: + self.constrain_margins() + self.h_pad = h_pad + self.w_pad = w_pad + + def constrain_margins(self): + """ + Only do this for pos. This sets a variable distance + margin between the position of the axes and the outer edge of + the axes. + + Margins are variable because they change with the fogure size. + + Margin minimums are set to make room for axes decorations. However, + the margins can be larger if we are mathicng the position size to + otehr axes. + """ + sol = self.solver + + # left + if not sol.hasEditVariable(self.left_margin_min): + sol.addEditVariable(self.left_margin_min, 'strong') + sol.suggestValue(self.left_margin_min, 0.0001) + c = (self.left_margin == self.left - self.parent.left) + self.solver.addConstraint(c | 'required') + c = (self.left_margin >= self.left_margin_min) + self.solver.addConstraint(c | 'strong') + + # right + if not sol.hasEditVariable(self.right_margin_min): + sol.addEditVariable(self.right_margin_min, 'strong') + sol.suggestValue(self.right_margin_min, 0.0001) + c = (self.right_margin == self.parent.right - self.right) + self.solver.addConstraint(c | 'required') + c = (self.right_margin >= self.right_margin_min) + self.solver.addConstraint(c | 'required') + # bottom + if not sol.hasEditVariable(self.bottom_margin_min): + sol.addEditVariable(self.bottom_margin_min, 'strong') + sol.suggestValue(self.bottom_margin_min, 0.0001) + c = (self.bottom_margin == self.bottom - self.parent.bottom) + self.solver.addConstraint(c | 'required') + c = (self.bottom_margin >= self.bottom_margin_min) + self.solver.addConstraint(c | 'required') + # top + if not sol.hasEditVariable(self.top_margin_min): + sol.addEditVariable(self.top_margin_min, 'strong') + sol.suggestValue(self.top_margin_min, 0.0001) + c = (self.top_margin == self.parent.top - self.top) + self.solver.addConstraint(c | 'required') + c = (self.top_margin >= self.top_margin_min) + self.solver.addConstraint(c | 'required') + + def add_child(self, child): + self.children += [child] + + def remove_child(self, child): + try: + self.children.remove(child) + except ValueError: + _log.info("Tried to remove child that doesn't belong to parent") + + def add_constraints(self): + sol = self.solver + # never let width and height go negative. + for i in [self.min_width, self.min_height]: + sol.addEditVariable(i, 1e9) + sol.suggestValue(i, 0.0) + # define relation ships between things thing width and right and left + self.hard_constraints() + # self.soft_constraints() + if self.parent: + self.parent_constrain() + # sol.updateVariables() + + def parent_constrain(self): + parent = self.parent + hc = [self.left >= parent.left, + self.bottom >= parent.bottom, + self.top <= parent.top, + self.right <= parent.right] + for c in hc: + self.solver.addConstraint(c | 'required') + + def hard_constraints(self): + hc = [self.width == self.right - self.left, + self.height == self.top - self.bottom, + self.h_center == (self.left + self.right) * 0.5, + self.v_center == (self.top + self.bottom) * 0.5, + self.width >= self.min_width, + self.height >= self.min_height] + for c in hc: + self.solver.addConstraint(c | 'required') + + def soft_constraints(self): + sol = self.solver + if self.tightwidth: + suggest = 0. + else: + suggest = 20. + c = (self.pref_width == suggest) + for i in c: + sol.addConstraint(i | 'required') + if self.tightheight: + suggest = 0. + else: + suggest = 20. + c = (self.pref_height == suggest) + for i in c: + sol.addConstraint(i | 'required') + + c = [(self.width >= suggest), + (self.height >= suggest)] + for i in c: + sol.addConstraint(i | 150000) + + def set_parent(self, parent): + ''' replace the parent of this with the new parent + ''' + self.parent = parent + self.parent_constrain() + + def constrain_geometry(self, left, bottom, right, top, strength='strong'): + hc = [self.left == left, + self.right == right, + self.bottom == bottom, + self.top == top] + for c in hc: + self.solver.addConstraint((c | strength)) + # self.solver.updateVariables() + + def constrain_same(self, other, strength='strong'): + """ + Make the layoutbox have same position as other layoutbox + """ + hc = [self.left == other.left, + self.right == other.right, + self.bottom == other.bottom, + self.top == other.top] + for c in hc: + self.solver.addConstraint((c | strength)) + + def constrain_left_margin(self, margin, strength='strong'): + c = (self.left == self.parent.left + margin) + self.solver.addConstraint(c | strength) + + def edit_left_margin_min(self, margin): + self.solver.suggestValue(self.left_margin_min, margin) + + def constrain_right_margin(self, margin, strength='strong'): + c = (self.right == self.parent.right - margin) + self.solver.addConstraint(c | strength) + + def edit_right_margin_min(self, margin): + self.solver.suggestValue(self.right_margin_min, margin) + + def constrain_bottom_margin(self, margin, strength='strong'): + c = (self.bottom == self.parent.bottom + margin) + self.solver.addConstraint(c | strength) + + def edit_bottom_margin_min(self, margin): + self.solver.suggestValue(self.bottom_margin_min, margin) + + def constrain_top_margin(self, margin, strength='strong'): + c = (self.top == self.parent.top - margin) + self.solver.addConstraint(c | strength) + + def edit_top_margin_min(self, margin): + self.solver.suggestValue(self.top_margin_min, margin) + + def get_rect(self): + return (self.left.value(), self.bottom.value(), + self.width.value(), self.height.value()) + + def update_variables(self): + ''' + Update *all* the variables that are part of the solver this LayoutBox + is created with + ''' + self.solver.updateVariables() + + def edit_height(self, height, strength='strong'): + ''' + Set the height of the layout box. + + This is done as an editable variable so that the value can change + due to resizing. + ''' + sol = self.solver + for i in [self.height]: + if not sol.hasEditVariable(i): + sol.addEditVariable(i, strength) + sol.suggestValue(self.height, height) + + def constrain_height(self, height, strength='strong'): + ''' + Constrain the height of the layout box. height is + either a float or a layoutbox.height. + ''' + c = (self.height == height) + self.solver.addConstraint(c | strength) + + def constrain_height_min(self, height, strength='strong'): + c = (self.height >= height) + self.solver.addConstraint(c | strength) + + def edit_width(self, width, strength='strong'): + sol = self.solver + for i in [self.width]: + if not sol.hasEditVariable(i): + sol.addEditVariable(i, strength) + sol.suggestValue(self.width, width) + + def constrain_width(self, width, strength='strong'): + ''' + Constrain the width of the layout box. `width` is + either a float or a layoutbox.width. + ''' + c = (self.width == width) + self.solver.addConstraint(c | strength) + + def constrain_width_min(self, width, strength='strong'): + c = (self.width >= width) + self.solver.addConstraint(c | strength) + + def constrain_left(self, left, strength='strong'): + c = (self.left == left) + self.solver.addConstraint(c | strength) + + def constrain_bottom(self, bottom, strength='strong'): + c = (self.bottom == bottom) + self.solver.addConstraint(c | strength) + + def constrain_right(self, right, strength='strong'): + c = (self.right == right) + self.solver.addConstraint(c | strength) + + def constrain_top(self, top, strength='strong'): + c = (self.top == top) + self.solver.addConstraint(c | strength) + + def _is_subplotspec_layoutbox(self): + ''' + Helper to check if this layoutbox is the layoutbox of a + subplotspec + ''' + name = (self.name).split('.')[-1] + return name[:2] == 'ss' + + def _is_gridspec_layoutbox(self): + ''' + Helper to check if this layoutbox is the layoutbox of a + gridspec + ''' + name = (self.name).split('.')[-1] + return name[:8] == 'gridspec' + + def find_child_subplots(self): + ''' + Find children of this layout box that are subplots. We want to line + poss up, and this is an easy way to find them all. + ''' + if self.subplot: + subplots = [self] + else: + subplots = [] + for child in self.children: + subplots += child.find_child_subplots() + return subplots + + def layout_from_subplotspec(self, subspec, + name='', artist=None, pos=False): + ''' Make a layout box from a subplotspec. The layout box is + constrained to be a fraction of the width/height of the parent, + and be a fraction of the parent width/height from the left/bottom + of the parent. Therefore the parent can move around and the + layout for the subplot spec should move with it. + + The parent is *usually* the gridspec that made the subplotspec.?? + ''' + lb = LayoutBox(parent=self, name=name, artist=artist, pos=pos) + gs = subspec.get_gridspec() + nrows, ncols = gs.get_geometry() + parent = self.parent + + # OK, now, we want to set the position of this subplotspec + # based on its subplotspec parameters. The new gridspec will inherit. + + # from gridspec. prob should be new method in gridspec + left = 0.0 + right = 1.0 + bottom = 0.0 + top = 1.0 + totWidth = right-left + totHeight = top-bottom + hspace = 0. + wspace = 0. + + # calculate accumulated heights of columns + cellH = totHeight / (nrows + hspace * (nrows - 1)) + sepH = hspace*cellH + + if gs._row_height_ratios is not None: + netHeight = cellH * nrows + tr = float(sum(gs._row_height_ratios)) + cellHeights = [netHeight*r/tr for r in gs._row_height_ratios] + else: + cellHeights = [cellH] * nrows + + sepHeights = [0] + ([sepH] * (nrows - 1)) + cellHs = np.add.accumulate(np.ravel( + list(zip(sepHeights, cellHeights)))) + + # calculate accumulated widths of rows + cellW = totWidth/(ncols + wspace * (ncols - 1)) + sepW = wspace*cellW + + if gs._col_width_ratios is not None: + netWidth = cellW * ncols + tr = float(sum(gs._col_width_ratios)) + cellWidths = [netWidth * r / tr for r in gs._col_width_ratios] + else: + cellWidths = [cellW] * ncols + + sepWidths = [0] + ([sepW] * (ncols - 1)) + cellWs = np.add.accumulate(np.ravel(list(zip(sepWidths, cellWidths)))) + + figTops = [top - cellHs[2 * rowNum] for rowNum in range(nrows)] + figBottoms = [top - cellHs[2 * rowNum + 1] for rowNum in range(nrows)] + figLefts = [left + cellWs[2 * colNum] for colNum in range(ncols)] + figRights = [left + cellWs[2 * colNum + 1] for colNum in range(ncols)] + + rowNum, colNum = divmod(subspec.num1, ncols) + figBottom = figBottoms[rowNum] + figTop = figTops[rowNum] + figLeft = figLefts[colNum] + figRight = figRights[colNum] + + if subspec.num2 is not None: + + rowNum2, colNum2 = divmod(subspec.num2, ncols) + figBottom2 = figBottoms[rowNum2] + figTop2 = figTops[rowNum2] + figLeft2 = figLefts[colNum2] + figRight2 = figRights[colNum2] + + figBottom = min(figBottom, figBottom2) + figLeft = min(figLeft, figLeft2) + figTop = max(figTop, figTop2) + figRight = max(figRight, figRight2) + # These are numbers relative to 0,0,1,1. Need to constrain + # relative to parent. + + width = figRight - figLeft + height = figTop - figBottom + parent = self.parent + cs = [self.left == parent.left + parent.width * figLeft, + self.bottom == parent.bottom + parent.height * figBottom, + self.width == parent.width * width, + self.height == parent.height * height] + for c in cs: + self.solver.addConstraint((c | 'required')) + + return lb + + def __repr__(self): + args = (self.name, self.left.value(), self.bottom.value(), + self.right.value(), self.top.value()) + return ('LayoutBox: %25s, (left: %1.3f) (bot: %1.3f) ' + '(right: %1.3f) (top: %1.3f) ') % args + + +# Utility functions that act on layoutboxes... +def hstack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from left to right. + `padding` is in figure-relative units. + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].right + padding <= boxes[i].left) + boxes[i].solver.addConstraint(c | strength) + + +def hpack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from left to right. + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].right + padding == boxes[i].left) + boxes[i].solver.addConstraint(c | strength) + + +def vstack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].bottom - padding >= boxes[i].top) + boxes[i].solver.addConstraint(c | strength) + + +def vpack(boxes, padding=0, strength='strong'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + for i in range(1, len(boxes)): + c = (boxes[i-1].bottom - padding >= boxes[i].top) + boxes[i].solver.addConstraint(c | strength) + + +def match_heights(boxes, height_ratios=None, strength='medium'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + if height_ratios is None: + height_ratios = np.ones(len(boxes)) + for i in range(1, len(boxes)): + c = (boxes[i-1].height == + boxes[i].height*height_ratios[i-1]/height_ratios[i]) + boxes[i].solver.addConstraint(c | strength) + + +def match_widths(boxes, width_ratios=None, strength='medium'): + ''' + Stack LayoutBox instances from top to bottom + ''' + + if width_ratios is None: + width_ratios = np.ones(len(boxes)) + for i in range(1, len(boxes)): + c = (boxes[i-1].width == + boxes[i].width*width_ratios[i-1]/width_ratios[i]) + boxes[i].solver.addConstraint(c | strength) + + +def vstackeq(boxes, padding=0, height_ratios=None): + vstack(boxes, padding=padding) + match_heights(boxes, height_ratios=height_ratios) + + +def hstackeq(boxes, padding=0, width_ratios=None): + hstack(boxes, padding=padding) + match_widths(boxes, width_ratios=width_ratios) + + +def align(boxes, attr, strength='strong'): + cons = [] + for box in boxes[1:]: + cons = (getattr(boxes[0], attr) == getattr(box, attr)) + boxes[0].solver.addConstraint(cons | strength) + + +def match_top_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.top-top0.top == box.top-topb.top) + box0.solver.addConstraint(c | 'strong') + + +def match_bottom_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.bottom-top0.bottom == box.bottom-topb.bottom) + box0.solver.addConstraint(c | 'strong') + + +def match_left_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.left-top0.left == box.left-topb.left) + box0.solver.addConstraint(c | 'strong') + + +def match_right_margins(boxes, levels=1): + box0 = boxes[0] + top0 = box0 + for n in range(levels): + top0 = top0.parent + for box in boxes[1:]: + topb = box + for n in range(levels): + topb = topb.parent + c = (box0.right-top0.right == box.right-topb.right) + box0.solver.addConstraint(c | 'strong') + + +def match_width_margins(boxes, levels=1): + match_left_margins(boxes, levels=levels) + match_right_margins(boxes, levels=levels) + + +def match_height_margins(boxes, levels=1): + match_top_margins(boxes, levels=levels) + match_bottom_margins(boxes, levels=levels) + + +def match_margins(boxes, levels=1): + match_width_margins(boxes, levels=levels) + match_height_margins(boxes, levels=levels) + + +_layoutboxobjnum = itertools.count() + + +def seq_id(): + ''' + Generate a short sequential id for layoutbox objects... + ''' + + global _layoutboxobjnum + + return ('%06d' % (next(_layoutboxobjnum))) + + +def print_children(lb): + ''' + Print the children of the layoutbox + ''' + print(lb) + for child in lb.children: + print_children(child) + + +def nonetree(lb): + ''' + Make all elements in this tree none... This signals not to do any more + layout. + ''' + if lb is not None: + if lb.parent is None: + # Clear the solver. Hopefully this garbage collects. + lb.solver.reset() + nonechildren(lb) + else: + nonetree(lb.parent) + + +def nonechildren(lb): + for child in lb.children: + nonechildren(child) + lb.artist._layoutbox = None + lb = None + + +def print_tree(lb): + ''' + Print the tree of layoutboxes + ''' + + if lb.parent is None: + print('LayoutBox Tree\n') + print('==============\n') + print_children(lb) + print('\n') + else: + print_tree(lb.parent) + + +def plot_children(fig, box, level=0, printit=True): + ''' + Simple plotting to show where boxes are + ''' + import matplotlib + import matplotlib.pyplot as plt + + if isinstance(fig, matplotlib.figure.Figure): + ax = fig.add_axes([0., 0., 1., 1.]) + ax.set_facecolor([1., 1., 1., 0.7]) + ax.set_alpha(0.3) + fig.draw(fig.canvas.get_renderer()) + else: + ax = fig + + import matplotlib.patches as patches + colors = plt.rcParams["axes.prop_cycle"].by_key()["color"] + if printit: + print("Level:", level) + for child in box.children: + rect = child.get_rect() + if printit: + print(child) + ax.add_patch( + patches.Rectangle( + (child.left.value(), child.bottom.value()), # (x,y) + child.width.value(), # width + child.height.value(), # height + fc='none', + alpha=0.8, + ec=colors[level] + ) + ) + if level > 0: + name = child.name.split('.')[-1] + if level % 2 == 0: + ax.text(child.left.value(), child.bottom.value(), name, + size=12-level, color=colors[level]) + else: + ax.text(child.right.value(), child.top.value(), name, + ha='right', va='top', size=12-level, + color=colors[level]) + + plot_children(ax, child, level=level+1, printit=printit) diff --git a/contrib/python/matplotlib/py2/matplotlib/_mathtext_data.py b/contrib/python/matplotlib/py2/matplotlib/_mathtext_data.py new file mode 100644 index 00000000000..d042d25892d --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_mathtext_data.py @@ -0,0 +1,2548 @@ +""" +font data tables for truetype and afm computer modern fonts +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +latex_to_bakoma = { + '\\__sqrt__' : ('cmex10', 0x70), + '\\bigcap' : ('cmex10', 0x5c), + '\\bigcup' : ('cmex10', 0x5b), + '\\bigodot' : ('cmex10', 0x4b), + '\\bigoplus' : ('cmex10', 0x4d), + '\\bigotimes' : ('cmex10', 0x4f), + '\\biguplus' : ('cmex10', 0x5d), + '\\bigvee' : ('cmex10', 0x5f), + '\\bigwedge' : ('cmex10', 0x5e), + '\\coprod' : ('cmex10', 0x61), + '\\int' : ('cmex10', 0x5a), + '\\langle' : ('cmex10', 0xad), + '\\leftangle' : ('cmex10', 0xad), + '\\leftbrace' : ('cmex10', 0xa9), + '\\oint' : ('cmex10', 0x49), + '\\prod' : ('cmex10', 0x59), + '\\rangle' : ('cmex10', 0xae), + '\\rightangle' : ('cmex10', 0xae), + '\\rightbrace' : ('cmex10', 0xaa), + '\\sum' : ('cmex10', 0x58), + '\\widehat' : ('cmex10', 0x62), + '\\widetilde' : ('cmex10', 0x65), + '\\{' : ('cmex10', 0xa9), + '\\}' : ('cmex10', 0xaa), + '{' : ('cmex10', 0xa9), + '}' : ('cmex10', 0xaa), + + ',' : ('cmmi10', 0x3b), + '.' : ('cmmi10', 0x3a), + '/' : ('cmmi10', 0x3d), + '<' : ('cmmi10', 0x3c), + '>' : ('cmmi10', 0x3e), + '\\alpha' : ('cmmi10', 0xae), + '\\beta' : ('cmmi10', 0xaf), + '\\chi' : ('cmmi10', 0xc2), + '\\combiningrightarrowabove' : ('cmmi10', 0x7e), + '\\delta' : ('cmmi10', 0xb1), + '\\ell' : ('cmmi10', 0x60), + '\\epsilon' : ('cmmi10', 0xb2), + '\\eta' : ('cmmi10', 0xb4), + '\\flat' : ('cmmi10', 0x5b), + '\\frown' : ('cmmi10', 0x5f), + '\\gamma' : ('cmmi10', 0xb0), + '\\imath' : ('cmmi10', 0x7b), + '\\iota' : ('cmmi10', 0xb6), + '\\jmath' : ('cmmi10', 0x7c), + '\\kappa' : ('cmmi10', 0x2219), + '\\lambda' : ('cmmi10', 0xb8), + '\\leftharpoondown' : ('cmmi10', 0x29), + '\\leftharpoonup' : ('cmmi10', 0x28), + '\\mu' : ('cmmi10', 0xb9), + '\\natural' : ('cmmi10', 0x5c), + '\\nu' : ('cmmi10', 0xba), + '\\omega' : ('cmmi10', 0x21), + '\\phi' : ('cmmi10', 0xc1), + '\\pi' : ('cmmi10', 0xbc), + '\\psi' : ('cmmi10', 0xc3), + '\\rho' : ('cmmi10', 0xbd), + '\\rightharpoondown' : ('cmmi10', 0x2b), + '\\rightharpoonup' : ('cmmi10', 0x2a), + '\\sharp' : ('cmmi10', 0x5d), + '\\sigma' : ('cmmi10', 0xbe), + '\\smile' : ('cmmi10', 0x5e), + '\\tau' : ('cmmi10', 0xbf), + '\\theta' : ('cmmi10', 0xb5), + '\\triangleleft' : ('cmmi10', 0x2f), + '\\triangleright' : ('cmmi10', 0x2e), + '\\upsilon' : ('cmmi10', 0xc0), + '\\varepsilon' : ('cmmi10', 0x22), + '\\varphi' : ('cmmi10', 0x27), + '\\varrho' : ('cmmi10', 0x25), + '\\varsigma' : ('cmmi10', 0x26), + '\\vartheta' : ('cmmi10', 0x23), + '\\wp' : ('cmmi10', 0x7d), + '\\xi' : ('cmmi10', 0xbb), + '\\zeta' : ('cmmi10', 0xb3), + + '!' : ('cmr10', 0x21), + '%' : ('cmr10', 0x25), + '&' : ('cmr10', 0x26), + '(' : ('cmr10', 0x28), + ')' : ('cmr10', 0x29), + '+' : ('cmr10', 0x2b), + '0' : ('cmr10', 0x30), + '1' : ('cmr10', 0x31), + '2' : ('cmr10', 0x32), + '3' : ('cmr10', 0x33), + '4' : ('cmr10', 0x34), + '5' : ('cmr10', 0x35), + '6' : ('cmr10', 0x36), + '7' : ('cmr10', 0x37), + '8' : ('cmr10', 0x38), + '9' : ('cmr10', 0x39), + ':' : ('cmr10', 0x3a), + ';' : ('cmr10', 0x3b), + '=' : ('cmr10', 0x3d), + '?' : ('cmr10', 0x3f), + '@' : ('cmr10', 0x40), + '[' : ('cmr10', 0x5b), + '\\#' : ('cmr10', 0x23), + '\\$' : ('cmr10', 0x24), + '\\%' : ('cmr10', 0x25), + '\\Delta' : ('cmr10', 0xa2), + '\\Gamma' : ('cmr10', 0xa1), + '\\Lambda' : ('cmr10', 0xa4), + '\\Omega' : ('cmr10', 0xad), + '\\Phi' : ('cmr10', 0xa9), + '\\Pi' : ('cmr10', 0xa6), + '\\Psi' : ('cmr10', 0xaa), + '\\Sigma' : ('cmr10', 0xa7), + '\\Theta' : ('cmr10', 0xa3), + '\\Upsilon' : ('cmr10', 0xa8), + '\\Xi' : ('cmr10', 0xa5), + '\\circumflexaccent' : ('cmr10', 0x5e), + '\\combiningacuteaccent' : ('cmr10', 0xb6), + '\\combiningbreve' : ('cmr10', 0xb8), + '\\combiningdiaeresis' : ('cmr10', 0xc4), + '\\combiningdotabove' : ('cmr10', 0x5f), + '\\combininggraveaccent' : ('cmr10', 0xb5), + '\\combiningoverline' : ('cmr10', 0xb9), + '\\combiningtilde' : ('cmr10', 0x7e), + '\\leftbracket' : ('cmr10', 0x5b), + '\\leftparen' : ('cmr10', 0x28), + '\\rightbracket' : ('cmr10', 0x5d), + '\\rightparen' : ('cmr10', 0x29), + '\\widebar' : ('cmr10', 0xb9), + ']' : ('cmr10', 0x5d), + + '*' : ('cmsy10', 0xa4), + '-' : ('cmsy10', 0xa1), + '\\Downarrow' : ('cmsy10', 0x2b), + '\\Im' : ('cmsy10', 0x3d), + '\\Leftarrow' : ('cmsy10', 0x28), + '\\Leftrightarrow' : ('cmsy10', 0x2c), + '\\P' : ('cmsy10', 0x7b), + '\\Re' : ('cmsy10', 0x3c), + '\\Rightarrow' : ('cmsy10', 0x29), + '\\S' : ('cmsy10', 0x78), + '\\Uparrow' : ('cmsy10', 0x2a), + '\\Updownarrow' : ('cmsy10', 0x6d), + '\\Vert' : ('cmsy10', 0x6b), + '\\aleph' : ('cmsy10', 0x40), + '\\approx' : ('cmsy10', 0xbc), + '\\ast' : ('cmsy10', 0xa4), + '\\asymp' : ('cmsy10', 0xb3), + '\\backslash' : ('cmsy10', 0x6e), + '\\bigcirc' : ('cmsy10', 0xb0), + '\\bigtriangledown' : ('cmsy10', 0x35), + '\\bigtriangleup' : ('cmsy10', 0x34), + '\\bot' : ('cmsy10', 0x3f), + '\\bullet' : ('cmsy10', 0xb2), + '\\cap' : ('cmsy10', 0x5c), + '\\cdot' : ('cmsy10', 0xa2), + '\\circ' : ('cmsy10', 0xb1), + '\\clubsuit' : ('cmsy10', 0x7c), + '\\cup' : ('cmsy10', 0x5b), + '\\dag' : ('cmsy10', 0x79), + '\\dashv' : ('cmsy10', 0x61), + '\\ddag' : ('cmsy10', 0x7a), + '\\diamond' : ('cmsy10', 0xa6), + '\\diamondsuit' : ('cmsy10', 0x7d), + '\\div' : ('cmsy10', 0xa5), + '\\downarrow' : ('cmsy10', 0x23), + '\\emptyset' : ('cmsy10', 0x3b), + '\\equiv' : ('cmsy10', 0xb4), + '\\exists' : ('cmsy10', 0x39), + '\\forall' : ('cmsy10', 0x38), + '\\geq' : ('cmsy10', 0xb8), + '\\gg' : ('cmsy10', 0xc0), + '\\heartsuit' : ('cmsy10', 0x7e), + '\\in' : ('cmsy10', 0x32), + '\\infty' : ('cmsy10', 0x31), + '\\lbrace' : ('cmsy10', 0x66), + '\\lceil' : ('cmsy10', 0x64), + '\\leftarrow' : ('cmsy10', 0xc3), + '\\leftrightarrow' : ('cmsy10', 0x24), + '\\leq' : ('cmsy10', 0x2219), + '\\lfloor' : ('cmsy10', 0x62), + '\\ll' : ('cmsy10', 0xbf), + '\\mid' : ('cmsy10', 0x6a), + '\\mp' : ('cmsy10', 0xa8), + '\\nabla' : ('cmsy10', 0x72), + '\\nearrow' : ('cmsy10', 0x25), + '\\neg' : ('cmsy10', 0x3a), + '\\ni' : ('cmsy10', 0x33), + '\\nwarrow' : ('cmsy10', 0x2d), + '\\odot' : ('cmsy10', 0xaf), + '\\ominus' : ('cmsy10', 0xaa), + '\\oplus' : ('cmsy10', 0xa9), + '\\oslash' : ('cmsy10', 0xae), + '\\otimes' : ('cmsy10', 0xad), + '\\pm' : ('cmsy10', 0xa7), + '\\prec' : ('cmsy10', 0xc1), + '\\preceq' : ('cmsy10', 0xb9), + '\\prime' : ('cmsy10', 0x30), + '\\propto' : ('cmsy10', 0x2f), + '\\rbrace' : ('cmsy10', 0x67), + '\\rceil' : ('cmsy10', 0x65), + '\\rfloor' : ('cmsy10', 0x63), + '\\rightarrow' : ('cmsy10', 0x21), + '\\searrow' : ('cmsy10', 0x26), + '\\sim' : ('cmsy10', 0xbb), + '\\simeq' : ('cmsy10', 0x27), + '\\slash' : ('cmsy10', 0x36), + '\\spadesuit' : ('cmsy10', 0xc4), + '\\sqcap' : ('cmsy10', 0x75), + '\\sqcup' : ('cmsy10', 0x74), + '\\sqsubseteq' : ('cmsy10', 0x76), + '\\sqsupseteq' : ('cmsy10', 0x77), + '\\subset' : ('cmsy10', 0xbd), + '\\subseteq' : ('cmsy10', 0xb5), + '\\succ' : ('cmsy10', 0xc2), + '\\succeq' : ('cmsy10', 0xba), + '\\supset' : ('cmsy10', 0xbe), + '\\supseteq' : ('cmsy10', 0xb6), + '\\swarrow' : ('cmsy10', 0x2e), + '\\times' : ('cmsy10', 0xa3), + '\\to' : ('cmsy10', 0x21), + '\\top' : ('cmsy10', 0x3e), + '\\uparrow' : ('cmsy10', 0x22), + '\\updownarrow' : ('cmsy10', 0x6c), + '\\uplus' : ('cmsy10', 0x5d), + '\\vdash' : ('cmsy10', 0x60), + '\\vee' : ('cmsy10', 0x5f), + '\\vert' : ('cmsy10', 0x6a), + '\\wedge' : ('cmsy10', 0x5e), + '\\wr' : ('cmsy10', 0x6f), + '\\|' : ('cmsy10', 0x6b), + '|' : ('cmsy10', 0x6a), + + '\\_' : ('cmtt10', 0x5f) +} + +latex_to_cmex = { + r'\__sqrt__' : 112, + r'\bigcap' : 92, + r'\bigcup' : 91, + r'\bigodot' : 75, + r'\bigoplus' : 77, + r'\bigotimes' : 79, + r'\biguplus' : 93, + r'\bigvee' : 95, + r'\bigwedge' : 94, + r'\coprod' : 97, + r'\int' : 90, + r'\leftangle' : 173, + r'\leftbrace' : 169, + r'\oint' : 73, + r'\prod' : 89, + r'\rightangle' : 174, + r'\rightbrace' : 170, + r'\sum' : 88, + r'\widehat' : 98, + r'\widetilde' : 101, +} + +latex_to_standard = { + r'\cong' : ('psyr', 64), + r'\Delta' : ('psyr', 68), + r'\Phi' : ('psyr', 70), + r'\Gamma' : ('psyr', 89), + r'\alpha' : ('psyr', 97), + r'\beta' : ('psyr', 98), + r'\chi' : ('psyr', 99), + r'\delta' : ('psyr', 100), + r'\varepsilon' : ('psyr', 101), + r'\phi' : ('psyr', 102), + r'\gamma' : ('psyr', 103), + r'\eta' : ('psyr', 104), + r'\iota' : ('psyr', 105), + r'\varpsi' : ('psyr', 106), + r'\kappa' : ('psyr', 108), + r'\nu' : ('psyr', 110), + r'\pi' : ('psyr', 112), + r'\theta' : ('psyr', 113), + r'\rho' : ('psyr', 114), + r'\sigma' : ('psyr', 115), + r'\tau' : ('psyr', 116), + '\\upsilon' : ('psyr', 117), + r'\varpi' : ('psyr', 118), + r'\omega' : ('psyr', 119), + r'\xi' : ('psyr', 120), + r'\psi' : ('psyr', 121), + r'\zeta' : ('psyr', 122), + r'\sim' : ('psyr', 126), + r'\leq' : ('psyr', 163), + r'\infty' : ('psyr', 165), + r'\clubsuit' : ('psyr', 167), + r'\diamondsuit' : ('psyr', 168), + r'\heartsuit' : ('psyr', 169), + r'\spadesuit' : ('psyr', 170), + r'\leftrightarrow' : ('psyr', 171), + r'\leftarrow' : ('psyr', 172), + '\\uparrow' : ('psyr', 173), + r'\rightarrow' : ('psyr', 174), + r'\downarrow' : ('psyr', 175), + r'\pm' : ('psyr', 176), + r'\geq' : ('psyr', 179), + r'\times' : ('psyr', 180), + r'\propto' : ('psyr', 181), + r'\partial' : ('psyr', 182), + r'\bullet' : ('psyr', 183), + r'\div' : ('psyr', 184), + r'\neq' : ('psyr', 185), + r'\equiv' : ('psyr', 186), + r'\approx' : ('psyr', 187), + r'\ldots' : ('psyr', 188), + r'\aleph' : ('psyr', 192), + r'\Im' : ('psyr', 193), + r'\Re' : ('psyr', 194), + r'\wp' : ('psyr', 195), + r'\otimes' : ('psyr', 196), + r'\oplus' : ('psyr', 197), + r'\oslash' : ('psyr', 198), + r'\cap' : ('psyr', 199), + r'\cup' : ('psyr', 200), + r'\supset' : ('psyr', 201), + r'\supseteq' : ('psyr', 202), + r'\subset' : ('psyr', 204), + r'\subseteq' : ('psyr', 205), + r'\in' : ('psyr', 206), + r'\notin' : ('psyr', 207), + r'\angle' : ('psyr', 208), + r'\nabla' : ('psyr', 209), + r'\textregistered' : ('psyr', 210), + r'\copyright' : ('psyr', 211), + r'\texttrademark' : ('psyr', 212), + r'\Pi' : ('psyr', 213), + r'\prod' : ('psyr', 213), + r'\surd' : ('psyr', 214), + r'\__sqrt__' : ('psyr', 214), + r'\cdot' : ('psyr', 215), + '\\urcorner' : ('psyr', 216), + r'\vee' : ('psyr', 217), + r'\wedge' : ('psyr', 218), + r'\Leftrightarrow' : ('psyr', 219), + r'\Leftarrow' : ('psyr', 220), + '\\Uparrow' : ('psyr', 221), + r'\Rightarrow' : ('psyr', 222), + r'\Downarrow' : ('psyr', 223), + r'\Diamond' : ('psyr', 224), + r'\Sigma' : ('psyr', 229), + r'\sum' : ('psyr', 229), + r'\forall' : ('psyr', 34), + r'\exists' : ('psyr', 36), + r'\lceil' : ('psyr', 233), + r'\lbrace' : ('psyr', 123), + r'\Psi' : ('psyr', 89), + r'\bot' : ('psyr', 0o136), + r'\Omega' : ('psyr', 0o127), + r'\leftbracket' : ('psyr', 0o133), + r'\rightbracket' : ('psyr', 0o135), + r'\leftbrace' : ('psyr', 123), + r'\leftparen' : ('psyr', 0o50), + r'\prime' : ('psyr', 0o242), + r'\sharp' : ('psyr', 0o43), + r'\slash' : ('psyr', 0o57), + r'\Lamda' : ('psyr', 0o114), + r'\neg' : ('psyr', 0o330), + '\\Upsilon' : ('psyr', 0o241), + r'\rightbrace' : ('psyr', 0o175), + r'\rfloor' : ('psyr', 0o373), + r'\lambda' : ('psyr', 0o154), + r'\to' : ('psyr', 0o256), + r'\Xi' : ('psyr', 0o130), + r'\emptyset' : ('psyr', 0o306), + r'\lfloor' : ('psyr', 0o353), + r'\rightparen' : ('psyr', 0o51), + r'\rceil' : ('psyr', 0o371), + r'\ni' : ('psyr', 0o47), + r'\epsilon' : ('psyr', 0o145), + r'\Theta' : ('psyr', 0o121), + r'\langle' : ('psyr', 0o341), + r'\leftangle' : ('psyr', 0o341), + r'\rangle' : ('psyr', 0o361), + r'\rightangle' : ('psyr', 0o361), + r'\rbrace' : ('psyr', 0o175), + r'\circ' : ('psyr', 0o260), + r'\diamond' : ('psyr', 0o340), + r'\mu' : ('psyr', 0o155), + r'\mid' : ('psyr', 0o352), + r'\imath' : ('pncri8a', 105), + r'\%' : ('pncr8a', 37), + r'\$' : ('pncr8a', 36), + r'\{' : ('pncr8a', 123), + r'\}' : ('pncr8a', 125), + r'\backslash' : ('pncr8a', 92), + r'\ast' : ('pncr8a', 42), + r'\#' : ('pncr8a', 35), + + r'\circumflexaccent' : ('pncri8a', 124), # for \hat + r'\combiningbreve' : ('pncri8a', 81), # for \breve + r'\combininggraveaccent' : ('pncri8a', 114), # for \grave + r'\combiningacuteaccent' : ('pncri8a', 63), # for \accute + r'\combiningdiaeresis' : ('pncri8a', 91), # for \ddot + r'\combiningtilde' : ('pncri8a', 75), # for \tilde + r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec + r'\combiningdotabove' : ('pncri8a', 26), # for \dot +} + +# Automatically generated. + +type12uni = { + 'uni24C8' : 9416, + 'aring' : 229, + 'uni22A0' : 8864, + 'uni2292' : 8850, + 'quotedblright' : 8221, + 'uni03D2' : 978, + 'uni2215' : 8725, + 'uni03D0' : 976, + 'V' : 86, + 'dollar' : 36, + 'uni301E' : 12318, + 'uni03D5' : 981, + 'four' : 52, + 'uni25A0' : 9632, + 'uni013C' : 316, + 'uni013B' : 315, + 'uni013E' : 318, + 'Yacute' : 221, + 'uni25DE' : 9694, + 'uni013F' : 319, + 'uni255A' : 9562, + 'uni2606' : 9734, + 'uni0180' : 384, + 'uni22B7' : 8887, + 'uni044F' : 1103, + 'uni22B5' : 8885, + 'uni22B4' : 8884, + 'uni22AE' : 8878, + 'uni22B2' : 8882, + 'uni22B1' : 8881, + 'uni22B0' : 8880, + 'uni25CD' : 9677, + 'uni03CE' : 974, + 'uni03CD' : 973, + 'uni03CC' : 972, + 'uni03CB' : 971, + 'uni03CA' : 970, + 'uni22B8' : 8888, + 'uni22C9' : 8905, + 'uni0449' : 1097, + 'uni20DD' : 8413, + 'uni20DC' : 8412, + 'uni20DB' : 8411, + 'uni2231' : 8753, + 'uni25CF' : 9679, + 'uni306E' : 12398, + 'uni03D1' : 977, + 'uni01A1' : 417, + 'uni20D7' : 8407, + 'uni03D6' : 982, + 'uni2233' : 8755, + 'uni20D2' : 8402, + 'uni20D1' : 8401, + 'uni20D0' : 8400, + 'P' : 80, + 'uni22BE' : 8894, + 'uni22BD' : 8893, + 'uni22BC' : 8892, + 'uni22BB' : 8891, + 'underscore' : 95, + 'uni03C8' : 968, + 'uni03C7' : 967, + 'uni0328' : 808, + 'uni03C5' : 965, + 'uni03C4' : 964, + 'uni03C3' : 963, + 'uni03C2' : 962, + 'uni03C1' : 961, + 'uni03C0' : 960, + 'uni2010' : 8208, + 'uni0130' : 304, + 'uni0133' : 307, + 'uni0132' : 306, + 'uni0135' : 309, + 'uni0134' : 308, + 'uni0137' : 311, + 'uni0136' : 310, + 'uni0139' : 313, + 'uni0138' : 312, + 'uni2244' : 8772, + 'uni229A' : 8858, + 'uni2571' : 9585, + 'uni0278' : 632, + 'uni2239' : 8761, + 'p' : 112, + 'uni3019' : 12313, + 'uni25CB' : 9675, + 'uni03DB' : 987, + 'uni03DC' : 988, + 'uni03DA' : 986, + 'uni03DF' : 991, + 'uni03DD' : 989, + 'uni013D' : 317, + 'uni220A' : 8714, + 'uni220C' : 8716, + 'uni220B' : 8715, + 'uni220E' : 8718, + 'uni220D' : 8717, + 'uni220F' : 8719, + 'uni22CC' : 8908, + 'Otilde' : 213, + 'uni25E5' : 9701, + 'uni2736' : 10038, + 'perthousand' : 8240, + 'zero' : 48, + 'uni279B' : 10139, + 'dotlessi' : 305, + 'uni2279' : 8825, + 'Scaron' : 352, + 'zcaron' : 382, + 'uni21D8' : 8664, + 'egrave' : 232, + 'uni0271' : 625, + 'uni01AA' : 426, + 'uni2332' : 9010, + 'section' : 167, + 'uni25E4' : 9700, + 'Icircumflex' : 206, + 'ntilde' : 241, + 'uni041E' : 1054, + 'ampersand' : 38, + 'uni041C' : 1052, + 'uni041A' : 1050, + 'uni22AB' : 8875, + 'uni21DB' : 8667, + 'dotaccent' : 729, + 'uni0416' : 1046, + 'uni0417' : 1047, + 'uni0414' : 1044, + 'uni0415' : 1045, + 'uni0412' : 1042, + 'uni0413' : 1043, + 'degree' : 176, + 'uni0411' : 1041, + 'K' : 75, + 'uni25EB' : 9707, + 'uni25EF' : 9711, + 'uni0418' : 1048, + 'uni0419' : 1049, + 'uni2263' : 8803, + 'uni226E' : 8814, + 'uni2251' : 8785, + 'uni02C8' : 712, + 'uni2262' : 8802, + 'acircumflex' : 226, + 'uni22B3' : 8883, + 'uni2261' : 8801, + 'uni2394' : 9108, + 'Aring' : 197, + 'uni2260' : 8800, + 'uni2254' : 8788, + 'uni0436' : 1078, + 'uni2267' : 8807, + 'k' : 107, + 'uni22C8' : 8904, + 'uni226A' : 8810, + 'uni231F' : 8991, + 'smalltilde' : 732, + 'uni2201' : 8705, + 'uni2200' : 8704, + 'uni2203' : 8707, + 'uni02BD' : 701, + 'uni2205' : 8709, + 'uni2204' : 8708, + 'Agrave' : 192, + 'uni2206' : 8710, + 'uni2209' : 8713, + 'uni2208' : 8712, + 'uni226D' : 8813, + 'uni2264' : 8804, + 'uni263D' : 9789, + 'uni2258' : 8792, + 'uni02D3' : 723, + 'uni02D2' : 722, + 'uni02D1' : 721, + 'uni02D0' : 720, + 'uni25E1' : 9697, + 'divide' : 247, + 'uni02D5' : 725, + 'uni02D4' : 724, + 'ocircumflex' : 244, + 'uni2524' : 9508, + 'uni043A' : 1082, + 'uni24CC' : 9420, + 'asciitilde' : 126, + 'uni22B9' : 8889, + 'uni24D2' : 9426, + 'uni211E' : 8478, + 'uni211D' : 8477, + 'uni24DD' : 9437, + 'uni211A' : 8474, + 'uni211C' : 8476, + 'uni211B' : 8475, + 'uni25C6' : 9670, + 'uni017F' : 383, + 'uni017A' : 378, + 'uni017C' : 380, + 'uni017B' : 379, + 'uni0346' : 838, + 'uni22F1' : 8945, + 'uni22F0' : 8944, + 'two' : 50, + 'uni2298' : 8856, + 'uni24D1' : 9425, + 'E' : 69, + 'uni025D' : 605, + 'scaron' : 353, + 'uni2322' : 8994, + 'uni25E3' : 9699, + 'uni22BF' : 8895, + 'F' : 70, + 'uni0440' : 1088, + 'uni255E' : 9566, + 'uni22BA' : 8890, + 'uni0175' : 373, + 'uni0174' : 372, + 'uni0177' : 375, + 'uni0176' : 374, + 'bracketleft' : 91, + 'uni0170' : 368, + 'uni0173' : 371, + 'uni0172' : 370, + 'asciicircum' : 94, + 'uni0179' : 377, + 'uni2590' : 9616, + 'uni25E2' : 9698, + 'uni2119' : 8473, + 'uni2118' : 8472, + 'uni25CC' : 9676, + 'f' : 102, + 'ordmasculine' : 186, + 'uni229B' : 8859, + 'uni22A1' : 8865, + 'uni2111' : 8465, + 'uni2110' : 8464, + 'uni2113' : 8467, + 'uni2112' : 8466, + 'mu' : 181, + 'uni2281' : 8833, + 'paragraph' : 182, + 'nine' : 57, + 'uni25EC' : 9708, + 'v' : 118, + 'uni040C' : 1036, + 'uni0113' : 275, + 'uni22D0' : 8912, + 'uni21CC' : 8652, + 'uni21CB' : 8651, + 'uni21CA' : 8650, + 'uni22A5' : 8869, + 'uni21CF' : 8655, + 'uni21CE' : 8654, + 'uni21CD' : 8653, + 'guilsinglleft' : 8249, + 'backslash' : 92, + 'uni2284' : 8836, + 'uni224E' : 8782, + 'uni224D' : 8781, + 'uni224F' : 8783, + 'uni224A' : 8778, + 'uni2287' : 8839, + 'uni224C' : 8780, + 'uni224B' : 8779, + 'uni21BD' : 8637, + 'uni2286' : 8838, + 'uni030F' : 783, + 'uni030D' : 781, + 'uni030E' : 782, + 'uni030B' : 779, + 'uni030C' : 780, + 'uni030A' : 778, + 'uni026E' : 622, + 'uni026D' : 621, + 'six' : 54, + 'uni026A' : 618, + 'uni026C' : 620, + 'uni25C1' : 9665, + 'uni20D6' : 8406, + 'uni045B' : 1115, + 'uni045C' : 1116, + 'uni256B' : 9579, + 'uni045A' : 1114, + 'uni045F' : 1119, + 'uni045E' : 1118, + 'A' : 65, + 'uni2569' : 9577, + 'uni0458' : 1112, + 'uni0459' : 1113, + 'uni0452' : 1106, + 'uni0453' : 1107, + 'uni2562' : 9570, + 'uni0451' : 1105, + 'uni0456' : 1110, + 'uni0457' : 1111, + 'uni0454' : 1108, + 'uni0455' : 1109, + 'icircumflex' : 238, + 'uni0307' : 775, + 'uni0304' : 772, + 'uni0305' : 773, + 'uni0269' : 617, + 'uni0268' : 616, + 'uni0300' : 768, + 'uni0301' : 769, + 'uni0265' : 613, + 'uni0264' : 612, + 'uni0267' : 615, + 'uni0266' : 614, + 'uni0261' : 609, + 'uni0260' : 608, + 'uni0263' : 611, + 'uni0262' : 610, + 'a' : 97, + 'uni2207' : 8711, + 'uni2247' : 8775, + 'uni2246' : 8774, + 'uni2241' : 8769, + 'uni2240' : 8768, + 'uni2243' : 8771, + 'uni2242' : 8770, + 'uni2312' : 8978, + 'ogonek' : 731, + 'uni2249' : 8777, + 'uni2248' : 8776, + 'uni3030' : 12336, + 'q' : 113, + 'uni21C2' : 8642, + 'uni21C1' : 8641, + 'uni21C0' : 8640, + 'uni21C7' : 8647, + 'uni21C6' : 8646, + 'uni21C5' : 8645, + 'uni21C4' : 8644, + 'uni225F' : 8799, + 'uni212C' : 8492, + 'uni21C8' : 8648, + 'uni2467' : 9319, + 'oacute' : 243, + 'uni028F' : 655, + 'uni028E' : 654, + 'uni026F' : 623, + 'uni028C' : 652, + 'uni028B' : 651, + 'uni028A' : 650, + 'uni2510' : 9488, + 'ograve' : 242, + 'edieresis' : 235, + 'uni22CE' : 8910, + 'uni22CF' : 8911, + 'uni219F' : 8607, + 'comma' : 44, + 'uni22CA' : 8906, + 'uni0429' : 1065, + 'uni03C6' : 966, + 'uni0427' : 1063, + 'uni0426' : 1062, + 'uni0425' : 1061, + 'uni0424' : 1060, + 'uni0423' : 1059, + 'uni0422' : 1058, + 'uni0421' : 1057, + 'uni0420' : 1056, + 'uni2465' : 9317, + 'uni24D0' : 9424, + 'uni2464' : 9316, + 'uni0430' : 1072, + 'otilde' : 245, + 'uni2661' : 9825, + 'uni24D6' : 9430, + 'uni2466' : 9318, + 'uni24D5' : 9429, + 'uni219A' : 8602, + 'uni2518' : 9496, + 'uni22B6' : 8886, + 'uni2461' : 9313, + 'uni24D4' : 9428, + 'uni2460' : 9312, + 'uni24EA' : 9450, + 'guillemotright' : 187, + 'ecircumflex' : 234, + 'greater' : 62, + 'uni2011' : 8209, + 'uacute' : 250, + 'uni2462' : 9314, + 'L' : 76, + 'bullet' : 8226, + 'uni02A4' : 676, + 'uni02A7' : 679, + 'cedilla' : 184, + 'uni02A2' : 674, + 'uni2015' : 8213, + 'uni22C4' : 8900, + 'uni22C5' : 8901, + 'uni22AD' : 8877, + 'uni22C7' : 8903, + 'uni22C0' : 8896, + 'uni2016' : 8214, + 'uni22C2' : 8898, + 'uni22C3' : 8899, + 'uni24CF' : 9423, + 'uni042F' : 1071, + 'uni042E' : 1070, + 'uni042D' : 1069, + 'ydieresis' : 255, + 'l' : 108, + 'logicalnot' : 172, + 'uni24CA' : 9418, + 'uni0287' : 647, + 'uni0286' : 646, + 'uni0285' : 645, + 'uni0284' : 644, + 'uni0283' : 643, + 'uni0282' : 642, + 'uni0281' : 641, + 'uni027C' : 636, + 'uni2664' : 9828, + 'exclamdown' : 161, + 'uni25C4' : 9668, + 'uni0289' : 649, + 'uni0288' : 648, + 'uni039A' : 922, + 'endash' : 8211, + 'uni2640' : 9792, + 'uni20E4' : 8420, + 'uni0473' : 1139, + 'uni20E1' : 8417, + 'uni2642' : 9794, + 'uni03B8' : 952, + 'uni03B9' : 953, + 'agrave' : 224, + 'uni03B4' : 948, + 'uni03B5' : 949, + 'uni03B6' : 950, + 'uni03B7' : 951, + 'uni03B0' : 944, + 'uni03B1' : 945, + 'uni03B2' : 946, + 'uni03B3' : 947, + 'uni2555' : 9557, + 'Adieresis' : 196, + 'germandbls' : 223, + 'Odieresis' : 214, + 'space' : 32, + 'uni0126' : 294, + 'uni0127' : 295, + 'uni0124' : 292, + 'uni0125' : 293, + 'uni0122' : 290, + 'uni0123' : 291, + 'uni0120' : 288, + 'uni0121' : 289, + 'quoteright' : 8217, + 'uni2560' : 9568, + 'uni2556' : 9558, + 'ucircumflex' : 251, + 'uni2561' : 9569, + 'uni2551' : 9553, + 'uni25B2' : 9650, + 'uni2550' : 9552, + 'uni2563' : 9571, + 'uni2553' : 9555, + 'G' : 71, + 'uni2564' : 9572, + 'uni2552' : 9554, + 'quoteleft' : 8216, + 'uni2565' : 9573, + 'uni2572' : 9586, + 'uni2568' : 9576, + 'uni2566' : 9574, + 'W' : 87, + 'uni214A' : 8522, + 'uni012F' : 303, + 'uni012D' : 301, + 'uni012E' : 302, + 'uni012B' : 299, + 'uni012C' : 300, + 'uni255C' : 9564, + 'uni012A' : 298, + 'uni2289' : 8841, + 'Q' : 81, + 'uni2320' : 8992, + 'uni2321' : 8993, + 'g' : 103, + 'uni03BD' : 957, + 'uni03BE' : 958, + 'uni03BF' : 959, + 'uni2282' : 8834, + 'uni2285' : 8837, + 'uni03BA' : 954, + 'uni03BB' : 955, + 'uni03BC' : 956, + 'uni2128' : 8488, + 'uni25B7' : 9655, + 'w' : 119, + 'uni0302' : 770, + 'uni03DE' : 990, + 'uni25DA' : 9690, + 'uni0303' : 771, + 'uni0463' : 1123, + 'uni0462' : 1122, + 'uni3018' : 12312, + 'uni2514' : 9492, + 'question' : 63, + 'uni25B3' : 9651, + 'uni24E1' : 9441, + 'one' : 49, + 'uni200A' : 8202, + 'uni2278' : 8824, + 'ring' : 730, + 'uni0195' : 405, + 'figuredash' : 8210, + 'uni22EC' : 8940, + 'uni0339' : 825, + 'uni0338' : 824, + 'uni0337' : 823, + 'uni0336' : 822, + 'uni0335' : 821, + 'uni0333' : 819, + 'uni0332' : 818, + 'uni0331' : 817, + 'uni0330' : 816, + 'uni01C1' : 449, + 'uni01C0' : 448, + 'uni01C3' : 451, + 'uni01C2' : 450, + 'uni2353' : 9043, + 'uni0308' : 776, + 'uni2218' : 8728, + 'uni2219' : 8729, + 'uni2216' : 8726, + 'uni2217' : 8727, + 'uni2214' : 8724, + 'uni0309' : 777, + 'uni2609' : 9737, + 'uni2213' : 8723, + 'uni2210' : 8720, + 'uni2211' : 8721, + 'uni2245' : 8773, + 'B' : 66, + 'uni25D6' : 9686, + 'iacute' : 237, + 'uni02E6' : 742, + 'uni02E7' : 743, + 'uni02E8' : 744, + 'uni02E9' : 745, + 'uni221D' : 8733, + 'uni221E' : 8734, + 'Ydieresis' : 376, + 'uni221C' : 8732, + 'uni22D7' : 8919, + 'uni221A' : 8730, + 'R' : 82, + 'uni24DC' : 9436, + 'uni033F' : 831, + 'uni033E' : 830, + 'uni033C' : 828, + 'uni033B' : 827, + 'uni033A' : 826, + 'b' : 98, + 'uni228A' : 8842, + 'uni22DB' : 8923, + 'uni2554' : 9556, + 'uni046B' : 1131, + 'uni046A' : 1130, + 'r' : 114, + 'uni24DB' : 9435, + 'Ccedilla' : 199, + 'minus' : 8722, + 'uni24DA' : 9434, + 'uni03F0' : 1008, + 'uni03F1' : 1009, + 'uni20AC' : 8364, + 'uni2276' : 8822, + 'uni24C0' : 9408, + 'uni0162' : 354, + 'uni0163' : 355, + 'uni011E' : 286, + 'uni011D' : 285, + 'uni011C' : 284, + 'uni011B' : 283, + 'uni0164' : 356, + 'uni0165' : 357, + 'Lslash' : 321, + 'uni0168' : 360, + 'uni0169' : 361, + 'uni25C9' : 9673, + 'uni02E5' : 741, + 'uni21C3' : 8643, + 'uni24C4' : 9412, + 'uni24E2' : 9442, + 'uni2277' : 8823, + 'uni013A' : 314, + 'uni2102' : 8450, + 'Uacute' : 218, + 'uni2317' : 8983, + 'uni2107' : 8455, + 'uni221F' : 8735, + 'yacute' : 253, + 'uni3012' : 12306, + 'Ucircumflex' : 219, + 'uni015D' : 349, + 'quotedbl' : 34, + 'uni25D9' : 9689, + 'uni2280' : 8832, + 'uni22AF' : 8879, + 'onehalf' : 189, + 'uni221B' : 8731, + 'Thorn' : 222, + 'uni2226' : 8742, + 'M' : 77, + 'uni25BA' : 9658, + 'uni2463' : 9315, + 'uni2336' : 9014, + 'eight' : 56, + 'uni2236' : 8758, + 'multiply' : 215, + 'uni210C' : 8460, + 'uni210A' : 8458, + 'uni21C9' : 8649, + 'grave' : 96, + 'uni210E' : 8462, + 'uni0117' : 279, + 'uni016C' : 364, + 'uni0115' : 277, + 'uni016A' : 362, + 'uni016F' : 367, + 'uni0112' : 274, + 'uni016D' : 365, + 'uni016E' : 366, + 'Ocircumflex' : 212, + 'uni2305' : 8965, + 'm' : 109, + 'uni24DF' : 9439, + 'uni0119' : 281, + 'uni0118' : 280, + 'uni20A3' : 8355, + 'uni20A4' : 8356, + 'uni20A7' : 8359, + 'uni2288' : 8840, + 'uni24C3' : 9411, + 'uni251C' : 9500, + 'uni228D' : 8845, + 'uni222F' : 8751, + 'uni222E' : 8750, + 'uni222D' : 8749, + 'uni222C' : 8748, + 'uni222B' : 8747, + 'uni222A' : 8746, + 'uni255B' : 9563, + 'Ugrave' : 217, + 'uni24DE' : 9438, + 'guilsinglright' : 8250, + 'uni250A' : 9482, + 'Ntilde' : 209, + 'uni0279' : 633, + 'questiondown' : 191, + 'uni256C' : 9580, + 'Atilde' : 195, + 'uni0272' : 626, + 'uni0273' : 627, + 'uni0270' : 624, + 'ccedilla' : 231, + 'uni0276' : 630, + 'uni0277' : 631, + 'uni0274' : 628, + 'uni0275' : 629, + 'uni2252' : 8786, + 'uni041F' : 1055, + 'uni2250' : 8784, + 'Z' : 90, + 'uni2256' : 8790, + 'uni2257' : 8791, + 'copyright' : 169, + 'uni2255' : 8789, + 'uni043D' : 1085, + 'uni043E' : 1086, + 'uni043F' : 1087, + 'yen' : 165, + 'uni041D' : 1053, + 'uni043B' : 1083, + 'uni043C' : 1084, + 'uni21B0' : 8624, + 'uni21B1' : 8625, + 'uni21B2' : 8626, + 'uni21B3' : 8627, + 'uni21B4' : 8628, + 'uni21B5' : 8629, + 'uni21B6' : 8630, + 'uni21B7' : 8631, + 'uni21B8' : 8632, + 'Eacute' : 201, + 'uni2311' : 8977, + 'uni2310' : 8976, + 'uni228F' : 8847, + 'uni25DB' : 9691, + 'uni21BA' : 8634, + 'uni21BB' : 8635, + 'uni21BC' : 8636, + 'uni2017' : 8215, + 'uni21BE' : 8638, + 'uni21BF' : 8639, + 'uni231C' : 8988, + 'H' : 72, + 'uni0293' : 659, + 'uni2202' : 8706, + 'uni22A4' : 8868, + 'uni231E' : 8990, + 'uni2232' : 8754, + 'uni225B' : 8795, + 'uni225C' : 8796, + 'uni24D9' : 9433, + 'uni225A' : 8794, + 'uni0438' : 1080, + 'uni0439' : 1081, + 'uni225D' : 8797, + 'uni225E' : 8798, + 'uni0434' : 1076, + 'X' : 88, + 'uni007F' : 127, + 'uni0437' : 1079, + 'Idieresis' : 207, + 'uni0431' : 1073, + 'uni0432' : 1074, + 'uni0433' : 1075, + 'uni22AC' : 8876, + 'uni22CD' : 8909, + 'uni25A3' : 9635, + 'bar' : 124, + 'uni24BB' : 9403, + 'uni037E' : 894, + 'uni027B' : 635, + 'h' : 104, + 'uni027A' : 634, + 'uni027F' : 639, + 'uni027D' : 637, + 'uni027E' : 638, + 'uni2227' : 8743, + 'uni2004' : 8196, + 'uni2225' : 8741, + 'uni2224' : 8740, + 'uni2223' : 8739, + 'uni2222' : 8738, + 'uni2221' : 8737, + 'uni2220' : 8736, + 'x' : 120, + 'uni2323' : 8995, + 'uni2559' : 9561, + 'uni2558' : 9560, + 'uni2229' : 8745, + 'uni2228' : 8744, + 'udieresis' : 252, + 'uni029D' : 669, + 'ordfeminine' : 170, + 'uni22CB' : 8907, + 'uni233D' : 9021, + 'uni0428' : 1064, + 'uni24C6' : 9414, + 'uni22DD' : 8925, + 'uni24C7' : 9415, + 'uni015C' : 348, + 'uni015B' : 347, + 'uni015A' : 346, + 'uni22AA' : 8874, + 'uni015F' : 351, + 'uni015E' : 350, + 'braceleft' : 123, + 'uni24C5' : 9413, + 'uni0410' : 1040, + 'uni03AA' : 938, + 'uni24C2' : 9410, + 'uni03AC' : 940, + 'uni03AB' : 939, + 'macron' : 175, + 'uni03AD' : 941, + 'uni03AF' : 943, + 'uni0294' : 660, + 'uni0295' : 661, + 'uni0296' : 662, + 'uni0297' : 663, + 'uni0290' : 656, + 'uni0291' : 657, + 'uni0292' : 658, + 'atilde' : 227, + 'Acircumflex' : 194, + 'uni2370' : 9072, + 'uni24C1' : 9409, + 'uni0298' : 664, + 'uni0299' : 665, + 'Oslash' : 216, + 'uni029E' : 670, + 'C' : 67, + 'quotedblleft' : 8220, + 'uni029B' : 667, + 'uni029C' : 668, + 'uni03A9' : 937, + 'uni03A8' : 936, + 'S' : 83, + 'uni24C9' : 9417, + 'uni03A1' : 929, + 'uni03A0' : 928, + 'exclam' : 33, + 'uni03A5' : 933, + 'uni03A4' : 932, + 'uni03A7' : 935, + 'Zcaron' : 381, + 'uni2133' : 8499, + 'uni2132' : 8498, + 'uni0159' : 345, + 'uni0158' : 344, + 'uni2137' : 8503, + 'uni2005' : 8197, + 'uni2135' : 8501, + 'uni2134' : 8500, + 'uni02BA' : 698, + 'uni2033' : 8243, + 'uni0151' : 337, + 'uni0150' : 336, + 'uni0157' : 343, + 'equal' : 61, + 'uni0155' : 341, + 'uni0154' : 340, + 's' : 115, + 'uni233F' : 9023, + 'eth' : 240, + 'uni24BE' : 9406, + 'uni21E9' : 8681, + 'uni2060' : 8288, + 'Egrave' : 200, + 'uni255D' : 9565, + 'uni24CD' : 9421, + 'uni21E1' : 8673, + 'uni21B9' : 8633, + 'hyphen' : 45, + 'uni01BE' : 446, + 'uni01BB' : 443, + 'period' : 46, + 'igrave' : 236, + 'uni01BA' : 442, + 'uni2296' : 8854, + 'uni2297' : 8855, + 'uni2294' : 8852, + 'uni2295' : 8853, + 'colon' : 58, + 'uni2293' : 8851, + 'uni2290' : 8848, + 'uni2291' : 8849, + 'uni032D' : 813, + 'uni032E' : 814, + 'uni032F' : 815, + 'uni032A' : 810, + 'uni032B' : 811, + 'uni032C' : 812, + 'uni231D' : 8989, + 'Ecircumflex' : 202, + 'uni24D7' : 9431, + 'uni25DD' : 9693, + 'trademark' : 8482, + 'Aacute' : 193, + 'cent' : 162, + 'uni0445' : 1093, + 'uni266E' : 9838, + 'uni266D' : 9837, + 'uni266B' : 9835, + 'uni03C9' : 969, + 'uni2003' : 8195, + 'uni2047' : 8263, + 'lslash' : 322, + 'uni03A6' : 934, + 'uni2043' : 8259, + 'uni250C' : 9484, + 'uni2040' : 8256, + 'uni255F' : 9567, + 'uni24CB' : 9419, + 'uni0472' : 1138, + 'uni0446' : 1094, + 'uni0474' : 1140, + 'uni0475' : 1141, + 'uni2508' : 9480, + 'uni2660' : 9824, + 'uni2506' : 9478, + 'uni2502' : 9474, + 'c' : 99, + 'uni2500' : 9472, + 'N' : 78, + 'uni22A6' : 8870, + 'uni21E7' : 8679, + 'uni2130' : 8496, + 'uni2002' : 8194, + 'breve' : 728, + 'uni0442' : 1090, + 'Oacute' : 211, + 'uni229F' : 8863, + 'uni25C7' : 9671, + 'uni229D' : 8861, + 'uni229E' : 8862, + 'guillemotleft' : 171, + 'uni0329' : 809, + 'uni24E5' : 9445, + 'uni011F' : 287, + 'uni0324' : 804, + 'uni0325' : 805, + 'uni0326' : 806, + 'uni0327' : 807, + 'uni0321' : 801, + 'uni0322' : 802, + 'n' : 110, + 'uni2032' : 8242, + 'uni2269' : 8809, + 'uni2268' : 8808, + 'uni0306' : 774, + 'uni226B' : 8811, + 'uni21EA' : 8682, + 'uni0166' : 358, + 'uni203B' : 8251, + 'uni01B5' : 437, + 'idieresis' : 239, + 'uni02BC' : 700, + 'uni01B0' : 432, + 'braceright' : 125, + 'seven' : 55, + 'uni02BB' : 699, + 'uni011A' : 282, + 'uni29FB' : 10747, + 'brokenbar' : 166, + 'uni2036' : 8246, + 'uni25C0' : 9664, + 'uni0156' : 342, + 'uni22D5' : 8917, + 'uni0258' : 600, + 'ugrave' : 249, + 'uni22D6' : 8918, + 'uni22D1' : 8913, + 'uni2034' : 8244, + 'uni22D3' : 8915, + 'uni22D2' : 8914, + 'uni203C' : 8252, + 'uni223E' : 8766, + 'uni02BF' : 703, + 'uni22D9' : 8921, + 'uni22D8' : 8920, + 'uni25BD' : 9661, + 'uni25BE' : 9662, + 'uni25BF' : 9663, + 'uni041B' : 1051, + 'periodcentered' : 183, + 'uni25BC' : 9660, + 'uni019E' : 414, + 'uni019B' : 411, + 'uni019A' : 410, + 'uni2007' : 8199, + 'uni0391' : 913, + 'uni0390' : 912, + 'uni0393' : 915, + 'uni0392' : 914, + 'uni0395' : 917, + 'uni0394' : 916, + 'uni0397' : 919, + 'uni0396' : 918, + 'uni0399' : 921, + 'uni0398' : 920, + 'uni25C8' : 9672, + 'uni2468' : 9320, + 'sterling' : 163, + 'uni22EB' : 8939, + 'uni039C' : 924, + 'uni039B' : 923, + 'uni039E' : 926, + 'uni039D' : 925, + 'uni039F' : 927, + 'I' : 73, + 'uni03E1' : 993, + 'uni03E0' : 992, + 'uni2319' : 8985, + 'uni228B' : 8843, + 'uni25B5' : 9653, + 'uni25B6' : 9654, + 'uni22EA' : 8938, + 'uni24B9' : 9401, + 'uni044E' : 1102, + 'uni0199' : 409, + 'uni2266' : 8806, + 'Y' : 89, + 'uni22A2' : 8866, + 'Eth' : 208, + 'uni266F' : 9839, + 'emdash' : 8212, + 'uni263B' : 9787, + 'uni24BD' : 9405, + 'uni22DE' : 8926, + 'uni0360' : 864, + 'uni2557' : 9559, + 'uni22DF' : 8927, + 'uni22DA' : 8922, + 'uni22DC' : 8924, + 'uni0361' : 865, + 'i' : 105, + 'uni24BF' : 9407, + 'uni0362' : 866, + 'uni263E' : 9790, + 'uni028D' : 653, + 'uni2259' : 8793, + 'uni0323' : 803, + 'uni2265' : 8805, + 'daggerdbl' : 8225, + 'y' : 121, + 'uni010A' : 266, + 'plusminus' : 177, + 'less' : 60, + 'uni21AE' : 8622, + 'uni0315' : 789, + 'uni230B' : 8971, + 'uni21AF' : 8623, + 'uni21AA' : 8618, + 'uni21AC' : 8620, + 'uni21AB' : 8619, + 'uni01FB' : 507, + 'uni01FC' : 508, + 'uni223A' : 8762, + 'uni01FA' : 506, + 'uni01FF' : 511, + 'uni01FD' : 509, + 'uni01FE' : 510, + 'uni2567' : 9575, + 'uni25E0' : 9696, + 'uni0104' : 260, + 'uni0105' : 261, + 'uni0106' : 262, + 'uni0107' : 263, + 'uni0100' : 256, + 'uni0101' : 257, + 'uni0102' : 258, + 'uni0103' : 259, + 'uni2038' : 8248, + 'uni2009' : 8201, + 'uni2008' : 8200, + 'uni0108' : 264, + 'uni0109' : 265, + 'uni02A1' : 673, + 'uni223B' : 8763, + 'uni226C' : 8812, + 'uni25AC' : 9644, + 'uni24D3' : 9427, + 'uni21E0' : 8672, + 'uni21E3' : 8675, + 'Udieresis' : 220, + 'uni21E2' : 8674, + 'D' : 68, + 'uni21E5' : 8677, + 'uni2621' : 9761, + 'uni21D1' : 8657, + 'uni203E' : 8254, + 'uni22C6' : 8902, + 'uni21E4' : 8676, + 'uni010D' : 269, + 'uni010E' : 270, + 'uni010F' : 271, + 'five' : 53, + 'T' : 84, + 'uni010B' : 267, + 'uni010C' : 268, + 'uni2605' : 9733, + 'uni2663' : 9827, + 'uni21E6' : 8678, + 'uni24B6' : 9398, + 'uni22C1' : 8897, + 'oslash' : 248, + 'acute' : 180, + 'uni01F0' : 496, + 'd' : 100, + 'OE' : 338, + 'uni22E3' : 8931, + 'Igrave' : 204, + 'uni2308' : 8968, + 'uni2309' : 8969, + 'uni21A9' : 8617, + 't' : 116, + 'uni2313' : 8979, + 'uni03A3' : 931, + 'uni21A4' : 8612, + 'uni21A7' : 8615, + 'uni21A6' : 8614, + 'uni21A1' : 8609, + 'uni21A0' : 8608, + 'uni21A3' : 8611, + 'uni21A2' : 8610, + 'parenright' : 41, + 'uni256A' : 9578, + 'uni25DC' : 9692, + 'uni24CE' : 9422, + 'uni042C' : 1068, + 'uni24E0' : 9440, + 'uni042B' : 1067, + 'uni0409' : 1033, + 'uni0408' : 1032, + 'uni24E7' : 9447, + 'uni25B4' : 9652, + 'uni042A' : 1066, + 'uni228E' : 8846, + 'uni0401' : 1025, + 'adieresis' : 228, + 'uni0403' : 1027, + 'quotesingle' : 39, + 'uni0405' : 1029, + 'uni0404' : 1028, + 'uni0407' : 1031, + 'uni0406' : 1030, + 'uni229C' : 8860, + 'uni2306' : 8966, + 'uni2253' : 8787, + 'twodotenleader' : 8229, + 'uni2131' : 8497, + 'uni21DA' : 8666, + 'uni2234' : 8756, + 'uni2235' : 8757, + 'uni01A5' : 421, + 'uni2237' : 8759, + 'uni2230' : 8752, + 'uni02CC' : 716, + 'slash' : 47, + 'uni01A0' : 416, + 'ellipsis' : 8230, + 'uni2299' : 8857, + 'uni2238' : 8760, + 'numbersign' : 35, + 'uni21A8' : 8616, + 'uni223D' : 8765, + 'uni01AF' : 431, + 'uni223F' : 8767, + 'uni01AD' : 429, + 'uni01AB' : 427, + 'odieresis' : 246, + 'uni223C' : 8764, + 'uni227D' : 8829, + 'uni0280' : 640, + 'O' : 79, + 'uni227E' : 8830, + 'uni21A5' : 8613, + 'uni22D4' : 8916, + 'uni25D4' : 9684, + 'uni227F' : 8831, + 'uni0435' : 1077, + 'uni2302' : 8962, + 'uni2669' : 9833, + 'uni24E3' : 9443, + 'uni2720' : 10016, + 'uni22A8' : 8872, + 'uni22A9' : 8873, + 'uni040A' : 1034, + 'uni22A7' : 8871, + 'oe' : 339, + 'uni040B' : 1035, + 'uni040E' : 1038, + 'uni22A3' : 8867, + 'o' : 111, + 'uni040F' : 1039, + 'Edieresis' : 203, + 'uni25D5' : 9685, + 'plus' : 43, + 'uni044D' : 1101, + 'uni263C' : 9788, + 'uni22E6' : 8934, + 'uni2283' : 8835, + 'uni258C' : 9612, + 'uni219E' : 8606, + 'uni24E4' : 9444, + 'uni2136' : 8502, + 'dagger' : 8224, + 'uni24B7' : 9399, + 'uni219B' : 8603, + 'uni22E5' : 8933, + 'three' : 51, + 'uni210B' : 8459, + 'uni2534' : 9524, + 'uni24B8' : 9400, + 'uni230A' : 8970, + 'hungarumlaut' : 733, + 'parenleft' : 40, + 'uni0148' : 328, + 'uni0149' : 329, + 'uni2124' : 8484, + 'uni2125' : 8485, + 'uni2126' : 8486, + 'uni2127' : 8487, + 'uni0140' : 320, + 'uni2129' : 8489, + 'uni25C5' : 9669, + 'uni0143' : 323, + 'uni0144' : 324, + 'uni0145' : 325, + 'uni0146' : 326, + 'uni0147' : 327, + 'uni210D' : 8461, + 'fraction' : 8260, + 'uni2031' : 8241, + 'uni2196' : 8598, + 'uni2035' : 8245, + 'uni24E6' : 9446, + 'uni016B' : 363, + 'uni24BA' : 9402, + 'uni266A' : 9834, + 'uni0116' : 278, + 'uni2115' : 8469, + 'registered' : 174, + 'J' : 74, + 'uni25DF' : 9695, + 'uni25CE' : 9678, + 'uni273D' : 10045, + 'dieresis' : 168, + 'uni212B' : 8491, + 'uni0114' : 276, + 'uni212D' : 8493, + 'uni212E' : 8494, + 'uni212F' : 8495, + 'uni014A' : 330, + 'uni014B' : 331, + 'uni014C' : 332, + 'uni014D' : 333, + 'uni014E' : 334, + 'uni014F' : 335, + 'uni025E' : 606, + 'uni24E8' : 9448, + 'uni0111' : 273, + 'uni24E9' : 9449, + 'Ograve' : 210, + 'j' : 106, + 'uni2195' : 8597, + 'uni2194' : 8596, + 'uni2197' : 8599, + 'uni2037' : 8247, + 'uni2191' : 8593, + 'uni2190' : 8592, + 'uni2193' : 8595, + 'uni2192' : 8594, + 'uni29FA' : 10746, + 'uni2713' : 10003, + 'z' : 122, + 'uni2199' : 8601, + 'uni2198' : 8600, + 'uni2667' : 9831, + 'ae' : 230, + 'uni0448' : 1096, + 'semicolon' : 59, + 'uni2666' : 9830, + 'uni038F' : 911, + 'uni0444' : 1092, + 'uni0447' : 1095, + 'uni038E' : 910, + 'uni0441' : 1089, + 'uni038C' : 908, + 'uni0443' : 1091, + 'uni038A' : 906, + 'uni0250' : 592, + 'uni0251' : 593, + 'uni0252' : 594, + 'uni0253' : 595, + 'uni0254' : 596, + 'at' : 64, + 'uni0256' : 598, + 'uni0257' : 599, + 'uni0167' : 359, + 'uni0259' : 601, + 'uni228C' : 8844, + 'uni2662' : 9826, + 'uni0319' : 793, + 'uni0318' : 792, + 'uni24BC' : 9404, + 'uni0402' : 1026, + 'uni22EF' : 8943, + 'Iacute' : 205, + 'uni22ED' : 8941, + 'uni22EE' : 8942, + 'uni0311' : 785, + 'uni0310' : 784, + 'uni21E8' : 8680, + 'uni0312' : 786, + 'percent' : 37, + 'uni0317' : 791, + 'uni0316' : 790, + 'uni21D6' : 8662, + 'uni21D7' : 8663, + 'uni21D4' : 8660, + 'uni21D5' : 8661, + 'uni21D2' : 8658, + 'uni21D3' : 8659, + 'uni21D0' : 8656, + 'uni2138' : 8504, + 'uni2270' : 8816, + 'uni2271' : 8817, + 'uni2272' : 8818, + 'uni2273' : 8819, + 'uni2274' : 8820, + 'uni2275' : 8821, + 'bracketright' : 93, + 'uni21D9' : 8665, + 'uni21DF' : 8671, + 'uni21DD' : 8669, + 'uni21DE' : 8670, + 'AE' : 198, + 'uni03AE' : 942, + 'uni227A' : 8826, + 'uni227B' : 8827, + 'uni227C' : 8828, + 'asterisk' : 42, + 'aacute' : 225, + 'uni226F' : 8815, + 'uni22E2' : 8930, + 'uni0386' : 902, + 'uni22E0' : 8928, + 'uni22E1' : 8929, + 'U' : 85, + 'uni22E7' : 8935, + 'uni22E4' : 8932, + 'uni0387' : 903, + 'uni031A' : 794, + 'eacute' : 233, + 'uni22E8' : 8936, + 'uni22E9' : 8937, + 'uni24D8' : 9432, + 'uni025A' : 602, + 'uni025B' : 603, + 'uni025C' : 604, + 'e' : 101, + 'uni0128' : 296, + 'uni025F' : 607, + 'uni2665' : 9829, + 'thorn' : 254, + 'uni0129' : 297, + 'uni253C' : 9532, + 'uni25D7' : 9687, + 'u' : 117, + 'uni0388' : 904, + 'uni0389' : 905, + 'uni0255' : 597, + 'uni0171' : 369, + 'uni0384' : 900, + 'uni0385' : 901, + 'uni044A' : 1098, + 'uni252C' : 9516, + 'uni044C' : 1100, + 'uni044B' : 1099 +} + +uni2type1 = dict(((v,k) for k,v in six.iteritems(type12uni))) + +tex2uni = { + 'widehat' : 0x0302, + 'widetilde' : 0x0303, + 'widebar' : 0x0305, + 'langle' : 0x27e8, + 'rangle' : 0x27e9, + 'perp' : 0x27c2, + 'neq' : 0x2260, + 'Join' : 0x2a1d, + 'leqslant' : 0x2a7d, + 'geqslant' : 0x2a7e, + 'lessapprox' : 0x2a85, + 'gtrapprox' : 0x2a86, + 'lesseqqgtr' : 0x2a8b, + 'gtreqqless' : 0x2a8c, + 'triangleeq' : 0x225c, + 'eqslantless' : 0x2a95, + 'eqslantgtr' : 0x2a96, + 'backepsilon' : 0x03f6, + 'precapprox' : 0x2ab7, + 'succapprox' : 0x2ab8, + 'fallingdotseq' : 0x2252, + 'subseteqq' : 0x2ac5, + 'supseteqq' : 0x2ac6, + 'varpropto' : 0x221d, + 'precnapprox' : 0x2ab9, + 'succnapprox' : 0x2aba, + 'subsetneqq' : 0x2acb, + 'supsetneqq' : 0x2acc, + 'lnapprox' : 0x2ab9, + 'gnapprox' : 0x2aba, + 'longleftarrow' : 0x27f5, + 'longrightarrow' : 0x27f6, + 'longleftrightarrow' : 0x27f7, + 'Longleftarrow' : 0x27f8, + 'Longrightarrow' : 0x27f9, + 'Longleftrightarrow' : 0x27fa, + 'longmapsto' : 0x27fc, + 'leadsto' : 0x21dd, + 'dashleftarrow' : 0x290e, + 'dashrightarrow' : 0x290f, + 'circlearrowleft' : 0x21ba, + 'circlearrowright' : 0x21bb, + 'leftrightsquigarrow' : 0x21ad, + 'leftsquigarrow' : 0x219c, + 'rightsquigarrow' : 0x219d, + 'Game' : 0x2141, + 'hbar' : 0x0127, + 'hslash' : 0x210f, + 'ldots' : 0x2026, + 'vdots' : 0x22ee, + 'doteqdot' : 0x2251, + 'doteq' : 8784, + 'partial' : 8706, + 'gg' : 8811, + 'asymp' : 8781, + 'blacktriangledown' : 9662, + 'otimes' : 8855, + 'nearrow' : 8599, + 'varpi' : 982, + 'vee' : 8744, + 'vec' : 8407, + 'smile' : 8995, + 'succnsim' : 8937, + 'gimel' : 8503, + 'vert' : 124, + '|' : 124, + 'varrho' : 1009, + 'P' : 182, + 'approxident' : 8779, + 'Swarrow' : 8665, + 'textasciicircum' : 94, + 'imageof' : 8887, + 'ntriangleleft' : 8938, + 'nleq' : 8816, + 'div' : 247, + 'nparallel' : 8742, + 'Leftarrow' : 8656, + 'lll' : 8920, + 'oiint' : 8751, + 'ngeq' : 8817, + 'Theta' : 920, + 'origof' : 8886, + 'blacksquare' : 9632, + 'solbar' : 9023, + 'neg' : 172, + 'sum' : 8721, + 'Vdash' : 8873, + 'coloneq' : 8788, + 'degree' : 176, + 'bowtie' : 8904, + 'blacktriangleright' : 9654, + 'varsigma' : 962, + 'leq' : 8804, + 'ggg' : 8921, + 'lneqq' : 8808, + 'scurel' : 8881, + 'stareq' : 8795, + 'BbbN' : 8469, + 'nLeftarrow' : 8653, + 'nLeftrightarrow' : 8654, + 'k' : 808, + 'bot' : 8869, + 'BbbC' : 8450, + 'Lsh' : 8624, + 'leftleftarrows' : 8647, + 'BbbZ' : 8484, + 'digamma' : 989, + 'BbbR' : 8477, + 'BbbP' : 8473, + 'BbbQ' : 8474, + 'vartriangleright' : 8883, + 'succsim' : 8831, + 'wedge' : 8743, + 'lessgtr' : 8822, + 'veebar' : 8891, + 'mapsdown' : 8615, + 'Rsh' : 8625, + 'chi' : 967, + 'prec' : 8826, + 'nsubseteq' : 8840, + 'therefore' : 8756, + 'eqcirc' : 8790, + 'textexclamdown' : 161, + 'nRightarrow' : 8655, + 'flat' : 9837, + 'notin' : 8713, + 'llcorner' : 8990, + 'varepsilon' : 949, + 'bigtriangleup' : 9651, + 'aleph' : 8501, + 'dotminus' : 8760, + 'upsilon' : 965, + 'Lambda' : 923, + 'cap' : 8745, + 'barleftarrow' : 8676, + 'mu' : 956, + 'boxplus' : 8862, + 'mp' : 8723, + 'circledast' : 8859, + 'tau' : 964, + 'in' : 8712, + 'backslash' : 92, + 'varnothing' : 8709, + 'sharp' : 9839, + 'eqsim' : 8770, + 'gnsim' : 8935, + 'Searrow' : 8664, + 'updownarrows' : 8645, + 'heartsuit' : 9825, + 'trianglelefteq' : 8884, + 'ddag' : 8225, + 'sqsubseteq' : 8849, + 'mapsfrom' : 8612, + 'boxbar' : 9707, + 'sim' : 8764, + 'Nwarrow' : 8662, + 'nequiv' : 8802, + 'succ' : 8827, + 'vdash' : 8866, + 'Leftrightarrow' : 8660, + 'parallel' : 8741, + 'invnot' : 8976, + 'natural' : 9838, + 'ss' : 223, + 'uparrow' : 8593, + 'nsim' : 8769, + 'hookrightarrow' : 8618, + 'Equiv' : 8803, + 'approx' : 8776, + 'Vvdash' : 8874, + 'nsucc' : 8833, + 'leftrightharpoons' : 8651, + 'Re' : 8476, + 'boxminus' : 8863, + 'equiv' : 8801, + 'Lleftarrow' : 8666, + 'll' : 8810, + 'Cup' : 8915, + 'measeq' : 8798, + 'upharpoonleft' : 8639, + 'lq' : 8216, + 'Upsilon' : 933, + 'subsetneq' : 8842, + 'greater' : 62, + 'supsetneq' : 8843, + 'Cap' : 8914, + 'L' : 321, + 'spadesuit' : 9824, + 'lrcorner' : 8991, + 'not' : 824, + 'bar' : 772, + 'rightharpoonaccent' : 8401, + 'boxdot' : 8865, + 'l' : 322, + 'leftharpoondown' : 8637, + 'bigcup' : 8899, + 'iint' : 8748, + 'bigwedge' : 8896, + 'downharpoonleft' : 8643, + 'textasciitilde' : 126, + 'subset' : 8834, + 'leqq' : 8806, + 'mapsup' : 8613, + 'nvDash' : 8877, + 'looparrowleft' : 8619, + 'nless' : 8814, + 'rightarrowbar' : 8677, + 'Vert' : 8214, + 'downdownarrows' : 8650, + 'uplus' : 8846, + 'simeq' : 8771, + 'napprox' : 8777, + 'ast' : 8727, + 'twoheaduparrow' : 8607, + 'doublebarwedge' : 8966, + 'Sigma' : 931, + 'leftharpoonaccent' : 8400, + 'ntrianglelefteq' : 8940, + 'nexists' : 8708, + 'times' : 215, + 'measuredangle' : 8737, + 'bumpeq' : 8783, + 'carriagereturn' : 8629, + 'adots' : 8944, + 'checkmark' : 10003, + 'lambda' : 955, + 'xi' : 958, + 'rbrace' : 125, + 'rbrack' : 93, + 'Nearrow' : 8663, + 'maltese' : 10016, + 'clubsuit' : 9827, + 'top' : 8868, + 'overarc' : 785, + 'varphi' : 966, + 'Delta' : 916, + 'iota' : 953, + 'nleftarrow' : 8602, + 'candra' : 784, + 'supset' : 8835, + 'triangleleft' : 9665, + 'gtreqless' : 8923, + 'ntrianglerighteq' : 8941, + 'quad' : 8195, + 'Xi' : 926, + 'gtrdot' : 8919, + 'leftthreetimes' : 8907, + 'minus' : 8722, + 'preccurlyeq' : 8828, + 'nleftrightarrow' : 8622, + 'lambdabar' : 411, + 'blacktriangle' : 9652, + 'kernelcontraction' : 8763, + 'Phi' : 934, + 'angle' : 8736, + 'spadesuitopen' : 9828, + 'eqless' : 8924, + 'mid' : 8739, + 'varkappa' : 1008, + 'Ldsh' : 8626, + 'updownarrow' : 8597, + 'beta' : 946, + 'textquotedblleft' : 8220, + 'rho' : 961, + 'alpha' : 945, + 'intercal' : 8890, + 'beth' : 8502, + 'grave' : 768, + 'acwopencirclearrow' : 8634, + 'nmid' : 8740, + 'nsupset' : 8837, + 'sigma' : 963, + 'dot' : 775, + 'Rightarrow' : 8658, + 'turnednot' : 8985, + 'backsimeq' : 8909, + 'leftarrowtail' : 8610, + 'approxeq' : 8778, + 'curlyeqsucc' : 8927, + 'rightarrowtail' : 8611, + 'Psi' : 936, + 'copyright' : 169, + 'yen' : 165, + 'vartriangleleft' : 8882, + 'rasp' : 700, + 'triangleright' : 9655, + 'precsim' : 8830, + 'infty' : 8734, + 'geq' : 8805, + 'updownarrowbar' : 8616, + 'precnsim' : 8936, + 'H' : 779, + 'ulcorner' : 8988, + 'looparrowright' : 8620, + 'ncong' : 8775, + 'downarrow' : 8595, + 'circeq' : 8791, + 'subseteq' : 8838, + 'bigstar' : 9733, + 'prime' : 8242, + 'lceil' : 8968, + 'Rrightarrow' : 8667, + 'oiiint' : 8752, + 'curlywedge' : 8911, + 'vDash' : 8872, + 'lfloor' : 8970, + 'ddots' : 8945, + 'exists' : 8707, + 'underbar' : 817, + 'Pi' : 928, + 'leftrightarrows' : 8646, + 'sphericalangle' : 8738, + 'coprod' : 8720, + 'circledcirc' : 8858, + 'gtrsim' : 8819, + 'gneqq' : 8809, + 'between' : 8812, + 'theta' : 952, + 'complement' : 8705, + 'arceq' : 8792, + 'nVdash' : 8878, + 'S' : 167, + 'wr' : 8768, + 'wp' : 8472, + 'backcong' : 8780, + 'lasp' : 701, + 'c' : 807, + 'nabla' : 8711, + 'dotplus' : 8724, + 'eta' : 951, + 'forall' : 8704, + 'eth' : 240, + 'colon' : 58, + 'sqcup' : 8852, + 'rightrightarrows' : 8649, + 'sqsupset' : 8848, + 'mapsto' : 8614, + 'bigtriangledown' : 9661, + 'sqsupseteq' : 8850, + 'propto' : 8733, + 'pi' : 960, + 'pm' : 177, + 'dots' : 0x2026, + 'nrightarrow' : 8603, + 'textasciiacute' : 180, + 'Doteq' : 8785, + 'breve' : 774, + 'sqcap' : 8851, + 'twoheadrightarrow' : 8608, + 'kappa' : 954, + 'vartriangle' : 9653, + 'diamondsuit' : 9826, + 'pitchfork' : 8916, + 'blacktriangleleft' : 9664, + 'nprec' : 8832, + 'curvearrowright' : 8631, + 'barwedge' : 8892, + 'multimap' : 8888, + 'textquestiondown' : 191, + 'cong' : 8773, + 'rtimes' : 8906, + 'rightzigzagarrow' : 8669, + 'rightarrow' : 8594, + 'leftarrow' : 8592, + '__sqrt__' : 8730, + 'twoheaddownarrow' : 8609, + 'oint' : 8750, + 'bigvee' : 8897, + 'eqdef' : 8797, + 'sterling' : 163, + 'phi' : 981, + 'Updownarrow' : 8661, + 'backprime' : 8245, + 'emdash' : 8212, + 'Gamma' : 915, + 'i' : 305, + 'rceil' : 8969, + 'leftharpoonup' : 8636, + 'Im' : 8465, + 'curvearrowleft' : 8630, + 'wedgeq' : 8793, + 'curlyeqprec' : 8926, + 'questeq' : 8799, + 'less' : 60, + 'upuparrows' : 8648, + 'tilde' : 771, + 'textasciigrave' : 96, + 'smallsetminus' : 8726, + 'ell' : 8467, + 'cup' : 8746, + 'danger' : 9761, + 'nVDash' : 8879, + 'cdotp' : 183, + 'cdots' : 8943, + 'hat' : 770, + 'eqgtr' : 8925, + 'psi' : 968, + 'frown' : 8994, + 'acute' : 769, + 'downzigzagarrow' : 8623, + 'ntriangleright' : 8939, + 'cupdot' : 8845, + 'circleddash' : 8861, + 'oslash' : 8856, + 'mho' : 8487, + 'd' : 803, + 'sqsubset' : 8847, + 'cdot' : 8901, + 'Omega' : 937, + 'OE' : 338, + 'veeeq' : 8794, + 'Finv' : 8498, + 't' : 865, + 'leftrightarrow' : 8596, + 'swarrow' : 8601, + 'rightthreetimes' : 8908, + 'rightleftharpoons' : 8652, + 'lesssim' : 8818, + 'searrow' : 8600, + 'because' : 8757, + 'gtrless' : 8823, + 'star' : 8902, + 'nsubset' : 8836, + 'zeta' : 950, + 'dddot' : 8411, + 'bigcirc' : 9675, + 'Supset' : 8913, + 'circ' : 8728, + 'slash' : 8725, + 'ocirc' : 778, + 'prod' : 8719, + 'twoheadleftarrow' : 8606, + 'daleth' : 8504, + 'upharpoonright' : 8638, + 'odot' : 8857, + 'Uparrow' : 8657, + 'O' : 216, + 'hookleftarrow' : 8617, + 'trianglerighteq' : 8885, + 'nsime' : 8772, + 'oe' : 339, + 'nwarrow' : 8598, + 'o' : 248, + 'ddddot' : 8412, + 'downharpoonright' : 8642, + 'succcurlyeq' : 8829, + 'gamma' : 947, + 'scrR' : 8475, + 'dag' : 8224, + 'thickspace' : 8197, + 'frakZ' : 8488, + 'lessdot' : 8918, + 'triangledown' : 9663, + 'ltimes' : 8905, + 'scrB' : 8492, + 'endash' : 8211, + 'scrE' : 8496, + 'scrF' : 8497, + 'scrH' : 8459, + 'scrI' : 8464, + 'rightharpoondown' : 8641, + 'scrL' : 8466, + 'scrM' : 8499, + 'frakC' : 8493, + 'nsupseteq' : 8841, + 'circledR' : 174, + 'circledS' : 9416, + 'ngtr' : 8815, + 'bigcap' : 8898, + 'scre' : 8495, + 'Downarrow' : 8659, + 'scrg' : 8458, + 'overleftrightarrow' : 8417, + 'scro' : 8500, + 'lnsim' : 8934, + 'eqcolon' : 8789, + 'curlyvee' : 8910, + 'urcorner' : 8989, + 'lbrace' : 123, + 'Bumpeq' : 8782, + 'delta' : 948, + 'boxtimes' : 8864, + 'overleftarrow' : 8406, + 'prurel' : 8880, + 'clubsuitopen' : 9831, + 'cwopencirclearrow' : 8635, + 'geqq' : 8807, + 'rightleftarrows' : 8644, + 'ac' : 8766, + 'ae' : 230, + 'int' : 8747, + 'rfloor' : 8971, + 'risingdotseq' : 8787, + 'nvdash' : 8876, + 'diamond' : 8900, + 'ddot' : 776, + 'backsim' : 8765, + 'oplus' : 8853, + 'triangleq' : 8796, + 'check' : 780, + 'ni' : 8715, + 'iiint' : 8749, + 'ne' : 8800, + 'lesseqgtr' : 8922, + 'obar' : 9021, + 'supseteq' : 8839, + 'nu' : 957, + 'AA' : 197, + 'AE' : 198, + 'models' : 8871, + 'ominus' : 8854, + 'dashv' : 8867, + 'omega' : 969, + 'rq' : 8217, + 'Subset' : 8912, + 'rightharpoonup' : 8640, + 'Rdsh' : 8627, + 'bullet' : 8729, + 'divideontimes' : 8903, + 'lbrack' : 91, + 'textquotedblright' : 8221, + 'Colon' : 8759, + '%' : 37, + '$' : 36, + '{' : 123, + '}' : 125, + '_' : 95, + '#' : 35, + 'imath' : 0x131, + 'circumflexaccent' : 770, + 'combiningbreve' : 774, + 'combiningoverline' : 772, + 'combininggraveaccent' : 768, + 'combiningacuteaccent' : 769, + 'combiningdiaeresis' : 776, + 'combiningtilde' : 771, + 'combiningrightarrowabove' : 8407, + 'combiningdotabove' : 775, + 'to' : 8594, + 'succeq' : 8829, + 'emptyset' : 8709, + 'leftparen' : 40, + 'rightparen' : 41, + 'bigoplus' : 10753, + 'leftangle' : 10216, + 'rightangle' : 10217, + 'leftbrace' : 124, + 'rightbrace' : 125, + 'jmath' : 567, + 'bigodot' : 10752, + 'preceq' : 8828, + 'biguplus' : 10756, + 'epsilon' : 949, + 'vartheta' : 977, + 'bigotimes' : 10754, + 'guillemotleft' : 171, + 'ring' : 730, + 'Thorn' : 222, + 'guilsinglright' : 8250, + 'perthousand' : 8240, + 'macron' : 175, + 'cent' : 162, + 'guillemotright' : 187, + 'equal' : 61, + 'asterisk' : 42, + 'guilsinglleft' : 8249, + 'plus' : 43, + 'thorn' : 254, + 'dagger' : 8224 +} + +# Each element is a 4-tuple of the form: +# src_start, src_end, dst_font, dst_start +# +stix_virtual_fonts = { + 'bb': + { + 'rm': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'rm', 0x1d538), # A-B + (0x0043, 0x0043, 'rm', 0x2102), # C + (0x0044, 0x0047, 'rm', 0x1d53b), # D-G + (0x0048, 0x0048, 'rm', 0x210d), # H + (0x0049, 0x004d, 'rm', 0x1d540), # I-M + (0x004e, 0x004e, 'rm', 0x2115), # N + (0x004f, 0x004f, 'rm', 0x1d546), # O + (0x0050, 0x0051, 'rm', 0x2119), # P-Q + (0x0052, 0x0052, 'rm', 0x211d), # R + (0x0053, 0x0059, 'rm', 0x1d54a), # S-Y + (0x005a, 0x005a, 'rm', 0x2124), # Z + (0x0061, 0x007a, 'rm', 0x1d552), # a-z + (0x0393, 0x0393, 'rm', 0x213e), # \Gamma + (0x03a0, 0x03a0, 'rm', 0x213f), # \Pi + (0x03a3, 0x03a3, 'rm', 0x2140), # \Sigma + (0x03b3, 0x03b3, 'rm', 0x213d), # \gamma + (0x03c0, 0x03c0, 'rm', 0x213c), # \pi + ], + 'it': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'it', 0xe154), # A-B + (0x0043, 0x0043, 'it', 0x2102), # C + (0x0044, 0x0044, 'it', 0x2145), # D + (0x0045, 0x0047, 'it', 0xe156), # E-G + (0x0048, 0x0048, 'it', 0x210d), # H + (0x0049, 0x004d, 'it', 0xe159), # I-M + (0x004e, 0x004e, 'it', 0x2115), # N + (0x004f, 0x004f, 'it', 0xe15e), # O + (0x0050, 0x0051, 'it', 0x2119), # P-Q + (0x0052, 0x0052, 'it', 0x211d), # R + (0x0053, 0x0059, 'it', 0xe15f), # S-Y + (0x005a, 0x005a, 'it', 0x2124), # Z + (0x0061, 0x0063, 'it', 0xe166), # a-c + (0x0064, 0x0065, 'it', 0x2146), # d-e + (0x0066, 0x0068, 'it', 0xe169), # f-h + (0x0069, 0x006a, 'it', 0x2148), # i-j + (0x006b, 0x007a, 'it', 0xe16c), # k-z + (0x0393, 0x0393, 'it', 0x213e), # \Gamma (not in beta STIX fonts) + (0x03a0, 0x03a0, 'it', 0x213f), # \Pi + (0x03a3, 0x03a3, 'it', 0x2140), # \Sigma (not in beta STIX fonts) + (0x03b3, 0x03b3, 'it', 0x213d), # \gamma (not in beta STIX fonts) + (0x03c0, 0x03c0, 'it', 0x213c), # \pi + ], + 'bf': + [ + (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9 + (0x0041, 0x0042, 'bf', 0xe38a), # A-B + (0x0043, 0x0043, 'bf', 0x2102), # C + (0x0044, 0x0044, 'bf', 0x2145), # D + (0x0045, 0x0047, 'bf', 0xe38d), # E-G + (0x0048, 0x0048, 'bf', 0x210d), # H + (0x0049, 0x004d, 'bf', 0xe390), # I-M + (0x004e, 0x004e, 'bf', 0x2115), # N + (0x004f, 0x004f, 'bf', 0xe395), # O + (0x0050, 0x0051, 'bf', 0x2119), # P-Q + (0x0052, 0x0052, 'bf', 0x211d), # R + (0x0053, 0x0059, 'bf', 0xe396), # S-Y + (0x005a, 0x005a, 'bf', 0x2124), # Z + (0x0061, 0x0063, 'bf', 0xe39d), # a-c + (0x0064, 0x0065, 'bf', 0x2146), # d-e + (0x0066, 0x0068, 'bf', 0xe3a2), # f-h + (0x0069, 0x006a, 'bf', 0x2148), # i-j + (0x006b, 0x007a, 'bf', 0xe3a7), # k-z + (0x0393, 0x0393, 'bf', 0x213e), # \Gamma + (0x03a0, 0x03a0, 'bf', 0x213f), # \Pi + (0x03a3, 0x03a3, 'bf', 0x2140), # \Sigma + (0x03b3, 0x03b3, 'bf', 0x213d), # \gamma + (0x03c0, 0x03c0, 'bf', 0x213c), # \pi + ], + }, + 'cal': + [ + (0x0041, 0x005a, 'it', 0xe22d), # A-Z + ], + 'circled': + { + 'rm': + [ + (0x0030, 0x0030, 'rm', 0x24ea), # 0 + (0x0031, 0x0039, 'rm', 0x2460), # 1-9 + (0x0041, 0x005a, 'rm', 0x24b6), # A-Z + (0x0061, 0x007a, 'rm', 0x24d0) # a-z + ], + 'it': + [ + (0x0030, 0x0030, 'rm', 0x24ea), # 0 + (0x0031, 0x0039, 'rm', 0x2460), # 1-9 + (0x0041, 0x005a, 'it', 0x24b6), # A-Z + (0x0061, 0x007a, 'it', 0x24d0) # a-z + ], + 'bf': + [ + (0x0030, 0x0030, 'bf', 0x24ea), # 0 + (0x0031, 0x0039, 'bf', 0x2460), # 1-9 + (0x0041, 0x005a, 'bf', 0x24b6), # A-Z + (0x0061, 0x007a, 'bf', 0x24d0) # a-z + ], + }, + 'frak': + { + 'rm': + [ + (0x0041, 0x0042, 'rm', 0x1d504), # A-B + (0x0043, 0x0043, 'rm', 0x212d), # C + (0x0044, 0x0047, 'rm', 0x1d507), # D-G + (0x0048, 0x0048, 'rm', 0x210c), # H + (0x0049, 0x0049, 'rm', 0x2111), # I + (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q + (0x0052, 0x0052, 'rm', 0x211c), # R + (0x0053, 0x0059, 'rm', 0x1d516), # S-Y + (0x005a, 0x005a, 'rm', 0x2128), # Z + (0x0061, 0x007a, 'rm', 0x1d51e), # a-z + ], + 'it': + [ + (0x0041, 0x0042, 'rm', 0x1d504), # A-B + (0x0043, 0x0043, 'rm', 0x212d), # C + (0x0044, 0x0047, 'rm', 0x1d507), # D-G + (0x0048, 0x0048, 'rm', 0x210c), # H + (0x0049, 0x0049, 'rm', 0x2111), # I + (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q + (0x0052, 0x0052, 'rm', 0x211c), # R + (0x0053, 0x0059, 'rm', 0x1d516), # S-Y + (0x005a, 0x005a, 'rm', 0x2128), # Z + (0x0061, 0x007a, 'rm', 0x1d51e), # a-z + ], + 'bf': + [ + (0x0041, 0x005a, 'bf', 0x1d56c), # A-Z + (0x0061, 0x007a, 'bf', 0x1d586), # a-z + ], + }, + 'scr': + [ + (0x0041, 0x0041, 'it', 0x1d49c), # A + (0x0042, 0x0042, 'it', 0x212c), # B + (0x0043, 0x0044, 'it', 0x1d49e), # C-D + (0x0045, 0x0046, 'it', 0x2130), # E-F + (0x0047, 0x0047, 'it', 0x1d4a2), # G + (0x0048, 0x0048, 'it', 0x210b), # H + (0x0049, 0x0049, 'it', 0x2110), # I + (0x004a, 0x004b, 'it', 0x1d4a5), # J-K + (0x004c, 0x004c, 'it', 0x2112), # L + (0x004d, 0x004d, 'it', 0x2133), # M + (0x004e, 0x0051, 'it', 0x1d4a9), # N-Q + (0x0052, 0x0052, 'it', 0x211b), # R + (0x0053, 0x005a, 'it', 0x1d4ae), # S-Z + (0x0061, 0x0064, 'it', 0x1d4b6), # a-d + (0x0065, 0x0065, 'it', 0x212f), # e + (0x0066, 0x0066, 'it', 0x1d4bb), # f + (0x0067, 0x0067, 'it', 0x210a), # g + (0x0068, 0x006e, 'it', 0x1d4bd), # h-n + (0x006f, 0x006f, 'it', 0x2134), # o + (0x0070, 0x007a, 'it', 0x1d4c5), # p-z + ], + 'sf': + { + 'rm': + [ + (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9 + (0x0041, 0x005a, 'rm', 0x1d5a0), # A-Z + (0x0061, 0x007a, 'rm', 0x1d5ba), # a-z + (0x0391, 0x03a9, 'rm', 0xe17d), # \Alpha-\Omega + (0x03b1, 0x03c9, 'rm', 0xe196), # \alpha-\omega + (0x03d1, 0x03d1, 'rm', 0xe1b0), # theta variant + (0x03d5, 0x03d5, 'rm', 0xe1b1), # phi variant + (0x03d6, 0x03d6, 'rm', 0xe1b3), # pi variant + (0x03f1, 0x03f1, 'rm', 0xe1b2), # rho variant + (0x03f5, 0x03f5, 'rm', 0xe1af), # lunate epsilon + (0x2202, 0x2202, 'rm', 0xe17c), # partial differential + ], + 'it': + [ + # These numerals are actually upright. We don't actually + # want italic numerals ever. + (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9 + (0x0041, 0x005a, 'it', 0x1d608), # A-Z + (0x0061, 0x007a, 'it', 0x1d622), # a-z + (0x0391, 0x03a9, 'rm', 0xe17d), # \Alpha-\Omega + (0x03b1, 0x03c9, 'it', 0xe1d8), # \alpha-\omega + (0x03d1, 0x03d1, 'it', 0xe1f2), # theta variant + (0x03d5, 0x03d5, 'it', 0xe1f3), # phi variant + (0x03d6, 0x03d6, 'it', 0xe1f5), # pi variant + (0x03f1, 0x03f1, 'it', 0xe1f4), # rho variant + (0x03f5, 0x03f5, 'it', 0xe1f1), # lunate epsilon + ], + 'bf': + [ + (0x0030, 0x0039, 'bf', 0x1d7ec), # 0-9 + (0x0041, 0x005a, 'bf', 0x1d5d4), # A-Z + (0x0061, 0x007a, 'bf', 0x1d5ee), # a-z + (0x0391, 0x03a9, 'bf', 0x1d756), # \Alpha-\Omega + (0x03b1, 0x03c9, 'bf', 0x1d770), # \alpha-\omega + (0x03d1, 0x03d1, 'bf', 0x1d78b), # theta variant + (0x03d5, 0x03d5, 'bf', 0x1d78d), # phi variant + (0x03d6, 0x03d6, 'bf', 0x1d78f), # pi variant + (0x03f0, 0x03f0, 'bf', 0x1d78c), # kappa variant + (0x03f1, 0x03f1, 'bf', 0x1d78e), # rho variant + (0x03f5, 0x03f5, 'bf', 0x1d78a), # lunate epsilon + (0x2202, 0x2202, 'bf', 0x1d789), # partial differential + (0x2207, 0x2207, 'bf', 0x1d76f), # \Nabla + ], + }, + 'tt': + [ + (0x0030, 0x0039, 'rm', 0x1d7f6), # 0-9 + (0x0041, 0x005a, 'rm', 0x1d670), # A-Z + (0x0061, 0x007a, 'rm', 0x1d68a) # a-z + ], + } diff --git a/contrib/python/matplotlib/py2/matplotlib/_pylab_helpers.py b/contrib/python/matplotlib/py2/matplotlib/_pylab_helpers.py new file mode 100644 index 00000000000..a1d37f21e20 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_pylab_helpers.py @@ -0,0 +1,138 @@ +""" +Manage figures for pyplot interface. +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import atexit +import gc +import sys + + +class Gcf(object): + """ + Singleton to manage a set of integer-numbered figures. + + This class is never instantiated; it consists of two class + attributes (a list and a dictionary), and a set of static + methods that operate on those attributes, accessing them + directly as class attributes. + + Attributes: + + *figs*: + dictionary of the form {*num*: *manager*, ...} + + *_activeQue*: + list of *managers*, with active one at the end + + """ + _activeQue = [] + figs = {} + + @classmethod + def get_fig_manager(cls, num): + """ + If figure manager *num* exists, make it the active + figure and return the manager; otherwise return *None*. + """ + manager = cls.figs.get(num, None) + if manager is not None: + cls.set_active(manager) + return manager + + @classmethod + def destroy(cls, num): + """ + Try to remove all traces of figure *num*. + + In the interactive backends, this is bound to the + window "destroy" and "delete" events. + """ + if not cls.has_fignum(num): + return + manager = cls.figs[num] + manager.canvas.mpl_disconnect(manager._cidgcf) + cls._activeQue.remove(manager) + del cls.figs[num] + manager.destroy() + gc.collect(1) + + @classmethod + def destroy_fig(cls, fig): + "*fig* is a Figure instance" + num = next((manager.num for manager in six.itervalues(cls.figs) + if manager.canvas.figure == fig), None) + if num is not None: + cls.destroy(num) + + @classmethod + def destroy_all(cls): + # this is need to ensure that gc is available in corner cases + # where modules are being torn down after install with easy_install + import gc # noqa + for manager in list(cls.figs.values()): + manager.canvas.mpl_disconnect(manager._cidgcf) + manager.destroy() + + cls._activeQue = [] + cls.figs.clear() + gc.collect(1) + + @classmethod + def has_fignum(cls, num): + """ + Return *True* if figure *num* exists. + """ + return num in cls.figs + + @classmethod + def get_all_fig_managers(cls): + """ + Return a list of figure managers. + """ + return list(cls.figs.values()) + + @classmethod + def get_num_fig_managers(cls): + """ + Return the number of figures being managed. + """ + return len(cls.figs) + + @classmethod + def get_active(cls): + """ + Return the manager of the active figure, or *None*. + """ + if len(cls._activeQue) == 0: + return None + else: + return cls._activeQue[-1] + + @classmethod + def set_active(cls, manager): + """ + Make the figure corresponding to *manager* the active one. + """ + oldQue = cls._activeQue[:] + cls._activeQue = [] + for m in oldQue: + if m != manager: + cls._activeQue.append(m) + cls._activeQue.append(manager) + cls.figs[manager.num] = manager + + @classmethod + def draw_all(cls, force=False): + """ + Redraw all figures registered with the pyplot + state machine. + """ + for f_mgr in cls.get_all_fig_managers(): + if force or f_mgr.canvas.figure.stale: + f_mgr.canvas.draw_idle() + +atexit.register(Gcf.destroy_all) diff --git a/contrib/python/matplotlib/py2/matplotlib/_version.py b/contrib/python/matplotlib/py2/matplotlib/_version.py new file mode 100644 index 00000000000..ea4bce57c9d --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/_version.py @@ -0,0 +1,21 @@ + +# This file was generated by 'versioneer.py' (0.15) from +# revision-control system data, or from the parent directory name of an +# unpacked source archive. Distribution tarballs contain a pre-generated copy +# of this file. + +import json +import sys + +version_json = ''' +{ + "dirty": false, + "error": null, + "full-revisionid": "61e004913460345d108b60506a4deb9f8380eeab", + "version": "2.2.5" +} +''' # END VERSION_JSON + + +def get_versions(): + return json.loads(version_json) diff --git a/contrib/python/matplotlib/py2/matplotlib/afm.py b/contrib/python/matplotlib/py2/matplotlib/afm.py new file mode 100644 index 00000000000..1b5f4d5f6a0 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/afm.py @@ -0,0 +1,547 @@ +""" +This is a python interface to Adobe Font Metrics Files. Although a +number of other python implementations exist, and may be more complete +than this, it was decided not to go with them because they were +either: + + 1) copyrighted or used a non-BSD compatible license + + 2) had too many dependencies and a free standing lib was needed + + 3) Did more than needed and it was easier to write afresh rather than + figure out how to get just what was needed. + +It is pretty easy to use, and requires only built-in python libs: + + >>> from matplotlib import rcParams + >>> import os.path + >>> afm_fname = os.path.join(rcParams['datapath'], + ... 'fonts', 'afm', 'ptmr8a.afm') + >>> + >>> from matplotlib.afm import AFM + >>> with open(afm_fname, 'rb') as fh: + ... afm = AFM(fh) + >>> afm.string_width_height('What the heck?') + (6220.0, 694) + >>> afm.get_fontname() + 'Times-Roman' + >>> afm.get_kern_dist('A', 'f') + 0 + >>> afm.get_kern_dist('A', 'y') + -92.0 + >>> afm.get_bbox_char('!') + [130, -9, 238, 676] + +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import map + +import sys +import re +from ._mathtext_data import uni2type1 + +# Convert string the a python type + +# some afm files have floats where we are expecting ints -- there is +# probably a better way to handle this (support floats, round rather +# than truncate). But I don't know what the best approach is now and +# this change to _to_int should at least prevent mpl from crashing on +# these JDH (2009-11-06) + + +def _to_int(x): + return int(float(x)) + + +_to_float = float + + +def _to_str(x): + return x.decode('utf8') + + +def _to_list_of_ints(s): + s = s.replace(b',', b' ') + return [_to_int(val) for val in s.split()] + + +def _to_list_of_floats(s): + return [_to_float(val) for val in s.split()] + + +def _to_bool(s): + if s.lower().strip() in (b'false', b'0', b'no'): + return False + else: + return True + + +def _sanity_check(fh): + """ + Check if the file at least looks like AFM. + If not, raise :exc:`RuntimeError`. + """ + + # Remember the file position in case the caller wants to + # do something else with the file. + pos = fh.tell() + try: + line = next(fh) + finally: + fh.seek(pos, 0) + + # AFM spec, Section 4: The StartFontMetrics keyword [followed by a + # version number] must be the first line in the file, and the + # EndFontMetrics keyword must be the last non-empty line in the + # file. We just check the first line. + if not line.startswith(b'StartFontMetrics'): + raise RuntimeError('Not an AFM file') + + +def _parse_header(fh): + """ + Reads the font metrics header (up to the char metrics) and returns + a dictionary mapping *key* to *val*. *val* will be converted to the + appropriate python type as necessary; e.g.: + + * 'False'->False + * '0'->0 + * '-168 -218 1000 898'-> [-168, -218, 1000, 898] + + Dictionary keys are + + StartFontMetrics, FontName, FullName, FamilyName, Weight, + ItalicAngle, IsFixedPitch, FontBBox, UnderlinePosition, + UnderlineThickness, Version, Notice, EncodingScheme, CapHeight, + XHeight, Ascender, Descender, StartCharMetrics + + """ + headerConverters = { + b'StartFontMetrics': _to_float, + b'FontName': _to_str, + b'FullName': _to_str, + b'FamilyName': _to_str, + b'Weight': _to_str, + b'ItalicAngle': _to_float, + b'IsFixedPitch': _to_bool, + b'FontBBox': _to_list_of_ints, + b'UnderlinePosition': _to_int, + b'UnderlineThickness': _to_int, + b'Version': _to_str, + b'Notice': _to_str, + b'EncodingScheme': _to_str, + b'CapHeight': _to_float, # Is the second version a mistake, or + b'Capheight': _to_float, # do some AFM files contain 'Capheight'? -JKS + b'XHeight': _to_float, + b'Ascender': _to_float, + b'Descender': _to_float, + b'StdHW': _to_float, + b'StdVW': _to_float, + b'StartCharMetrics': _to_int, + b'CharacterSet': _to_str, + b'Characters': _to_int, + } + + d = {} + for line in fh: + line = line.rstrip() + if line.startswith(b'Comment'): + continue + lst = line.split(b' ', 1) + + key = lst[0] + if len(lst) == 2: + val = lst[1] + else: + val = b'' + + try: + d[key] = headerConverters[key](val) + except ValueError: + print('Value error parsing header in AFM:', + key, val, file=sys.stderr) + continue + except KeyError: + print('Found an unknown keyword in AFM header (was %r)' % key, + file=sys.stderr) + continue + if key == b'StartCharMetrics': + return d + raise RuntimeError('Bad parse') + + +def _parse_char_metrics(fh): + """ + Return a character metric dictionary. Keys are the ASCII num of + the character, values are a (*wx*, *name*, *bbox*) tuple, where + *wx* is the character width, *name* is the postscript language + name, and *bbox* is a (*llx*, *lly*, *urx*, *ury*) tuple. + + This function is incomplete per the standard, but thus far parses + all the sample afm files tried. + """ + + ascii_d = {} + name_d = {} + for line in fh: + # We are defensively letting values be utf8. The spec requires + # ascii, but there are non-compliant fonts in circulation + line = _to_str(line.rstrip()) # Convert from byte-literal + if line.startswith('EndCharMetrics'): + return ascii_d, name_d + # Split the metric line into a dictionary, keyed by metric identifiers + vals = dict(s.strip().split(' ', 1) for s in line.split(';') if s) + # There may be other metrics present, but only these are needed + if not {'C', 'WX', 'N', 'B'}.issubset(vals): + raise RuntimeError('Bad char metrics line: %s' % line) + num = _to_int(vals['C']) + wx = _to_float(vals['WX']) + name = vals['N'] + bbox = _to_list_of_floats(vals['B']) + bbox = list(map(int, bbox)) + # Workaround: If the character name is 'Euro', give it the + # corresponding character code, according to WinAnsiEncoding (see PDF + # Reference). + if name == 'Euro': + num = 128 + if num != -1: + ascii_d[num] = (wx, name, bbox) + name_d[name] = (wx, bbox) + raise RuntimeError('Bad parse') + + +def _parse_kern_pairs(fh): + """ + Return a kern pairs dictionary; keys are (*char1*, *char2*) tuples and + values are the kern pair value. For example, a kern pairs line like + ``KPX A y -50`` + + will be represented as:: + + d[ ('A', 'y') ] = -50 + + """ + + line = next(fh) + if not line.startswith(b'StartKernPairs'): + raise RuntimeError('Bad start of kern pairs data: %s' % line) + + d = {} + for line in fh: + line = line.rstrip() + if not line: + continue + if line.startswith(b'EndKernPairs'): + next(fh) # EndKernData + return d + vals = line.split() + if len(vals) != 4 or vals[0] != b'KPX': + raise RuntimeError('Bad kern pairs line: %s' % line) + c1, c2, val = _to_str(vals[1]), _to_str(vals[2]), _to_float(vals[3]) + d[(c1, c2)] = val + raise RuntimeError('Bad kern pairs parse') + + +def _parse_composites(fh): + """ + Return a composites dictionary. Keys are the names of the + composites. Values are a num parts list of composite information, + with each element being a (*name*, *dx*, *dy*) tuple. Thus a + composites line reading: + + CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 170 ; + + will be represented as:: + + d['Aacute'] = [ ('A', 0, 0), ('acute', 160, 170) ] + + """ + d = {} + for line in fh: + line = line.rstrip() + if not line: + continue + if line.startswith(b'EndComposites'): + return d + vals = line.split(b';') + cc = vals[0].split() + name, numParts = cc[1], _to_int(cc[2]) + pccParts = [] + for s in vals[1:-1]: + pcc = s.split() + name, dx, dy = pcc[1], _to_float(pcc[2]), _to_float(pcc[3]) + pccParts.append((name, dx, dy)) + d[name] = pccParts + + raise RuntimeError('Bad composites parse') + + +def _parse_optional(fh): + """ + Parse the optional fields for kern pair data and composites + + return value is a (*kernDict*, *compositeDict*) which are the + return values from :func:`_parse_kern_pairs`, and + :func:`_parse_composites` if the data exists, or empty dicts + otherwise + """ + optional = { + b'StartKernData': _parse_kern_pairs, + b'StartComposites': _parse_composites, + } + + d = {b'StartKernData': {}, b'StartComposites': {}} + for line in fh: + line = line.rstrip() + if not line: + continue + key = line.split()[0] + + if key in optional: + d[key] = optional[key](fh) + + l = (d[b'StartKernData'], d[b'StartComposites']) + return l + + +def parse_afm(fh): + """ + Parse the Adobe Font Metics file in file handle *fh*. Return value + is a (*dhead*, *dcmetrics_ascii*, *dmetrics_name*, *dkernpairs*, + *dcomposite*) tuple where + *dhead* is a :func:`_parse_header` dict, + *dcmetrics_ascii* and *dcmetrics_name* are the two resulting dicts + from :func:`_parse_char_metrics`, + *dkernpairs* is a :func:`_parse_kern_pairs` dict (possibly {}) and + *dcomposite* is a :func:`_parse_composites` dict (possibly {}) + """ + _sanity_check(fh) + dhead = _parse_header(fh) + dcmetrics_ascii, dcmetrics_name = _parse_char_metrics(fh) + doptional = _parse_optional(fh) + return dhead, dcmetrics_ascii, dcmetrics_name, doptional[0], doptional[1] + + +class AFM(object): + + def __init__(self, fh): + """ + Parse the AFM file in file object *fh* + """ + (dhead, dcmetrics_ascii, dcmetrics_name, dkernpairs, dcomposite) = \ + parse_afm(fh) + self._header = dhead + self._kern = dkernpairs + self._metrics = dcmetrics_ascii + self._metrics_by_name = dcmetrics_name + self._composite = dcomposite + + def get_bbox_char(self, c, isord=False): + if not isord: + c = ord(c) + wx, name, bbox = self._metrics[c] + return bbox + + def string_width_height(self, s): + """ + Return the string width (including kerning) and string height + as a (*w*, *h*) tuple. + """ + if not len(s): + return 0, 0 + totalw = 0 + namelast = None + miny = 1e9 + maxy = 0 + for c in s: + if c == '\n': + continue + wx, name, bbox = self._metrics[ord(c)] + l, b, w, h = bbox + + # find the width with kerning + try: + kp = self._kern[(namelast, name)] + except KeyError: + kp = 0 + totalw += wx + kp + + # find the max y + thismax = b + h + if thismax > maxy: + maxy = thismax + + # find the min y + thismin = b + if thismin < miny: + miny = thismin + namelast = name + + return totalw, maxy - miny + + def get_str_bbox_and_descent(self, s): + """ + Return the string bounding box + """ + if not len(s): + return 0, 0, 0, 0 + totalw = 0 + namelast = None + miny = 1e9 + maxy = 0 + left = 0 + if not isinstance(s, six.text_type): + s = _to_str(s) + for c in s: + if c == '\n': + continue + name = uni2type1.get(ord(c), 'question') + try: + wx, bbox = self._metrics_by_name[name] + except KeyError: + name = 'question' + wx, bbox = self._metrics_by_name[name] + l, b, w, h = bbox + if l < left: + left = l + # find the width with kerning + try: + kp = self._kern[(namelast, name)] + except KeyError: + kp = 0 + totalw += wx + kp + + # find the max y + thismax = b + h + if thismax > maxy: + maxy = thismax + + # find the min y + thismin = b + if thismin < miny: + miny = thismin + namelast = name + + return left, miny, totalw, maxy - miny, -miny + + def get_str_bbox(self, s): + """ + Return the string bounding box + """ + return self.get_str_bbox_and_descent(s)[:4] + + def get_name_char(self, c, isord=False): + """ + Get the name of the character, i.e., ';' is 'semicolon' + """ + if not isord: + c = ord(c) + wx, name, bbox = self._metrics[c] + return name + + def get_width_char(self, c, isord=False): + """ + Get the width of the character from the character metric WX + field + """ + if not isord: + c = ord(c) + wx, name, bbox = self._metrics[c] + return wx + + def get_width_from_char_name(self, name): + """ + Get the width of the character from a type1 character name + """ + wx, bbox = self._metrics_by_name[name] + return wx + + def get_height_char(self, c, isord=False): + """ + Get the height of character *c* from the bounding box. This + is the ink height (space is 0) + """ + if not isord: + c = ord(c) + wx, name, bbox = self._metrics[c] + return bbox[-1] + + def get_kern_dist(self, c1, c2): + """ + Return the kerning pair distance (possibly 0) for chars *c1* + and *c2* + """ + name1, name2 = self.get_name_char(c1), self.get_name_char(c2) + return self.get_kern_dist_from_name(name1, name2) + + def get_kern_dist_from_name(self, name1, name2): + """ + Return the kerning pair distance (possibly 0) for chars + *name1* and *name2* + """ + return self._kern.get((name1, name2), 0) + + def get_fontname(self): + "Return the font name, e.g., 'Times-Roman'" + return self._header[b'FontName'] + + def get_fullname(self): + "Return the font full name, e.g., 'Times-Roman'" + name = self._header.get(b'FullName') + if name is None: # use FontName as a substitute + name = self._header[b'FontName'] + return name + + def get_familyname(self): + "Return the font family name, e.g., 'Times'" + name = self._header.get(b'FamilyName') + if name is not None: + return name + + # FamilyName not specified so we'll make a guess + name = self.get_fullname() + extras = (r'(?i)([ -](regular|plain|italic|oblique|bold|semibold|' + r'light|ultralight|extra|condensed))+$') + return re.sub(extras, '', name) + + @property + def family_name(self): + return self.get_familyname() + + def get_weight(self): + "Return the font weight, e.g., 'Bold' or 'Roman'" + return self._header[b'Weight'] + + def get_angle(self): + "Return the fontangle as float" + return self._header[b'ItalicAngle'] + + def get_capheight(self): + "Return the cap height as float" + return self._header[b'CapHeight'] + + def get_xheight(self): + "Return the xheight as float" + return self._header[b'XHeight'] + + def get_underline_thickness(self): + "Return the underline thickness as float" + return self._header[b'UnderlineThickness'] + + def get_horizontal_stem_width(self): + """ + Return the standard horizontal stem width as float, or *None* if + not specified in AFM file. + """ + return self._header.get(b'StdHW', None) + + def get_vertical_stem_width(self): + """ + Return the standard vertical stem width as float, or *None* if + not specified in AFM file. + """ + return self._header.get(b'StdVW', None) diff --git a/contrib/python/matplotlib/py2/matplotlib/animation.py b/contrib/python/matplotlib/py2/matplotlib/animation.py new file mode 100644 index 00000000000..e2e6f51e706 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/animation.py @@ -0,0 +1,1778 @@ +# TODO: +# * Loop Delay is broken on GTKAgg. This is because source_remove() is not +# working as we want. PyGTK bug? +# * Documentation -- this will need a new section of the User's Guide. +# Both for Animations and just timers. +# - Also need to update http://www.scipy.org/Cookbook/Matplotlib/Animations +# * Blit +# * Currently broken with Qt4 for widgets that don't start on screen +# * Still a few edge cases that aren't working correctly +# * Can this integrate better with existing matplotlib animation artist flag? +# - If animated removes from default draw(), perhaps we could use this to +# simplify initial draw. +# * Example +# * Frameless animation - pure procedural with no loop +# * Need example that uses something like inotify or subprocess +# * Complex syncing examples +# * Movies +# * Can blit be enabled for movies? +# * Need to consider event sources to allow clicking through multiple figures +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import xrange, zip + +import abc +import contextlib +from io import BytesIO +import itertools +import logging +import os +import platform +import sys +import tempfile +import uuid + +import numpy as np + +from matplotlib._animation_data import (DISPLAY_TEMPLATE, INCLUDED_FRAMES, + JS_INCLUDE) +from matplotlib.compat import subprocess +from matplotlib import cbook, rcParams, rcParamsDefault, rc_context + +if six.PY2: + from base64 import encodestring as encodebytes +else: + from base64 import encodebytes + + +_log = logging.getLogger(__name__) + +# Process creation flag for subprocess to prevent it raising a terminal +# window. See for example: +# https://stackoverflow.com/questions/24130623/using-python-subprocess-popen-cant-prevent-exe-stopped-working-prompt +if platform.system() == 'Windows': + subprocess_creation_flags = CREATE_NO_WINDOW = 0x08000000 +else: + # Apparently None won't work here + subprocess_creation_flags = 0 + +# Other potential writing methods: +# * http://pymedia.org/ +# * libmng (produces swf) python wrappers: https://github.com/libming/libming +# * Wrap x264 API: + +# (http://stackoverflow.com/questions/2940671/ +# how-to-encode-series-of-images-into-h264-using-x264-api-c-c ) + + +def adjusted_figsize(w, h, dpi, n): + '''Compute figure size so that pixels are a multiple of n + + Parameters + ---------- + w, h : float + Size in inches + + dpi : float + The dpi + + n : int + The target multiple + + Returns + ------- + wnew, hnew : float + The new figure size in inches. + ''' + + # this maybe simplified if / when we adopt consistent rounding for + # pixel size across the whole library + def correct_roundoff(x, dpi, n): + if int(x*dpi) % n != 0: + if int(np.nextafter(x, np.inf)*dpi) % n == 0: + x = np.nextafter(x, np.inf) + elif int(np.nextafter(x, -np.inf)*dpi) % n == 0: + x = np.nextafter(x, -np.inf) + return x + + wnew = int(w * dpi / n) * n / dpi + hnew = int(h * dpi / n) * n / dpi + return (correct_roundoff(wnew, dpi, n), correct_roundoff(hnew, dpi, n)) + + +# A registry for available MovieWriter classes +class MovieWriterRegistry(object): + '''Registry of available writer classes by human readable name.''' + def __init__(self): + self.avail = dict() + self._registered = dict() + self._dirty = False + + def set_dirty(self): + """Sets a flag to re-setup the writers.""" + self._dirty = True + + def register(self, name): + """Decorator for registering a class under a name. + + Example use:: + + @registry.register(name) + class Foo: + pass + """ + def wrapper(writerClass): + self._registered[name] = writerClass + if writerClass.isAvailable(): + self.avail[name] = writerClass + return writerClass + return wrapper + + def ensure_not_dirty(self): + """If dirty, reasks the writers if they are available""" + if self._dirty: + self.reset_available_writers() + + def reset_available_writers(self): + """Reset the available state of all registered writers""" + self.avail = {} + for name, writerClass in self._registered.items(): + if writerClass.isAvailable(): + self.avail[name] = writerClass + self._dirty = False + + def list(self): + '''Get a list of available MovieWriters.''' + self.ensure_not_dirty() + return list(self.avail) + + def is_available(self, name): + '''Check if given writer is available by name. + + Parameters + ---------- + name : str + + Returns + ------- + available : bool + ''' + self.ensure_not_dirty() + return name in self.avail + + def __getitem__(self, name): + self.ensure_not_dirty() + if not self.avail: + raise RuntimeError("No MovieWriters available!") + try: + return self.avail[name] + except KeyError: + raise RuntimeError( + 'Requested MovieWriter ({}) not available'.format(name)) + + +writers = MovieWriterRegistry() + + +class AbstractMovieWriter(six.with_metaclass(abc.ABCMeta)): + ''' + Abstract base class for writing movies. Fundamentally, what a MovieWriter + does is provide is a way to grab frames by calling grab_frame(). + + setup() is called to start the process and finish() is called afterwards. + + This class is set up to provide for writing movie frame data to a pipe. + saving() is provided as a context manager to facilitate this process as:: + + with moviewriter.saving(fig, outfile='myfile.mp4', dpi=100): + # Iterate over frames + moviewriter.grab_frame(**savefig_kwargs) + + The use of the context manager ensures that setup() and finish() are + performed as necessary. + + An instance of a concrete subclass of this class can be given as the + ``writer`` argument of `Animation.save()`. + ''' + + @abc.abstractmethod + def setup(self, fig, outfile, dpi=None): + ''' + Perform setup for writing the movie file. + + Parameters + ---------- + fig: `matplotlib.figure.Figure` instance + The figure object that contains the information for frames + outfile: string + The filename of the resulting movie file + dpi: int, optional + The DPI (or resolution) for the file. This controls the size + in pixels of the resulting movie file. Default is ``fig.dpi``. + ''' + + @abc.abstractmethod + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + + @abc.abstractmethod + def finish(self): + '''Finish any processing for writing the movie.''' + + @contextlib.contextmanager + def saving(self, fig, outfile, dpi, *args, **kwargs): + ''' + Context manager to facilitate writing the movie file. + + ``*args, **kw`` are any parameters that should be passed to `setup`. + ''' + # This particular sequence is what contextlib.contextmanager wants + self.setup(fig, outfile, dpi, *args, **kwargs) + try: + yield self + finally: + self.finish() + + +class MovieWriter(AbstractMovieWriter): + '''Base class for writing movies. + + This class is set up to provide for writing movie frame data to a pipe. + See examples for how to use these classes. + + Attributes + ---------- + frame_format : str + The format used in writing frame data, defaults to 'rgba' + fig : `~matplotlib.figure.Figure` + The figure to capture data from. + This must be provided by the sub-classes. + + ''' + + def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None, + metadata=None): + '''MovieWriter + + Parameters + ---------- + fps: int + Framerate for movie. + codec: string or None, optional + The codec to use. If ``None`` (the default) the ``animation.codec`` + rcParam is used. + bitrate: int or None, optional + The bitrate for the saved movie file, which is one way to control + the output file size and quality. The default value is ``None``, + which uses the ``animation.bitrate`` rcParam. A value of -1 + implies that the bitrate should be determined automatically by the + underlying utility. + extra_args: list of strings or None, optional + A list of extra string arguments to be passed to the underlying + movie utility. The default is ``None``, which passes the additional + arguments in the ``animation.extra_args`` rcParam. + metadata: Dict[str, str] or None + A dictionary of keys and values for metadata to include in the + output file. Some keys that may be of use include: + title, artist, genre, subject, copyright, srcform, comment. + ''' + self.fps = fps + self.frame_format = 'rgba' + + if codec is None: + self.codec = rcParams['animation.codec'] + else: + self.codec = codec + + if bitrate is None: + self.bitrate = rcParams['animation.bitrate'] + else: + self.bitrate = bitrate + + if extra_args is None: + self.extra_args = list(rcParams[self.args_key]) + else: + self.extra_args = extra_args + + if metadata is None: + self.metadata = dict() + else: + self.metadata = metadata + + @property + def frame_size(self): + '''A tuple ``(width, height)`` in pixels of a movie frame.''' + w, h = self.fig.get_size_inches() + return int(w * self.dpi), int(h * self.dpi) + + def _adjust_frame_size(self): + if self.codec == 'h264': + wo, ho = self.fig.get_size_inches() + w, h = adjusted_figsize(wo, ho, self.dpi, 2) + if not (wo, ho) == (w, h): + self.fig.set_size_inches(w, h, forward=True) + _log.info('figure size (inches) has been adjusted ' + 'from %s x %s to %s x %s', wo, ho, w, h) + else: + w, h = self.fig.get_size_inches() + _log.debug('frame size in pixels is %s x %s', *self.frame_size) + return w, h + + def setup(self, fig, outfile, dpi=None): + ''' + Perform setup for writing the movie file. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that contains the information for frames + outfile : string + The filename of the resulting movie file + dpi : int, optional + The DPI (or resolution) for the file. This controls the size + in pixels of the resulting movie file. Default is fig.dpi. + ''' + self.outfile = outfile + self.fig = fig + if dpi is None: + dpi = self.fig.dpi + self.dpi = dpi + self._w, self._h = self._adjust_frame_size() + + # Run here so that grab_frame() can write the data to a pipe. This + # eliminates the need for temp files. + self._run() + + def _run(self): + # Uses subprocess to call the program for assembling frames into a + # movie file. *args* returns the sequence of command line arguments + # from a few configuration options. + command = self._args() + output = subprocess.PIPE + _log.info('MovieWriter.run: running command: %s', command) + self._proc = subprocess.Popen(command, shell=False, + stdout=output, stderr=output, + stdin=subprocess.PIPE, + creationflags=subprocess_creation_flags) + + def finish(self): + '''Finish any processing for writing the movie.''' + self.cleanup() + + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + _log.debug('MovieWriter.grab_frame: Grabbing frame.') + try: + # re-adjust the figure size in case it has been changed by the + # user. We must ensure that every frame is the same size or + # the movie will not save correctly. + self.fig.set_size_inches(self._w, self._h) + # Tell the figure to save its data to the sink, using the + # frame format and dpi. + self.fig.savefig(self._frame_sink(), format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + except (RuntimeError, IOError) as e: + out, err = self._proc.communicate() + _log.info('MovieWriter -- Error ' + 'running proc:\n%s\n%s' % (out, err)) + raise IOError('Error saving animation to file (cause: {0}) ' + 'Stdout: {1} StdError: {2}. It may help to re-run ' + 'with logging level set to ' + 'DEBUG.'.format(e, out, err)) + + def _frame_sink(self): + '''Returns the place to which frames should be written.''' + return self._proc.stdin + + def _args(self): + '''Assemble list of utility-specific command-line arguments.''' + return NotImplementedError("args needs to be implemented by subclass.") + + def cleanup(self): + '''Clean-up and collect the process used to write the movie file.''' + out, err = self._proc.communicate() + self._frame_sink().close() + _log.debug('MovieWriter -- Command stdout:\n%s', out) + _log.debug('MovieWriter -- Command stderr:\n%s', err) + + @classmethod + def bin_path(cls): + ''' + Returns the binary path to the commandline tool used by a specific + subclass. This is a class method so that the tool can be looked for + before making a particular MovieWriter subclass available. + ''' + return str(rcParams[cls.exec_key]) + + @classmethod + def isAvailable(cls): + ''' + Check to see if a MovieWriter subclass is actually available by + running the commandline tool. + ''' + bin_path = cls.bin_path() + if not bin_path: + return False + try: + p = subprocess.Popen( + bin_path, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + creationflags=subprocess_creation_flags) + return cls._handle_subprocess(p) + except OSError: + return False + + @classmethod + def _handle_subprocess(cls, process): + process.communicate() + return True + + +class FileMovieWriter(MovieWriter): + '''`MovieWriter` for writing to individual files and stitching at the end. + + This must be sub-classed to be useful. + ''' + def __init__(self, *args, **kwargs): + MovieWriter.__init__(self, *args, **kwargs) + self.frame_format = rcParams['animation.frame_format'] + + def setup(self, fig, outfile, dpi=None, frame_prefix='_tmp', + clear_temp=True): + '''Perform setup for writing the movie file. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure to grab the rendered frames from. + outfile : str + The filename of the resulting movie file. + dpi : number, optional + The dpi of the output file. This, with the figure size, + controls the size in pixels of the resulting movie file. + Default is fig.dpi. + frame_prefix : str, optional + The filename prefix to use for temporary files. Defaults to + ``'_tmp'``. + clear_temp : bool, optional + If the temporary files should be deleted after stitching + the final result. Setting this to ``False`` can be useful for + debugging. Defaults to ``True``. + + ''' + self.fig = fig + self.outfile = outfile + if dpi is None: + dpi = self.fig.dpi + self.dpi = dpi + self._adjust_frame_size() + + self.clear_temp = clear_temp + self.temp_prefix = frame_prefix + self._frame_counter = 0 # used for generating sequential file names + self._temp_names = list() + self.fname_format_str = '%s%%07d.%s' + + @property + def frame_format(self): + ''' + Format (png, jpeg, etc.) to use for saving the frames, which can be + decided by the individual subclasses. + ''' + return self._frame_format + + @frame_format.setter + def frame_format(self, frame_format): + if frame_format in self.supported_formats: + self._frame_format = frame_format + else: + self._frame_format = self.supported_formats[0] + + def _base_temp_name(self): + # Generates a template name (without number) given the frame format + # for extension and the prefix. + return self.fname_format_str % (self.temp_prefix, self.frame_format) + + def _frame_sink(self): + # Creates a filename for saving using the basename and the current + # counter. + fname = self._base_temp_name() % self._frame_counter + + # Save the filename so we can delete it later if necessary + self._temp_names.append(fname) + _log.debug('FileMovieWriter.frame_sink: saving frame %d to fname=%s', + self._frame_counter, fname) + self._frame_counter += 1 # Ensures each created name is 'unique' + + # This file returned here will be closed once it's used by savefig() + # because it will no longer be referenced and will be gc-ed. + return open(fname, 'wb') + + def grab_frame(self, **savefig_kwargs): + ''' + Grab the image information from the figure and save as a movie frame. + All keyword arguments in savefig_kwargs are passed on to the `savefig` + command that saves the figure. + ''' + # Overloaded to explicitly close temp file. + _log.debug('MovieWriter.grab_frame: Grabbing frame.') + try: + # Tell the figure to save its data to the sink, using the + # frame format and dpi. + with self._frame_sink() as myframesink: + self.fig.savefig(myframesink, format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + + except RuntimeError: + out, err = self._proc.communicate() + _log.info('MovieWriter -- Error ' + 'running proc:\n%s\n%s' % (out, err)) + raise + + def finish(self): + # Call run here now that all frame grabbing is done. All temp files + # are available to be assembled. + self._run() + MovieWriter.finish(self) # Will call clean-up + + # Check error code for creating file here, since we just run + # the process here, rather than having an open pipe. + if self._proc.returncode: + try: + stdout = [s.decode() for s in self._proc._stdout_buff] + stderr = [s.decode() for s in self._proc._stderr_buff] + _log.info("MovieWriter.finish: stdout: %s", stdout) + _log.info("MovieWriter.finish: stderr: %s", stderr) + except Exception as e: + pass + raise RuntimeError('Error creating movie, return code: {}' + .format(self._proc.returncode)) + + def cleanup(self): + MovieWriter.cleanup(self) + + # Delete temporary files + if self.clear_temp: + _log.debug('MovieWriter: clearing temporary fnames=%s', + self._temp_names) + for fname in self._temp_names: + os.remove(fname) + + +@writers.register('pillow') +class PillowWriter(MovieWriter): + @classmethod + def isAvailable(cls): + try: + import PIL + except ImportError: + return False + return True + + def __init__(self, *args, **kwargs): + if kwargs.get("extra_args") is None: + kwargs["extra_args"] = () + super(PillowWriter, self).__init__(*args, **kwargs) + + def setup(self, fig, outfile, dpi=None): + self._frames = [] + self._outfile = outfile + self._dpi = dpi + self._fig = fig + + def grab_frame(self, **savefig_kwargs): + from PIL import Image + buf = BytesIO() + self._fig.savefig(buf, **dict(savefig_kwargs, format="rgba")) + renderer = self._fig.canvas.get_renderer() + # Using frombuffer / getbuffer may be slightly more efficient, but + # Py3-only. + self._frames.append(Image.frombytes( + "RGBA", + (int(renderer.width), int(renderer.height)), + buf.getvalue())) + + def finish(self): + self._frames[0].save( + self._outfile, save_all=True, append_images=self._frames[1:], + duration=int(1000 / self.fps)) + + +# Base class of ffmpeg information. Has the config keys and the common set +# of arguments that controls the *output* side of things. +class FFMpegBase(object): + '''Mixin class for FFMpeg output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.ffmpeg_path' + args_key = 'animation.ffmpeg_args' + + @property + def output_args(self): + args = ['-vcodec', self.codec] + # For h264, the default format is yuv444p, which is not compatible + # with quicktime (and others). Specifying yuv420p fixes playback on + # iOS,as well as HTML5 video in firefox and safari (on both Win and + # OSX). Also fixes internet explorer. This is as of 2015/10/29. + if self.codec == 'h264' and '-pix_fmt' not in self.extra_args: + args.extend(['-pix_fmt', 'yuv420p']) + # The %dk adds 'k' as a suffix so that ffmpeg treats our bitrate as in + # kbps + if self.bitrate > 0: + args.extend(['-b', '%dk' % self.bitrate]) + if self.extra_args: + args.extend(self.extra_args) + for k, v in six.iteritems(self.metadata): + args.extend(['-metadata', '%s=%s' % (k, v)]) + + return args + ['-y', self.outfile] + + @classmethod + def _handle_subprocess(cls, process): + _, err = process.communicate() + # Ubuntu 12.04 ships a broken ffmpeg binary which we shouldn't use + # NOTE : when removed, remove the same method in AVConvBase. + if 'Libav' in err.decode(): + return False + return True + + +# Combine FFMpeg options with pipe-based writing +@writers.register('ffmpeg') +class FFMpegWriter(FFMpegBase, MovieWriter): + '''Pipe-based ffmpeg writer. + + Frames are streamed directly to ffmpeg via a pipe and written in a single + pass. + ''' + def _args(self): + # Returns the command line parameters for subprocess to use + # ffmpeg to create a movie using a pipe. + args = [self.bin_path(), '-f', 'rawvideo', '-vcodec', 'rawvideo', + '-s', '%dx%d' % self.frame_size, '-pix_fmt', self.frame_format, + '-r', str(self.fps)] + # Logging is quieted because subprocess.PIPE has limited buffer size. + # If you have a lot of frames in your animation and set logging to + # DEBUG, you will have a buffer overrun. + if (_log.getEffectiveLevel() > logging.DEBUG): + args += ['-loglevel', 'quiet'] + args += ['-i', 'pipe:'] + self.output_args + return args + + +# Combine FFMpeg options with temp file-based writing +@writers.register('ffmpeg_file') +class FFMpegFileWriter(FFMpegBase, FileMovieWriter): + '''File-based ffmpeg writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' + supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', + 'pbm', 'raw', 'rgba'] + + def _args(self): + # Returns the command line parameters for subprocess to use + # ffmpeg to create a movie using a collection of temp images + return [self.bin_path(), '-r', str(self.fps), + '-i', self._base_temp_name(), + '-vframes', str(self._frame_counter)] + self.output_args + + +# Base class of avconv information. AVConv has identical arguments to +# FFMpeg +class AVConvBase(FFMpegBase): + '''Mixin class for avconv output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.avconv_path' + args_key = 'animation.avconv_args' + + # NOTE : should be removed when the same method is removed in FFMpegBase. + @classmethod + def _handle_subprocess(cls, process): + return MovieWriter._handle_subprocess(process) + + +# Combine AVConv options with pipe-based writing +@writers.register('avconv') +class AVConvWriter(AVConvBase, FFMpegWriter): + '''Pipe-based avconv writer. + + Frames are streamed directly to avconv via a pipe and written in a single + pass. + ''' + + +# Combine AVConv options with file-based writing +@writers.register('avconv_file') +class AVConvFileWriter(AVConvBase, FFMpegFileWriter): + '''File-based avconv writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + ''' + + +# Base class for animated GIFs with convert utility +class ImageMagickBase(object): + '''Mixin class for ImageMagick output. + + To be useful this must be multiply-inherited from with a + `MovieWriterBase` sub-class. + ''' + + exec_key = 'animation.convert_path' + args_key = 'animation.convert_args' + + @property + def delay(self): + return 100. / self.fps + + @property + def output_args(self): + return [self.outfile] + + @classmethod + def _init_from_registry(cls): + if sys.platform != 'win32' or rcParams[cls.exec_key] != 'convert': + return + from six.moves import winreg + for flag in (0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY): + try: + hkey = winreg.OpenKeyEx(winreg.HKEY_LOCAL_MACHINE, + 'Software\\Imagemagick\\Current', + 0, winreg.KEY_QUERY_VALUE | flag) + binpath = winreg.QueryValueEx(hkey, 'BinPath')[0] + winreg.CloseKey(hkey) + binpath += '\\convert.exe' + break + except Exception: + binpath = '' + rcParams[cls.exec_key] = rcParamsDefault[cls.exec_key] = binpath + + @classmethod + def isAvailable(cls): + ''' + Check to see if a ImageMagickWriter is actually available. + + Done by first checking the windows registry (if applicable) and then + running the commandline tool. + ''' + bin_path = cls.bin_path() + if bin_path == "convert": + cls._init_from_registry() + return super(ImageMagickBase, cls).isAvailable() + +ImageMagickBase._init_from_registry() + + +# Note: the base classes need to be in that order to get +# isAvailable() from ImageMagickBase called and not the +# one from MovieWriter. The latter is then called by the +# former. +@writers.register('imagemagick') +class ImageMagickWriter(ImageMagickBase, MovieWriter): + '''Pipe-based animated gif. + + Frames are streamed directly to ImageMagick via a pipe and written + in a single pass. + + ''' + def _args(self): + return ([self.bin_path(), + '-size', '%ix%i' % self.frame_size, '-depth', '8', + '-delay', str(self.delay), '-loop', '0', + '%s:-' % self.frame_format] + + self.output_args) + + +# Note: the base classes need to be in that order to get +# isAvailable() from ImageMagickBase called and not the +# one from MovieWriter. The latter is then called by the +# former. +@writers.register('imagemagick_file') +class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter): + '''File-based animated gif writer. + + Frames are written to temporary files on disk and then stitched + together at the end. + + ''' + + supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp', + 'pbm', 'raw', 'rgba'] + + def _args(self): + return ([self.bin_path(), '-delay', str(self.delay), '-loop', '0', + '%s*.%s' % (self.temp_prefix, self.frame_format)] + + self.output_args) + + +# Taken directly from jakevdp's JSAnimation package at +# http://github.com/jakevdp/JSAnimation +def _included_frames(frame_list, frame_format): + """frame_list should be a list of filenames""" + return INCLUDED_FRAMES.format(Nframes=len(frame_list), + frame_dir=os.path.dirname(frame_list[0]), + frame_format=frame_format) + + +def _embedded_frames(frame_list, frame_format): + """frame_list should be a list of base64-encoded png files""" + template = ' frames[{0}] = "data:image/{1};base64,{2}"\n' + return "\n" + "".join( + template.format(i, frame_format, frame_data.replace('\n', '\\\n')) + for i, frame_data in enumerate(frame_list)) + + +@writers.register('html') +class HTMLWriter(FileMovieWriter): + supported_formats = ['png', 'jpeg', 'tiff', 'svg'] + args_key = 'animation.html_args' + + @classmethod + def isAvailable(cls): + return True + + def __init__(self, fps=30, codec=None, bitrate=None, extra_args=None, + metadata=None, embed_frames=False, default_mode='loop', + embed_limit=None): + self.embed_frames = embed_frames + self.default_mode = default_mode.lower() + + # Save embed limit, which is given in MB + if embed_limit is None: + self._bytes_limit = rcParams['animation.embed_limit'] + else: + self._bytes_limit = embed_limit + + # Convert from MB to bytes + self._bytes_limit *= 1024 * 1024 + + if self.default_mode not in ['loop', 'once', 'reflect']: + self.default_mode = 'loop' + _log.warning("unrecognized default_mode: using 'loop'") + + self._saved_frames = [] + self._total_bytes = 0 + self._hit_limit = False + super(HTMLWriter, self).__init__(fps, codec, bitrate, + extra_args, metadata) + + def setup(self, fig, outfile, dpi, frame_dir=None): + root, ext = os.path.splitext(outfile) + if ext not in ['.html', '.htm']: + raise ValueError("outfile must be *.htm or *.html") + + if not self.embed_frames: + if frame_dir is None: + frame_dir = root + '_frames' + if not os.path.exists(frame_dir): + os.makedirs(frame_dir) + frame_prefix = os.path.join(frame_dir, 'frame') + else: + frame_prefix = None + + super(HTMLWriter, self).setup(fig, outfile, dpi, + frame_prefix, clear_temp=False) + + def grab_frame(self, **savefig_kwargs): + if self.embed_frames: + # Just stop processing if we hit the limit + if self._hit_limit: + return + suffix = '.' + self.frame_format + f = BytesIO() + self.fig.savefig(f, format=self.frame_format, + dpi=self.dpi, **savefig_kwargs) + imgdata64 = encodebytes(f.getvalue()).decode('ascii') + self._total_bytes += len(imgdata64) + if self._total_bytes >= self._bytes_limit: + _log.warning( + "Animation size has reached %s bytes, exceeding the limit " + "of %s. If you're sure you want a larger animation " + "embedded, set the animation.embed_limit rc parameter to " + "a larger value (in MB). This and further frames will be " + "dropped.", self._total_bytes, self._bytes_limit) + self._hit_limit = True + else: + self._saved_frames.append(imgdata64) + else: + return super(HTMLWriter, self).grab_frame(**savefig_kwargs) + + def _run(self): + # make a duck-typed subprocess stand in + # this is called by the MovieWriter base class, but not used here. + class ProcessStandin(object): + returncode = 0 + + def communicate(self): + return '', '' + + self._proc = ProcessStandin() + + # save the frames to an html file + if self.embed_frames: + fill_frames = _embedded_frames(self._saved_frames, + self.frame_format) + else: + # temp names is filled by FileMovieWriter + fill_frames = _included_frames(self._temp_names, + self.frame_format) + + mode_dict = dict(once_checked='', + loop_checked='', + reflect_checked='') + mode_dict[self.default_mode + '_checked'] = 'checked' + + interval = 1000 // self.fps + + with open(self.outfile, 'w') as of: + of.write(JS_INCLUDE) + of.write(DISPLAY_TEMPLATE.format(id=uuid.uuid4().hex, + Nframes=len(self._temp_names), + fill_frames=fill_frames, + interval=interval, + **mode_dict)) + + +class Animation(object): + '''This class wraps the creation of an animation using matplotlib. + + It is only a base class which should be subclassed to provide + needed behavior. + + This class is not typically used directly. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + event_source : object, optional + A class that can run a callback when desired events + are generated, as well as be stopped and started. + + Examples include timers (see :class:`TimedAnimation`) and file + system notifications. + + blit : bool, optional + controls whether blitting is used to optimize drawing. Defaults + to ``False``. + + See Also + -------- + FuncAnimation, ArtistAnimation + + ''' + def __init__(self, fig, event_source=None, blit=False): + self._fig = fig + # Disables blitting for backends that don't support it. This + # allows users to request it if available, but still have a + # fallback that works if it is not. + self._blit = blit and fig.canvas.supports_blit + + # These are the basics of the animation. The frame sequence represents + # information for each frame of the animation and depends on how the + # drawing is handled by the subclasses. The event source fires events + # that cause the frame sequence to be iterated. + self.frame_seq = self.new_frame_seq() + self.event_source = event_source + + # Instead of starting the event source now, we connect to the figure's + # draw_event, so that we only start once the figure has been drawn. + self._first_draw_id = fig.canvas.mpl_connect('draw_event', self._start) + + # Connect to the figure's close_event so that we don't continue to + # fire events and try to draw to a deleted figure. + self._close_id = self._fig.canvas.mpl_connect('close_event', + self._stop) + if self._blit: + self._setup_blit() + + def _start(self, *args): + ''' + Starts interactive animation. Adds the draw frame command to the GUI + handler, calls show to start the event loop. + ''' + # First disconnect our draw event handler + self._fig.canvas.mpl_disconnect(self._first_draw_id) + self._first_draw_id = None # So we can check on save + + # Now do any initial draw + self._init_draw() + + # Add our callback for stepping the animation and + # actually start the event_source. + self.event_source.add_callback(self._step) + self.event_source.start() + + def _stop(self, *args): + # On stop we disconnect all of our events. + if self._blit: + self._fig.canvas.mpl_disconnect(self._resize_id) + self._fig.canvas.mpl_disconnect(self._close_id) + self.event_source.remove_callback(self._step) + self.event_source = None + + def save(self, filename, writer=None, fps=None, dpi=None, codec=None, + bitrate=None, extra_args=None, metadata=None, extra_anim=None, + savefig_kwargs=None): + '''Saves a movie file by drawing every frame. + + Parameters + ---------- + + filename : str + The output filename, e.g., :file:`mymovie.mp4`. + + writer : :class:`MovieWriter` or str, optional + A `MovieWriter` instance to use or a key that identifies a + class to use, such as 'ffmpeg'. If ``None``, defaults to + :rc:`animation.writer`. + + fps : number, optional + Frames per second in the movie. Defaults to ``None``, which will use + the animation's specified interval to set the frames per second. + + dpi : number, optional + Controls the dots per inch for the movie frames. This combined with + the figure's size in inches controls the size of the movie. If + ``None``, defaults to :rc:`savefig.dpi`. + + codec : str, optional + The video codec to be used. Not all codecs are supported + by a given :class:`MovieWriter`. If ``None``, default to + :rc:`animation.codec`. + + bitrate : number, optional + Specifies the number of bits used per second in the compressed + movie, in kilobits per second. A higher number means a higher + quality movie, but at the cost of increased file size. If ``None``, + defaults to :rc:`animation.bitrate`. + + extra_args : list, optional + List of extra string arguments to be passed to the underlying movie + utility. If ``None``, defaults to :rc:`animation.extra_args`. + + metadata : Dict[str, str], optional + Dictionary of keys and values for metadata to include in + the output file. Some keys that may be of use include: + title, artist, genre, subject, copyright, srcform, comment. + + extra_anim : list, optional + Additional `Animation` objects that should be included + in the saved movie file. These need to be from the same + `matplotlib.figure.Figure` instance. Also, animation frames will + just be simply combined, so there should be a 1:1 correspondence + between the frames from the different animations. + + savefig_kwargs : dict, optional + Is a dictionary containing keyword arguments to be passed + on to the `savefig` command which is called repeatedly to + save the individual frames. + + Notes + ----- + fps, codec, bitrate, extra_args, metadata are used to + construct a :class:`MovieWriter` instance and can only be + passed if `writer` is a string. If they are passed as + non-`None` and ``writer`` is a :class:`MovieWriter`, a + `RuntimeError` will be raised. + + ''' + # If the writer is None, use the rc param to find the name of the one + # to use + if writer is None: + writer = rcParams['animation.writer'] + elif (not isinstance(writer, six.string_types) and + any(arg is not None + for arg in (fps, codec, bitrate, extra_args, metadata))): + raise RuntimeError('Passing in values for arguments ' + 'fps, codec, bitrate, extra_args, or metadata ' + 'is not supported when writer is an existing ' + 'MovieWriter instance. These should instead be ' + 'passed as arguments when creating the ' + 'MovieWriter instance.') + + if savefig_kwargs is None: + savefig_kwargs = {} + + # Need to disconnect the first draw callback, since we'll be doing + # draws. Otherwise, we'll end up starting the animation. + if self._first_draw_id is not None: + self._fig.canvas.mpl_disconnect(self._first_draw_id) + reconnect_first_draw = True + else: + reconnect_first_draw = False + + if fps is None and hasattr(self, '_interval'): + # Convert interval in ms to frames per second + fps = 1000. / self._interval + + # Re-use the savefig DPI for ours if none is given + if dpi is None: + dpi = rcParams['savefig.dpi'] + if dpi == 'figure': + dpi = self._fig.dpi + + if codec is None: + codec = rcParams['animation.codec'] + + if bitrate is None: + bitrate = rcParams['animation.bitrate'] + + all_anim = [self] + if extra_anim is not None: + all_anim.extend(anim + for anim + in extra_anim if anim._fig is self._fig) + + # If we have the name of a writer, instantiate an instance of the + # registered class. + if isinstance(writer, six.string_types): + if writer in writers.avail: + writer = writers[writer](fps, codec, bitrate, + extra_args=extra_args, + metadata=metadata) + else: + _log.warning("MovieWriter %s unavailable.", writer) + + try: + writer = writers[writers.list()[0]](fps, codec, bitrate, + extra_args=extra_args, + metadata=metadata) + except IndexError: + raise ValueError("Cannot save animation: no writers are " + "available. Please install ffmpeg to " + "save animations.") + _log.info('Animation.save using %s', type(writer)) + + if 'bbox_inches' in savefig_kwargs: + _log.warning("Warning: discarding the 'bbox_inches' argument in " + "'savefig_kwargs' as it may cause frame size " + "to vary, which is inappropriate for animation.") + savefig_kwargs.pop('bbox_inches') + + # Create a new sequence of frames for saved data. This is different + # from new_frame_seq() to give the ability to save 'live' generated + # frame information to be saved later. + # TODO: Right now, after closing the figure, saving a movie won't work + # since GUI widgets are gone. Either need to remove extra code to + # allow for this non-existent use case or find a way to make it work. + with rc_context(): + if rcParams['savefig.bbox'] == 'tight': + _log.info("Disabling savefig.bbox = 'tight', as it may cause " + "frame size to vary, which is inappropriate for " + "animation.") + rcParams['savefig.bbox'] = None + with writer.saving(self._fig, filename, dpi): + for anim in all_anim: + # Clear the initial frame + anim._init_draw() + for data in zip(*[a.new_saved_frame_seq() for a in all_anim]): + for anim, d in zip(all_anim, data): + # TODO: See if turning off blit is really necessary + anim._draw_next_frame(d, blit=False) + writer.grab_frame(**savefig_kwargs) + + # Reconnect signal for first draw if necessary + if reconnect_first_draw: + self._first_draw_id = self._fig.canvas.mpl_connect('draw_event', + self._start) + + def _step(self, *args): + ''' + Handler for getting events. By default, gets the next frame in the + sequence and hands the data off to be drawn. + ''' + # Returns True to indicate that the event source should continue to + # call _step, until the frame sequence reaches the end of iteration, + # at which point False will be returned. + try: + framedata = next(self.frame_seq) + self._draw_next_frame(framedata, self._blit) + return True + except StopIteration: + return False + + def new_frame_seq(self): + '''Creates a new sequence of frame information.''' + # Default implementation is just an iterator over self._framedata + return iter(self._framedata) + + def new_saved_frame_seq(self): + '''Creates a new sequence of saved/cached frame information.''' + # Default is the same as the regular frame sequence + return self.new_frame_seq() + + def _draw_next_frame(self, framedata, blit): + # Breaks down the drawing of the next frame into steps of pre- and + # post- draw, as well as the drawing of the frame itself. + self._pre_draw(framedata, blit) + self._draw_frame(framedata) + self._post_draw(framedata, blit) + + def _init_draw(self): + # Initial draw to clear the frame. Also used by the blitting code + # when a clean base is required. + pass + + def _pre_draw(self, framedata, blit): + # Perform any cleaning or whatnot before the drawing of the frame. + # This default implementation allows blit to clear the frame. + if blit: + self._blit_clear(self._drawn_artists, self._blit_cache) + + def _draw_frame(self, framedata): + # Performs actual drawing of the frame. + raise NotImplementedError('Needs to be implemented by subclasses to' + ' actually make an animation.') + + def _post_draw(self, framedata, blit): + # After the frame is rendered, this handles the actual flushing of + # the draw, which can be a direct draw_idle() or make use of the + # blitting. + if blit and self._drawn_artists: + self._blit_draw(self._drawn_artists, self._blit_cache) + else: + self._fig.canvas.draw_idle() + + # The rest of the code in this class is to facilitate easy blitting + def _blit_draw(self, artists, bg_cache): + # Handles blitted drawing, which renders only the artists given instead + # of the entire figure. + updated_ax = [] + for a in artists: + # If we haven't cached the background for this axes object, do + # so now. This might not always be reliable, but it's an attempt + # to automate the process. + if a.axes not in bg_cache: + bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox) + a.axes.draw_artist(a) + updated_ax.append(a.axes) + + # After rendering all the needed artists, blit each axes individually. + for ax in set(updated_ax): + ax.figure.canvas.blit(ax.bbox) + + def _blit_clear(self, artists, bg_cache): + # Get a list of the axes that need clearing from the artists that + # have been drawn. Grab the appropriate saved background from the + # cache and restore. + axes = set(a.axes for a in artists) + for a in axes: + if a in bg_cache: + a.figure.canvas.restore_region(bg_cache[a]) + + def _setup_blit(self): + # Setting up the blit requires: a cache of the background for the + # axes + self._blit_cache = dict() + self._drawn_artists = [] + self._resize_id = self._fig.canvas.mpl_connect('resize_event', + self._handle_resize) + self._post_draw(None, self._blit) + + def _handle_resize(self, *args): + # On resize, we need to disable the resize event handling so we don't + # get too many events. Also stop the animation events, so that + # we're paused. Reset the cache and re-init. Set up an event handler + # to catch once the draw has actually taken place. + self._fig.canvas.mpl_disconnect(self._resize_id) + self.event_source.stop() + self._blit_cache.clear() + self._init_draw() + self._resize_id = self._fig.canvas.mpl_connect('draw_event', + self._end_redraw) + + def _end_redraw(self, evt): + # Now that the redraw has happened, do the post draw flushing and + # blit handling. Then re-enable all of the original events. + self._post_draw(None, False) + self.event_source.start() + self._fig.canvas.mpl_disconnect(self._resize_id) + self._resize_id = self._fig.canvas.mpl_connect('resize_event', + self._handle_resize) + + def to_html5_video(self, embed_limit=None): + '''Returns animation as an HTML5 video tag. + + This saves the animation as an h264 video, encoded in base64 + directly into the HTML5 video tag. This respects the rc parameters + for the writer as well as the bitrate. This also makes use of the + ``interval`` to control the speed, and uses the ``repeat`` + parameter to decide whether to loop. + ''' + VIDEO_TAG = r'''''' + # Cache the rendering of the video as HTML + if not hasattr(self, '_base64_video'): + # Save embed limit, which is given in MB + if embed_limit is None: + embed_limit = rcParams['animation.embed_limit'] + + # Convert from MB to bytes + embed_limit *= 1024 * 1024 + + # First write the video to a tempfile. Set delete to False + # so we can re-open to read binary data. + with tempfile.NamedTemporaryFile(suffix='.m4v', + delete=False) as f: + # We create a writer manually so that we can get the + # appropriate size for the tag + Writer = writers[rcParams['animation.writer']] + writer = Writer(codec='h264', + bitrate=rcParams['animation.bitrate'], + fps=1000. / self._interval) + self.save(f.name, writer=writer) + + # Now open and base64 encode + with open(f.name, 'rb') as video: + vid64 = encodebytes(video.read()) + vid_len = len(vid64) + if vid_len >= embed_limit: + _log.warning( + "Animation movie is %s bytes, exceeding the limit of " + "%s. If you're sure you want a large animation " + "embedded, set the animation.embed_limit rc parameter " + "to a larger value (in MB).", vid_len, embed_limit) + else: + self._base64_video = vid64.decode('ascii') + self._video_size = 'width="{}" height="{}"'.format( + *writer.frame_size) + + # Now we can remove + os.remove(f.name) + + # If we exceeded the size, this attribute won't exist + if hasattr(self, '_base64_video'): + # Default HTML5 options are to autoplay and display video controls + options = ['controls', 'autoplay'] + + # If we're set to repeat, make it loop + if hasattr(self, 'repeat') and self.repeat: + options.append('loop') + + return VIDEO_TAG.format(video=self._base64_video, + size=self._video_size, + options=' '.join(options)) + else: + return 'Video too large to embed.' + + def to_jshtml(self, fps=None, embed_frames=True, default_mode=None): + """Generate HTML representation of the animation""" + if fps is None and hasattr(self, '_interval'): + # Convert interval in ms to frames per second + fps = 1000 / self._interval + + # If we're not given a default mode, choose one base on the value of + # the repeat attribute + if default_mode is None: + default_mode = 'loop' if self.repeat else 'once' + + if hasattr(self, "_html_representation"): + return self._html_representation + else: + # Can't open a second time while opened on windows. So we avoid + # deleting when closed, and delete manually later. + with tempfile.NamedTemporaryFile(suffix='.html', + delete=False) as f: + self.save(f.name, writer=HTMLWriter(fps=fps, + embed_frames=embed_frames, + default_mode=default_mode)) + # Re-open and get content + with open(f.name) as fobj: + html = fobj.read() + + # Now we can delete + os.remove(f.name) + + self._html_representation = html + return html + + def _repr_html_(self): + '''IPython display hook for rendering.''' + fmt = rcParams['animation.html'] + if fmt == 'html5': + return self.to_html5_video() + elif fmt == 'jshtml': + return self.to_jshtml() + + +class TimedAnimation(Animation): + ''':class:`Animation` subclass for time-based animation. + + A new frame is drawn every *interval* milliseconds. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + interval : number, optional + Delay between frames in milliseconds. Defaults to 200. + + repeat_delay : number, optional + If the animation in repeated, adds a delay in milliseconds + before repeating the animation. Defaults to ``None``. + + repeat : bool, optional + Controls whether the animation should repeat when the sequence + of frames is completed. Defaults to ``True``. + + blit : bool, optional + Controls whether blitting is used to optimize drawing. Defaults + to ``False``. + + ''' + def __init__(self, fig, interval=200, repeat_delay=None, repeat=True, + event_source=None, *args, **kwargs): + # Store the timing information + self._interval = interval + self._repeat_delay = repeat_delay + self.repeat = repeat + + # If we're not given an event source, create a new timer. This permits + # sharing timers between animation objects for syncing animations. + if event_source is None: + event_source = fig.canvas.new_timer() + event_source.interval = self._interval + + Animation.__init__(self, fig, event_source=event_source, + *args, **kwargs) + + def _step(self, *args): + ''' + Handler for getting events. + ''' + # Extends the _step() method for the Animation class. If + # Animation._step signals that it reached the end and we want to + # repeat, we refresh the frame sequence and return True. If + # _repeat_delay is set, change the event_source's interval to our loop + # delay and set the callback to one which will then set the interval + # back. + still_going = Animation._step(self, *args) + if not still_going and self.repeat: + self._init_draw() + self.frame_seq = self.new_frame_seq() + if self._repeat_delay: + self.event_source.remove_callback(self._step) + self.event_source.add_callback(self._loop_delay) + self.event_source.interval = self._repeat_delay + return True + else: + return Animation._step(self, *args) + else: + return still_going + + def _stop(self, *args): + # If we stop in the middle of a loop delay (which is relatively likely + # given the potential pause here, remove the loop_delay callback as + # well. + self.event_source.remove_callback(self._loop_delay) + Animation._stop(self) + + def _loop_delay(self, *args): + # Reset the interval and change callbacks after the delay. + self.event_source.remove_callback(self._loop_delay) + self.event_source.interval = self._interval + self.event_source.add_callback(self._step) + Animation._step(self) + + +class ArtistAnimation(TimedAnimation): + '''Animation using a fixed set of `Artist` objects. + + Before creating an instance, all plotting should have taken place + and the relevant artists saved. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + artists : list + Each list entry a collection of artists that represent what + needs to be enabled on each frame. These will be disabled for + other frames. + + interval : number, optional + Delay between frames in milliseconds. Defaults to 200. + + repeat_delay : number, optional + If the animation in repeated, adds a delay in milliseconds + before repeating the animation. Defaults to ``None``. + + repeat : bool, optional + Controls whether the animation should repeat when the sequence + of frames is completed. Defaults to ``True``. + + blit : bool, optional + Controls whether blitting is used to optimize drawing. Defaults + to ``False``. + + ''' + def __init__(self, fig, artists, *args, **kwargs): + # Internal list of artists drawn in the most recent frame. + self._drawn_artists = [] + + # Use the list of artists as the framedata, which will be iterated + # over by the machinery. + self._framedata = artists + TimedAnimation.__init__(self, fig, *args, **kwargs) + + def _init_draw(self): + # Make all the artists involved in *any* frame invisible + figs = set() + for f in self.new_frame_seq(): + for artist in f: + artist.set_visible(False) + artist.set_animated(self._blit) + # Assemble a list of unique figures that need flushing + if artist.get_figure() not in figs: + figs.add(artist.get_figure()) + + # Flush the needed figures + for fig in figs: + fig.canvas.draw_idle() + + def _pre_draw(self, framedata, blit): + ''' + Clears artists from the last frame. + ''' + if blit: + # Let blit handle clearing + self._blit_clear(self._drawn_artists, self._blit_cache) + else: + # Otherwise, make all the artists from the previous frame invisible + for artist in self._drawn_artists: + artist.set_visible(False) + + def _draw_frame(self, artists): + # Save the artists that were passed in as framedata for the other + # steps (esp. blitting) to use. + self._drawn_artists = artists + + # Make all the artists from the current frame visible + for artist in artists: + artist.set_visible(True) + + +class FuncAnimation(TimedAnimation): + ''' + Makes an animation by repeatedly calling a function ``func``. + + Parameters + ---------- + fig : matplotlib.figure.Figure + The figure object that is used to get draw, resize, and any + other needed events. + + func : callable + The function to call at each frame. The first argument will + be the next value in ``frames``. Any additional positional + arguments can be supplied via the ``fargs`` parameter. + + The required signature is:: + + def func(frame, *fargs) -> iterable_of_artists: + + frames : iterable, int, generator function, or None, optional + Source of data to pass ``func`` and each frame of the animation + + If an iterable, then simply use the values provided. If the + iterable has a length, it will override the ``save_count`` kwarg. + + If an integer, then equivalent to passing ``range(frames)`` + + If a generator function, then must have the signature:: + + def gen_function() -> obj: + + If ``None``, then equivalent to passing ``itertools.count``. + + In all of these cases, the values in *frames* is simply passed through + to the user-supplied *func* and thus can be of any type. + + init_func : callable, optional + A function used to draw a clear frame. If not given, the + results of drawing from the first item in the frames sequence + will be used. This function will be called once before the + first frame. + + If ``blit == True``, ``init_func`` must return an iterable of artists + to be re-drawn. + + The required signature is:: + + def init_func() -> iterable_of_artists: + + fargs : tuple or None, optional + Additional arguments to pass to each call to *func*. + + save_count : int, optional + The number of values from *frames* to cache. + + interval : number, optional + Delay between frames in milliseconds. Defaults to 200. + + repeat_delay : number, optional + If the animation in repeated, adds a delay in milliseconds + before repeating the animation. Defaults to ``None``. + + repeat : bool, optional + Controls whether the animation should repeat when the sequence + of frames is completed. Defaults to ``True``. + + blit : bool, optional + Controls whether blitting is used to optimize drawing. Defaults + to ``False``. + + ''' + def __init__(self, fig, func, frames=None, init_func=None, fargs=None, + save_count=None, **kwargs): + if fargs: + self._args = fargs + else: + self._args = () + self._func = func + + # Amount of framedata to keep around for saving movies. This is only + # used if we don't know how many frames there will be: in the case + # of no generator or in the case of a callable. + self.save_count = save_count + # Set up a function that creates a new iterable when needed. If nothing + # is passed in for frames, just use itertools.count, which will just + # keep counting from 0. A callable passed in for frames is assumed to + # be a generator. An iterable will be used as is, and anything else + # will be treated as a number of frames. + if frames is None: + self._iter_gen = itertools.count + elif callable(frames): + self._iter_gen = frames + elif cbook.iterable(frames): + self._iter_gen = lambda: iter(frames) + if hasattr(frames, '__len__'): + self.save_count = len(frames) + else: + self._iter_gen = lambda: iter(xrange(frames)) + self.save_count = frames + + if self.save_count is None: + # If we're passed in and using the default, set save_count to 100. + self.save_count = 100 + else: + # itertools.islice returns an error when passed a numpy int instead + # of a native python int (http://bugs.python.org/issue30537). + # As a workaround, convert save_count to a native python int. + self.save_count = int(self.save_count) + + self._init_func = init_func + + # Needs to be initialized so the draw functions work without checking + self._save_seq = [] + + TimedAnimation.__init__(self, fig, **kwargs) + + # Need to reset the saved seq, since right now it will contain data + # for a single frame from init, which is not what we want. + self._save_seq = [] + + def new_frame_seq(self): + # Use the generating function to generate a new frame sequence + return self._iter_gen() + + def new_saved_frame_seq(self): + # Generate an iterator for the sequence of saved data. If there are + # no saved frames, generate a new frame sequence and take the first + # save_count entries in it. + if self._save_seq: + # While iterating we are going to update _save_seq + # so make a copy to safely iterate over + self._old_saved_seq = list(self._save_seq) + return iter(self._old_saved_seq) + else: + if self.save_count is not None: + return itertools.islice(self.new_frame_seq(), self.save_count) + + else: + frame_seq = self.new_frame_seq() + + def gen(): + try: + for _ in range(100): + yield next(frame_seq) + except StopIteration: + pass + else: + cbook.warn_deprecated( + "2.2", "FuncAnimation.save has truncated your " + "animation to 100 frames. In the future, no such " + "truncation will occur; please pass 'save_count' " + "accordingly.") + + return gen() + + def _init_draw(self): + # Initialize the drawing either using the given init_func or by + # calling the draw function with the first item of the frame sequence. + # For blitting, the init_func should return a sequence of modified + # artists. + if self._init_func is None: + self._draw_frame(next(self.new_frame_seq())) + + else: + self._drawn_artists = self._init_func() + if self._blit: + if self._drawn_artists is None: + raise RuntimeError('The init_func must return a ' + 'sequence of Artist objects.') + for a in self._drawn_artists: + a.set_animated(self._blit) + self._save_seq = [] + + def _draw_frame(self, framedata): + # Save the data for potential saving of movies. + self._save_seq.append(framedata) + + # Make sure to respect save_count (keep only the last save_count + # around) + self._save_seq = self._save_seq[-self.save_count:] + + # Call the func with framedata and args. If blitting is desired, + # func needs to return a sequence of any artists that were modified. + self._drawn_artists = self._func(framedata, *self._args) + if self._blit: + if self._drawn_artists is None: + raise RuntimeError('The animation function must return a ' + 'sequence of Artist objects.') + for a in self._drawn_artists: + a.set_animated(self._blit) diff --git a/contrib/python/matplotlib/py2/matplotlib/artist.py b/contrib/python/matplotlib/py2/matplotlib/artist.py new file mode 100644 index 00000000000..8dc1034bc70 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/artist.py @@ -0,0 +1,1482 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from collections import OrderedDict, namedtuple +from functools import wraps +import inspect +import re +import warnings + +import numpy as np + +import matplotlib +from . import cbook, docstring, rcParams +from .path import Path +from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox, + TransformedPatchPath, TransformedPath) +# Note, matplotlib artists use the doc strings for set and get +# methods to enable the introspection methods of setp and getp. Every +# set_* method should have a docstring containing the line +# +# ACCEPTS: [ legal | values ] +# +# and aliases for setters and getters should have a docstring that +# starts with 'alias for ', as in 'alias for set_somemethod' +# +# You may wonder why we use so much boiler-plate manually defining the +# set_alias and get_alias functions, rather than using some clever +# python trick. The answer is that I need to be able to manipulate +# the docstring, and there is no clever way to do that in python 2.2, +# as far as I can see - see +# +# https://mail.python.org/pipermail/python-list/2004-October/242925.html + + +def allow_rasterization(draw): + """ + Decorator for Artist.draw method. Provides routines + that run before and after the draw call. The before and after functions + are useful for changing artist-dependent renderer attributes or making + other setup function calls, such as starting and flushing a mixed-mode + renderer. + """ + + # the axes class has a second argument inframe for its draw method. + @wraps(draw) + def draw_wrapper(artist, renderer, *args, **kwargs): + try: + if artist.get_rasterized(): + renderer.start_rasterizing() + if artist.get_agg_filter() is not None: + renderer.start_filter() + + return draw(artist, renderer, *args, **kwargs) + finally: + if artist.get_agg_filter() is not None: + renderer.stop_filter(artist.get_agg_filter()) + if artist.get_rasterized(): + renderer.stop_rasterizing() + + draw_wrapper._supports_rasterization = True + return draw_wrapper + + +def _stale_axes_callback(self, val): + if self.axes: + self.axes.stale = val + + +_XYPair = namedtuple("_XYPair", "x y") + + +class Artist(object): + """ + Abstract base class for someone who renders into a + :class:`FigureCanvas`. + """ + + aname = 'Artist' + zorder = 0 + # order of precedence when bulk setting/updating properties + # via update. The keys should be property names and the values + # integers + _prop_order = dict(color=-1) + + def __init__(self): + self._stale = True + self.stale_callback = None + self._axes = None + self.figure = None + + self._transform = None + self._transformSet = False + self._visible = True + self._animated = False + self._alpha = None + self.clipbox = None + self._clippath = None + self._clipon = True + self._label = '' + self._picker = None + self._contains = None + self._rasterized = None + self._agg_filter = None + self._mouseover = False + self.eventson = False # fire events only if eventson + self._oid = 0 # an observer id + self._propobservers = {} # a dict from oids to funcs + try: + self.axes = None + except AttributeError: + # Handle self.axes as a read-only property, as in Figure. + pass + self._remove_method = None + self._url = None + self._gid = None + self._snap = None + self._sketch = rcParams['path.sketch'] + self._path_effects = rcParams['path.effects'] + self._sticky_edges = _XYPair([], []) + + def __getstate__(self): + d = self.__dict__.copy() + # remove the unpicklable remove method, this will get re-added on load + # (by the axes) if the artist lives on an axes. + d['_remove_method'] = None + d['stale_callback'] = None + return d + + def remove(self): + """ + Remove the artist from the figure if possible. The effect + will not be visible until the figure is redrawn, e.g., with + :meth:`matplotlib.axes.Axes.draw_idle`. Call + :meth:`matplotlib.axes.Axes.relim` to update the axes limits + if desired. + + Note: :meth:`~matplotlib.axes.Axes.relim` will not see + collections even if the collection was added to axes with + *autolim* = True. + + Note: there is no support for removing the artist's legend entry. + """ + + # There is no method to set the callback. Instead the parent should + # set the _remove_method attribute directly. This would be a + # protected attribute if Python supported that sort of thing. The + # callback has one parameter, which is the child to be removed. + if self._remove_method is not None: + self._remove_method(self) + # clear stale callback + self.stale_callback = None + _ax_flag = False + if hasattr(self, 'axes') and self.axes: + # remove from the mouse hit list + self.axes.mouseover_set.discard(self) + # mark the axes as stale + self.axes.stale = True + # decouple the artist from the axes + self.axes = None + _ax_flag = True + + if self.figure: + self.figure = None + if not _ax_flag: + self.figure = True + + else: + raise NotImplementedError('cannot remove artist') + # TODO: the fix for the collections relim problem is to move the + # limits calculation into the artist itself, including the property of + # whether or not the artist should affect the limits. Then there will + # be no distinction between axes.add_line, axes.add_patch, etc. + # TODO: add legend support + + def have_units(self): + 'Return *True* if units are set on the *x* or *y* axes' + ax = self.axes + if ax is None or ax.xaxis is None: + return False + return ax.xaxis.have_units() or ax.yaxis.have_units() + + def convert_xunits(self, x): + """For artists in an axes, if the xaxis has units support, + convert *x* using xaxis unit type + """ + ax = getattr(self, 'axes', None) + if ax is None or ax.xaxis is None: + return x + return ax.xaxis.convert_units(x) + + def convert_yunits(self, y): + """For artists in an axes, if the yaxis has units support, + convert *y* using yaxis unit type + """ + ax = getattr(self, 'axes', None) + if ax is None or ax.yaxis is None: + return y + return ax.yaxis.convert_units(y) + + @property + def axes(self): + """ + The :class:`~matplotlib.axes.Axes` instance the artist + resides in, or *None*. + """ + return self._axes + + @axes.setter + def axes(self, new_axes): + if (new_axes is not None and self._axes is not None + and new_axes != self._axes): + raise ValueError("Can not reset the axes. You are probably " + "trying to re-use an artist in more than one " + "Axes which is not supported") + self._axes = new_axes + if new_axes is not None and new_axes is not self: + self.stale_callback = _stale_axes_callback + return new_axes + + @property + def stale(self): + """ + If the artist is 'stale' and needs to be re-drawn for the output to + match the internal state of the artist. + """ + return self._stale + + @stale.setter + def stale(self, val): + self._stale = val + + # if the artist is animated it does not take normal part in the + # draw stack and is not expected to be drawn as part of the normal + # draw loop (when not saving) so do not propagate this change + if self.get_animated(): + return + + if val and self.stale_callback is not None: + self.stale_callback(self, val) + + def get_window_extent(self, renderer): + """ + Get the axes bounding box in display space. + Subclasses should override for inclusion in the bounding box + "tight" calculation. Default is to return an empty bounding + box at 0, 0. + + Be careful when using this function, the results will not update + if the artist window extent of the artist changes. The extent + can change due to any changes in the transform stack, such as + changing the axes limits, the figure size, or the canvas used + (as is done when saving a figure). This can lead to unexpected + behavior where interactive figures will look fine on the screen, + but will save incorrectly. + """ + return Bbox([[0, 0], [0, 0]]) + + def add_callback(self, func): + """ + Adds a callback function that will be called whenever one of + the :class:`Artist`'s properties changes. + + Returns an *id* that is useful for removing the callback with + :meth:`remove_callback` later. + """ + oid = self._oid + self._propobservers[oid] = func + self._oid += 1 + return oid + + def remove_callback(self, oid): + """ + Remove a callback based on its *id*. + + .. seealso:: + + :meth:`add_callback` + For adding callbacks + + """ + try: + del self._propobservers[oid] + except KeyError: + pass + + def pchanged(self): + """ + Fire an event when property changed, calling all of the + registered callbacks. + """ + for oid, func in six.iteritems(self._propobservers): + func(self) + + def is_transform_set(self): + """ + Returns *True* if :class:`Artist` has a transform explicitly + set. + """ + return self._transformSet + + def set_transform(self, t): + """ + Set the artist transform. + + Parameters + ---------- + t : `.Transform` + .. ACCEPTS: `.Transform` + """ + self._transform = t + self._transformSet = True + self.pchanged() + self.stale = True + + def get_transform(self): + """ + Return the :class:`~matplotlib.transforms.Transform` + instance used by this artist. + """ + if self._transform is None: + self._transform = IdentityTransform() + elif (not isinstance(self._transform, Transform) + and hasattr(self._transform, '_as_mpl_transform')): + self._transform = self._transform._as_mpl_transform(self.axes) + return self._transform + + @cbook.deprecated("2.2") + def hitlist(self, event): + """ + List the children of the artist which contain the mouse event *event*. + """ + L = [] + try: + hascursor, info = self.contains(event) + if hascursor: + L.append(self) + except: + import traceback + traceback.print_exc() + print("while checking", self.__class__) + + for a in self.get_children(): + L.extend(a.hitlist(event)) + return L + + def get_children(self): + """ + Return a list of the child :class:`Artist`s this + :class:`Artist` contains. + """ + return [] + + def contains(self, mouseevent): + """Test whether the artist contains the mouse event. + + Returns the truth value and a dictionary of artist specific details of + selection, such as which points are contained in the pick radius. See + individual artists for details. + """ + if callable(self._contains): + return self._contains(self, mouseevent) + warnings.warn("'%s' needs 'contains' method" % self.__class__.__name__) + return False, {} + + def set_contains(self, picker): + """ + Replace the contains test used by this artist. The new picker + should be a callable function which determines whether the + artist is hit by the mouse event:: + + hit, props = picker(artist, mouseevent) + + If the mouse event is over the artist, return *hit* = *True* + and *props* is a dictionary of properties you want returned + with the contains test. + + Parameters + ---------- + picker : callable + .. ACCEPTS: a callable function + """ + self._contains = picker + + def get_contains(self): + """ + Return the _contains test used by the artist, or *None* for default. + """ + return self._contains + + def pickable(self): + 'Return *True* if :class:`Artist` is pickable.' + return (self.figure is not None and + self.figure.canvas is not None and + self._picker is not None) + + def pick(self, mouseevent): + """ + Process pick event + + each child artist will fire a pick event if *mouseevent* is over + the artist and the artist has picker set + """ + # Pick self + if self.pickable(): + picker = self.get_picker() + if callable(picker): + inside, prop = picker(self, mouseevent) + else: + inside, prop = self.contains(mouseevent) + if inside: + self.figure.canvas.pick_event(mouseevent, self, **prop) + + # Pick children + for a in self.get_children(): + # make sure the event happened in the same axes + ax = getattr(a, 'axes', None) + if (mouseevent.inaxes is None or ax is None + or mouseevent.inaxes == ax): + # we need to check if mouseevent.inaxes is None + # because some objects associated with an axes (e.g., a + # tick label) can be outside the bounding box of the + # axes and inaxes will be None + # also check that ax is None so that it traverse objects + # which do no have an axes property but children might + a.pick(mouseevent) + + def set_picker(self, picker): + """ + Set the epsilon for picking used by this artist + + *picker* can be one of the following: + + * *None*: picking is disabled for this artist (default) + + * A boolean: if *True* then picking will be enabled and the + artist will fire a pick event if the mouse event is over + the artist + + * A float: if picker is a number it is interpreted as an + epsilon tolerance in points and the artist will fire + off an event if it's data is within epsilon of the mouse + event. For some artists like lines and patch collections, + the artist may provide additional data to the pick event + that is generated, e.g., the indices of the data within + epsilon of the pick event + + * A function: if picker is callable, it is a user supplied + function which determines whether the artist is hit by the + mouse event:: + + hit, props = picker(artist, mouseevent) + + to determine the hit test. if the mouse event is over the + artist, return *hit=True* and props is a dictionary of + properties you want added to the PickEvent attributes. + + Parameters + ---------- + picker : None or bool or float or callable + .. ACCEPTS: [None | bool | float | callable] + """ + self._picker = picker + + def get_picker(self): + """Return the picker object used by this artist.""" + return self._picker + + @cbook.deprecated("2.2", "artist.figure is not None") + def is_figure_set(self): + """Returns whether the artist is assigned to a `.Figure`.""" + return self.figure is not None + + def get_url(self): + """Returns the url.""" + return self._url + + def set_url(self, url): + """ + Sets the url for the artist. + + Parameters + ---------- + url : str + .. ACCEPTS: a url string + """ + self._url = url + + def get_gid(self): + """Returns the group id.""" + return self._gid + + def set_gid(self, gid): + """ + Sets the (group) id for the artist. + + Parameters + ---------- + gid : str + .. ACCEPTS: an id string + """ + self._gid = gid + + def get_snap(self): + """ + Returns the snap setting which may be: + + * True: snap vertices to the nearest pixel center + + * False: leave vertices as-is + + * None: (auto) If the path contains only rectilinear line + segments, round to the nearest pixel center + + Only supported by the Agg and MacOSX backends. + """ + if rcParams['path.snap']: + return self._snap + else: + return False + + def set_snap(self, snap): + """ + Sets the snap setting which may be: + + * True: snap vertices to the nearest pixel center + + * False: leave vertices as-is + + * None: (auto) If the path contains only rectilinear line + segments, round to the nearest pixel center + + Only supported by the Agg and MacOSX backends. + + Parameters + ---------- + snap : bool or None + .. ACCEPTS: bool or None + """ + self._snap = snap + self.stale = True + + def get_sketch_params(self): + """ + Returns the sketch parameters for the artist. + + Returns + ------- + sketch_params : tuple or `None` + + A 3-tuple with the following elements: + + * `scale`: The amplitude of the wiggle perpendicular to the + source line. + + * `length`: The length of the wiggle along the line. + + * `randomness`: The scale factor by which the length is + shrunken or expanded. + + May return `None` if no sketch parameters were set. + """ + return self._sketch + + def set_sketch_params(self, scale=None, length=None, randomness=None): + """ + Sets the sketch parameters. + + Parameters + ---------- + + scale : float, optional + The amplitude of the wiggle perpendicular to the source + line, in pixels. If scale is `None`, or not provided, no + sketch filter will be provided. + + length : float, optional + The length of the wiggle along the line, in pixels + (default 128.0) + + randomness : float, optional + The scale factor by which the length is shrunken or + expanded (default 16.0) + + .. ACCEPTS: (scale: float, length: float, randomness: float) + """ + if scale is None: + self._sketch = None + else: + self._sketch = (scale, length or 128.0, randomness or 16.0) + self.stale = True + + def set_path_effects(self, path_effects): + """Set the path effects. + + Parameters + ---------- + path_effects : `.AbstractPathEffect` + .. ACCEPTS: `.AbstractPathEffect` + """ + self._path_effects = path_effects + self.stale = True + + def get_path_effects(self): + return self._path_effects + + def get_figure(self): + """Return the `.Figure` instance the artist belongs to.""" + return self.figure + + def set_figure(self, fig): + """ + Set the `.Figure` instance the artist belongs to. + + Parameters + ---------- + fig : `.Figure` + .. ACCEPTS: a `.Figure` instance + """ + # if this is a no-op just return + if self.figure is fig: + return + # if we currently have a figure (the case of both `self.figure` + # and `fig` being none is taken care of above) we then user is + # trying to change the figure an artist is associated with which + # is not allowed for the same reason as adding the same instance + # to more than one Axes + if self.figure is not None: + raise RuntimeError("Can not put single artist in " + "more than one figure") + self.figure = fig + if self.figure and self.figure is not self: + self.pchanged() + self.stale = True + + def set_clip_box(self, clipbox): + """ + Set the artist's clip `.Bbox`. + + Parameters + ---------- + clipbox : `.Bbox` + .. ACCEPTS: a `.Bbox` instance + """ + self.clipbox = clipbox + self.pchanged() + self.stale = True + + def set_clip_path(self, path, transform=None): + """ + Set the artist's clip path, which may be: + + - a :class:`~matplotlib.patches.Patch` (or subclass) instance; or + - a :class:`~matplotlib.path.Path` instance, in which case a + :class:`~matplotlib.transforms.Transform` instance, which will be + applied to the path before using it for clipping, must be provided; + or + - ``None``, to remove a previously set clipping path. + + For efficiency, if the path happens to be an axis-aligned rectangle, + this method will set the clipping box to the corresponding rectangle + and set the clipping path to ``None``. + + ACCEPTS: [(`~matplotlib.path.Path`, `.Transform`) | `.Patch` | None] + """ + from matplotlib.patches import Patch, Rectangle + + success = False + if transform is None: + if isinstance(path, Rectangle): + self.clipbox = TransformedBbox(Bbox.unit(), + path.get_transform()) + self._clippath = None + success = True + elif isinstance(path, Patch): + self._clippath = TransformedPatchPath(path) + success = True + elif isinstance(path, tuple): + path, transform = path + + if path is None: + self._clippath = None + success = True + elif isinstance(path, Path): + self._clippath = TransformedPath(path, transform) + success = True + elif isinstance(path, TransformedPatchPath): + self._clippath = path + success = True + elif isinstance(path, TransformedPath): + self._clippath = path + success = True + + if not success: + raise TypeError( + "Invalid arguments to set_clip_path, of type {} and {}" + .format(type(path).__name__, type(transform).__name__)) + # This may result in the callbacks being hit twice, but guarantees they + # will be hit at least once. + self.pchanged() + self.stale = True + + def get_alpha(self): + """ + Return the alpha value used for blending - not supported on all + backends + """ + return self._alpha + + def get_visible(self): + "Return the artist's visiblity" + return self._visible + + def get_animated(self): + "Return the artist's animated state" + return self._animated + + def get_clip_on(self): + 'Return whether artist uses clipping' + return self._clipon + + def get_clip_box(self): + 'Return artist clipbox' + return self.clipbox + + def get_clip_path(self): + 'Return artist clip path' + return self._clippath + + def get_transformed_clip_path_and_affine(self): + ''' + Return the clip path with the non-affine part of its + transformation applied, and the remaining affine part of its + transformation. + ''' + if self._clippath is not None: + return self._clippath.get_transformed_path_and_affine() + return None, None + + def set_clip_on(self, b): + """ + Set whether artist uses clipping. + + When False artists will be visible out side of the axes which + can lead to unexpected results. + + Parameters + ---------- + b : bool + .. ACCEPTS: bool + """ + self._clipon = b + # This may result in the callbacks being hit twice, but ensures they + # are hit at least once + self.pchanged() + self.stale = True + + def _set_gc_clip(self, gc): + 'Set the clip properly for the gc' + if self._clipon: + if self.clipbox is not None: + gc.set_clip_rectangle(self.clipbox) + gc.set_clip_path(self._clippath) + else: + gc.set_clip_rectangle(None) + gc.set_clip_path(None) + + def get_rasterized(self): + """Return whether the artist is to be rasterized.""" + return self._rasterized + + def set_rasterized(self, rasterized): + """ + Force rasterized (bitmap) drawing in vector backend output. + + Defaults to None, which implies the backend's default behavior. + + Parameters + ---------- + rasterized : bool or None + .. ACCEPTS: bool or None + """ + if rasterized and not hasattr(self.draw, "_supports_rasterization"): + warnings.warn("Rasterization of '%s' will be ignored" % self) + + self._rasterized = rasterized + + def get_agg_filter(self): + """Return filter function to be used for agg filter.""" + return self._agg_filter + + def set_agg_filter(self, filter_func): + """Set the agg filter. + + Parameters + ---------- + filter_func : callable + A filter function, which takes a (m, n, 3) float array and a dpi + value, and returns a (m, n, 3) array. + + .. ACCEPTS: a filter function, which takes a (m, n, 3) float array + and a dpi value, and returns a (m, n, 3) array + """ + self._agg_filter = filter_func + self.stale = True + + def draw(self, renderer, *args, **kwargs): + 'Derived classes drawing method' + if not self.get_visible(): + return + self.stale = False + + def set_alpha(self, alpha): + """ + Set the alpha value used for blending - not supported on + all backends. + + Parameters + ---------- + alpha : float + .. ACCEPTS: float (0.0 transparent through 1.0 opaque) + """ + self._alpha = alpha + self.pchanged() + self.stale = True + + def set_visible(self, b): + """ + Set the artist's visibility. + + Parameters + ---------- + b : bool + .. ACCEPTS: bool + """ + self._visible = b + self.pchanged() + self.stale = True + + def set_animated(self, b): + """ + Set the artist's animation state. + + Parameters + ---------- + b : bool + .. ACCEPTS: bool + """ + if self._animated != b: + self._animated = b + self.pchanged() + + def update(self, props): + """ + Update this artist's properties from the dictionary *prop*. + """ + def _update_property(self, k, v): + """Sorting out how to update property (setter or setattr). + + Parameters + ---------- + k : str + The name of property to update + v : obj + The value to assign to the property + + Returns + ------- + ret : obj or None + If using a `set_*` method return it's return, else None. + """ + k = k.lower() + # white list attributes we want to be able to update through + # art.update, art.set, setp + if k in {'axes'}: + return setattr(self, k, v) + else: + func = getattr(self, 'set_' + k, None) + if not callable(func): + raise AttributeError('Unknown property %s' % k) + return func(v) + + store = self.eventson + self.eventson = False + try: + ret = [_update_property(self, k, v) + for k, v in props.items()] + finally: + self.eventson = store + + if len(ret): + self.pchanged() + self.stale = True + return ret + + def get_label(self): + """Get the label used for this artist in the legend.""" + return self._label + + def set_label(self, s): + """ + Set the label to *s* for auto legend. + + Parameters + ---------- + s : object + *s* will be converted to a string by calling `str` (`unicode` on + Py2). + + .. ACCEPTS: object + """ + if s is not None: + self._label = six.text_type(s) + else: + self._label = None + self.pchanged() + self.stale = True + + def get_zorder(self): + """Return the artist's zorder.""" + return self.zorder + + def set_zorder(self, level): + """ + Set the zorder for the artist. Artists with lower zorder + values are drawn first. + + Parameters + ---------- + level : float + .. ACCEPTS: float + """ + if level is None: + level = self.__class__.zorder + self.zorder = level + self.pchanged() + self.stale = True + + @property + def sticky_edges(self): + """ + `x` and `y` sticky edge lists. + + When performing autoscaling, if a data limit coincides with a value in + the corresponding sticky_edges list, then no margin will be added--the + view limit "sticks" to the edge. A typical usecase is histograms, + where one usually expects no margin on the bottom edge (0) of the + histogram. + + This attribute cannot be assigned to; however, the `x` and `y` lists + can be modified in place as needed. + + Examples + -------- + + >>> artist.sticky_edges.x[:] = (xmin, xmax) + >>> artist.sticky_edges.y[:] = (ymin, ymax) + + """ + return self._sticky_edges + + def update_from(self, other): + 'Copy properties from *other* to *self*.' + self._transform = other._transform + self._transformSet = other._transformSet + self._visible = other._visible + self._alpha = other._alpha + self.clipbox = other.clipbox + self._clipon = other._clipon + self._clippath = other._clippath + self._label = other._label + self._sketch = other._sketch + self._path_effects = other._path_effects + self.sticky_edges.x[:] = other.sticky_edges.x[:] + self.sticky_edges.y[:] = other.sticky_edges.y[:] + self.pchanged() + self.stale = True + + def properties(self): + """ + return a dictionary mapping property name -> value for all Artist props + """ + return ArtistInspector(self).properties() + + def set(self, **kwargs): + """A property batch setter. Pass *kwargs* to set properties. + """ + props = OrderedDict( + sorted(kwargs.items(), reverse=True, + key=lambda x: (self._prop_order.get(x[0], 0), x[0]))) + + return self.update(props) + + def findobj(self, match=None, include_self=True): + """ + Find artist objects. + + Recursively find all :class:`~matplotlib.artist.Artist` instances + contained in self. + + *match* can be + + - None: return all objects contained in artist. + + - function with signature ``boolean = match(artist)`` + used to filter matches + + - class instance: e.g., Line2D. Only return artists of class type. + + If *include_self* is True (default), include self in the list to be + checked for a match. + + """ + if match is None: # always return True + def matchfunc(x): + return True + elif isinstance(match, type) and issubclass(match, Artist): + def matchfunc(x): + return isinstance(x, match) + elif callable(match): + matchfunc = match + else: + raise ValueError('match must be None, a matplotlib.artist.Artist ' + 'subclass, or a callable') + + artists = sum([c.findobj(matchfunc) for c in self.get_children()], []) + if include_self and matchfunc(self): + artists.append(self) + return artists + + def get_cursor_data(self, event): + """ + Get the cursor data for a given event. + """ + return None + + def format_cursor_data(self, data): + """ + Return *cursor data* string formatted. + """ + try: + data[0] + except (TypeError, IndexError): + data = [data] + return ', '.join('{:0.3g}'.format(item) for item in data if + isinstance(item, (np.floating, np.integer, int, float))) + + @property + def mouseover(self): + return self._mouseover + + @mouseover.setter + def mouseover(self, val): + val = bool(val) + self._mouseover = val + ax = self.axes + if ax: + if val: + ax.mouseover_set.add(self) + else: + ax.mouseover_set.discard(self) + + +class ArtistInspector(object): + """ + A helper class to inspect an :class:`~matplotlib.artist.Artist` + and return information about it's settable properties and their + current values. + """ + def __init__(self, o): + r""" + Initialize the artist inspector with an `Artist` or an iterable of + `Artist`\s. If an iterable is used, we assume it is a homogeneous + sequence (all `Artists` are of the same type) and it is your + responsibility to make sure this is so. + """ + if not isinstance(o, Artist): + if cbook.iterable(o): + o = list(o) + if len(o): + o = o[0] + + self.oorig = o + if not inspect.isclass(o): + o = type(o) + self.o = o + + self.aliasd = self.get_aliases() + + def get_aliases(self): + """ + Get a dict mapping *fullname* -> *alias* for each *alias* in + the :class:`~matplotlib.artist.ArtistInspector`. + + e.g., for lines:: + + {'markerfacecolor': 'mfc', + 'linewidth' : 'lw', + } + + """ + names = [name for name in dir(self.o) + if name.startswith(('set_', 'get_')) + and callable(getattr(self.o, name))] + aliases = {} + for name in names: + func = getattr(self.o, name) + if not self.is_alias(func): + continue + docstring = func.__doc__ + fullname = docstring[10:] + aliases.setdefault(fullname[4:], {})[name[4:]] = None + return aliases + + _get_valid_values_regex = re.compile( + r"\n\s*(?:\.\.\s+)?ACCEPTS:\s*((?:.|\n)*?)(?:$|(?:\n\n))" + ) + + def get_valid_values(self, attr): + """ + Get the legal arguments for the setter associated with *attr*. + + This is done by querying the docstring of the function *set_attr* + for a line that begins with "ACCEPTS" or ".. ACCEPTS": + + e.g., for a line linestyle, return + "[ ``'-'`` | ``'--'`` | ``'-.'`` | ``':'`` | ``'steps'`` | ``'None'`` + ]" + """ + + name = 'set_%s' % attr + if not hasattr(self.o, name): + raise AttributeError('%s has no function %s' % (self.o, name)) + func = getattr(self.o, name) + + docstring = func.__doc__ + if docstring is None: + return 'unknown' + + if docstring.startswith('alias for '): + return None + + match = self._get_valid_values_regex.search(docstring) + if match is not None: + return re.sub("\n *", " ", match.group(1)) + return 'unknown' + + def _get_setters_and_targets(self): + """ + Get the attribute strings and a full path to where the setter + is defined for all setters in an object. + """ + + setters = [] + for name in dir(self.o): + if not name.startswith('set_'): + continue + func = getattr(self.o, name) + if not callable(func): + continue + if six.PY2: + nargs = len(inspect.getargspec(func)[0]) + else: + nargs = len(inspect.getfullargspec(func)[0]) + if nargs < 2 or self.is_alias(func): + continue + source_class = self.o.__module__ + "." + self.o.__name__ + for cls in self.o.mro(): + if name in cls.__dict__: + source_class = cls.__module__ + "." + cls.__name__ + break + setters.append((name[4:], source_class + "." + name)) + return setters + + def get_setters(self): + """ + Get the attribute strings with setters for object. e.g., for a line, + return ``['markerfacecolor', 'linewidth', ....]``. + """ + + return [prop for prop, target in self._get_setters_and_targets()] + + def is_alias(self, o): + """ + Return *True* if method object *o* is an alias for another + function. + """ + ds = o.__doc__ + if ds is None: + return False + return ds.startswith('alias for ') + + def aliased_name(self, s): + """ + return 'PROPNAME or alias' if *s* has an alias, else return + PROPNAME. + + e.g., for the line markerfacecolor property, which has an + alias, return 'markerfacecolor or mfc' and for the transform + property, which does not, return 'transform' + """ + + if s in self.aliasd: + return s + ''.join([' or %s' % x + for x in sorted(self.aliasd[s])]) + else: + return s + + def aliased_name_rest(self, s, target): + """ + return 'PROPNAME or alias' if *s* has an alias, else return + PROPNAME formatted for ReST + + e.g., for the line markerfacecolor property, which has an + alias, return 'markerfacecolor or mfc' and for the transform + property, which does not, return 'transform' + """ + + if s in self.aliasd: + aliases = ''.join([' or %s' % x + for x in sorted(self.aliasd[s])]) + else: + aliases = '' + return ':meth:`%s <%s>`%s' % (s, target, aliases) + + def pprint_setters(self, prop=None, leadingspace=2): + """ + If *prop* is *None*, return a list of strings of all settable + properties and their valid values. + + If *prop* is not *None*, it is a valid property name and that + property will be returned as a string of property : valid + values. + """ + if leadingspace: + pad = ' ' * leadingspace + else: + pad = '' + if prop is not None: + accepts = self.get_valid_values(prop) + return '%s%s: %s' % (pad, prop, accepts) + + attrs = self._get_setters_and_targets() + attrs.sort() + lines = [] + + for prop, path in attrs: + accepts = self.get_valid_values(prop) + name = self.aliased_name(prop) + + lines.append('%s%s: %s' % (pad, name, accepts)) + return lines + + def pprint_setters_rest(self, prop=None, leadingspace=4): + """ + If *prop* is *None*, return a list of strings of all settable + properties and their valid values. Format the output for ReST + + If *prop* is not *None*, it is a valid property name and that + property will be returned as a string of property : valid + values. + """ + if leadingspace: + pad = ' ' * leadingspace + else: + pad = '' + if prop is not None: + accepts = self.get_valid_values(prop) + return '%s%s: %s' % (pad, prop, accepts) + + attrs = self._get_setters_and_targets() + attrs.sort() + lines = [] + + ######## + names = [self.aliased_name_rest(prop, target) + for prop, target in attrs] + accepts = [self.get_valid_values(prop) for prop, target in attrs] + + col0_len = max(len(n) for n in names) + col1_len = max(len(a) for a in accepts) + + lines.append('') + lines.append(pad + '.. table::') + lines.append(pad + ' :class: property-table') + pad += ' ' + + table_formatstr = pad + '=' * col0_len + ' ' + '=' * col1_len + + lines.append('') + lines.append(table_formatstr) + lines.append(pad + 'Property'.ljust(col0_len + 3) + + 'Description'.ljust(col1_len)) + lines.append(table_formatstr) + + lines.extend([pad + n.ljust(col0_len + 3) + a.ljust(col1_len) + for n, a in zip(names, accepts)]) + + lines.append(table_formatstr) + lines.append('') + return lines + + def properties(self): + """ + return a dictionary mapping property name -> value + """ + o = self.oorig + getters = [name for name in dir(o) + if name.startswith('get_') and callable(getattr(o, name))] + getters.sort() + d = dict() + for name in getters: + func = getattr(o, name) + if self.is_alias(func): + continue + + try: + with warnings.catch_warnings(): + warnings.simplefilter('ignore') + val = func() + except: + continue + else: + d[name[4:]] = val + + return d + + def pprint_getters(self): + """ + Return the getters and actual values as list of strings. + """ + + lines = [] + for name, val in sorted(six.iteritems(self.properties())): + if getattr(val, 'shape', ()) != () and len(val) > 6: + s = str(val[:6]) + '...' + else: + s = str(val) + s = s.replace('\n', ' ') + if len(s) > 50: + s = s[:50] + '...' + name = self.aliased_name(name) + lines.append(' %s = %s' % (name, s)) + return lines + + +def getp(obj, property=None): + """ + Return the value of object's property. *property* is an optional string + for the property you want to return + + Example usage:: + + getp(obj) # get all the object properties + getp(obj, 'linestyle') # get the linestyle property + + *obj* is a :class:`Artist` instance, e.g., + :class:`~matplotllib.lines.Line2D` or an instance of a + :class:`~matplotlib.axes.Axes` or :class:`matplotlib.text.Text`. + If the *property* is 'somename', this function returns + + obj.get_somename() + + :func:`getp` can be used to query all the gettable properties with + ``getp(obj)``. Many properties have aliases for shorter typing, e.g. + 'lw' is an alias for 'linewidth'. In the output, aliases and full + property names will be listed as: + + property or alias = value + + e.g.: + + linewidth or lw = 2 + """ + if property is None: + insp = ArtistInspector(obj) + ret = insp.pprint_getters() + print('\n'.join(ret)) + return + + func = getattr(obj, 'get_' + property) + return func() + +# alias +get = getp + + +def setp(obj, *args, **kwargs): + """ + Set a property on an artist object. + + matplotlib supports the use of :func:`setp` ("set property") and + :func:`getp` to set and get object properties, as well as to do + introspection on the object. For example, to set the linestyle of a + line to be dashed, you can do:: + + >>> line, = plot([1,2,3]) + >>> setp(line, linestyle='--') + + If you want to know the valid types of arguments, you can provide + the name of the property you want to set without a value:: + + >>> setp(line, 'linestyle') + linestyle: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' ] + + If you want to see all the properties that can be set, and their + possible values, you can do:: + + >>> setp(line) + ... long output listing omitted + + You may specify another output file to `setp` if `sys.stdout` is not + acceptable for some reason using the `file` keyword-only argument:: + + >>> with fopen('output.log') as f: + >>> setp(line, file=f) + + :func:`setp` operates on a single instance or a iterable of + instances. If you are in query mode introspecting the possible + values, only the first instance in the sequence is used. When + actually setting values, all the instances will be set. e.g., + suppose you have a list of two lines, the following will make both + lines thicker and red:: + + >>> x = arange(0,1.0,0.01) + >>> y1 = sin(2*pi*x) + >>> y2 = sin(4*pi*x) + >>> lines = plot(x, y1, x, y2) + >>> setp(lines, linewidth=2, color='r') + + :func:`setp` works with the MATLAB style string/value pairs or + with python kwargs. For example, the following are equivalent:: + + >>> setp(lines, 'linewidth', 2, 'color', 'r') # MATLAB style + >>> setp(lines, linewidth=2, color='r') # python style + """ + + if isinstance(obj, Artist): + objs = [obj] + else: + objs = list(cbook.flatten(obj)) + + if not objs: + return + + insp = ArtistInspector(objs[0]) + + # file has to be popped before checking if kwargs is empty + printArgs = {} + if 'file' in kwargs: + printArgs['file'] = kwargs.pop('file') + + if not kwargs and len(args) < 2: + if args: + print(insp.pprint_setters(prop=args[0]), **printArgs) + else: + print('\n'.join(insp.pprint_setters()), **printArgs) + return + + if len(args) % 2: + raise ValueError('The set args must be string, value pairs') + + # put args into ordereddict to maintain order + funcvals = OrderedDict() + for i in range(0, len(args) - 1, 2): + funcvals[args[i]] = args[i + 1] + + ret = [o.update(funcvals) for o in objs] + ret.extend([o.set(**kwargs) for o in objs]) + return [x for x in cbook.flatten(ret)] + + +def kwdoc(a): + hardcopy = matplotlib.rcParams['docstring.hardcopy'] + if hardcopy: + return '\n'.join(ArtistInspector(a).pprint_setters_rest( + leadingspace=4)) + else: + return '\n'.join(ArtistInspector(a).pprint_setters(leadingspace=2)) + +docstring.interpd.update(Artist=kwdoc(Artist)) diff --git a/contrib/python/matplotlib/py2/matplotlib/axes/__init__.py b/contrib/python/matplotlib/py2/matplotlib/axes/__init__.py new file mode 100644 index 00000000000..82c54389194 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/axes/__init__.py @@ -0,0 +1,5 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from ._subplots import * +from ._axes import * diff --git a/contrib/python/matplotlib/py2/matplotlib/axes/_axes.py b/contrib/python/matplotlib/py2/matplotlib/axes/_axes.py new file mode 100644 index 00000000000..2027d250a8a --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/axes/_axes.py @@ -0,0 +1,8153 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import xrange, zip, zip_longest + +import functools +import itertools +import logging +import math +import warnings + +import numpy as np +from numpy import ma + +import matplotlib +from matplotlib import _preprocess_data + +import matplotlib.cbook as cbook +import matplotlib.collections as mcoll +import matplotlib.colors as mcolors +import matplotlib.contour as mcontour +import matplotlib.category as _ # <-registers a category unit converter +import matplotlib.dates as _ # <-registers a date unit converter +import matplotlib.docstring as docstring +import matplotlib.image as mimage +import matplotlib.legend as mlegend +import matplotlib.lines as mlines +import matplotlib.markers as mmarkers +import matplotlib.mlab as mlab +import matplotlib.path as mpath +import matplotlib.patches as mpatches +import matplotlib.quiver as mquiver +import matplotlib.stackplot as mstack +import matplotlib.streamplot as mstream +import matplotlib.table as mtable +import matplotlib.text as mtext +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import matplotlib.tri as mtri +from matplotlib.cbook import ( + _backports, mplDeprecation, warn_deprecated, + STEP_LOOKUP_MAP, iterable, safe_first_element) +from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer +from matplotlib.axes._base import _AxesBase, _process_plot_format + +_log = logging.getLogger(__name__) + +rcParams = matplotlib.rcParams + +_alias_map = {'color': ['c'], + 'linewidth': ['lw'], + 'linestyle': ['ls'], + 'facecolor': ['fc'], + 'edgecolor': ['ec'], + 'markerfacecolor': ['mfc'], + 'markeredgecolor': ['mec'], + 'markeredgewidth': ['mew'], + 'markersize': ['ms'], + } + + +def _plot_args_replacer(args, data): + if len(args) == 1: + return ["y"] + elif len(args) == 2: + # this can be two cases: x,y or y,c + if not args[1] in data: + # this is not in data, so just assume that it is something which + # will not get replaced (color spec or array like). + return ["y", "c"] + # it's data, but could be a color code like 'ro' or 'b--' + # -> warn the user in that case... + try: + _process_plot_format(args[1]) + except ValueError: + pass + else: + warnings.warn( + "Second argument {!r} is ambiguous: could be a color spec but " + "is in data; using as data. Either rename the entry in data " + "or use three arguments to plot.".format(args[1]), + RuntimeWarning, stacklevel=3) + return ["x", "y"] + elif len(args) == 3: + return ["x", "y", "c"] + else: + raise ValueError("Using arbitrary long args with data is not " + "supported due to ambiguity of arguments.\nUse " + "multiple plotting calls instead.") + + +# The axes module contains all the wrappers to plotting functions. +# All the other methods should go in the _AxesBase class. + +class Axes(_AxesBase): + """ + The :class:`Axes` contains most of the figure elements: + :class:`~matplotlib.axis.Axis`, :class:`~matplotlib.axis.Tick`, + :class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.text.Text`, + :class:`~matplotlib.patches.Polygon`, etc., and sets the + coordinate system. + + The :class:`Axes` instance supports callbacks through a callbacks + attribute which is a :class:`~matplotlib.cbook.CallbackRegistry` + instance. The events you can connect to are 'xlim_changed' and + 'ylim_changed' and the callback will be called with func(*ax*) + where *ax* is the :class:`Axes` instance. + """ + ### Labelling, legend and texts + + aname = 'Axes' + + def get_title(self, loc="center"): + """ + Get an axes title. + + Get one of the three available axes titles. The available titles + are positioned above the axes in the center, flush with the left + edge, and flush with the right edge. + + Parameters + ---------- + loc : {'center', 'left', 'right'}, str, optional + Which title to get, defaults to 'center'. + + Returns + ------- + title : str + The title text string. + + """ + try: + title = {'left': self._left_title, + 'center': self.title, + 'right': self._right_title}[loc.lower()] + except KeyError: + raise ValueError("'%s' is not a valid location" % loc) + return title.get_text() + + def set_title(self, label, fontdict=None, loc="center", pad=None, + **kwargs): + """ + Set a title for the axes. + + Set one of the three available axes titles. The available titles + are positioned above the axes in the center, flush with the left + edge, and flush with the right edge. + + Parameters + ---------- + label : str + Text to use for the title + + fontdict : dict + A dictionary controlling the appearance of the title text, + the default `fontdict` is:: + + {'fontsize': rcParams['axes.titlesize'], + 'fontweight' : rcParams['axes.titleweight'], + 'verticalalignment': 'baseline', + 'horizontalalignment': loc} + + loc : {'center', 'left', 'right'}, str, optional + Which title to set, defaults to 'center' + + pad : float + The offset of the title from the top of the axes, in points. + Default is ``None`` to use rcParams['axes.titlepad']. + + Returns + ------- + text : :class:`~matplotlib.text.Text` + The matplotlib text instance representing the title + + Other Parameters + ---------------- + **kwargs : `~matplotlib.text.Text` properties + Other keyword arguments are text properties, see + :class:`~matplotlib.text.Text` for a list of valid text + properties. + """ + try: + title = {'left': self._left_title, + 'center': self.title, + 'right': self._right_title}[loc.lower()] + except KeyError: + raise ValueError("'%s' is not a valid location" % loc) + default = { + 'fontsize': rcParams['axes.titlesize'], + 'fontweight': rcParams['axes.titleweight'], + 'verticalalignment': 'baseline', + 'horizontalalignment': loc.lower()} + if pad is None: + pad = rcParams['axes.titlepad'] + self._set_title_offset_trans(float(pad)) + title.set_text(label) + title.update(default) + if fontdict is not None: + title.update(fontdict) + title.update(kwargs) + return title + + def get_xlabel(self): + """ + Get the xlabel text string. + """ + label = self.xaxis.get_label() + return label.get_text() + + def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs): + """ + Set the label for the x-axis. + + Parameters + ---------- + xlabel : str + The label text. + + labelpad : scalar, optional, default: None + Spacing in points between the label and the x-axis. + + Other Parameters + ---------------- + **kwargs : `.Text` properties + `.Text` properties control the appearance of the label. + + See also + -------- + text : for information on how override and the optional args work + """ + if labelpad is not None: + self.xaxis.labelpad = labelpad + return self.xaxis.set_label_text(xlabel, fontdict, **kwargs) + + def get_ylabel(self): + """ + Get the ylabel text string. + """ + label = self.yaxis.get_label() + return label.get_text() + + def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs): + """ + Set the label for the y-axis. + + Parameters + ---------- + ylabel : str + The label text. + + labelpad : scalar, optional, default: None + Spacing in points between the label and the y-axis. + + Other Parameters + ---------------- + **kwargs : `.Text` properties + `.Text` properties control the appearance of the label. + + See also + -------- + text : for information on how override and the optional args work + + """ + if labelpad is not None: + self.yaxis.labelpad = labelpad + return self.yaxis.set_label_text(ylabel, fontdict, **kwargs) + + def get_legend_handles_labels(self, legend_handler_map=None): + """ + Return handles and labels for legend + + ``ax.legend()`` is equivalent to :: + + h, l = ax.get_legend_handles_labels() + ax.legend(h, l) + + """ + + # pass through to legend. + handles, labels = mlegend._get_legend_handles_labels([self], + legend_handler_map) + return handles, labels + + @docstring.dedent_interpd + def legend(self, *args, **kwargs): + """ + Places a legend on the axes. + + Call signatures:: + + legend() + legend(labels) + legend(handles, labels) + + The call signatures correspond to three different ways how to use + this method. + + **1. Automatic detection of elements to be shown in the legend** + + The elements to be added to the legend are automatically determined, + when you do not pass in any extra arguments. + + In this case, the labels are taken from the artist. You can specify + them either at artist creation or by calling the + :meth:`~.Artist.set_label` method on the artist:: + + line, = ax.plot([1, 2, 3], label='Inline label') + ax.legend() + + or:: + + line.set_label('Label via method') + line, = ax.plot([1, 2, 3]) + ax.legend() + + Specific lines can be excluded from the automatic legend element + selection by defining a label starting with an underscore. + This is default for all artists, so calling `Axes.legend` without + any arguments and without setting the labels manually will result in + no legend being drawn. + + + **2. Labeling existing plot elements** + + To make a legend for lines which already exist on the axes + (via plot for instance), simply call this function with an iterable + of strings, one for each legend item. For example:: + + ax.plot([1, 2, 3]) + ax.legend(['A simple line']) + + Note: This way of using is discouraged, because the relation between + plot elements and labels is only implicit by their order and can + easily be mixed up. + + + **3. Explicitly defining the elements in the legend** + + For full control of which artists have a legend entry, it is possible + to pass an iterable of legend artists followed by an iterable of + legend labels respectively:: + + legend((line1, line2, line3), ('label1', 'label2', 'label3')) + + Parameters + ---------- + + handles : sequence of `.Artist`, optional + A list of Artists (lines, patches) to be added to the legend. + Use this together with *labels*, if you need full control on what + is shown in the legend and the automatic mechanism described above + is not sufficient. + + The length of handles and labels should be the same in this + case. If they are not, they are truncated to the smaller length. + + labels : sequence of strings, optional + A list of labels to show next to the artists. + Use this together with *handles*, if you need full control on what + is shown in the legend and the automatic mechanism described above + is not sufficient. + + Other Parameters + ---------------- + + loc : int or string or pair of floats, default: 'upper right' + The location of the legend. Possible codes are: + + =============== ============= + Location String Location Code + =============== ============= + 'best' 0 + 'upper right' 1 + 'upper left' 2 + 'lower left' 3 + 'lower right' 4 + 'right' 5 + 'center left' 6 + 'center right' 7 + 'lower center' 8 + 'upper center' 9 + 'center' 10 + =============== ============= + + + Alternatively can be a 2-tuple giving ``x, y`` of the lower-left + corner of the legend in axes coordinates (in which case + ``bbox_to_anchor`` will be ignored). + + bbox_to_anchor : `.BboxBase` or pair of floats + Specify any arbitrary location for the legend in `bbox_transform` + coordinates (default Axes coordinates). + + For example, to put the legend's upper right hand corner in the + center of the axes the following keywords can be used:: + + loc='upper right', bbox_to_anchor=(0.5, 0.5) + + ncol : integer + The number of columns that the legend has. Default is 1. + + prop : None or :class:`matplotlib.font_manager.FontProperties` or dict + The font properties of the legend. If None (default), the current + :data:`matplotlib.rcParams` will be used. + + fontsize : int or float or {'xx-small', 'x-small', 'small', 'medium', \ +'large', 'x-large', 'xx-large'} + Controls the font size of the legend. If the value is numeric the + size will be the absolute font size in points. String values are + relative to the current default font size. This argument is only + used if `prop` is not specified. + + numpoints : None or int + The number of marker points in the legend when creating a legend + entry for a `.Line2D` (line). + Default is ``None``, which will take the value from + :rc:`legend.numpoints`. + + scatterpoints : None or int + The number of marker points in the legend when creating + a legend entry for a `.PathCollection` (scatter plot). + Default is ``None``, which will take the value from + :rc:`legend.scatterpoints`. + + scatteryoffsets : iterable of floats + The vertical offset (relative to the font size) for the markers + created for a scatter plot legend entry. 0.0 is at the base the + legend text, and 1.0 is at the top. To draw all markers at the + same height, set to ``[0.5]``. Default is ``[0.375, 0.5, 0.3125]``. + + markerscale : None or int or float + The relative size of legend markers compared with the originally + drawn ones. + Default is ``None``, which will take the value from + :rc:`legend.markerscale`. + + markerfirst : bool + If *True*, legend marker is placed to the left of the legend label. + If *False*, legend marker is placed to the right of the legend + label. + Default is *True*. + + frameon : None or bool + Control whether the legend should be drawn on a patch + (frame). + Default is ``None``, which will take the value from + :rc:`legend.frameon`. + + fancybox : None or bool + Control whether round edges should be enabled around the + :class:`~matplotlib.patches.FancyBboxPatch` which makes up the + legend's background. + Default is ``None``, which will take the value from + :rc:`legend.fancybox`. + + shadow : None or bool + Control whether to draw a shadow behind the legend. + Default is ``None``, which will take the value from + :rc:`legend.shadow`. + + framealpha : None or float + Control the alpha transparency of the legend's background. + Default is ``None``, which will take the value from + :rc:`legend.framealpha`. If shadow is activated and + *framealpha* is ``None``, the default value is ignored. + + facecolor : None or "inherit" or a color spec + Control the legend's background color. + Default is ``None``, which will take the value from + :rc:`legend.facecolor`. If ``"inherit"``, it will take + :rc:`axes.facecolor`. + + edgecolor : None or "inherit" or a color spec + Control the legend's background patch edge color. + Default is ``None``, which will take the value from + :rc:`legend.edgecolor` If ``"inherit"``, it will take + :rc:`axes.edgecolor`. + + mode : {"expand", None} + If `mode` is set to ``"expand"`` the legend will be horizontally + expanded to fill the axes area (or `bbox_to_anchor` if defines + the legend's size). + + bbox_transform : None or :class:`matplotlib.transforms.Transform` + The transform for the bounding box (`bbox_to_anchor`). For a value + of ``None`` (default) the Axes' + :data:`~matplotlib.axes.Axes.transAxes` transform will be used. + + title : str or None + The legend's title. Default is no title (``None``). + + borderpad : float or None + The fractional whitespace inside the legend border. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.borderpad`. + + labelspacing : float or None + The vertical space between the legend entries. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.labelspacing`. + + handlelength : float or None + The length of the legend handles. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.handlelength`. + + handletextpad : float or None + The pad between the legend handle and text. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.handletextpad`. + + borderaxespad : float or None + The pad between the axes and legend border. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.borderaxespad`. + + columnspacing : float or None + The spacing between columns. + Measured in font-size units. + Default is ``None``, which will take the value from + :rc:`legend.columnspacing`. + + handler_map : dict or None + The custom dictionary mapping instances or types to a legend + handler. This `handler_map` updates the default handler map + found at :func:`matplotlib.legend.Legend.get_legend_handler_map`. + + Returns + ------- + + :class:`matplotlib.legend.Legend` instance + + Notes + ----- + + Not all kinds of artist are supported by the legend command. See + :doc:`/tutorials/intermediate/legend_guide` for details. + + Examples + -------- + + .. plot:: gallery/api/legend.py + + """ + handles, labels, extra_args, kwargs = mlegend._parse_legend_args( + [self], + *args, + **kwargs) + if len(extra_args): + raise TypeError('legend only accepts two non-keyword arguments') + self.legend_ = mlegend.Legend(self, handles, labels, **kwargs) + self.legend_._remove_method = lambda h: setattr(self, 'legend_', None) + return self.legend_ + + def text(self, x, y, s, fontdict=None, withdash=False, **kwargs): + """ + Add text to the axes. + + Add the text *s* to the axes at location *x*, *y* in data coordinates. + + Parameters + ---------- + x, y : scalars + The position to place the text. By default, this is in data + coordinates. The coordinate system can be changed using the + *transform* parameter. + + s : str + The text. + + fontdict : dictionary, optional, default: None + A dictionary to override the default text properties. If fontdict + is None, the defaults are determined by your rc parameters. + + withdash : boolean, optional, default: False + Creates a `~matplotlib.text.TextWithDash` instance instead of a + `~matplotlib.text.Text` instance. + + Returns + ------- + text : `.Text` + The created `.Text` instance. + + Other Parameters + ---------------- + **kwargs : `~matplotlib.text.Text` properties. + Other miscellaneous text parameters. + + Examples + -------- + Individual keyword arguments can be used to override any given + parameter:: + + >>> text(x, y, s, fontsize=12) + + The default transform specifies that text is in data coords, + alternatively, you can specify text in axis coords (0,0 is + lower-left and 1,1 is upper-right). The example below places + text in the center of the axes:: + + >>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center', + ... verticalalignment='center', transform=ax.transAxes) + + You can put a rectangular box around the text instance (e.g., to + set a background color) by using the keyword `bbox`. `bbox` is + a dictionary of `~matplotlib.patches.Rectangle` + properties. For example:: + + >>> text(x, y, s, bbox=dict(facecolor='red', alpha=0.5)) + """ + default = { + 'verticalalignment': 'baseline', + 'horizontalalignment': 'left', + 'transform': self.transData, + 'clip_on': False} + + # At some point if we feel confident that TextWithDash + # is robust as a drop-in replacement for Text and that + # the performance impact of the heavier-weight class + # isn't too significant, it may make sense to eliminate + # the withdash kwarg and simply delegate whether there's + # a dash to TextWithDash and dashlength. + if withdash: + t = mtext.TextWithDash( + x=x, y=y, text=s) + else: + t = mtext.Text( + x=x, y=y, text=s) + + t.update(default) + if fontdict is not None: + t.update(fontdict) + t.update(kwargs) + + t.set_clip_path(self.patch) + self._add_text(t) + return t + + @docstring.dedent_interpd + def annotate(self, *args, **kwargs): + a = mtext.Annotation(*args, **kwargs) + a.set_transform(mtransforms.IdentityTransform()) + if 'clip_on' in kwargs: + a.set_clip_path(self.patch) + self._add_text(a) + return a + annotate.__doc__ = mtext.Annotation.__init__.__doc__ + #### Lines and spans + + @docstring.dedent_interpd + def axhline(self, y=0, xmin=0, xmax=1, **kwargs): + """ + Add a horizontal line across the axis. + + Parameters + ---------- + y : scalar, optional, default: 0 + y position in data coordinates of the horizontal line. + + xmin : scalar, optional, default: 0 + Should be between 0 and 1, 0 being the far left of the plot, 1 the + far right of the plot. + + xmax : scalar, optional, default: 1 + Should be between 0 and 1, 0 being the far left of the plot, 1 the + far right of the plot. + + Returns + ------- + line : :class:`~matplotlib.lines.Line2D` + + Other Parameters + ---------------- + **kwargs : + Valid kwargs are :class:`~matplotlib.lines.Line2D` properties, + with the exception of 'transform': + + %(Line2D)s + + See also + -------- + hlines : Add horizontal lines in data coordinates. + axhspan : Add a horizontal span (rectangle) across the axis. + + Examples + -------- + + * draw a thick red hline at 'y' = 0 that spans the xrange:: + + >>> axhline(linewidth=4, color='r') + + * draw a default hline at 'y' = 1 that spans the xrange:: + + >>> axhline(y=1) + + * draw a default hline at 'y' = .5 that spans the middle half of + the xrange:: + + >>> axhline(y=.5, xmin=0.25, xmax=0.75) + + """ + if "transform" in kwargs: + raise ValueError( + "'transform' is not allowed as a kwarg;" + + "axhline generates its own transform.") + ymin, ymax = self.get_ybound() + + # We need to strip away the units for comparison with + # non-unitized bounds + self._process_unit_info(ydata=y, kwargs=kwargs) + yy = self.convert_yunits(y) + scaley = (yy < ymin) or (yy > ymax) + + trans = self.get_yaxis_transform(which='grid') + l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs) + self.add_line(l) + self.autoscale_view(scalex=False, scaley=scaley) + return l + + @docstring.dedent_interpd + def axvline(self, x=0, ymin=0, ymax=1, **kwargs): + """ + Add a vertical line across the axes. + + Parameters + ---------- + x : scalar, optional, default: 0 + x position in data coordinates of the vertical line. + + ymin : scalar, optional, default: 0 + Should be between 0 and 1, 0 being the bottom of the plot, 1 the + top of the plot. + + ymax : scalar, optional, default: 1 + Should be between 0 and 1, 0 being the bottom of the plot, 1 the + top of the plot. + + Returns + ------- + line : :class:`~matplotlib.lines.Line2D` + + Other Parameters + ---------------- + **kwargs : + Valid kwargs are :class:`~matplotlib.lines.Line2D` properties, + with the exception of 'transform': + + %(Line2D)s + + Examples + -------- + * draw a thick red vline at *x* = 0 that spans the yrange:: + + >>> axvline(linewidth=4, color='r') + + * draw a default vline at *x* = 1 that spans the yrange:: + + >>> axvline(x=1) + + * draw a default vline at *x* = .5 that spans the middle half of + the yrange:: + + >>> axvline(x=.5, ymin=0.25, ymax=0.75) + + See also + -------- + vlines : Add vertical lines in data coordinates. + axvspan : Add a vertical span (rectangle) across the axis. + """ + + if "transform" in kwargs: + raise ValueError( + "'transform' is not allowed as a kwarg;" + + "axvline generates its own transform.") + xmin, xmax = self.get_xbound() + + # We need to strip away the units for comparison with + # non-unitized bounds + self._process_unit_info(xdata=x, kwargs=kwargs) + xx = self.convert_xunits(x) + scalex = (xx < xmin) or (xx > xmax) + + trans = self.get_xaxis_transform(which='grid') + l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs) + self.add_line(l) + self.autoscale_view(scalex=scalex, scaley=False) + return l + + @docstring.dedent_interpd + def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs): + """ + Add a horizontal span (rectangle) across the axis. + + Draw a horizontal span (rectangle) from *ymin* to *ymax*. + With the default values of *xmin* = 0 and *xmax* = 1, this + always spans the xrange, regardless of the xlim settings, even + if you change them, e.g., with the :meth:`set_xlim` command. + That is, the horizontal extent is in axes coords: 0=left, + 0.5=middle, 1.0=right but the *y* location is in data + coordinates. + + Parameters + ---------- + ymin : float + Lower limit of the horizontal span in data units. + ymax : float + Upper limit of the horizontal span in data units. + xmin : float, optional, default: 0 + Lower limit of the vertical span in axes (relative + 0-1) units. + xmax : float, optional, default: 1 + Upper limit of the vertical span in axes (relative + 0-1) units. + + Returns + ------- + Polygon : `~matplotlib.patches.Polygon` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.patches.Polygon` properties. + + %(Polygon)s + + See Also + -------- + axvspan : Add a vertical span across the axes. + """ + trans = self.get_yaxis_transform(which='grid') + + # process the unit information + self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs) + + # first we need to strip away the units + xmin, xmax = self.convert_xunits([xmin, xmax]) + ymin, ymax = self.convert_yunits([ymin, ymax]) + + verts = (xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin) + p = mpatches.Polygon(verts, **kwargs) + p.set_transform(trans) + self.add_patch(p) + self.autoscale_view(scalex=False) + return p + + def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs): + """ + Add a vertical span (rectangle) across the axes. + + Draw a vertical span (rectangle) from `xmin` to `xmax`. With + the default values of `ymin` = 0 and `ymax` = 1. This always + spans the yrange, regardless of the ylim settings, even if you + change them, e.g., with the :meth:`set_ylim` command. That is, + the vertical extent is in axes coords: 0=bottom, 0.5=middle, + 1.0=top but the y location is in data coordinates. + + Parameters + ---------- + xmin : scalar + Number indicating the first X-axis coordinate of the vertical + span rectangle in data units. + xmax : scalar + Number indicating the second X-axis coordinate of the vertical + span rectangle in data units. + ymin : scalar, optional + Number indicating the first Y-axis coordinate of the vertical + span rectangle in relative Y-axis units (0-1). Default to 0. + ymax : scalar, optional + Number indicating the second Y-axis coordinate of the vertical + span rectangle in relative Y-axis units (0-1). Default to 1. + + Returns + ------- + rectangle : matplotlib.patches.Polygon + Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax). + + Other Parameters + ---------------- + **kwargs + Optional parameters are properties of the class + matplotlib.patches.Polygon. + + See Also + -------- + axhspan : Add a horizontal span across the axes. + + Examples + -------- + Draw a vertical, green, translucent rectangle from x = 1.25 to + x = 1.55 that spans the yrange of the axes. + + >>> axvspan(1.25, 1.55, facecolor='g', alpha=0.5) + + """ + trans = self.get_xaxis_transform(which='grid') + + # process the unit information + self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs) + + # first we need to strip away the units + xmin, xmax = self.convert_xunits([xmin, xmax]) + ymin, ymax = self.convert_yunits([ymin, ymax]) + + verts = [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)] + p = mpatches.Polygon(verts, **kwargs) + p.set_transform(trans) + self.add_patch(p) + self.autoscale_view(scaley=False) + return p + + @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"], + label_namer="y") + def hlines(self, y, xmin, xmax, colors='k', linestyles='solid', + label='', **kwargs): + """ + Plot horizontal lines at each *y* from *xmin* to *xmax*. + + Parameters + ---------- + y : scalar or sequence of scalar + y-indexes where to plot the lines. + + xmin, xmax : scalar or 1D array_like + Respective beginning and end of each line. If scalars are + provided, all lines will have same length. + + colors : array_like of colors, optional, default: 'k' + + linestyles : ['solid' | 'dashed' | 'dashdot' | 'dotted'], optional + + label : string, optional, default: '' + + Returns + ------- + lines : `~matplotlib.collections.LineCollection` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.collections.LineCollection` properties. + + See also + -------- + vlines : vertical lines + axhline: horizontal line across the axes + """ + + # We do the conversion first since not all unitized data is uniform + # process the unit information + self._process_unit_info([xmin, xmax], y, kwargs=kwargs) + y = self.convert_yunits(y) + xmin = self.convert_xunits(xmin) + xmax = self.convert_xunits(xmax) + + if not iterable(y): + y = [y] + if not iterable(xmin): + xmin = [xmin] + if not iterable(xmax): + xmax = [xmax] + + y, xmin, xmax = cbook.delete_masked_points(y, xmin, xmax) + + y = np.ravel(y) + xmin = np.resize(xmin, y.shape) + xmax = np.resize(xmax, y.shape) + + verts = [((thisxmin, thisy), (thisxmax, thisy)) + for thisxmin, thisxmax, thisy in zip(xmin, xmax, y)] + lines = mcoll.LineCollection(verts, colors=colors, + linestyles=linestyles, label=label) + self.add_collection(lines, autolim=False) + lines.update(kwargs) + + if len(y) > 0: + minx = min(xmin.min(), xmax.min()) + maxx = max(xmin.max(), xmax.max()) + miny = y.min() + maxy = y.max() + + corners = (minx, miny), (maxx, maxy) + + self.update_datalim(corners) + self.autoscale_view() + + return lines + + @_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"], + label_namer="x") + def vlines(self, x, ymin, ymax, colors='k', linestyles='solid', + label='', **kwargs): + """ + Plot vertical lines. + + Plot vertical lines at each *x* from *ymin* to *ymax*. + + Parameters + ---------- + x : scalar or 1D array_like + x-indexes where to plot the lines. + + ymin, ymax : scalar or 1D array_like + Respective beginning and end of each line. If scalars are + provided, all lines will have same length. + + colors : array_like of colors, optional, default: 'k' + + linestyles : ['solid' | 'dashed' | 'dashdot' | 'dotted'], optional + + label : string, optional, default: '' + + Returns + ------- + lines : `~matplotlib.collections.LineCollection` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.collections.LineCollection` properties. + + See also + -------- + hlines : horizontal lines + axvline: vertical line across the axes + """ + + self._process_unit_info(xdata=x, ydata=[ymin, ymax], kwargs=kwargs) + + # We do the conversion first since not all unitized data is uniform + x = self.convert_xunits(x) + ymin = self.convert_yunits(ymin) + ymax = self.convert_yunits(ymax) + + if not iterable(x): + x = [x] + if not iterable(ymin): + ymin = [ymin] + if not iterable(ymax): + ymax = [ymax] + + x, ymin, ymax = cbook.delete_masked_points(x, ymin, ymax) + + x = np.ravel(x) + ymin = np.resize(ymin, x.shape) + ymax = np.resize(ymax, x.shape) + + verts = [((thisx, thisymin), (thisx, thisymax)) + for thisx, thisymin, thisymax in zip(x, ymin, ymax)] + lines = mcoll.LineCollection(verts, colors=colors, + linestyles=linestyles, label=label) + self.add_collection(lines, autolim=False) + lines.update(kwargs) + + if len(x) > 0: + minx = x.min() + maxx = x.max() + miny = min(ymin.min(), ymax.min()) + maxy = max(ymin.max(), ymax.max()) + + corners = (minx, miny), (maxx, maxy) + self.update_datalim(corners) + self.autoscale_view() + + return lines + + @_preprocess_data(replace_names=["positions", "lineoffsets", + "linelengths", "linewidths", + "colors", "linestyles"], + label_namer=None) + @docstring.dedent_interpd + def eventplot(self, positions, orientation='horizontal', lineoffsets=1, + linelengths=1, linewidths=None, colors=None, + linestyles='solid', **kwargs): + """ + Plot identical parallel lines at the given positions. + + *positions* should be a 1D or 2D array-like object, with each row + corresponding to a row or column of lines. + + This type of plot is commonly used in neuroscience for representing + neural events, where it is usually called a spike raster, dot raster, + or raster plot. + + However, it is useful in any situation where you wish to show the + timing or position of multiple sets of discrete events, such as the + arrival times of people to a business on each day of the month or the + date of hurricanes each year of the last century. + + Parameters + ---------- + positions : 1D or 2D array-like object + Each value is an event. If *positions* is a 2D array-like, each + row corresponds to a row or a column of lines (depending on the + *orientation* parameter). + + orientation : {'horizontal', 'vertical'}, optional + Controls the direction of the event collections: + + - 'horizontal' : the lines are arranged horizontally in rows, + and are vertical. + - 'vertical' : the lines are arranged vertically in columns, + and are horizontal. + + lineoffsets : scalar or sequence of scalars, optional, default: 1 + The offset of the center of the lines from the origin, in the + direction orthogonal to *orientation*. + + linelengths : scalar or sequence of scalars, optional, default: 1 + The total height of the lines (i.e. the lines stretches from + ``lineoffset - linelength/2`` to ``lineoffset + linelength/2``). + + linewidths : scalar, scalar sequence or None, optional, default: None + The line width(s) of the event lines, in points. If it is None, + defaults to its rcParams setting. + + colors : color, sequence of colors or None, optional, default: None + The color(s) of the event lines. If it is None, defaults to its + rcParams setting. + + linestyles : str or tuple or a sequence of such values, optional + Default is 'solid'. Valid strings are ['solid', 'dashed', + 'dashdot', 'dotted', '-', '--', '-.', ':']. Dash tuples + should be of the form:: + + (offset, onoffseq), + + where *onoffseq* is an even length tuple of on and off ink + in points. + + **kwargs : optional + Other keyword arguments are line collection properties. See + :class:`~matplotlib.collections.LineCollection` for a list of + the valid properties. + + Returns + ------- + + list : A list of :class:`~.collections.EventCollection` objects. + Contains the :class:`~.collections.EventCollection` that + were added. + + Notes + ----- + + For *linelengths*, *linewidths*, *colors*, and *linestyles*, if only + a single value is given, that value is applied to all lines. If an + array-like is given, it must have the same length as *positions*, and + each value will be applied to the corresponding row of the array. + + Examples + -------- + + .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py + """ + self._process_unit_info(xdata=positions, + ydata=[lineoffsets, linelengths], + kwargs=kwargs) + + # We do the conversion first since not all unitized data is uniform + positions = self.convert_xunits(positions) + lineoffsets = self.convert_yunits(lineoffsets) + linelengths = self.convert_yunits(linelengths) + + if not iterable(positions): + positions = [positions] + elif any(iterable(position) for position in positions): + positions = [np.asanyarray(position) for position in positions] + else: + positions = [np.asanyarray(positions)] + + if len(positions) == 0: + return [] + + # prevent 'singular' keys from **kwargs dict from overriding the effect + # of 'plural' keyword arguments (e.g. 'color' overriding 'colors') + colors = cbook.local_over_kwdict(colors, kwargs, 'color') + linewidths = cbook.local_over_kwdict(linewidths, kwargs, 'linewidth') + linestyles = cbook.local_over_kwdict(linestyles, kwargs, 'linestyle') + + if not iterable(lineoffsets): + lineoffsets = [lineoffsets] + if not iterable(linelengths): + linelengths = [linelengths] + if not iterable(linewidths): + linewidths = [linewidths] + if not iterable(colors): + colors = [colors] + if hasattr(linestyles, 'lower') or not iterable(linestyles): + linestyles = [linestyles] + + lineoffsets = np.asarray(lineoffsets) + linelengths = np.asarray(linelengths) + linewidths = np.asarray(linewidths) + + if len(lineoffsets) == 0: + lineoffsets = [None] + if len(linelengths) == 0: + linelengths = [None] + if len(linewidths) == 0: + lineoffsets = [None] + if len(linewidths) == 0: + lineoffsets = [None] + if len(colors) == 0: + colors = [None] + try: + # Early conversion of the colors into RGBA values to take care + # of cases like colors='0.5' or colors='C1'. (Issue #8193) + colors = mcolors.to_rgba_array(colors) + except ValueError: + # Will fail if any element of *colors* is None. But as long + # as len(colors) == 1 or len(positions), the rest of the + # code should process *colors* properly. + pass + + if len(lineoffsets) == 1 and len(positions) != 1: + lineoffsets = np.tile(lineoffsets, len(positions)) + lineoffsets[0] = 0 + lineoffsets = np.cumsum(lineoffsets) + if len(linelengths) == 1: + linelengths = np.tile(linelengths, len(positions)) + if len(linewidths) == 1: + linewidths = np.tile(linewidths, len(positions)) + if len(colors) == 1: + colors = list(colors) + colors = colors * len(positions) + if len(linestyles) == 1: + linestyles = [linestyles] * len(positions) + + if len(lineoffsets) != len(positions): + raise ValueError('lineoffsets and positions are unequal sized ' + 'sequences') + if len(linelengths) != len(positions): + raise ValueError('linelengths and positions are unequal sized ' + 'sequences') + if len(linewidths) != len(positions): + raise ValueError('linewidths and positions are unequal sized ' + 'sequences') + if len(colors) != len(positions): + raise ValueError('colors and positions are unequal sized ' + 'sequences') + if len(linestyles) != len(positions): + raise ValueError('linestyles and positions are unequal sized ' + 'sequences') + + colls = [] + for position, lineoffset, linelength, linewidth, color, linestyle in \ + zip(positions, lineoffsets, linelengths, linewidths, + colors, linestyles): + coll = mcoll.EventCollection(position, + orientation=orientation, + lineoffset=lineoffset, + linelength=linelength, + linewidth=linewidth, + color=color, + linestyle=linestyle) + self.add_collection(coll, autolim=False) + coll.update(kwargs) + colls.append(coll) + + if len(positions) > 0: + # try to get min/max + min_max = [(np.min(_p), np.max(_p)) for _p in positions + if len(_p) > 0] + # if we have any non-empty positions, try to autoscale + if len(min_max) > 0: + mins, maxes = zip(*min_max) + minpos = np.min(mins) + maxpos = np.max(maxes) + + minline = (lineoffsets - linelengths).min() + maxline = (lineoffsets + linelengths).max() + + if (orientation is not None and + orientation.lower() == "vertical"): + corners = (minline, minpos), (maxline, maxpos) + else: # "horizontal", None or "none" (see EventCollection) + corners = (minpos, minline), (maxpos, maxline) + self.update_datalim(corners) + self.autoscale_view() + + return colls + + # ### Basic plotting + # The label_naming happens in `matplotlib.axes._base._plot_args` + @_preprocess_data(replace_names=["x", "y"], + positional_parameter_names=_plot_args_replacer, + label_namer=None) + @docstring.dedent_interpd + def plot(self, *args, **kwargs): + """ + Plot y versus x as lines and/or markers. + + Call signatures:: + + plot([x], y, [fmt], data=None, **kwargs) + plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) + + The coordinates of the points or line nodes are given by *x*, *y*. + + The optional parameter *fmt* is a convenient way for defining basic + formatting like color, marker and linestyle. It's a shortcut string + notation described in the *Notes* section below. + + >>> plot(x, y) # plot x and y using default line style and color + >>> plot(x, y, 'bo') # plot x and y using blue circle markers + >>> plot(y) # plot y using x as index array 0..N-1 + >>> plot(y, 'r+') # ditto, but with red plusses + + You can use `.Line2D` properties as keyword arguments for more + control on the appearance. Line properties and *fmt* can be mixed. + The following two calls yield identical results: + + >>> plot(x, y, 'go--', linewidth=2, markersize=12) + >>> plot(x, y, color='green', marker='o', linestyle='dashed', + linewidth=2, markersize=12) + + When conflicting with *fmt*, keyword arguments take precedence. + + **Plotting labelled data** + + There's a convenient way for plotting objects with labelled data (i.e. + data that can be accessed by index ``obj['y']``). Instead of giving + the data in *x* and *y*, you can provide the object in the *data* + parameter and just give the labels for *x* and *y*:: + + >>> plot('xlabel', 'ylabel', data=obj) + + All indexable objects are supported. This could e.g. be a `dict`, a + `pandas.DataFame` or a structured numpy array. + + + **Plotting multiple sets of data** + + There are various ways to plot multiple sets of data. + + - The most straight forward way is just to call `plot` multiple times. + Example: + + >>> plot(x1, y1, 'bo') + >>> plot(x2, y2, 'go') + + - Alternatively, if your data is already a 2d array, you can pass it + directly to *x*, *y*. A separate data set will be drawn for every + column. + + Example: an array ``a`` where the first column represents the *x* + values and the other columns are the *y* columns:: + + >>> plot(a[0], a[1:]) + + - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]* + groups:: + + >>> plot(x1, y1, 'g^', x2, y2, 'g-') + + In this case, any additional keyword argument applies to all + datasets. Also this syntax cannot be combined with the *data* + parameter. + + By default, each line is assigned a different style specified by a + 'style cycle'. The *fmt* and line property parameters are only + necessary if you want explicit deviations from these defaults. + Alternatively, you can also change the style cycle using the + 'axes.prop_cycle' rcParam. + + Parameters + ---------- + x, y : array-like or scalar + The horizontal / vertical coordinates of the data points. + *x* values are optional. If not given, they default to + ``[0, ..., N-1]``. + + Commonly, these parameters are arrays of length N. However, + scalars are supported as well (equivalent to an array with + constant value). + + The parameters can also be 2-dimensional. Then, the columns + represent separate data sets. + + fmt : str, optional + A format string, e.g. 'ro' for red circles. See the *Notes* + section for a full description of the format strings. + + Format strings are just an abbreviation for quickly setting + basic line properties. All of these and more can also be + controlled by keyword arguments. + + data : indexable object, optional + An object with labelled data. If given, provide the label names to + plot in *x* and *y*. + + .. note:: + Technically there's a slight ambiguity in calls where the + second label is a valid *fmt*. `plot('n', 'o', data=obj)` + could be `plt(x, y)` or `plt(y, fmt)`. In such cases, + the former interpretation is chosen, but a warning is issued. + You may suppress the warning by adding an empty format string + `plot('n', 'o', '', data=obj)`. + + + Other Parameters + ---------------- + scalex, scaley : bool, optional, default: True + These parameters determined if the view limits are adapted to + the data limits. The values are passed on to `autoscale_view`. + + **kwargs : `.Line2D` properties, optional + *kwargs* are used to specify properties like a line label (for + auto legends), linewidth, antialiasing, marker face color. + Example:: + + >>> plot([1,2,3], [1,2,3], 'go-', label='line 1', linewidth=2) + >>> plot([1,2,3], [1,4,9], 'rs', label='line 2') + + If you make multiple lines with one plot command, the kwargs + apply to all those lines. + + Here is a list of available `.Line2D` properties: + + %(Line2D)s + + Returns + ------- + lines + A list of `.Line2D` objects representing the plotted data. + + + See Also + -------- + scatter : XY scatter plot with markers of variing size and/or color ( + sometimes also called bubble chart). + + + Notes + ----- + **Format Strings** + + A format string consists of a part for color, marker and line:: + + fmt = '[color][marker][line]' + + Each of them is optional. If not provided, the value from the style + cycle is used. Exception: If ``line`` is given, but no ``marker``, + the data will be a line without markers. + + **Colors** + + The following color abbreviations are supported: + + ============= =============================== + character color + ============= =============================== + ``'b'`` blue + ``'g'`` green + ``'r'`` red + ``'c'`` cyan + ``'m'`` magenta + ``'y'`` yellow + ``'k'`` black + ``'w'`` white + ============= =============================== + + If the color is the only part of the format string, you can + additionally use any `matplotlib.colors` spec, e.g. full names + (``'green'``) or hex strings (``'#008000'``). + + **Markers** + + ============= =============================== + character description + ============= =============================== + ``'.'`` point marker + ``','`` pixel marker + ``'o'`` circle marker + ``'v'`` triangle_down marker + ``'^'`` triangle_up marker + ``'<'`` triangle_left marker + ``'>'`` triangle_right marker + ``'1'`` tri_down marker + ``'2'`` tri_up marker + ``'3'`` tri_left marker + ``'4'`` tri_right marker + ``'s'`` square marker + ``'p'`` pentagon marker + ``'*'`` star marker + ``'h'`` hexagon1 marker + ``'H'`` hexagon2 marker + ``'+'`` plus marker + ``'x'`` x marker + ``'D'`` diamond marker + ``'d'`` thin_diamond marker + ``'|'`` vline marker + ``'_'`` hline marker + ============= =============================== + + **Line Styles** + + ============= =============================== + character description + ============= =============================== + ``'-'`` solid line style + ``'--'`` dashed line style + ``'-.'`` dash-dot line style + ``':'`` dotted line style + ============= =============================== + + Example format strings:: + + 'b' # blue markers with default shape + 'ro' # red circles + 'g-' # green solid line + '--' # dashed line with default color + 'k^:' # black triangle_up markers connected by a dotted line + + """ + scalex = kwargs.pop('scalex', True) + scaley = kwargs.pop('scaley', True) + + if not self._hold: + self.cla() + lines = [] + + kwargs = cbook.normalize_kwargs(kwargs, _alias_map) + + for line in self._get_lines(*args, **kwargs): + self.add_line(line) + lines.append(line) + + self.autoscale_view(scalex=scalex, scaley=scaley) + return lines + + @_preprocess_data(replace_names=["x", "y"], label_namer="y") + @docstring.dedent_interpd + def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False, + **kwargs): + """ + Plot data that contains dates. + + Similar to `.plot`, this plots *y* vs. *x* as lines or markers. + However, the axis labels are formatted as dates depending on *xdate* + and *ydate*. + + Parameters + ---------- + x, y : array-like + The coordinates of the data points. If *xdate* or *ydate* is + *True*, the respective values *x* or *y* are interpreted as + :ref:`Matplotlib dates `. + + fmt : str, optional + The plot format string. For details, see the corresponding + parameter in `.plot`. + + tz : [ *None* | timezone string | :class:`tzinfo` instance] + The time zone to use in labeling dates. If *None*, defaults to + rcParam ``timezone``. + + xdate : bool, optional, default: True + If *True*, the *x*-axis will be interpreted as Matplotlib dates. + + ydate : bool, optional, default: False + If *True*, the *y*-axis will be interpreted as Matplotlib dates. + + + Returns + ------- + lines + A list of `~.Line2D` objects representing the plotted data. + + + Other Parameters + ---------------- + **kwargs + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + + See Also + -------- + matplotlib.dates : Helper functions on dates. + matplotlib.dates.date2num : Convert dates to num. + matplotlib.dates.num2date : Convert num to dates. + matplotlib.dates.drange : Create an equally spaced sequence of dates. + + + Notes + ----- + If you are using custom date tickers and formatters, it may be + necessary to set the formatters/locators after the call to + `.plot_date`. `.plot_date` will set the default tick locator to + `.AutoDateLocator` (if the tick locator is not already set to a + `.DateLocator` instance) and the default tick formatter to + `.AutoDateFormatter` (if the tick formatter is not already set to a + `.DateFormatter` instance). + """ + + if not self._hold: + self.cla() + + if xdate: + self.xaxis_date(tz) + if ydate: + self.yaxis_date(tz) + + ret = self.plot(x, y, fmt, **kwargs) + + self.autoscale_view() + + return ret + + # @_preprocess_data() # let 'plot' do the unpacking.. + @docstring.dedent_interpd + def loglog(self, *args, **kwargs): + """ + Make a plot with log scaling on both the x and y axis. + + Call signatures:: + + loglog([x], y, [fmt], data=None, **kwargs) + loglog([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) + + This is just a thin wrapper around `.plot` which additionally changes + both the x-axis and the y-axis to log scaling. All of the concepts and + parameters of plot can be used here as well. + + The additional parameters *basex/y*, *subsx/y* and *nonposx/y* control + the x/y-axis properties. They are just forwarded to `.Axes.set_xscale` + and `.Axes.set_yscale`. + + Parameters + ---------- + basex, basey : scalar, optional, default 10 + Base of the x/y logarithm. + + subsx, subsy : sequence, optional + The location of the minor x/y ticks. If *None*, reasonable + locations are automatically chosen depending on the number of + decades in the plot. + See `.Axes.set_xscale` / `.Axes.set_yscale` for details. + + nonposx, nonposy : {'mask', 'clip'}, optional, default 'mask' + Non-positive values in x or y can be masked as invalid, or clipped + to a very small positive number. + + Returns + ------- + lines + A list of `~.Line2D` objects representing the plotted data. + + Other Parameters + ---------------- + **kwargs + All parameters supported by `.plot`. + """ + if not self._hold: + self.cla() + + dx = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx'] + if k in kwargs} + dy = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy'] + if k in kwargs} + + self.set_xscale('log', **dx) + self.set_yscale('log', **dy) + + b = self._hold + self._hold = True # we've already processed the hold + l = self.plot(*args, **kwargs) + self._hold = b # restore the hold + + return l + + # @_preprocess_data() # let 'plot' do the unpacking.. + @docstring.dedent_interpd + def semilogx(self, *args, **kwargs): + """ + Make a plot with log scaling on the x axis. + + Call signatures:: + + semilogx([x], y, [fmt], data=None, **kwargs) + semilogx([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) + + This is just a thin wrapper around `.plot` which additionally changes + the x-axis to log scaling. All of the concepts and parameters of plot + can be used here as well. + + The additional parameters *basex*, *subsx* and *nonposx* control the + x-axis properties. They are just forwarded to `.Axes.set_xscale`. + + Parameters + ---------- + basex : scalar, optional, default 10 + Base of the x logarithm. + + subsx : array_like, optional + The location of the minor xticks. If *None*, reasonable locations + are automatically chosen depending on the number of decades in the + plot. See `.Axes.set_xscale` for details. + + nonposx : {'mask', 'clip'}, optional, default 'mask' + Non-positive values in x can be masked as invalid, or clipped to a + very small positive number. + + Returns + ------- + lines + A list of `~.Line2D` objects representing the plotted data. + + Other Parameters + ---------------- + **kwargs + All parameters supported by `.plot`. + """ + if not self._hold: + self.cla() + d = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx'] + if k in kwargs} + + self.set_xscale('log', **d) + b = self._hold + self._hold = True # we've already processed the hold + l = self.plot(*args, **kwargs) + self._hold = b # restore the hold + return l + + # @_preprocess_data() # let 'plot' do the unpacking.. + @docstring.dedent_interpd + def semilogy(self, *args, **kwargs): + """ + Make a plot with log scaling on the y axis. + + Call signatures:: + + semilogy([x], y, [fmt], data=None, **kwargs) + semilogy([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs) + + This is just a thin wrapper around `.plot` which additionally changes + the y-axis to log scaling. All of the concepts and parameters of plot + can be used here as well. + + The additional parameters *basey*, *subsy* and *nonposy* control the + y-axis properties. They are just forwarded to `.Axes.set_yscale`. + + Parameters + ---------- + basey : scalar, optional, default 10 + Base of the y logarithm. + + subsy : array_like, optional + The location of the minor yticks. If *None*, reasonable locations + are automatically chosen depending on the number of decades in the + plot. See `.Axes.set_yscale` for details. + + nonposy : {'mask', 'clip'}, optional, default 'mask' + Non-positive values in y can be masked as invalid, or clipped to a + very small positive number. + + Returns + ------- + lines + A list of `~.Line2D` objects representing the plotted data. + + Other Parameters + ---------------- + **kwargs + All parameters supported by `.plot`. + """ + if not self._hold: + self.cla() + d = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy'] + if k in kwargs} + self.set_yscale('log', **d) + b = self._hold + self._hold = True # we've already processed the hold + l = self.plot(*args, **kwargs) + self._hold = b # restore the hold + + return l + + @_preprocess_data(replace_names=["x"], label_namer="x") + def acorr(self, x, **kwargs): + """ + Plot the autocorrelation of *x*. + + Parameters + ---------- + + x : sequence of scalar + + hold : bool, optional, *deprecated*, default: True + + detrend : callable, optional, default: `mlab.detrend_none` + *x* is detrended by the *detrend* callable. Default is no + normalization. + + normed : bool, optional, default: True + If ``True``, input vectors are normalised to unit length. + + usevlines : bool, optional, default: True + If ``True``, `Axes.vlines` is used to plot the vertical lines from + the origin to the acorr. Otherwise, `Axes.plot` is used. + + maxlags : integer, optional, default: 10 + Number of lags to show. If ``None``, will return all + ``2 * len(x) - 1`` lags. + + Returns + ------- + lags : array (lenth ``2*maxlags+1``) + lag vector. + c : array (length ``2*maxlags+1``) + auto correlation vector. + line : `.LineCollection` or `.Line2D` + `.Artist` added to the axes of the correlation. + + `.LineCollection` if *usevlines* is True + `.Line2D` if *usevlines* is False + b : `.Line2D` or None + Horizontal line at 0 if *usevlines* is True + None *usevlines* is False + + Other Parameters + ---------------- + linestyle : `~matplotlib.lines.Line2D` prop, optional, default: None + Only used if usevlines is ``False``. + + marker : string, optional, default: 'o' + + Notes + ----- + The cross correlation is performed with :func:`numpy.correlate` with + ``mode = 2``. + """ + if "hold" in kwargs: + warnings.warn("the 'hold' kwarg is deprecated", mplDeprecation) + return self.xcorr(x, x, **kwargs) + + @_preprocess_data(replace_names=["x", "y"], label_namer="y") + def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none, + usevlines=True, maxlags=10, **kwargs): + r""" + Plot the cross correlation between *x* and *y*. + + The correlation with lag k is defined as sum_n x[n+k] * conj(y[n]). + + Parameters + ---------- + x : sequence of scalars of length n + + y : sequence of scalars of length n + + hold : bool, optional, *deprecated*, default: True + + detrend : callable, optional, default: `mlab.detrend_none` + *x* is detrended by the *detrend* callable. Default is no + normalization. + + normed : bool, optional, default: True + If ``True``, input vectors are normalised to unit length. + + usevlines : bool, optional, default: True + If ``True``, `Axes.vlines` is used to plot the vertical lines from + the origin to the acorr. Otherwise, `Axes.plot` is used. + + maxlags : int, optional + Number of lags to show. If None, will return all ``2 * len(x) - 1`` + lags. Default is 10. + + Returns + ------- + lags : array (lenth ``2*maxlags+1``) + lag vector. + c : array (length ``2*maxlags+1``) + auto correlation vector. + line : `.LineCollection` or `.Line2D` + `.Artist` added to the axes of the correlation + + `.LineCollection` if *usevlines* is True + `.Line2D` if *usevlines* is False + b : `.Line2D` or None + Horizontal line at 0 if *usevlines* is True + None *usevlines* is False + + Other Parameters + ---------------- + linestyle : `~matplotlib.lines.Line2D` property, optional + Only used if usevlines is ``False``. + + marker : string, optional + Default is 'o'. + + Notes + ----- + The cross correlation is performed with :func:`numpy.correlate` with + ``mode = 2``. + """ + if "hold" in kwargs: + warnings.warn("the 'hold' kwarg is deprecated", mplDeprecation) + + Nx = len(x) + if Nx != len(y): + raise ValueError('x and y must be equal length') + + x = detrend(np.asarray(x)) + y = detrend(np.asarray(y)) + + correls = np.correlate(x, y, mode=2) + + if normed: + correls /= np.sqrt(np.dot(x, x) * np.dot(y, y)) + + if maxlags is None: + maxlags = Nx - 1 + + if maxlags >= Nx or maxlags < 1: + raise ValueError('maxlags must be None or strictly ' + 'positive < %d' % Nx) + + lags = np.arange(-maxlags, maxlags + 1) + correls = correls[Nx - 1 - maxlags:Nx + maxlags] + + if usevlines: + a = self.vlines(lags, [0], correls, **kwargs) + # Make label empty so only vertical lines get a legend entry + kwargs.pop('label', '') + b = self.axhline(**kwargs) + else: + kwargs.setdefault('marker', 'o') + kwargs.setdefault('linestyle', 'None') + a, = self.plot(lags, correls, **kwargs) + b = None + return lags, correls, a, b + + #### Specialized plotting + + @_preprocess_data(replace_names=["x", "y"], label_namer="y") + def step(self, x, y, *args, **kwargs): + """ + Make a step plot. + + Call signatures:: + + step(x, y, [fmt], *, data=None, where='pre', **kwargs) + step(x, y, [fmt], x2, y2, [fmt2], ..., *, where='pre', **kwargs) + + This is just a thin wrapper around `.plot` which changes some + formatting options. Most of the concepts and parameters of plot can be + used here as well. + + Parameters + ---------- + x : array_like + 1-D sequence of x positions. It is assumed, but not checked, that + it is uniformly increasing. + + y : array_like + 1-D sequence of y levels. + + fmt : str, optional + A format string, e.g. 'g' for a green line. See `.plot` for a more + detailed description. + + Note: While full format strings are accepted, it is recommended to + only specify the color. Line styles are currently ignored (use + the keyword argument *linestyle* instead). Markers are accepted + and plotted on the given positions, however, this is a rarely + needed feature for step plots. + + data : indexable object, optional + An object with labelled data. If given, provide the label names to + plot in *x* and *y*. + + where : {'pre', 'post', 'mid'}, optional, default 'pre' + Define where the steps should be placed: + + - 'pre': The y value is continued constantly to the left from + every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the + value ``y[i]``. + - 'post': The y value is continued constantly to the right from + every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the + value ``y[i]``. + - 'mid': Steps occur half-way between the *x* positions. + + Returns + ------- + lines + A list of `.Line2D` objects representing the plotted data. + + Other Parameters + ---------------- + **kwargs + Additional parameters are the same as those for `.plot`. + + Notes + ----- + .. [notes section required to get data note injection right] + """ + where = kwargs.pop('where', 'pre') + if where not in ('pre', 'post', 'mid'): + raise ValueError("'where' argument to step must be " + "'pre', 'post' or 'mid'") + usr_linestyle = kwargs.pop('linestyle', '') + kwargs['linestyle'] = 'steps-' + where + usr_linestyle + + return self.plot(x, y, *args, **kwargs) + + @_preprocess_data(replace_names=["x", "left", + "height", "width", + "y", "bottom", + "color", "edgecolor", "linewidth", + "tick_label", "xerr", "yerr", + "ecolor"], + label_namer=None, + replace_all_args=True + ) + @docstring.dedent_interpd + def bar(self, *args, **kwargs): + r""" + Make a bar plot. + + Call signatures:: + + bar(x, height, *, align='center', **kwargs) + bar(x, height, width, *, align='center', **kwargs) + bar(x, height, width, bottom, *, align='center', **kwargs) + + The bars are positioned at *x* with the given *align* ment. Their + dimensions are given by *width* and *height*. The vertical baseline + is *bottom* (default 0). + + Each of *x*, *height*, *width*, and *bottom* may either be a scalar + applying to all bars, or it may be a sequence of length N providing a + separate value for each bar. + + + Parameters + ---------- + x : sequence of scalars + The x coordinates of the bars. See also *align* for the + alignment of the bars to the coordinates. + + height : scalar or sequence of scalars + The height(s) of the bars. + + width : scalar or array-like, optional + The width(s) of the bars (default: 0.8). + + bottom : scalar or array-like, optional + The y coordinate(s) of the bars bases (default: 0). + + align : {'center', 'edge'}, optional, default: 'center' + Alignment of the bars to the *x* coordinates: + + - 'center': Center the base on the *x* positions. + - 'edge': Align the left edges of the bars with the *x* positions. + + To align the bars on the right edge pass a negative *width* and + ``align='edge'``. + + Returns + ------- + container : `.BarContainer` + Container with all the bars and optionally errorbars. + + Other Parameters + ---------------- + color : scalar or array-like, optional + The colors of the bar faces. + + edgecolor : scalar or array-like, optional + The colors of the bar edges. + + linewidth : scalar or array-like, optional + Width of the bar edge(s). If 0, don't draw edges. + + tick_label : string or array-like, optional + The tick labels of the bars. + Default: None (Use default numeric labels.) + + xerr, yerr : scalar or array-like of shape(N,) or shape(2,N), optional + If not *None*, add horizontal / vertical errorbars to the bar tips. + The values are +/- sizes relative to the data: + + - scalar: symmetric +/- values for all bars + - shape(N,): symmetric +/- values for each bar + - shape(2,N): Separate - and + values for each bar. First row + contains the lower errors, the second row contains the + upper errors. + - *None*: No errorbar. (Default) + + See :doc:`/gallery/statistics/errorbar_features` + for an example on the usage of ``xerr`` and ``yerr``. + + ecolor : scalar or array-like, optional, default: 'black' + The line color of the errorbars. + + capsize : scalar, optional + The length of the error bar caps in points. + Default: None, which will take the value from + :rc:`errorbar.capsize`. + + error_kw : dict, optional + Dictionary of kwargs to be passed to the `~.Axes.errorbar` + method. Values of *ecolor* or *capsize* defined here take + precedence over the independent kwargs. + + log : bool, optional, default: False + If *True*, set the y-axis to be log scale. + + orientation : {'vertical', 'horizontal'}, optional + *This is for internal use only.* Please use `barh` for + horizontal bar plots. Default: 'vertical'. + + See also + -------- + barh: Plot a horizontal bar plot. + + Notes + ----- + The optional arguments *color*, *edgecolor*, *linewidth*, + *xerr*, and *yerr* can be either scalars or sequences of + length equal to the number of bars. This enables you to use + bar as the basis for stacked bar charts, or candlestick plots. + Detail: *xerr* and *yerr* are passed directly to + :meth:`errorbar`, so they can also have shape 2xN for + independent specification of lower and upper errors. + + Other optional kwargs: + + %(Rectangle)s + + """ + kwargs = cbook.normalize_kwargs(kwargs, mpatches._patch_alias_map) + # this is using the lambdas to do the arg/kwarg unpacking rather + # than trying to re-implement all of that logic our selves. + matchers = [ + (lambda x, height, width=0.8, bottom=None, **kwargs: + (False, x, height, width, bottom, kwargs)), + (lambda left, height, width=0.8, bottom=None, **kwargs: + (True, left, height, width, bottom, kwargs)), + ] + exps = [] + for matcher in matchers: + try: + dp, x, height, width, y, kwargs = matcher(*args, **kwargs) + except TypeError as e: + # This can only come from a no-match as there is + # no other logic in the matchers. + exps.append(e) + else: + break + else: + raise exps[0] + # if we matched the second-case, then the user passed in + # left=val as a kwarg which we want to deprecate + if dp: + warnings.warn( + "The *left* kwarg to `bar` is deprecated use *x* instead. " + "Support for *left* will be removed in Matplotlib 3.0", + mplDeprecation, stacklevel=2) + if not self._hold: + self.cla() + color = kwargs.pop('color', None) + if color is None: + color = self._get_patches_for_fill.get_next_color() + edgecolor = kwargs.pop('edgecolor', None) + linewidth = kwargs.pop('linewidth', None) + + # Because xerr and yerr will be passed to errorbar, + # most dimension checking and processing will be left + # to the errorbar method. + xerr = kwargs.pop('xerr', None) + yerr = kwargs.pop('yerr', None) + error_kw = kwargs.pop('error_kw', dict()) + ecolor = kwargs.pop('ecolor', 'k') + capsize = kwargs.pop('capsize', rcParams["errorbar.capsize"]) + error_kw.setdefault('ecolor', ecolor) + error_kw.setdefault('capsize', capsize) + + if rcParams['_internal.classic_mode']: + align = kwargs.pop('align', 'edge') + else: + align = kwargs.pop('align', 'center') + + orientation = kwargs.pop('orientation', 'vertical') + log = kwargs.pop('log', False) + label = kwargs.pop('label', '') + tick_labels = kwargs.pop('tick_label', None) + + adjust_ylim = False + adjust_xlim = False + + if orientation == 'vertical': + if y is None: + if self.get_yscale() == 'log': + adjust_ylim = True + y = 0 + + elif orientation == 'horizontal': + if x is None: + if self.get_xscale() == 'log': + adjust_xlim = True + x = 0 + + if orientation == 'vertical': + self._process_unit_info(xdata=x, ydata=height, kwargs=kwargs) + if log: + self.set_yscale('log', nonposy='clip') + elif orientation == 'horizontal': + self._process_unit_info(xdata=width, ydata=y, kwargs=kwargs) + if log: + self.set_xscale('log', nonposx='clip') + else: + raise ValueError('invalid orientation: %s' % orientation) + + # lets do some conversions now since some types cannot be + # subtracted uniformly + if self.xaxis is not None: + x = self.convert_xunits(x) + width = self.convert_xunits(width) + if xerr is not None: + xerr = self.convert_xunits(xerr) + + if self.yaxis is not None: + y = self.convert_yunits(y) + height = self.convert_yunits(height) + if yerr is not None: + yerr = self.convert_yunits(yerr) + + x, height, width, y, linewidth = np.broadcast_arrays( + # Make args iterable too. + np.atleast_1d(x), height, width, y, linewidth) + + # Now that units have been converted, set the tick locations. + if orientation == 'vertical': + tick_label_axis = self.xaxis + tick_label_position = x + elif orientation == 'horizontal': + tick_label_axis = self.yaxis + tick_label_position = y + + linewidth = itertools.cycle(np.atleast_1d(linewidth)) + color = itertools.chain(itertools.cycle(mcolors.to_rgba_array(color)), + # Fallback if color == "none". + itertools.repeat([0, 0, 0, 0])) + if edgecolor is None: + edgecolor = itertools.repeat(None) + else: + edgecolor = itertools.chain( + itertools.cycle(mcolors.to_rgba_array(edgecolor)), + # Fallback if edgecolor == "none". + itertools.repeat([0, 0, 0, 0])) + + # We will now resolve the alignment and really have + # left, bottom, width, height vectors + if align == 'center': + if orientation == 'vertical': + left = x - width / 2 + bottom = y + elif orientation == 'horizontal': + bottom = y - height / 2 + left = x + elif align == 'edge': + left = x + bottom = y + else: + raise ValueError('invalid alignment: %s' % align) + + patches = [] + args = zip(left, bottom, width, height, color, edgecolor, linewidth) + for l, b, w, h, c, e, lw in args: + r = mpatches.Rectangle( + xy=(l, b), width=w, height=h, + facecolor=c, + edgecolor=e, + linewidth=lw, + label='_nolegend_', + ) + r.update(kwargs) + r.get_path()._interpolation_steps = 100 + if orientation == 'vertical': + r.sticky_edges.y.append(b) + elif orientation == 'horizontal': + r.sticky_edges.x.append(l) + self.add_patch(r) + patches.append(r) + + holdstate = self._hold + self._hold = True # ensure hold is on before plotting errorbars + + if xerr is not None or yerr is not None: + if orientation == 'vertical': + # using list comps rather than arrays to preserve unit info + ex = [l + 0.5 * w for l, w in zip(left, width)] + ey = [b + h for b, h in zip(bottom, height)] + + elif orientation == 'horizontal': + # using list comps rather than arrays to preserve unit info + ex = [l + w for l, w in zip(left, width)] + ey = [b + 0.5 * h for b, h in zip(bottom, height)] + + error_kw.setdefault("label", '_nolegend_') + + errorbar = self.errorbar(ex, ey, + yerr=yerr, xerr=xerr, + fmt='none', **error_kw) + else: + errorbar = None + + self._hold = holdstate # restore previous hold state + + if adjust_xlim: + xmin, xmax = self.dataLim.intervalx + xmin = min(w for w in width if w > 0) + if xerr is not None: + xmin = xmin - np.max(xerr) + xmin = max(xmin * 0.9, 1e-100) + self.dataLim.intervalx = (xmin, xmax) + + if adjust_ylim: + ymin, ymax = self.dataLim.intervaly + ymin = min(h for h in height if h > 0) + if yerr is not None: + ymin = ymin - np.max(yerr) + ymin = max(ymin * 0.9, 1e-100) + self.dataLim.intervaly = (ymin, ymax) + self.autoscale_view() + + bar_container = BarContainer(patches, errorbar, label=label) + self.add_container(bar_container) + + if tick_labels is not None: + tick_labels = _backports.broadcast_to(tick_labels, len(patches)) + tick_label_axis.set_ticks(tick_label_position) + tick_label_axis.set_ticklabels(tick_labels) + + return bar_container + + @docstring.dedent_interpd + def barh(self, *args, **kwargs): + r""" + Make a horizontal bar plot. + + Call signatures:: + + bar(y, width, *, align='center', **kwargs) + bar(y, width, height, *, align='center', **kwargs) + bar(y, width, height, left, *, align='center', **kwargs) + + The bars are positioned at *y* with the given *align*. Their + dimensions are given by *width* and *height*. The horizontal baseline + is *left* (default 0). + + Each of *y*, *width*, *height*, and *left* may either be a scalar + applying to all bars, or it may be a sequence of length N providing a + separate value for each bar. + + + Parameters + ---------- + y : scalar or array-like + The y coordinates of the bars. See also *align* for the + alignment of the bars to the coordinates. + + width : scalar or array-like + The width(s) of the bars. + + height : sequence of scalars, optional, default: 0.8 + The heights of the bars. + + left : sequence of scalars + The x coordinates of the left sides of the bars (default: 0). + + align : {'center', 'edge'}, optional, default: 'center' + Alignment of the base to the *y* coordinates*: + + - 'center': Center the bars on the *y* positions. + - 'edge': Align the bottom edges of the bars with the *y* + positions. + + To align the bars on the top edge pass a negative *height* and + ``align='edge'``. + + Returns + ------- + container : `.BarContainer` + Container with all the bars and optionally errorbars. + + Other Parameters + ---------------- + color : scalar or array-like, optional + The colors of the bar faces. + + edgecolor : scalar or array-like, optional + The colors of the bar edges. + + linewidth : scalar or array-like, optional + Width of the bar edge(s). If 0, don't draw edges. + + tick_label : string or array-like, optional + The tick labels of the bars. + Default: None (Use default numeric labels.) + + xerr, yerr : scalar or array-like of shape(N,) or shape(2,N), optional + If not ``None``, add horizontal / vertical errorbars to the + bar tips. The values are +/- sizes relative to the data: + + - scalar: symmetric +/- values for all bars + - shape(N,): symmetric +/- values for each bar + - shape(2,N): Separate - and + values for each bar. First row + contains the lower errors, the second row contains the + upper errors. + - *None*: No errorbar. (default) + + See :doc:`/gallery/statistics/errorbar_features` + for an example on the usage of ``xerr`` and ``yerr``. + + ecolor : scalar or array-like, optional, default: 'black' + The line color of the errorbars. + + capsize : scalar, optional + The length of the error bar caps in points. + Default: None, which will take the value from + :rc:`errorbar.capsize`. + + error_kw : dict, optional + Dictionary of kwargs to be passed to the `~.Axes.errorbar` + method. Values of *ecolor* or *capsize* defined here take + precedence over the independent kwargs. + + log : bool, optional, default: False + If ``True``, set the x-axis to be log scale. + + See also + -------- + bar: Plot a vertical bar plot. + + Notes + ----- + The optional arguments *color*, *edgecolor*, *linewidth*, + *xerr*, and *yerr* can be either scalars or sequences of + length equal to the number of bars. This enables you to use + bar as the basis for stacked bar charts, or candlestick plots. + Detail: *xerr* and *yerr* are passed directly to + :meth:`errorbar`, so they can also have shape 2xN for + independent specification of lower and upper errors. + + Other optional kwargs: + + %(Rectangle)s + + """ + # this is using the lambdas to do the arg/kwarg unpacking rather + # than trying to re-implement all of that logic our selves. + matchers = [ + (lambda y, width, height=0.8, left=None, **kwargs: + (False, y, width, height, left, kwargs)), + (lambda bottom, width, height=0.8, left=None, **kwargs: + (True, bottom, width, height, left, kwargs)), + ] + excs = [] + for matcher in matchers: + try: + dp, y, width, height, left, kwargs = matcher(*args, **kwargs) + except TypeError as e: + # This can only come from a no-match as there is + # no other logic in the matchers. + excs.append(e) + else: + break + else: + raise excs[0] + + if dp: + warnings.warn( + "The *bottom* kwarg to `barh` is deprecated use *y* instead. " + "Support for *bottom* will be removed in Matplotlib 3.0", + mplDeprecation, stacklevel=2) + kwargs.setdefault('orientation', 'horizontal') + patches = self.bar(x=left, height=height, width=width, + bottom=y, **kwargs) + return patches + + @_preprocess_data(label_namer=None) + @docstring.dedent_interpd + def broken_barh(self, xranges, yrange, **kwargs): + """ + Plot a horizontal sequence of rectangles. + + A rectangle is drawn for each element of *xranges*. All rectangles + have the same vertical position and size defined by *yrange*. + + This is a convenience function for instantiating a + `.BrokenBarHCollection`, adding it to the axes and autoscaling the + view. + + Parameters + ---------- + xranges : sequence of tuples (*xmin*, *xwidth*) + The x-positions and extends of the rectangles. For each tuple + (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* + + *xwidth*. + yranges : (*ymin*, *ymax*) + The y-position and extend for all the rectangles. + + Other Parameters + ---------------- + **kwargs : :class:`.BrokenBarHCollection` properties + + Each *kwarg* can be either a single argument applying to all + rectangles, e.g.:: + + facecolors='black' + + or a sequence of arguments over which is cycled, e.g.:: + + facecolors=('black', 'blue') + + would create interleaving black and blue rectangles. + + Supported keywords: + + %(BrokenBarHCollection)s + + Returns + ------- + collection : A :class:`~.collections.BrokenBarHCollection` + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + # process the unit information + if len(xranges): + xdata = cbook.safe_first_element(xranges) + else: + xdata = None + if len(yrange): + ydata = cbook.safe_first_element(yrange) + else: + ydata = None + self._process_unit_info(xdata=xdata, + ydata=ydata, + kwargs=kwargs) + xranges = self.convert_xunits(xranges) + yrange = self.convert_yunits(yrange) + + col = mcoll.BrokenBarHCollection(xranges, yrange, **kwargs) + self.add_collection(col, autolim=True) + self.autoscale_view() + + return col + + @_preprocess_data(replace_all_args=True, label_namer=None) + def stem(self, *args, **kwargs): + """ + Create a stem plot. + + A stem plot plots vertical lines at each *x* location from the baseline + to *y*, and places a marker there. + + Call signature:: + + stem([x,] y, linefmt=None, markerfmt=None, basefmt=None) + + The x-positions are optional. The formats may be provided either as + positional or as keyword-arguments. + + Parameters + ---------- + x : array-like, optional + The x-positions of the stems. Default: (0, 1, ..., len(y) - 1). + + y : array-like + The y-values of the stem heads. + + linefmt : str, optional + A string defining the properties of the vertical lines. Usually, + this will be a color or a color and a linestyle: + + ========= ============= + Character Line Style + ========= ============= + ``'-'`` solid line + ``'--'`` dashed line + ``'-.'`` dash-dot line + ``':'`` dotted line + ========= ============= + + Default: 'C0-', i.e. solid line with the first color of the color + cycle. + + Note: While it is technically possible to specify valid formats + other than color or color and linestyle (e.g. 'rx' or '-.'), this + is beyond the intention of the method and will most likely not + result in a reasonable reasonable plot. + + markerfmt : str, optional + A string defining the properties of the markers at the stem heads. + Default: 'C0o', i.e. filled circles with the first color of the + color cycle. + + basefmt : str, optional + A format string defining the properties of the baseline. + + Default: 'C3-' ('C2-' in classic mode). + + bottom : float, optional, default: 0 + The y-position of the baseline. + + label : str, optional, default: None + The label to use for the stems in legends. + + + Other Parameters + ---------------- + **kwargs + No other parameters are supported. They are currently ignored + silently for backward compatibility. This behavior is deprecated. + Future versions will not accept any other parameters and will + raise a TypeError instead. + + + Returns + ------- + container : :class:`~matplotlib.container.StemContainer` + The container may be treated like a tuple + (*markerline*, *stemlines*, *baseline*) + + + Notes + ----- + + .. seealso:: + The MATLAB function + `stem `_ + which inspired this method. + + """ + + # kwargs handling + # We would like to have a signature with explicit kewords: + # stem(*args, linefmt=None, markerfmt=None, basefmt=None, + # bottom=0, label=None) + # Unfortunately, this is not supported in Python 2.x. There, *args + # can only exist after keyword arguments. + linefmt = kwargs.pop('linefmt', None) + markerfmt = kwargs.pop('markerfmt', None) + basefmt = kwargs.pop('basefmt', None) + bottom = kwargs.pop('bottom', None) + if bottom is None: + bottom = 0 + label = kwargs.pop('label', None) + if kwargs: + warn_deprecated(since='2.2', + message="stem() got an unexpected keyword " + "argument '%s'. This will raise a " + "TypeError in future versions." % ( + next(k for k in kwargs), ) + ) + + remember_hold = self._hold + if not self._hold: + self.cla() + self._hold = True + + # Assume there's at least one data array + y = np.asarray(args[0]) + args = args[1:] + + # Try a second one + try: + second = np.asarray(args[0], dtype=float) + x, y = y, second + args = args[1:] + except (IndexError, ValueError): + # The second array doesn't make sense, or it doesn't exist + second = np.arange(len(y)) + x = second + + # defaults for formats + if linefmt is None: + try: + # fallback to positional argument + linefmt = args[0] + except IndexError: + linecolor = 'C0' + linemarker = 'None' + linestyle = '-' + else: + linestyle, linemarker, linecolor = \ + _process_plot_format(linefmt) + else: + linestyle, linemarker, linecolor = _process_plot_format(linefmt) + + if markerfmt is None: + try: + # fallback to positional argument + markerfmt = args[1] + except IndexError: + markercolor = 'C0' + markermarker = 'o' + markerstyle = 'None' + else: + markerstyle, markermarker, markercolor = \ + _process_plot_format(markerfmt) + else: + markerstyle, markermarker, markercolor = \ + _process_plot_format(markerfmt) + + if basefmt is None: + try: + # fallback to positional argument + basefmt = args[2] + except IndexError: + if rcParams['_internal.classic_mode']: + basecolor = 'C2' + else: + basecolor = 'C3' + basemarker = 'None' + basestyle = '-' + else: + basestyle, basemarker, basecolor = \ + _process_plot_format(basefmt) + else: + basestyle, basemarker, basecolor = _process_plot_format(basefmt) + + markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle, + marker=markermarker, label="_nolegend_") + + stemlines = [] + for thisx, thisy in zip(x, y): + l, = self.plot([thisx, thisx], [bottom, thisy], + color=linecolor, linestyle=linestyle, + marker=linemarker, label="_nolegend_") + stemlines.append(l) + + baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom], + color=basecolor, linestyle=basestyle, + marker=basemarker, label="_nolegend_") + + self._hold = remember_hold + + stem_container = StemContainer((markerline, stemlines, baseline), + label=label) + self.add_container(stem_container) + + return stem_container + + @_preprocess_data(replace_names=["x", "explode", "labels", "colors"], + label_namer=None) + def pie(self, x, explode=None, labels=None, colors=None, + autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1, + startangle=None, radius=None, counterclock=True, + wedgeprops=None, textprops=None, center=(0, 0), + frame=False, rotatelabels=False): + """ + Plot a pie chart. + + Make a pie chart of array *x*. The fractional area of each wedge is + given by ``x/sum(x)``. If ``sum(x) < 1``, then the values of *x* give + the fractional area directly and the array will not be normalized. The + resulting pie will have an empty wedge of size ``1 - sum(x)``. + + The wedges are plotted counterclockwise, by default starting from the + x-axis. + + Parameters + ---------- + x : array-like + The wedge sizes. + + explode : array-like, optional, default: None + If not *None*, is a ``len(x)`` array which specifies the fraction + of the radius with which to offset each wedge. + + labels : list, optional, default: None + A sequence of strings providing the labels for each wedge + + colors : array-like, optional, default: None + A sequence of matplotlib color args through which the pie chart + will cycle. If *None*, will use the colors in the currently + active cycle. + + autopct : None (default), string, or function, optional + If not *None*, is a string or function used to label the wedges + with their numeric value. The label will be placed inside the + wedge. If it is a format string, the label will be ``fmt%pct``. + If it is a function, it will be called. + + pctdistance : float, optional, default: 0.6 + The ratio between the center of each pie slice and the start of + the text generated by *autopct*. Ignored if *autopct* is *None*. + + shadow : bool, optional, default: False + Draw a shadow beneath the pie. + + labeldistance : float, optional, default: 1.1 + The radial distance at which the pie labels are drawn + + startangle : float, optional, default: None + If not *None*, rotates the start of the pie chart by *angle* + degrees counterclockwise from the x-axis. + + radius : float, optional, default: None + The radius of the pie, if *radius* is *None* it will be set to 1. + + counterclock : bool, optional, default: True + Specify fractions direction, clockwise or counterclockwise. + + wedgeprops : dict, optional, default: None + Dict of arguments passed to the wedge objects making the pie. + For example, you can pass in ``wedgeprops = {'linewidth': 3}`` + to set the width of the wedge border lines equal to 3. + For more details, look at the doc/arguments of the wedge object. + By default ``clip_on=False``. + + textprops : dict, optional, default: None + Dict of arguments to pass to the text objects. + + center : list of float, optional, default: (0, 0) + Center position of the chart. Takes value (0, 0) or is a sequence + of 2 scalars. + + frame : bool, optional, default: False + Plot axes frame with the chart if true. + + rotatelabels : bool, optional, default: False + Rotate each label to the angle of the corresponding slice if true. + + Returns + ------- + patches : list + A sequence of :class:`matplotlib.patches.Wedge` instances + + texts : list + A list of the label :class:`matplotlib.text.Text` instances. + + autotexts : list + A list of :class:`~matplotlib.text.Text` instances for the numeric + labels. This will only be returned if the parameter *autopct* is + not *None*. + + Notes + ----- + The pie chart will probably look best if the figure and axes are + square, or the Axes aspect is equal. + """ + x = np.array(x, np.float32) + + sx = x.sum() + if sx > 1: + x /= sx + + if labels is None: + labels = [''] * len(x) + if explode is None: + explode = [0] * len(x) + if len(x) != len(labels): + raise ValueError("'label' must be of length 'x'") + if len(x) != len(explode): + raise ValueError("'explode' must be of length 'x'") + if colors is None: + get_next_color = self._get_patches_for_fill.get_next_color + else: + color_cycle = itertools.cycle(colors) + + def get_next_color(): + return next(color_cycle) + + if radius is None: + radius = 1 + + # Starting theta1 is the start fraction of the circle + if startangle is None: + theta1 = 0 + else: + theta1 = startangle / 360.0 + + # set default values in wedge_prop + if wedgeprops is None: + wedgeprops = {} + wedgeprops.setdefault('clip_on', False) + + if textprops is None: + textprops = {} + textprops.setdefault('clip_on', False) + + texts = [] + slices = [] + autotexts = [] + + i = 0 + for frac, label, expl in zip(x, labels, explode): + x, y = center + theta2 = (theta1 + frac) if counterclock else (theta1 - frac) + thetam = 2 * np.pi * 0.5 * (theta1 + theta2) + x += expl * math.cos(thetam) + y += expl * math.sin(thetam) + + w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2), + 360. * max(theta1, theta2), + facecolor=get_next_color(), + **wedgeprops) + slices.append(w) + self.add_patch(w) + w.set_label(label) + + if shadow: + # make sure to add a shadow after the call to + # add_patch so the figure and transform props will be + # set + shad = mpatches.Shadow(w, -0.02, -0.02) + shad.set_zorder(0.9 * w.get_zorder()) + shad.set_label('_nolegend_') + self.add_patch(shad) + + xt = x + labeldistance * radius * math.cos(thetam) + yt = y + labeldistance * radius * math.sin(thetam) + label_alignment_h = xt > 0 and 'left' or 'right' + label_alignment_v = 'center' + label_rotation = 'horizontal' + if rotatelabels: + label_alignment_v = yt > 0 and 'bottom' or 'top' + label_rotation = np.rad2deg(thetam) + (0 if xt > 0 else 180) + + t = self.text(xt, yt, label, + size=rcParams['xtick.labelsize'], + horizontalalignment=label_alignment_h, + verticalalignment=label_alignment_v, + rotation=label_rotation, + **textprops) + + texts.append(t) + + if autopct is not None: + xt = x + pctdistance * radius * math.cos(thetam) + yt = y + pctdistance * radius * math.sin(thetam) + if isinstance(autopct, six.string_types): + s = autopct % (100. * frac) + elif callable(autopct): + s = autopct(100. * frac) + else: + raise TypeError( + 'autopct must be callable or a format string') + + t = self.text(xt, yt, s, + horizontalalignment='center', + verticalalignment='center', + **textprops) + + autotexts.append(t) + + theta1 = theta2 + i += 1 + + if not frame: + self.set_frame_on(False) + + self.set_xlim((-1.25 + center[0], + 1.25 + center[0])) + self.set_ylim((-1.25 + center[1], + 1.25 + center[1])) + self.set_xticks([]) + self.set_yticks([]) + + if autopct is None: + return slices, texts + else: + return slices, texts, autotexts + + @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"], + label_namer="y") + @docstring.dedent_interpd + def errorbar(self, x, y, yerr=None, xerr=None, + fmt='', ecolor=None, elinewidth=None, capsize=None, + barsabove=False, lolims=False, uplims=False, + xlolims=False, xuplims=False, errorevery=1, capthick=None, + **kwargs): + """ + Plot y versus x as lines and/or markers with attached errorbars. + + *x*, *y* define the data locations, *xerr*, *yerr* define the errorbar + sizes. By default, this draws the data markers/lines as well the + errorbars. Use fmt='none' to draw errorbars without any data markers. + + Parameters + ---------- + x, y : scalar or array-like + The data positions. + + xerr, yerr : scalar or array-like, shape(N,) or shape(2,N), optional + The errorbar sizes: + + - scalar: Symmetric +/- values for all data points. + - shape(N,): Symmetric +/-values for each data point. + - shape(2,N): Separate - and + values for each bar. First row + contains the lower errors, the second row contains the + upper errors. + - *None*: No errorbar. + + See :doc:`/gallery/statistics/errorbar_features` + for an example on the usage of ``xerr`` and ``yerr``. + + fmt : plot format string, optional, default: '' + The format for the data points / data lines. See `.plot` for + details. + + Use 'none' (case insensitive) to plot errorbars without any data + markers. + + ecolor : mpl color, optional, default: None + A matplotlib color arg which gives the color the errorbar lines. + If None, use the color of the line connecting the markers. + + elinewidth : scalar, optional, default: None + The linewidth of the errorbar lines. If None, the linewidth of + the current style is used. + + capsize : scalar, optional, default: None + The length of the error bar caps in points. If None, it will take + the value from :rc:`errorbar.capsize`. + + capthick : scalar, optional, default: None + An alias to the keyword argument *markeredgewidth* (a.k.a. *mew*). + This setting is a more sensible name for the property that + controls the thickness of the error bar cap in points. For + backwards compatibility, if *mew* or *markeredgewidth* are given, + then they will over-ride *capthick*. This may change in future + releases. + + barsabove : bool, optional, default: False + If True, will plot the errorbars above the plot + symbols. Default is below. + + lolims, uplims, xlolims, xuplims : bool, optional, default: None + These arguments can be used to indicate that a value gives only + upper/lower limits. In that case a caret symbol is used to + indicate this. *lims*-arguments may be of the same type as *xerr* + and *yerr*. To use limits with inverted axes, :meth:`set_xlim` + or :meth:`set_ylim` must be called before :meth:`errorbar`. + + errorevery : positive integer, optional, default: 1 + Subsamples the errorbars. e.g., if errorevery=5, errorbars for + every 5-th datapoint will be plotted. The data plot itself still + shows all data points. + + Returns + ------- + container : :class:`~.container.ErrorbarContainer` + The container contains: + + - plotline: :class:`~matplotlib.lines.Line2D` instance of + x, y plot markers and/or line. + - caplines: A tuple of :class:`~matplotlib.lines.Line2D` instances + of the error bar caps. + - barlinecols: A tuple of + :class:`~matplotlib.collections.LineCollection` with the + horizontal and vertical error ranges. + + Other Parameters + ---------------- + **kwargs : + All other keyword arguments are passed on to the plot + command for the markers. For example, this code makes big red + squares with thick green edges:: + + x,y,yerr = rand(3,10) + errorbar(x, y, yerr, marker='s', mfc='red', + mec='green', ms=20, mew=4) + + where *mfc*, *mec*, *ms* and *mew* are aliases for the longer + property names, *markerfacecolor*, *markeredgecolor*, *markersize* + and *markeredgewidth*. + + Valid kwargs for the marker properties are `.Lines2D` properties: + + %(Line2D)s + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + kwargs = cbook.normalize_kwargs(kwargs, _alias_map) + # anything that comes in as 'None', drop so the default thing + # happens down stream + kwargs = {k: v for k, v in kwargs.items() if v is not None} + kwargs.setdefault('zorder', 2) + + if errorevery < 1: + raise ValueError( + 'errorevery has to be a strictly positive integer') + + self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) + if not self._hold: + self.cla() + holdstate = self._hold + self._hold = True + + plot_line = (fmt.lower() != 'none') + label = kwargs.pop("label", None) + + if fmt == '': + fmt_style_kwargs = {} + else: + fmt_style_kwargs = {k: v for k, v in + zip(('linestyle', 'marker', 'color'), + _process_plot_format(fmt)) if v is not None} + if fmt == 'none': + # Remove alpha=0 color that _process_plot_format returns + fmt_style_kwargs.pop('color') + + if ('color' in kwargs or 'color' in fmt_style_kwargs or + ecolor is not None): + base_style = {} + if 'color' in kwargs: + base_style['color'] = kwargs.pop('color') + else: + base_style = next(self._get_lines.prop_cycler) + + base_style['label'] = '_nolegend_' + base_style.update(fmt_style_kwargs) + if 'color' not in base_style: + base_style['color'] = 'C0' + if ecolor is None: + ecolor = base_style['color'] + # make sure all the args are iterable; use lists not arrays to + # preserve units + if not iterable(x): + x = [x] + + if not iterable(y): + y = [y] + + if xerr is not None: + if not iterable(xerr): + xerr = [xerr] * len(x) + + if yerr is not None: + if not iterable(yerr): + yerr = [yerr] * len(y) + + # make the style dict for the 'normal' plot line + plot_line_style = dict(base_style) + plot_line_style.update(**kwargs) + if barsabove: + plot_line_style['zorder'] = kwargs['zorder'] - .1 + else: + plot_line_style['zorder'] = kwargs['zorder'] + .1 + + # make the style dict for the line collections (the bars) + eb_lines_style = dict(base_style) + eb_lines_style.pop('marker', None) + eb_lines_style.pop('linestyle', None) + eb_lines_style['color'] = ecolor + + if elinewidth: + eb_lines_style['linewidth'] = elinewidth + elif 'linewidth' in kwargs: + eb_lines_style['linewidth'] = kwargs['linewidth'] + + for key in ('transform', 'alpha', 'zorder', 'rasterized'): + if key in kwargs: + eb_lines_style[key] = kwargs[key] + + # set up cap style dictionary + eb_cap_style = dict(base_style) + # eject any marker information from format string + eb_cap_style.pop('marker', None) + eb_lines_style.pop('markerfacecolor', None) + eb_lines_style.pop('markeredgewidth', None) + eb_lines_style.pop('markeredgecolor', None) + eb_cap_style.pop('ls', None) + eb_cap_style['linestyle'] = 'none' + if capsize is None: + capsize = rcParams["errorbar.capsize"] + if capsize > 0: + eb_cap_style['markersize'] = 2. * capsize + if capthick is not None: + eb_cap_style['markeredgewidth'] = capthick + + # For backwards-compat, allow explicit setting of + # 'markeredgewidth' to over-ride capthick. + for key in ('markeredgewidth', 'transform', 'alpha', + 'zorder', 'rasterized'): + if key in kwargs: + eb_cap_style[key] = kwargs[key] + eb_cap_style['color'] = ecolor + + data_line = None + if plot_line: + data_line = mlines.Line2D(x, y, **plot_line_style) + self.add_line(data_line) + + barcols = [] + caplines = [] + + # arrays fine here, they are booleans and hence not units + def _bool_asarray_helper(d, expected): + if not iterable(d): + return np.asarray([d] * expected, bool) + else: + return np.asarray(d, bool) + + lolims = _bool_asarray_helper(lolims, len(x)) + uplims = _bool_asarray_helper(uplims, len(x)) + xlolims = _bool_asarray_helper(xlolims, len(x)) + xuplims = _bool_asarray_helper(xuplims, len(x)) + + everymask = np.arange(len(x)) % errorevery == 0 + + def xywhere(xs, ys, mask): + """ + return xs[mask], ys[mask] where mask is True but xs and + ys are not arrays + """ + assert len(xs) == len(ys) + assert len(xs) == len(mask) + xs = [thisx for thisx, b in zip(xs, mask) if b] + ys = [thisy for thisy, b in zip(ys, mask) if b] + return xs, ys + + def extract_err(err, data): + '''private function to compute error bars + + Parameters + ---------- + err : iterable + xerr or yerr from errorbar + data : iterable + x or y from errorbar + ''' + try: + a, b = err + except (TypeError, ValueError): + pass + else: + if iterable(a) and iterable(b): + # using list comps rather than arrays to preserve units + low = [thisx - thiserr for (thisx, thiserr) + in cbook.safezip(data, a)] + high = [thisx + thiserr for (thisx, thiserr) + in cbook.safezip(data, b)] + return low, high + # Check if xerr is scalar or symmetric. Asymmetric is handled + # above. This prevents Nx2 arrays from accidentally + # being accepted, when the user meant the 2xN transpose. + # special case for empty lists + if len(err) > 1: + fe = safe_first_element(err) + if (len(err) != len(data) or np.size(fe) > 1): + raise ValueError("err must be [ scalar | N, Nx1 " + "or 2xN array-like ]") + # using list comps rather than arrays to preserve units + low = [thisx - thiserr for (thisx, thiserr) + in cbook.safezip(data, err)] + high = [thisx + thiserr for (thisx, thiserr) + in cbook.safezip(data, err)] + return low, high + + if xerr is not None: + left, right = extract_err(xerr, x) + # select points without upper/lower limits in x and + # draw normal errorbars for these points + noxlims = ~(xlolims | xuplims) + if noxlims.any() or len(noxlims) == 0: + yo, _ = xywhere(y, right, noxlims & everymask) + lo, ro = xywhere(left, right, noxlims & everymask) + barcols.append(self.hlines(yo, lo, ro, **eb_lines_style)) + if capsize > 0: + caplines.append(mlines.Line2D(lo, yo, marker='|', + **eb_cap_style)) + caplines.append(mlines.Line2D(ro, yo, marker='|', + **eb_cap_style)) + + if xlolims.any(): + yo, _ = xywhere(y, right, xlolims & everymask) + lo, ro = xywhere(x, right, xlolims & everymask) + barcols.append(self.hlines(yo, lo, ro, **eb_lines_style)) + rightup, yup = xywhere(right, y, xlolims & everymask) + if self.xaxis_inverted(): + marker = mlines.CARETLEFTBASE + else: + marker = mlines.CARETRIGHTBASE + caplines.append( + mlines.Line2D(rightup, yup, ls='None', marker=marker, + **eb_cap_style)) + if capsize > 0: + xlo, ylo = xywhere(x, y, xlolims & everymask) + caplines.append(mlines.Line2D(xlo, ylo, marker='|', + **eb_cap_style)) + + if xuplims.any(): + yo, _ = xywhere(y, right, xuplims & everymask) + lo, ro = xywhere(left, x, xuplims & everymask) + barcols.append(self.hlines(yo, lo, ro, **eb_lines_style)) + leftlo, ylo = xywhere(left, y, xuplims & everymask) + if self.xaxis_inverted(): + marker = mlines.CARETRIGHTBASE + else: + marker = mlines.CARETLEFTBASE + caplines.append( + mlines.Line2D(leftlo, ylo, ls='None', marker=marker, + **eb_cap_style)) + if capsize > 0: + xup, yup = xywhere(x, y, xuplims & everymask) + caplines.append(mlines.Line2D(xup, yup, marker='|', + **eb_cap_style)) + + if yerr is not None: + lower, upper = extract_err(yerr, y) + # select points without upper/lower limits in y and + # draw normal errorbars for these points + noylims = ~(lolims | uplims) + if noylims.any() or len(noylims) == 0: + xo, _ = xywhere(x, lower, noylims & everymask) + lo, uo = xywhere(lower, upper, noylims & everymask) + barcols.append(self.vlines(xo, lo, uo, **eb_lines_style)) + if capsize > 0: + caplines.append(mlines.Line2D(xo, lo, marker='_', + **eb_cap_style)) + caplines.append(mlines.Line2D(xo, uo, marker='_', + **eb_cap_style)) + + if lolims.any(): + xo, _ = xywhere(x, lower, lolims & everymask) + lo, uo = xywhere(y, upper, lolims & everymask) + barcols.append(self.vlines(xo, lo, uo, **eb_lines_style)) + xup, upperup = xywhere(x, upper, lolims & everymask) + if self.yaxis_inverted(): + marker = mlines.CARETDOWNBASE + else: + marker = mlines.CARETUPBASE + caplines.append( + mlines.Line2D(xup, upperup, ls='None', marker=marker, + **eb_cap_style)) + if capsize > 0: + xlo, ylo = xywhere(x, y, lolims & everymask) + caplines.append(mlines.Line2D(xlo, ylo, marker='_', + **eb_cap_style)) + + if uplims.any(): + xo, _ = xywhere(x, lower, uplims & everymask) + lo, uo = xywhere(lower, y, uplims & everymask) + barcols.append(self.vlines(xo, lo, uo, **eb_lines_style)) + xlo, lowerlo = xywhere(x, lower, uplims & everymask) + if self.yaxis_inverted(): + marker = mlines.CARETUPBASE + else: + marker = mlines.CARETDOWNBASE + caplines.append( + mlines.Line2D(xlo, lowerlo, ls='None', marker=marker, + **eb_cap_style)) + if capsize > 0: + xup, yup = xywhere(x, y, uplims & everymask) + caplines.append(mlines.Line2D(xup, yup, marker='_', + **eb_cap_style)) + for l in caplines: + self.add_line(l) + + self.autoscale_view() + self._hold = holdstate + + errorbar_container = ErrorbarContainer((data_line, tuple(caplines), + tuple(barcols)), + has_xerr=(xerr is not None), + has_yerr=(yerr is not None), + label=label) + self.containers.append(errorbar_container) + + return errorbar_container # (l0, caplines, barcols) + + @_preprocess_data(label_namer=None) + def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, + positions=None, widths=None, patch_artist=None, + bootstrap=None, usermedians=None, conf_intervals=None, + meanline=None, showmeans=None, showcaps=None, + showbox=None, showfliers=None, boxprops=None, + labels=None, flierprops=None, medianprops=None, + meanprops=None, capprops=None, whiskerprops=None, + manage_xticks=True, autorange=False, zorder=None): + """ + Make a box and whisker plot. + + Make a box and whisker plot for each column of ``x`` or each + vector in sequence ``x``. The box extends from the lower to + upper quartile values of the data, with a line at the median. + The whiskers extend from the box to show the range of the + data. Flier points are those past the end of the whiskers. + + Parameters + ---------- + x : Array or a sequence of vectors. + The input data. + + notch : bool, optional (False) + If `True`, will produce a notched box plot. Otherwise, a + rectangular boxplot is produced. The notches represent the + confidence interval (CI) around the median. See the entry + for the ``bootstrap`` parameter for information regarding + how the locations of the notches are computed. + + .. note:: + + In cases where the values of the CI are less than the + lower quartile or greater than the upper quartile, the + notches will extend beyond the box, giving it a + distinctive "flipped" appearance. This is expected + behavior and consistent with other statistical + visualization packages. + + sym : str, optional + The default symbol for flier points. Enter an empty string + ('') if you don't want to show fliers. If `None`, then the + fliers default to 'b+' If you want more control use the + flierprops kwarg. + + vert : bool, optional (True) + If `True` (default), makes the boxes vertical. If `False`, + everything is drawn horizontally. + + whis : float, sequence, or string (default = 1.5) + As a float, determines the reach of the whiskers to the beyond the + first and third quartiles. In other words, where IQR is the + interquartile range (`Q3-Q1`), the upper whisker will extend to + last datum less than `Q3 + whis*IQR`). Similarly, the lower whisker + will extend to the first datum greater than `Q1 - whis*IQR`. + Beyond the whiskers, data + are considered outliers and are plotted as individual + points. Set this to an unreasonably high value to force the + whiskers to show the min and max values. Alternatively, set + this to an ascending sequence of percentile (e.g., [5, 95]) + to set the whiskers at specific percentiles of the data. + Finally, ``whis`` can be the string ``'range'`` to force the + whiskers to the min and max of the data. + + bootstrap : int, optional + Specifies whether to bootstrap the confidence intervals + around the median for notched boxplots. If ``bootstrap`` is + None, no bootstrapping is performed, and notches are + calculated using a Gaussian-based asymptotic approximation + (see McGill, R., Tukey, J.W., and Larsen, W.A., 1978, and + Kendall and Stuart, 1967). Otherwise, bootstrap specifies + the number of times to bootstrap the median to determine its + 95% confidence intervals. Values between 1000 and 10000 are + recommended. + + usermedians : array-like, optional + An array or sequence whose first dimension (or length) is + compatible with ``x``. This overrides the medians computed + by matplotlib for each element of ``usermedians`` that is not + `None`. When an element of ``usermedians`` is None, the median + will be computed by matplotlib as normal. + + conf_intervals : array-like, optional + Array or sequence whose first dimension (or length) is + compatible with ``x`` and whose second dimension is 2. When + the an element of ``conf_intervals`` is not None, the + notch locations computed by matplotlib are overridden + (provided ``notch`` is `True`). When an element of + ``conf_intervals`` is `None`, the notches are computed by the + method specified by the other kwargs (e.g., ``bootstrap``). + + positions : array-like, optional + Sets the positions of the boxes. The ticks and limits are + automatically set to match the positions. Defaults to + `range(1, N+1)` where N is the number of boxes to be drawn. + + widths : scalar or array-like + Sets the width of each box either with a scalar or a + sequence. The default is 0.5, or ``0.15*(distance between + extreme positions)``, if that is smaller. + + patch_artist : bool, optional (False) + If `False` produces boxes with the Line2D artist. Otherwise, + boxes and drawn with Patch artists. + + labels : sequence, optional + Labels for each dataset. Length must be compatible with + dimensions of ``x``. + + manage_xticks : bool, optional (True) + If the function should adjust the xlim and xtick locations. + + autorange : bool, optional (False) + When `True` and the data are distributed such that the 25th and + 75th percentiles are equal, ``whis`` is set to ``'range'`` such + that the whisker ends are at the minimum and maximum of the + data. + + meanline : bool, optional (False) + If `True` (and ``showmeans`` is `True`), will try to render + the mean as a line spanning the full width of the box + according to ``meanprops`` (see below). Not recommended if + ``shownotches`` is also True. Otherwise, means will be shown + as points. + + zorder : scalar, optional (None) + Sets the zorder of the boxplot. + + Other Parameters + ---------------- + showcaps : bool, optional (True) + Show the caps on the ends of whiskers. + showbox : bool, optional (True) + Show the central box. + showfliers : bool, optional (True) + Show the outliers beyond the caps. + showmeans : bool, optional (False) + Show the arithmetic means. + capprops : dict, optional (None) + Specifies the style of the caps. + boxprops : dict, optional (None) + Specifies the style of the box. + whiskerprops : dict, optional (None) + Specifies the style of the whiskers. + flierprops : dict, optional (None) + Specifies the style of the fliers. + medianprops : dict, optional (None) + Specifies the style of the median. + meanprops : dict, optional (None) + Specifies the style of the mean. + + Returns + ------- + result : dict + A dictionary mapping each component of the boxplot to a list + of the :class:`matplotlib.lines.Line2D` instances + created. That dictionary has the following keys (assuming + vertical boxplots): + + - ``boxes``: the main body of the boxplot showing the + quartiles and the median's confidence intervals if + enabled. + + - ``medians``: horizontal lines at the median of each box. + + - ``whiskers``: the vertical lines extending to the most + extreme, non-outlier data points. + + - ``caps``: the horizontal lines at the ends of the + whiskers. + + - ``fliers``: points representing data that extend beyond + the whiskers (fliers). + + - ``means``: points or lines representing the means. + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + + # If defined in matplotlibrc, apply the value from rc file + # Overridden if argument is passed + if whis is None: + whis = rcParams['boxplot.whiskers'] + if bootstrap is None: + bootstrap = rcParams['boxplot.bootstrap'] + + bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap, + labels=labels, autorange=autorange) + if notch is None: + notch = rcParams['boxplot.notch'] + if vert is None: + vert = rcParams['boxplot.vertical'] + if patch_artist is None: + patch_artist = rcParams['boxplot.patchartist'] + if meanline is None: + meanline = rcParams['boxplot.meanline'] + if showmeans is None: + showmeans = rcParams['boxplot.showmeans'] + if showcaps is None: + showcaps = rcParams['boxplot.showcaps'] + if showbox is None: + showbox = rcParams['boxplot.showbox'] + if showfliers is None: + showfliers = rcParams['boxplot.showfliers'] + + def _update_dict(dictionary, rc_name, properties): + """ Loads properties in the dictionary from rc file if not already + in the dictionary""" + rc_str = 'boxplot.{0}.{1}' + if dictionary is None: + dictionary = dict() + for prop_dict in properties: + dictionary.setdefault(prop_dict, + rcParams[rc_str.format(rc_name, prop_dict)]) + return dictionary + + # Common property dictionnaries loading from rc + flier_props = ['color', 'marker', 'markerfacecolor', 'markeredgecolor', + 'markersize', 'linestyle', 'linewidth'] + default_props = ['color', 'linewidth', 'linestyle'] + + boxprops = _update_dict(boxprops, 'boxprops', default_props) + whiskerprops = _update_dict(whiskerprops, 'whiskerprops', + default_props) + capprops = _update_dict(capprops, 'capprops', default_props) + medianprops = _update_dict(medianprops, 'medianprops', default_props) + meanprops = _update_dict(meanprops, 'meanprops', default_props) + flierprops = _update_dict(flierprops, 'flierprops', flier_props) + + if patch_artist: + boxprops['linestyle'] = 'solid' + boxprops['edgecolor'] = boxprops.pop('color') + + # if non-default sym value, put it into the flier dictionary + # the logic for providing the default symbol ('b+') now lives + # in bxp in the initial value of final_flierprops + # handle all of the `sym` related logic here so we only have to pass + # on the flierprops dict. + if sym is not None: + # no-flier case, which should really be done with + # 'showfliers=False' but none-the-less deal with it to keep back + # compatibility + if sym == '': + # blow away existing dict and make one for invisible markers + flierprops = dict(linestyle='none', marker='', color='none') + # turn the fliers off just to be safe + showfliers = False + # now process the symbol string + else: + # process the symbol string + # discarded linestyle + _, marker, color = _process_plot_format(sym) + # if we have a marker, use it + if marker is not None: + flierprops['marker'] = marker + # if we have a color, use it + if color is not None: + # assume that if color is passed in the user want + # filled symbol, if the users want more control use + # flierprops + flierprops['color'] = color + flierprops['markerfacecolor'] = color + flierprops['markeredgecolor'] = color + + # replace medians if necessary: + if usermedians is not None: + if (len(np.ravel(usermedians)) != len(bxpstats) or + np.shape(usermedians)[0] != len(bxpstats)): + raise ValueError('usermedians length not compatible with x') + else: + # reassign medians as necessary + for stats, med in zip(bxpstats, usermedians): + if med is not None: + stats['med'] = med + + if conf_intervals is not None: + if np.shape(conf_intervals)[0] != len(bxpstats): + err_mess = 'conf_intervals length not compatible with x' + raise ValueError(err_mess) + else: + for stats, ci in zip(bxpstats, conf_intervals): + if ci is not None: + if len(ci) != 2: + raise ValueError('each confidence interval must ' + 'have two values') + else: + if ci[0] is not None: + stats['cilo'] = ci[0] + if ci[1] is not None: + stats['cihi'] = ci[1] + + artists = self.bxp(bxpstats, positions=positions, widths=widths, + vert=vert, patch_artist=patch_artist, + shownotches=notch, showmeans=showmeans, + showcaps=showcaps, showbox=showbox, + boxprops=boxprops, flierprops=flierprops, + medianprops=medianprops, meanprops=meanprops, + meanline=meanline, showfliers=showfliers, + capprops=capprops, whiskerprops=whiskerprops, + manage_xticks=manage_xticks, zorder=zorder) + return artists + + def bxp(self, bxpstats, positions=None, widths=None, vert=True, + patch_artist=False, shownotches=False, showmeans=False, + showcaps=True, showbox=True, showfliers=True, + boxprops=None, whiskerprops=None, flierprops=None, + medianprops=None, capprops=None, meanprops=None, + meanline=False, manage_xticks=True, zorder=None): + """ + Drawing function for box and whisker plots. + + Make a box and whisker plot for each column of *x* or each + vector in sequence *x*. The box extends from the lower to + upper quartile values of the data, with a line at the median. + The whiskers extend from the box to show the range of the + data. Flier points are those past the end of the whiskers. + + Parameters + ---------- + + bxpstats : list of dicts + A list of dictionaries containing stats for each boxplot. + Required keys are: + + - ``med``: The median (scalar float). + + - ``q1``: The first quartile (25th percentile) (scalar + float). + + - ``q3``: The third quartile (75th percentile) (scalar + float). + + - ``whislo``: Lower bound of the lower whisker (scalar + float). + + - ``whishi``: Upper bound of the upper whisker (scalar + float). + + Optional keys are: + + - ``mean``: The mean (scalar float). Needed if + ``showmeans=True``. + + - ``fliers``: Data beyond the whiskers (sequence of floats). + Needed if ``showfliers=True``. + + - ``cilo`` & ``cihi``: Lower and upper confidence intervals + about the median. Needed if ``shownotches=True``. + + - ``label``: Name of the dataset (string). If available, + this will be used a tick label for the boxplot + + positions : array-like, default = [1, 2, ..., n] + Sets the positions of the boxes. The ticks and limits + are automatically set to match the positions. + + widths : array-like, default = None + Either a scalar or a vector and sets the width of each + box. The default is ``0.15*(distance between extreme + positions)``, clipped to no less than 0.15 and no more than + 0.5. + + vert : bool, default = False + If `True` (default), makes the boxes vertical. If `False`, + makes horizontal boxes. + + patch_artist : bool, default = False + If `False` produces boxes with the + `~matplotlib.lines.Line2D` artist. If `True` produces boxes + with the `~matplotlib.patches.Patch` artist. + + shownotches : bool, default = False + If `False` (default), produces a rectangular box plot. + If `True`, will produce a notched box plot + + showmeans : bool, default = False + If `True`, will toggle on the rendering of the means + + showcaps : bool, default = True + If `True`, will toggle on the rendering of the caps + + showbox : bool, default = True + If `True`, will toggle on the rendering of the box + + showfliers : bool, default = True + If `True`, will toggle on the rendering of the fliers + + boxprops : dict or None (default) + If provided, will set the plotting style of the boxes + + whiskerprops : dict or None (default) + If provided, will set the plotting style of the whiskers + + capprops : dict or None (default) + If provided, will set the plotting style of the caps + + flierprops : dict or None (default) + If provided will set the plotting style of the fliers + + medianprops : dict or None (default) + If provided, will set the plotting style of the medians + + meanprops : dict or None (default) + If provided, will set the plotting style of the means + + meanline : bool, default = False + If `True` (and *showmeans* is `True`), will try to render the mean + as a line spanning the full width of the box according to + *meanprops*. Not recommended if *shownotches* is also True. + Otherwise, means will be shown as points. + + manage_xticks : bool, default = True + If the function should adjust the xlim and xtick locations. + + zorder : scalar, default = None + The zorder of the resulting boxplot + + Returns + ------- + result : dict + A dictionary mapping each component of the boxplot to a list + of the :class:`matplotlib.lines.Line2D` instances + created. That dictionary has the following keys (assuming + vertical boxplots): + + - ``boxes``: the main body of the boxplot showing the + quartiles and the median's confidence intervals if + enabled. + + - ``medians``: horizontal lines at the median of each box. + + - ``whiskers``: the vertical lines extending to the most + extreme, non-outlier data points. + + - ``caps``: the horizontal lines at the ends of the + whiskers. + + - ``fliers``: points representing data that extend beyond + the whiskers (fliers). + + - ``means``: points or lines representing the means. + + Examples + -------- + + .. plot:: gallery/statistics/bxp.py + + """ + # lists of artists to be output + whiskers = [] + caps = [] + boxes = [] + medians = [] + means = [] + fliers = [] + + # empty list of xticklabels + datalabels = [] + + # Use default zorder if none specified + if zorder is None: + zorder = mlines.Line2D.zorder + + zdelta = 0.1 + # box properties + if patch_artist: + final_boxprops = dict( + linestyle=rcParams['boxplot.boxprops.linestyle'], + edgecolor=rcParams['boxplot.boxprops.color'], + facecolor=rcParams['patch.facecolor'], + linewidth=rcParams['boxplot.boxprops.linewidth'] + ) + if rcParams['_internal.classic_mode']: + final_boxprops['facecolor'] = 'white' + else: + final_boxprops = dict( + linestyle=rcParams['boxplot.boxprops.linestyle'], + color=rcParams['boxplot.boxprops.color'], + ) + + final_boxprops['zorder'] = zorder + if boxprops is not None: + final_boxprops.update(boxprops) + + # other (cap, whisker) properties + final_whiskerprops = dict( + linestyle=rcParams['boxplot.whiskerprops.linestyle'], + linewidth=rcParams['boxplot.whiskerprops.linewidth'], + color=rcParams['boxplot.whiskerprops.color'], + ) + + final_capprops = dict( + linestyle=rcParams['boxplot.capprops.linestyle'], + linewidth=rcParams['boxplot.capprops.linewidth'], + color=rcParams['boxplot.capprops.color'], + ) + + final_capprops['zorder'] = zorder + if capprops is not None: + final_capprops.update(capprops) + + final_whiskerprops['zorder'] = zorder + if whiskerprops is not None: + final_whiskerprops.update(whiskerprops) + + # set up the default flier properties + final_flierprops = dict( + linestyle=rcParams['boxplot.flierprops.linestyle'], + linewidth=rcParams['boxplot.flierprops.linewidth'], + color=rcParams['boxplot.flierprops.color'], + marker=rcParams['boxplot.flierprops.marker'], + markerfacecolor=rcParams['boxplot.flierprops.markerfacecolor'], + markeredgecolor=rcParams['boxplot.flierprops.markeredgecolor'], + markersize=rcParams['boxplot.flierprops.markersize'], + ) + + final_flierprops['zorder'] = zorder + # flier (outlier) properties + if flierprops is not None: + final_flierprops.update(flierprops) + + # median line properties + final_medianprops = dict( + linestyle=rcParams['boxplot.medianprops.linestyle'], + linewidth=rcParams['boxplot.medianprops.linewidth'], + color=rcParams['boxplot.medianprops.color'], + ) + final_medianprops['zorder'] = zorder + zdelta + if medianprops is not None: + final_medianprops.update(medianprops) + + # mean (line or point) properties + if meanline: + final_meanprops = dict( + linestyle=rcParams['boxplot.meanprops.linestyle'], + linewidth=rcParams['boxplot.meanprops.linewidth'], + color=rcParams['boxplot.meanprops.color'], + ) + else: + final_meanprops = dict( + linestyle='', + marker=rcParams['boxplot.meanprops.marker'], + markerfacecolor=rcParams['boxplot.meanprops.markerfacecolor'], + markeredgecolor=rcParams['boxplot.meanprops.markeredgecolor'], + markersize=rcParams['boxplot.meanprops.markersize'], + ) + final_meanprops['zorder'] = zorder + zdelta + if meanprops is not None: + final_meanprops.update(meanprops) + + def to_vc(xs, ys): + # convert arguments to verts and codes, append (0, 0) (ignored). + verts = np.append(np.column_stack([xs, ys]), [(0, 0)], 0) + codes = ([mpath.Path.MOVETO] + + [mpath.Path.LINETO] * (len(verts) - 2) + + [mpath.Path.CLOSEPOLY]) + return verts, codes + + def patch_list(xs, ys, **kwargs): + verts, codes = to_vc(xs, ys) + path = mpath.Path(verts, codes) + patch = mpatches.PathPatch(path, **kwargs) + self.add_artist(patch) + return [patch] + + # vertical or horizontal plot? + if vert: + def doplot(*args, **kwargs): + return self.plot(*args, **kwargs) + + def dopatch(xs, ys, **kwargs): + return patch_list(xs, ys, **kwargs) + + else: + def doplot(*args, **kwargs): + shuffled = [] + for i in xrange(0, len(args), 2): + shuffled.extend([args[i + 1], args[i]]) + return self.plot(*shuffled, **kwargs) + + def dopatch(xs, ys, **kwargs): + xs, ys = ys, xs # flip X, Y + return patch_list(xs, ys, **kwargs) + + # input validation + N = len(bxpstats) + datashape_message = ("List of boxplot statistics and `{0}` " + "values must have same the length") + # check position + if positions is None: + positions = list(xrange(1, N + 1)) + elif len(positions) != N: + raise ValueError(datashape_message.format("positions")) + + # width + if widths is None: + widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N + elif np.isscalar(widths): + widths = [widths] * N + elif len(widths) != N: + raise ValueError(datashape_message.format("widths")) + + # check and save the `hold` state of the current axes + if not self._hold: + self.cla() + holdStatus = self._hold + for pos, width, stats in zip(positions, widths, bxpstats): + # try to find a new label + datalabels.append(stats.get('label', pos)) + + # whisker coords + whisker_x = np.ones(2) * pos + whiskerlo_y = np.array([stats['q1'], stats['whislo']]) + whiskerhi_y = np.array([stats['q3'], stats['whishi']]) + + # cap coords + cap_left = pos - width * 0.25 + cap_right = pos + width * 0.25 + cap_x = np.array([cap_left, cap_right]) + cap_lo = np.ones(2) * stats['whislo'] + cap_hi = np.ones(2) * stats['whishi'] + + # box and median coords + box_left = pos - width * 0.5 + box_right = pos + width * 0.5 + med_y = [stats['med'], stats['med']] + + # notched boxes + if shownotches: + box_x = [box_left, box_right, box_right, cap_right, box_right, + box_right, box_left, box_left, cap_left, box_left, + box_left] + box_y = [stats['q1'], stats['q1'], stats['cilo'], + stats['med'], stats['cihi'], stats['q3'], + stats['q3'], stats['cihi'], stats['med'], + stats['cilo'], stats['q1']] + med_x = cap_x + + # plain boxes + else: + box_x = [box_left, box_right, box_right, box_left, box_left] + box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'], + stats['q1']] + med_x = [box_left, box_right] + + # maybe draw the box: + if showbox: + if patch_artist: + boxes.extend(dopatch(box_x, box_y, **final_boxprops)) + else: + boxes.extend(doplot(box_x, box_y, **final_boxprops)) + + # draw the whiskers + whiskers.extend(doplot( + whisker_x, whiskerlo_y, **final_whiskerprops + )) + whiskers.extend(doplot( + whisker_x, whiskerhi_y, **final_whiskerprops + )) + + # maybe draw the caps: + if showcaps: + caps.extend(doplot(cap_x, cap_lo, **final_capprops)) + caps.extend(doplot(cap_x, cap_hi, **final_capprops)) + + # draw the medians + medians.extend(doplot(med_x, med_y, **final_medianprops)) + + # maybe draw the means + if showmeans: + if meanline: + means.extend(doplot( + [box_left, box_right], [stats['mean'], stats['mean']], + **final_meanprops + )) + else: + means.extend(doplot( + [pos], [stats['mean']], **final_meanprops + )) + + # maybe draw the fliers + if showfliers: + # fliers coords + flier_x = np.ones(len(stats['fliers'])) * pos + flier_y = stats['fliers'] + + fliers.extend(doplot( + flier_x, flier_y, **final_flierprops + )) + + # fix our axes/ticks up a little + if vert: + setticks = self.set_xticks + setlim = self.set_xlim + setlabels = self.set_xticklabels + else: + setticks = self.set_yticks + setlim = self.set_ylim + setlabels = self.set_yticklabels + + if manage_xticks: + newlimits = min(positions) - 0.5, max(positions) + 0.5 + setlim(newlimits) + setticks(positions) + setlabels(datalabels) + + # reset hold status + self._hold = holdStatus + + return dict(whiskers=whiskers, caps=caps, boxes=boxes, + medians=medians, fliers=fliers, means=means) + + @_preprocess_data(replace_names=["x", "y", "s", "linewidths", + "edgecolors", "c", "facecolor", + "facecolors", "color"], + label_namer="y") + def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None, + vmin=None, vmax=None, alpha=None, linewidths=None, + verts=None, edgecolors=None, + **kwargs): + """ + A scatter plot of *y* vs *x* with varying marker size and/or color. + + Parameters + ---------- + x, y : array_like, shape (n, ) + The data positions. + + s : scalar or array_like, shape (n, ), optional + The marker size in points**2. + Default is ``rcParams['lines.markersize'] ** 2``. + + c : color, sequence, or sequence of color, optional, default: 'b' + The marker color. Possible values: + + - A single color format string. + - A sequence of color specifications of length n. + - A sequence of n numbers to be mapped to colors using *cmap* and + *norm*. + - A 2-D array in which the rows are RGB or RGBA. + + Note that *c* should not be a single numeric RGB or RGBA sequence + because that is indistinguishable from an array of values to be + colormapped. If you want to specify the same RGB or RGBA value for + all points, use a 2-D array with a single row. + + marker : `~matplotlib.markers.MarkerStyle`, optional, default: 'o' + The marker style. *marker* can be either an instance of the class + or the text shorthand for a particular marker. + See `~matplotlib.markers` for more information marker styles. + + cmap : `~matplotlib.colors.Colormap`, optional, default: None + A `.Colormap` instance or registered colormap name. *cmap* is only + used if *c* is an array of floats. If ``None``, defaults to rc + ``image.cmap``. + + norm : `~matplotlib.colors.Normalize`, optional, default: None + A `.Normalize` instance is used to scale luminance data to 0, 1. + *norm* is only used if *c* is an array of floats. If *None*, use + the default `.colors.Normalize`. + + vmin, vmax : scalar, optional, default: None + *vmin* and *vmax* are used in conjunction with *norm* to normalize + luminance data. If None, the respective min and max of the color + array is used. *vmin* and *vmax* are ignored if you pass a *norm* + instance. + + alpha : scalar, optional, default: None + The alpha blending value, between 0 (transparent) and 1 (opaque). + + linewidths : scalar or array_like, optional, default: None + The linewidth of the marker edges. Note: The default *edgecolors* + is 'face'. You may want to change this as well. + If *None*, defaults to rcParams ``lines.linewidth``. + + verts : sequence of (x, y), optional + If *marker* is *None*, these vertices will be used to construct + the marker. The center of the marker is located at (0, 0) in + normalized units. The overall marker is rescaled by *s*. + + edgecolors : color or sequence of color, optional, default: 'face' + The edge color of the marker. Possible values: + + - 'face': The edge color will always be the same as the face color. + - 'none': No patch boundary will be drawn. + - A matplotib color. + + For non-filled markers, the *edgecolors* kwarg is ignored and + forced to 'face' internally. + + Returns + ------- + paths : `~matplotlib.collections.PathCollection` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.collections.Collection` properties + + See Also + -------- + plot : To plot scatter plots when markers are identical in size and + color. + + Notes + ----- + + * The `.plot` function will be faster for scatterplots where markers + don't vary in size or color. + + * Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in which + case all masks will be combined and only unmasked points will be + plotted. + + * Fundamentally, scatter works with 1-D arrays; *x*, *y*, *s*, and *c* + may be input as 2-D arrays, but within scatter they will be + flattened. The exception is *c*, which will be flattened only if its + size matches the size of *x* and *y*. + + """ + + if not self._hold: + self.cla() + + # Process **kwargs to handle aliases, conflicts with explicit kwargs: + + facecolors = None + edgecolors = kwargs.pop('edgecolor', edgecolors) + fc = kwargs.pop('facecolors', None) + fc = kwargs.pop('facecolor', fc) + if fc is not None: + facecolors = fc + co = kwargs.pop('color', None) + if co is not None: + try: + mcolors.to_rgba_array(co) + except ValueError: + raise ValueError("'color' kwarg must be an mpl color" + " spec or sequence of color specs.\n" + "For a sequence of values to be" + " color-mapped, use the 'c' kwarg instead.") + if edgecolors is None: + edgecolors = co + if facecolors is None: + facecolors = co + if c is not None: + raise ValueError("Supply a 'c' kwarg or a 'color' kwarg" + " but not both; they differ but" + " their functionalities overlap.") + if c is None: + if facecolors is not None: + c = facecolors + else: + if rcParams['_internal.classic_mode']: + c = 'b' # The original default + else: + c = self._get_patches_for_fill.get_next_color() + c_none = True + else: + c_none = False + + if edgecolors is None and not rcParams['_internal.classic_mode']: + edgecolors = 'face' + + self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) + x = self.convert_xunits(x) + y = self.convert_yunits(y) + + # np.ma.ravel yields an ndarray, not a masked array, + # unless its argument is a masked array. + xy_shape = (np.shape(x), np.shape(y)) + x = np.ma.ravel(x) + y = np.ma.ravel(y) + if x.size != y.size: + raise ValueError("x and y must be the same size") + + if s is None: + if rcParams['_internal.classic_mode']: + s = 20 + else: + s = rcParams['lines.markersize'] ** 2.0 + + s = np.ma.ravel(s) # This doesn't have to match x, y in size. + + # After this block, c_array will be None unless + # c is an array for mapping. The potential ambiguity + # with a sequence of 3 or 4 numbers is resolved in + # favor of mapping, not rgb or rgba. + if c_none or co is not None: + c_array = None + else: + try: + c_array = np.asanyarray(c, dtype=float) + if c_array.shape in xy_shape: + c = np.ma.ravel(c_array) + else: + # Wrong size; it must not be intended for mapping. + c_array = None + except ValueError: + # Failed to make a floating-point array; c must be color specs. + c_array = None + + if c_array is None: + try: + # must be acceptable as PathCollection facecolors + colors = mcolors.to_rgba_array(c) + except ValueError: + # c not acceptable as PathCollection facecolor + raise ValueError("c of shape {} not acceptable as a color " + "sequence for x with size {}, y with size {}" + .format(c.shape, x.size, y.size)) + else: + colors = None # use cmap, norm after collection is created + + # `delete_masked_points` only modifies arguments of the same length as + # `x`. + x, y, s, c, colors, edgecolors, linewidths =\ + cbook.delete_masked_points( + x, y, s, c, colors, edgecolors, linewidths) + + scales = s # Renamed for readability below. + + # to be API compatible + if marker is None and verts is not None: + marker = (verts, 0) + verts = None + + # load default marker from rcParams + if marker is None: + marker = rcParams['scatter.marker'] + + if isinstance(marker, mmarkers.MarkerStyle): + marker_obj = marker + else: + marker_obj = mmarkers.MarkerStyle(marker) + + path = marker_obj.get_path().transformed( + marker_obj.get_transform()) + if not marker_obj.is_filled(): + edgecolors = 'face' + linewidths = rcParams['lines.linewidth'] + + offsets = np.column_stack([x, y]) + + collection = mcoll.PathCollection( + (path,), scales, + facecolors=colors, + edgecolors=edgecolors, + linewidths=linewidths, + offsets=offsets, + transOffset=kwargs.pop('transform', self.transData), + alpha=alpha + ) + collection.set_transform(mtransforms.IdentityTransform()) + collection.update(kwargs) + + if colors is None: + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + collection.set_array(np.asarray(c)) + collection.set_cmap(cmap) + collection.set_norm(norm) + + if vmin is not None or vmax is not None: + collection.set_clim(vmin, vmax) + else: + collection.autoscale_None() + + # Classic mode only: + # ensure there are margins to allow for the + # finite size of the symbols. In v2.x, margins + # are present by default, so we disable this + # scatter-specific override. + if rcParams['_internal.classic_mode']: + if self._xmargin < 0.05 and x.size > 0: + self.set_xmargin(0.05) + if self._ymargin < 0.05 and x.size > 0: + self.set_ymargin(0.05) + + self.add_collection(collection) + self.autoscale_view() + + return collection + + @_preprocess_data(replace_names=["x", "y"], label_namer="y") + @docstring.dedent_interpd + def hexbin(self, x, y, C=None, gridsize=100, bins=None, + xscale='linear', yscale='linear', extent=None, + cmap=None, norm=None, vmin=None, vmax=None, + alpha=None, linewidths=None, edgecolors='face', + reduce_C_function=np.mean, mincnt=None, marginals=False, + **kwargs): + """ + Make a hexagonal binning plot. + + Make a hexagonal binning plot of *x* versus *y*, where *x*, + *y* are 1-D sequences of the same length, *N*. If *C* is *None* + (the default), this is a histogram of the number of occurrences + of the observations at (x[i],y[i]). + + If *C* is specified, it specifies values at the coordinate + (x[i],y[i]). These values are accumulated for each hexagonal + bin and then reduced according to *reduce_C_function*, which + defaults to numpy's mean function (np.mean). (If *C* is + specified, it must also be a 1-D sequence of the same length + as *x* and *y*.) + + Parameters + ---------- + x, y : array or masked array + + C : array or masked array, optional, default is *None* + + gridsize : int or (int, int), optional, default is 100 + The number of hexagons in the *x*-direction, default is + 100. The corresponding number of hexagons in the + *y*-direction is chosen such that the hexagons are + approximately regular. Alternatively, gridsize can be a + tuple with two elements specifying the number of hexagons + in the *x*-direction and the *y*-direction. + + bins : {'log'} or int or sequence, optional, default is *None* + If *None*, no binning is applied; the color of each hexagon + directly corresponds to its count value. + + If 'log', use a logarithmic scale for the color + map. Internally, :math:`log_{10}(i+1)` is used to + determine the hexagon color. + + If an integer, divide the counts in the specified number + of bins, and color the hexagons accordingly. + + If a sequence of values, the values of the lower bound of + the bins to be used. + + xscale : {'linear', 'log'}, optional, default is 'linear' + Use a linear or log10 scale on the horizontal axis. + + yscale : {'linear', 'log'}, optional, default is 'linear' + Use a linear or log10 scale on the vertical axis. + + mincnt : int > 0, optional, default is *None* + If not *None*, only display cells with more than *mincnt* + number of points in the cell + + marginals : bool, optional, default is *False* + if marginals is *True*, plot the marginal density as + colormapped rectagles along the bottom of the x-axis and + left of the y-axis + + extent : scalar, optional, default is *None* + The limits of the bins. The default assigns the limits + based on *gridsize*, *x*, *y*, *xscale* and *yscale*. + + If *xscale* or *yscale* is set to 'log', the limits are + expected to be the exponent for a power of 10. E.g. for + x-limits of 1 and 50 in 'linear' scale and y-limits + of 10 and 1000 in 'log' scale, enter (1, 50, 1, 3). + + Order of scalars is (left, right, bottom, top). + + Other Parameters + ---------------- + cmap : object, optional, default is *None* + a :class:`matplotlib.colors.Colormap` instance. If *None*, + defaults to rc ``image.cmap``. + + norm : object, optional, default is *None* + :class:`matplotlib.colors.Normalize` instance is used to + scale luminance data to 0,1. + + vmin, vmax : scalar, optional, default is *None* + *vmin* and *vmax* are used in conjunction with *norm* to + normalize luminance data. If *None*, the min and max of the + color array *C* are used. Note if you pass a norm instance + your settings for *vmin* and *vmax* will be ignored. + + alpha : scalar between 0 and 1, optional, default is *None* + the alpha value for the patches + + linewidths : scalar, optional, default is *None* + If *None*, defaults to 1.0. + + edgecolors : {'face', 'none', *None*} or color, optional + + If 'face' (the default), draws the edges in the same color as the + fill color. + + If 'none', no edge is drawn; this can sometimes lead to unsightly + unpainted pixels between the hexagons. + + If *None*, draws outlines in the default color. + + If a matplotlib color arg, draws outlines in the specified color. + + Returns + ------- + object + a :class:`~matplotlib.collections.PolyCollection` instance; use + :meth:`~matplotlib.collections.PolyCollection.get_array` on + this :class:`~matplotlib.collections.PolyCollection` to get + the counts in each hexagon. + + If *marginals* is *True*, horizontal + bar and vertical bar (both PolyCollections) will be attached + to the return collection as attributes *hbar* and *vbar*. + + Notes + ----- + The standard descriptions of all the + :class:`~matplotlib.collections.Collection` parameters: + + %(Collection)s + + """ + + if not self._hold: + self.cla() + + self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs) + + x, y, C = cbook.delete_masked_points(x, y, C) + + # Set the size of the hexagon grid + if iterable(gridsize): + nx, ny = gridsize + else: + nx = gridsize + ny = int(nx / math.sqrt(3)) + # Count the number of data in each hexagon + x = np.array(x, float) + y = np.array(y, float) + if xscale == 'log': + if np.any(x <= 0.0): + raise ValueError("x contains non-positive values, so can not" + " be log-scaled") + x = np.log10(x) + if yscale == 'log': + if np.any(y <= 0.0): + raise ValueError("y contains non-positive values, so can not" + " be log-scaled") + y = np.log10(y) + if extent is not None: + xmin, xmax, ymin, ymax = extent + else: + xmin, xmax = (np.min(x), np.max(x)) if len(x) else (0, 1) + ymin, ymax = (np.min(y), np.max(y)) if len(y) else (0, 1) + + # to avoid issues with singular data, expand the min/max pairs + xmin, xmax = mtransforms.nonsingular(xmin, xmax, expander=0.1) + ymin, ymax = mtransforms.nonsingular(ymin, ymax, expander=0.1) + + # In the x-direction, the hexagons exactly cover the region from + # xmin to xmax. Need some padding to avoid roundoff errors. + padding = 1.e-9 * (xmax - xmin) + xmin -= padding + xmax += padding + sx = (xmax - xmin) / nx + sy = (ymax - ymin) / ny + + if marginals: + xorig = x.copy() + yorig = y.copy() + + x = (x - xmin) / sx + y = (y - ymin) / sy + ix1 = np.round(x).astype(int) + iy1 = np.round(y).astype(int) + ix2 = np.floor(x).astype(int) + iy2 = np.floor(y).astype(int) + + nx1 = nx + 1 + ny1 = ny + 1 + nx2 = nx + ny2 = ny + n = nx1 * ny1 + nx2 * ny2 + + d1 = (x - ix1) ** 2 + 3.0 * (y - iy1) ** 2 + d2 = (x - ix2 - 0.5) ** 2 + 3.0 * (y - iy2 - 0.5) ** 2 + bdist = (d1 < d2) + if C is None: + lattice1 = np.zeros((nx1, ny1)) + lattice2 = np.zeros((nx2, ny2)) + + cond1 = (0 <= ix1) * (ix1 < nx1) * (0 <= iy1) * (iy1 < ny1) + cond2 = (0 <= ix2) * (ix2 < nx2) * (0 <= iy2) * (iy2 < ny2) + + cond1 *= bdist + cond2 *= np.logical_not(bdist) + ix1, iy1 = ix1[cond1], iy1[cond1] + ix2, iy2 = ix2[cond2], iy2[cond2] + + for ix, iy in zip(ix1, iy1): + lattice1[ix, iy] += 1 + for ix, iy in zip(ix2, iy2): + lattice2[ix, iy] += 1 + + # threshold + if mincnt is not None: + lattice1[lattice1 < mincnt] = np.nan + lattice2[lattice2 < mincnt] = np.nan + accum = np.hstack((lattice1.ravel(), + lattice2.ravel())) + good_idxs = ~np.isnan(accum) + + else: + if mincnt is None: + mincnt = 0 + + # create accumulation arrays + lattice1 = np.empty((nx1, ny1), dtype=object) + for i in xrange(nx1): + for j in xrange(ny1): + lattice1[i, j] = [] + lattice2 = np.empty((nx2, ny2), dtype=object) + for i in xrange(nx2): + for j in xrange(ny2): + lattice2[i, j] = [] + + for i in xrange(len(x)): + if bdist[i]: + if 0 <= ix1[i] < nx1 and 0 <= iy1[i] < ny1: + lattice1[ix1[i], iy1[i]].append(C[i]) + else: + if 0 <= ix2[i] < nx2 and 0 <= iy2[i] < ny2: + lattice2[ix2[i], iy2[i]].append(C[i]) + + for i in xrange(nx1): + for j in xrange(ny1): + vals = lattice1[i, j] + if len(vals) > mincnt: + lattice1[i, j] = reduce_C_function(vals) + else: + lattice1[i, j] = np.nan + for i in xrange(nx2): + for j in xrange(ny2): + vals = lattice2[i, j] + if len(vals) > mincnt: + lattice2[i, j] = reduce_C_function(vals) + else: + lattice2[i, j] = np.nan + + accum = np.hstack((lattice1.astype(float).ravel(), + lattice2.astype(float).ravel())) + good_idxs = ~np.isnan(accum) + + offsets = np.zeros((n, 2), float) + offsets[:nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1) + offsets[:nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1) + offsets[nx1 * ny1:, 0] = np.repeat(np.arange(nx2) + 0.5, ny2) + offsets[nx1 * ny1:, 1] = np.tile(np.arange(ny2), nx2) + 0.5 + offsets[:, 0] *= sx + offsets[:, 1] *= sy + offsets[:, 0] += xmin + offsets[:, 1] += ymin + # remove accumulation bins with no data + offsets = offsets[good_idxs, :] + accum = accum[good_idxs] + + polygon = np.zeros((6, 2), float) + polygon[:, 0] = sx * np.array([0.5, 0.5, 0.0, -0.5, -0.5, 0.0]) + polygon[:, 1] = sy * np.array([-0.5, 0.5, 1.0, 0.5, -0.5, -1.0]) / 3.0 + + if linewidths is None: + linewidths = [1.0] + + if xscale == 'log' or yscale == 'log': + polygons = np.expand_dims(polygon, 0) + np.expand_dims(offsets, 1) + if xscale == 'log': + polygons[:, :, 0] = 10.0 ** polygons[:, :, 0] + xmin = 10.0 ** xmin + xmax = 10.0 ** xmax + self.set_xscale(xscale) + if yscale == 'log': + polygons[:, :, 1] = 10.0 ** polygons[:, :, 1] + ymin = 10.0 ** ymin + ymax = 10.0 ** ymax + self.set_yscale(yscale) + collection = mcoll.PolyCollection( + polygons, + edgecolors=edgecolors, + linewidths=linewidths, + ) + else: + collection = mcoll.PolyCollection( + [polygon], + edgecolors=edgecolors, + linewidths=linewidths, + offsets=offsets, + transOffset=mtransforms.IdentityTransform(), + offset_position="data" + ) + + if isinstance(norm, mcolors.LogNorm): + if (accum == 0).any(): + # make sure we have not zeros + accum += 1 + + # autoscale the norm with curren accum values if it hasn't + # been set + if norm is not None: + if norm.vmin is None and norm.vmax is None: + norm.autoscale(accum) + + # Transform accum if needed + if bins == 'log': + accum = np.log10(accum + 1) + elif bins is not None: + if not iterable(bins): + minimum, maximum = min(accum), max(accum) + bins -= 1 # one less edge than bins + bins = minimum + (maximum - minimum) * np.arange(bins) / bins + bins = np.sort(bins) + accum = bins.searchsorted(accum) + + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + collection.set_array(accum) + collection.set_cmap(cmap) + collection.set_norm(norm) + collection.set_alpha(alpha) + collection.update(kwargs) + + if vmin is not None or vmax is not None: + collection.set_clim(vmin, vmax) + else: + collection.autoscale_None() + + corners = ((xmin, ymin), (xmax, ymax)) + self.update_datalim(corners) + collection.sticky_edges.x[:] = [xmin, xmax] + collection.sticky_edges.y[:] = [ymin, ymax] + self.autoscale_view(tight=True) + + # add the collection last + self.add_collection(collection, autolim=False) + if not marginals: + return collection + + if C is None: + C = np.ones(len(x)) + + def coarse_bin(x, y, coarse): + ind = coarse.searchsorted(x).clip(0, len(coarse) - 1) + mus = np.zeros(len(coarse)) + for i in range(len(coarse)): + yi = y[ind == i] + if len(yi) > 0: + mu = reduce_C_function(yi) + else: + mu = np.nan + mus[i] = mu + return mus + + coarse = np.linspace(xmin, xmax, gridsize) + + xcoarse = coarse_bin(xorig, C, coarse) + valid = ~np.isnan(xcoarse) + verts, values = [], [] + for i, val in enumerate(xcoarse): + thismin = coarse[i] + if i < len(coarse) - 1: + thismax = coarse[i + 1] + else: + thismax = thismin + np.diff(coarse)[-1] + + if not valid[i]: + continue + + verts.append([(thismin, 0), + (thismin, 0.05), + (thismax, 0.05), + (thismax, 0)]) + values.append(val) + + values = np.array(values) + trans = self.get_xaxis_transform(which='grid') + + hbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face') + + hbar.set_array(values) + hbar.set_cmap(cmap) + hbar.set_norm(norm) + hbar.set_alpha(alpha) + hbar.update(kwargs) + self.add_collection(hbar, autolim=False) + + coarse = np.linspace(ymin, ymax, gridsize) + ycoarse = coarse_bin(yorig, C, coarse) + valid = ~np.isnan(ycoarse) + verts, values = [], [] + for i, val in enumerate(ycoarse): + thismin = coarse[i] + if i < len(coarse) - 1: + thismax = coarse[i + 1] + else: + thismax = thismin + np.diff(coarse)[-1] + if not valid[i]: + continue + verts.append([(0, thismin), (0.0, thismax), + (0.05, thismax), (0.05, thismin)]) + values.append(val) + + values = np.array(values) + + trans = self.get_yaxis_transform(which='grid') + + vbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face') + vbar.set_array(values) + vbar.set_cmap(cmap) + vbar.set_norm(norm) + vbar.set_alpha(alpha) + vbar.update(kwargs) + self.add_collection(vbar, autolim=False) + + collection.hbar = hbar + collection.vbar = vbar + + def on_changed(collection): + hbar.set_cmap(collection.get_cmap()) + hbar.set_clim(collection.get_clim()) + vbar.set_cmap(collection.get_cmap()) + vbar.set_clim(collection.get_clim()) + + collection.callbacksSM.connect('changed', on_changed) + + return collection + + @docstring.dedent_interpd + def arrow(self, x, y, dx, dy, **kwargs): + """ + Add an arrow to the axes. + + This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``. + + Parameters + ---------- + x, y : float + The x/y-coordinate of the arrow base. + dx, dy : float + The length of the arrow along x/y-direction. + + Returns + ------- + arrow : `.FancyArrow` + The created `.FancyArrow` object. + + Other Parameters + ---------------- + **kwargs + Optional kwargs (inherited from `.FancyArrow` patch) control the + arrow construction and properties: + + %(FancyArrow)s + + Notes + ----- + The resulting arrow is affected by the axes aspect ratio and limits. + This may produce an arrow whose head is not square with its stem. To + create an arrow whose head is square with its stem, + use :meth:`annotate` for example: + + >>> ax.annotate("", xy=(0.5, 0.5), xytext=(0, 0), + ... arrowprops=dict(arrowstyle="->")) + + """ + # Strip away units for the underlying patch since units + # do not make sense to most patch-like code + x = self.convert_xunits(x) + y = self.convert_yunits(y) + dx = self.convert_xunits(dx) + dy = self.convert_yunits(dy) + + a = mpatches.FancyArrow(x, y, dx, dy, **kwargs) + self.add_artist(a) + return a + + def quiverkey(self, *args, **kw): + qk = mquiver.QuiverKey(*args, **kw) + self.add_artist(qk) + return qk + quiverkey.__doc__ = mquiver.QuiverKey.quiverkey_doc + + # Handle units for x and y, if they've been passed + def _quiver_units(self, args, kw): + if len(args) > 3: + x, y = args[0:2] + self._process_unit_info(xdata=x, ydata=y, kwargs=kw) + x = self.convert_xunits(x) + y = self.convert_yunits(y) + return (x, y) + args[2:] + return args + + # args can by a combination if X, Y, U, V, C and all should be replaced + @_preprocess_data(replace_all_args=True, label_namer=None) + def quiver(self, *args, **kw): + if not self._hold: + self.cla() + + # Make sure units are handled for x and y values + args = self._quiver_units(args, kw) + + q = mquiver.Quiver(self, *args, **kw) + + self.add_collection(q, autolim=True) + self.autoscale_view() + return q + quiver.__doc__ = mquiver.Quiver.quiver_doc + + # args can by either Y or y1,y2,... and all should be replaced + @_preprocess_data(replace_all_args=True, label_namer=None) + def stackplot(self, x, *args, **kwargs): + return mstack.stackplot(self, x, *args, **kwargs) + stackplot.__doc__ = mstack.stackplot.__doc__ + + @_preprocess_data(replace_names=["x", "y", "u", "v", "start_points"], + label_namer=None) + def streamplot(self, x, y, u, v, density=1, linewidth=None, color=None, + cmap=None, norm=None, arrowsize=1, arrowstyle='-|>', + minlength=0.1, transform=None, zorder=None, + start_points=None, maxlength=4.0, + integration_direction='both'): + if not self._hold: + self.cla() + stream_container = mstream.streamplot( + self, x, y, u, v, + density=density, + linewidth=linewidth, + color=color, + cmap=cmap, + norm=norm, + arrowsize=arrowsize, + arrowstyle=arrowstyle, + minlength=minlength, + start_points=start_points, + transform=transform, + zorder=zorder, + maxlength=maxlength, + integration_direction=integration_direction) + return stream_container + streamplot.__doc__ = mstream.streamplot.__doc__ + + # args can be some combination of X, Y, U, V, C and all should be replaced + @_preprocess_data(replace_all_args=True, label_namer=None) + @docstring.dedent_interpd + def barbs(self, *args, **kw): + """ + %(barbs_doc)s + """ + if not self._hold: + self.cla() + + # Make sure units are handled for x and y values + args = self._quiver_units(args, kw) + + b = mquiver.Barbs(self, *args, **kw) + self.add_collection(b, autolim=True) + self.autoscale_view() + return b + + @_preprocess_data(replace_names=["x", "y"], label_namer=None, + positional_parameter_names=["x", "y", "c"]) + def fill(self, *args, **kwargs): + """ + Plot filled polygons. + + Parameters + ---------- + args : sequence of x, y, [color] + Each polygon is defined by the lists of *x* and *y* positions of + its nodes, optionally followed by by a *color* specifier. See + :mod:`matplotlib.colors` for supported color specifiers. The + standard color cycle is used for polygons without a color + specifier. + + You can plot multiple polygons by providing multiple *x*, *y*, + *[color]* groups. + + For example, each of the following is legal:: + + ax.fill(x, y) # a polygon with default color + ax.fill(x, y, "b") # a blue polygon + ax.fill(x, y, x2, y2) # two polygons + ax.fill(x, y, "b", x2, y2, "r") # a blue and a red polygon + + Returns + ------- + a list of :class:`~matplotlib.patches.Polygon` + + Other Parameters + ---------------- + **kwargs : :class:`~matplotlib.patches.Polygon` properties + + Notes + ----- + Use :meth:`fill_between` if you would like to fill the region between + two curves. + """ + if not self._hold: + self.cla() + + kwargs = cbook.normalize_kwargs(kwargs, _alias_map) + + patches = [] + for poly in self._get_patches_for_fill(*args, **kwargs): + self.add_patch(poly) + patches.append(poly) + self.autoscale_view() + return patches + + @_preprocess_data(replace_names=["x", "y1", "y2", "where"], + label_namer=None) + @docstring.dedent_interpd + def fill_between(self, x, y1, y2=0, where=None, interpolate=False, + step=None, **kwargs): + """ + Fill the area between two horizontal curves. + + The curves are defined by the points (*x*, *y1*) and (*x*, *y2*). This + creates one or multiple polygons describing the filled area. + + You may exclude some horizontal sections from filling using *where*. + + By default, the edges connect the given points directly. Use *step* if + the filling should be a step function, i.e. constant in between *x*. + + + Parameters + ---------- + x : array (length N) + The x coordinates of the nodes defining the curves. + + y1 : array (length N) or scalar + The y coordinates of the nodes defining the first curve. + + y2 : array (length N) or scalar, optional, default: 0 + The y coordinates of the nodes defining the second curve. + + where : array of bool (length N), optional, default: None + Define *where* to exclude some horizontal regions from being + filled. The filled regions are defined by the coordinates + ``x[where]``. More precisely, fill between ``x[i]`` and ``x[i+1]`` + if ``where[i] and where[i+1]``. Note that this definition implies + that an isolated *True* value between two *False* values in + *where* will not result in filling. Both sides of the *True* + position remain unfilled due to the adjacent *False* values. + + interpolate : bool, optional + This option is only relvant if *where* is used and the two curves + are crossing each other. + + Semantically, *where* is often used for *y1* > *y2* or similar. + By default, the nodes of the polygon defining the filled region + will only be placed at the positions in the *x* array. Such a + polygon cannot describe the above semantics close to the + intersection. The x-sections containing the intersection are + simply clipped. + + Setting *interpolate* to *True* will calculate the actual + intersection point and extend the filled region up to this point. + + step : {'pre', 'post', 'mid'}, optional + Define *step* if the filling should be a step function, + i.e. constant in between *x*. The value determines where the + step will occur: + + - 'pre': The y value is continued constantly to the left from + every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the + value ``y[i]``. + - 'post': The y value is continued constantly to the right from + every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the + value ``y[i]``. + - 'mid': Steps occur half-way between the *x* positions. + + Other Parameters + ---------------- + **kwargs + All other keyword arguments are passed on to `.PolyCollection`. + They control the `.Polygon` properties: + + %(PolyCollection)s + + Returns + ------- + `.PolyCollection` + A `.PolyCollection` containing the plotted polygons. + + See Also + -------- + fill_betweenx : Fill between two sets of x-values. + + Notes + ----- + .. [notes section required to get data note injection right] + + """ + if not rcParams['_internal.classic_mode']: + color_aliases = mcoll._color_aliases + kwargs = cbook.normalize_kwargs(kwargs, color_aliases) + + if not any(c in kwargs for c in ('color', 'facecolors')): + fc = self._get_patches_for_fill.get_next_color() + kwargs['facecolors'] = fc + + # Handle united data, such as dates + self._process_unit_info(xdata=x, ydata=y1, kwargs=kwargs) + self._process_unit_info(ydata=y2) + + # Convert the arrays so we can work with them + x = ma.masked_invalid(self.convert_xunits(x)) + y1 = ma.masked_invalid(self.convert_yunits(y1)) + y2 = ma.masked_invalid(self.convert_yunits(y2)) + + for name, array in [('x', x), ('y1', y1), ('y2', y2)]: + if array.ndim > 1: + raise ValueError('Input passed into argument "%r"' % name + + 'is not 1-dimensional.') + + if where is None: + where = True + where = where & ~functools.reduce(np.logical_or, + map(np.ma.getmask, [x, y1, y2])) + + x, y1, y2 = np.broadcast_arrays(np.atleast_1d(x), y1, y2) + + polys = [] + for ind0, ind1 in cbook.contiguous_regions(where): + xslice = x[ind0:ind1] + y1slice = y1[ind0:ind1] + y2slice = y2[ind0:ind1] + if step is not None: + step_func = STEP_LOOKUP_MAP["steps-" + step] + xslice, y1slice, y2slice = step_func(xslice, y1slice, y2slice) + + if not len(xslice): + continue + + N = len(xslice) + X = np.zeros((2 * N + 2, 2), float) + + if interpolate: + def get_interp_point(ind): + im1 = max(ind - 1, 0) + x_values = x[im1:ind + 1] + diff_values = y1[im1:ind + 1] - y2[im1:ind + 1] + y1_values = y1[im1:ind + 1] + + if len(diff_values) == 2: + if np.ma.is_masked(diff_values[1]): + return x[im1], y1[im1] + elif np.ma.is_masked(diff_values[0]): + return x[ind], y1[ind] + + diff_order = diff_values.argsort() + diff_root_x = np.interp( + 0, diff_values[diff_order], x_values[diff_order]) + x_order = x_values.argsort() + diff_root_y = np.interp(diff_root_x, x_values[x_order], + y1_values[x_order]) + return diff_root_x, diff_root_y + + start = get_interp_point(ind0) + end = get_interp_point(ind1) + else: + # the purpose of the next two lines is for when y2 is a + # scalar like 0 and we want the fill to go all the way + # down to 0 even if none of the y1 sample points do + start = xslice[0], y2slice[0] + end = xslice[-1], y2slice[-1] + + X[0] = start + X[N + 1] = end + + X[1:N + 1, 0] = xslice + X[1:N + 1, 1] = y1slice + X[N + 2:, 0] = xslice[::-1] + X[N + 2:, 1] = y2slice[::-1] + + polys.append(X) + + collection = mcoll.PolyCollection(polys, **kwargs) + + # now update the datalim and autoscale + XY1 = np.array([x[where], y1[where]]).T + XY2 = np.array([x[where], y2[where]]).T + self.dataLim.update_from_data_xy(XY1, self.ignore_existing_data_limits, + updatex=True, updatey=True) + self.ignore_existing_data_limits = False + self.dataLim.update_from_data_xy(XY2, self.ignore_existing_data_limits, + updatex=False, updatey=True) + self.add_collection(collection, autolim=False) + self.autoscale_view() + return collection + + @_preprocess_data(replace_names=["y", "x1", "x2", "where"], + label_namer=None) + @docstring.dedent_interpd + def fill_betweenx(self, y, x1, x2=0, where=None, + step=None, interpolate=False, **kwargs): + """ + Fill the area between two vertical curves. + + The curves are defined by the points (*x1*, *y*) and (*x2*, *y*). This + creates one or multiple polygons describing the filled area. + + You may exclude some vertical sections from filling using *where*. + + By default, the edges connect the given points directly. Use *step* if + the filling should be a step function, i.e. constant in between *y*. + + + Parameters + ---------- + y : array (length N) + The y coordinates of the nodes defining the curves. + + x1 : array (length N) or scalar + The x coordinates of the nodes defining the first curve. + + x2 : array (length N) or scalar, optional, default: 0 + The x coordinates of the nodes defining the second curve. + + where : array of bool (length N), optional, default: None + Define *where* to exclude some vertical regions from being + filled. The filled regions are defined by the coordinates + ``y[where]``. More precisely, fill between ``y[i]`` and ``y[i+1]`` + if ``where[i] and where[i+1]``. Note that this definition implies + that an isolated *True* value between two *False* values in + *where* will not result in filling. Both sides of the *True* + position remain unfilled due to the adjacent *False* values. + + interpolate : bool, optional + This option is only relvant if *where* is used and the two curves + are crossing each other. + + Semantically, *where* is often used for *x1* > *x2* or similar. + By default, the nodes of the polygon defining the filled region + will only be placed at the positions in the *y* array. Such a + polygon cannot describe the above semantics close to the + intersection. The y-sections containing the intersecion are + simply clipped. + + Setting *interpolate* to *True* will calculate the actual + interscection point and extend the filled region up to this point. + + step : {'pre', 'post', 'mid'}, optional + Define *step* if the filling should be a step function, + i.e. constant in between *y*. The value determines where the + step will occur: + + - 'pre': The y value is continued constantly to the left from + every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the + value ``y[i]``. + - 'post': The y value is continued constantly to the right from + every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the + value ``y[i]``. + - 'mid': Steps occur half-way between the *x* positions. + + Other Parameters + ---------------- + **kwargs + All other keyword arguments are passed on to `.PolyCollection`. + They control the `.Polygon` properties: + + %(PolyCollection)s + + Returns + ------- + `.PolyCollection` + A `.PolyCollection` containing the plotted polygons. + + See Also + -------- + fill_between : Fill between two sets of y-values. + + Notes + ----- + .. [notes section required to get data note injection right] + + """ + if not rcParams['_internal.classic_mode']: + color_aliases = mcoll._color_aliases + kwargs = cbook.normalize_kwargs(kwargs, color_aliases) + + if not any(c in kwargs for c in ('color', 'facecolors')): + fc = self._get_patches_for_fill.get_next_color() + kwargs['facecolors'] = fc + # Handle united data, such as dates + self._process_unit_info(ydata=y, xdata=x1, kwargs=kwargs) + self._process_unit_info(xdata=x2) + + # Convert the arrays so we can work with them + y = ma.masked_invalid(self.convert_yunits(y)) + x1 = ma.masked_invalid(self.convert_xunits(x1)) + x2 = ma.masked_invalid(self.convert_xunits(x2)) + + for name, array in [('y', y), ('x1', x1), ('x2', x2)]: + if array.ndim > 1: + raise ValueError('Input passed into argument "%r"' % name + + 'is not 1-dimensional.') + + if where is None: + where = True + where = where & ~functools.reduce(np.logical_or, + map(np.ma.getmask, [y, x1, x2])) + + y, x1, x2 = np.broadcast_arrays(np.atleast_1d(y), x1, x2) + + polys = [] + for ind0, ind1 in cbook.contiguous_regions(where): + yslice = y[ind0:ind1] + x1slice = x1[ind0:ind1] + x2slice = x2[ind0:ind1] + if step is not None: + step_func = STEP_LOOKUP_MAP["steps-" + step] + yslice, x1slice, x2slice = step_func(yslice, x1slice, x2slice) + + if not len(yslice): + continue + + N = len(yslice) + Y = np.zeros((2 * N + 2, 2), float) + if interpolate: + def get_interp_point(ind): + im1 = max(ind - 1, 0) + y_values = y[im1:ind + 1] + diff_values = x1[im1:ind + 1] - x2[im1:ind + 1] + x1_values = x1[im1:ind + 1] + + if len(diff_values) == 2: + if np.ma.is_masked(diff_values[1]): + return x1[im1], y[im1] + elif np.ma.is_masked(diff_values[0]): + return x1[ind], y[ind] + + diff_order = diff_values.argsort() + diff_root_y = np.interp( + 0, diff_values[diff_order], y_values[diff_order]) + y_order = y_values.argsort() + diff_root_x = np.interp(diff_root_y, y_values[y_order], + x1_values[y_order]) + return diff_root_x, diff_root_y + + start = get_interp_point(ind0) + end = get_interp_point(ind1) + else: + # the purpose of the next two lines is for when x2 is a + # scalar like 0 and we want the fill to go all the way + # down to 0 even if none of the x1 sample points do + start = x2slice[0], yslice[0] + end = x2slice[-1], yslice[-1] + + Y[0] = start + Y[N + 1] = end + + Y[1:N + 1, 0] = x1slice + Y[1:N + 1, 1] = yslice + Y[N + 2:, 0] = x2slice[::-1] + Y[N + 2:, 1] = yslice[::-1] + + polys.append(Y) + + collection = mcoll.PolyCollection(polys, **kwargs) + + # now update the datalim and autoscale + X1Y = np.array([x1[where], y[where]]).T + X2Y = np.array([x2[where], y[where]]).T + self.dataLim.update_from_data_xy(X1Y, self.ignore_existing_data_limits, + updatex=True, updatey=True) + self.ignore_existing_data_limits = False + self.dataLim.update_from_data_xy(X2Y, self.ignore_existing_data_limits, + updatex=True, updatey=False) + self.add_collection(collection, autolim=False) + self.autoscale_view() + return collection + + #### plotting z(x,y): imshow, pcolor and relatives, contour + @_preprocess_data(label_namer=None) + def imshow(self, X, cmap=None, norm=None, aspect=None, + interpolation=None, alpha=None, vmin=None, vmax=None, + origin=None, extent=None, shape=None, filternorm=1, + filterrad=4.0, imlim=None, resample=None, url=None, **kwargs): + """ + Display an image on the axes. + + Parameters + ---------- + X : array_like, shape (n, m) or (n, m, 3) or (n, m, 4) + Display the image in `X` to current axes. `X` may be an + array or a PIL image. If `X` is an array, it + can have the following shapes and types: + + - MxN -- values to be mapped (float or int) + - MxNx3 -- RGB (float or uint8) + - MxNx4 -- RGBA (float or uint8) + + MxN arrays are mapped to colors based on the `norm` (mapping + scalar to scalar) and the `cmap` (mapping the normed scalar to + a color). + + Elements of RGB and RGBA arrays represent pixels of an MxN image. + All values should be in the range [0 .. 1] for floats or + [0 .. 255] for integers. Out-of-range values will be clipped to + these bounds. + + cmap : `~matplotlib.colors.Colormap`, optional, default: None + If None, default to rc `image.cmap` value. `cmap` is ignored + if `X` is 3-D, directly specifying RGB(A) values. + + aspect : ['auto' | 'equal' | scalar], optional, default: None + If 'auto', changes the image aspect ratio to match that of the + axes. + + If 'equal', and `extent` is None, changes the axes aspect ratio to + match that of the image. If `extent` is not `None`, the axes + aspect ratio is changed to match that of the extent. + + If None, default to rc ``image.aspect`` value. + + interpolation : string, optional, default: None + Acceptable values are 'none', 'nearest', 'bilinear', 'bicubic', + 'spline16', 'spline36', 'hanning', 'hamming', 'hermite', 'kaiser', + 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell', 'sinc', + 'lanczos' + + If `interpolation` is None, default to rc `image.interpolation`. + See also the `filternorm` and `filterrad` parameters. + If `interpolation` is 'none', then no interpolation is performed + on the Agg, ps and pdf backends. Other backends will fall back to + 'nearest'. + + norm : `~matplotlib.colors.Normalize`, optional, default: None + A `~matplotlib.colors.Normalize` instance is used to scale + a 2-D float `X` input to the (0, 1) range for input to the + `cmap`. If `norm` is None, use the default func:`normalize`. + If `norm` is an instance of `~matplotlib.colors.NoNorm`, + `X` must be an array of integers that index directly into + the lookup table of the `cmap`. + + vmin, vmax : scalar, optional, default: None + `vmin` and `vmax` are used in conjunction with norm to normalize + luminance data. Note if you pass a `norm` instance, your + settings for `vmin` and `vmax` will be ignored. + + alpha : scalar, optional, default: None + The alpha blending value, between 0 (transparent) and 1 (opaque). + The ``alpha`` argument is ignored for RGBA input data. + + origin : ['upper' | 'lower'], optional, default: None + Place the [0,0] index of the array in the upper left or lower left + corner of the axes. If None, default to rc `image.origin`. + + extent : scalars (left, right, bottom, top), optional, default: None + The location, in data-coordinates, of the lower-left and + upper-right corners. If `None`, the image is positioned such that + the pixel centers fall on zero-based (row, column) indices. + + shape : scalars (columns, rows), optional, default: None + For raw buffer images + + filternorm : scalar, optional, default: 1 + A parameter for the antigrain image resize filter. From the + antigrain documentation, if `filternorm` = 1, the filter + normalizes integer values and corrects the rounding errors. It + doesn't do anything with the source floating point values, it + corrects only integers according to the rule of 1.0 which means + that any sum of pixel weights must be equal to 1.0. So, the + filter function must produce a graph of the proper shape. + + filterrad : scalar, optional, default: 4.0 + The filter radius for filters that have a radius parameter, i.e. + when interpolation is one of: 'sinc', 'lanczos' or 'blackman' + + Returns + ------- + image : `~matplotlib.image.AxesImage` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.artist.Artist` properties. + + See also + -------- + matshow : Plot a matrix or an array as an image. + + Notes + ----- + Unless *extent* is used, pixel centers will be located at integer + coordinates. In other words: the origin will coincide with the center + of pixel (0, 0). + + Two typical representations are used for RGB images with an alpha + channel: + + - Straight (unassociated) alpha: R, G, and B channels represent the + color of the pixel, disregarding its opacity. + - Premultiplied (associated) alpha: R, G, and B channels represent + the color of the pixel, adjusted for its opacity by multiplication. + + `~matplotlib.pyplot.imshow` expects RGB images adopting the straight + (unassociated) alpha representation. + """ + + if not self._hold: + self.cla() + + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + if aspect is None: + aspect = rcParams['image.aspect'] + self.set_aspect(aspect) + im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent, + filternorm=filternorm, filterrad=filterrad, + resample=resample, **kwargs) + + im.set_data(X) + im.set_alpha(alpha) + if im.get_clip_path() is None: + # image does not already have clipping set, clip to axes patch + im.set_clip_path(self.patch) + #if norm is None and shape is None: + # im.set_clim(vmin, vmax) + if vmin is not None or vmax is not None: + im.set_clim(vmin, vmax) + else: + im.autoscale_None() + im.set_url(url) + + # update ax.dataLim, and, if autoscaling, set viewLim + # to tightly fit the image, regardless of dataLim. + im.set_extent(im.get_extent()) + + self.add_image(im) + return im + + @staticmethod + def _pcolorargs(funcname, *args, **kw): + # This takes one kwarg, allmatch. + # If allmatch is True, then the incoming X, Y, C must + # have matching dimensions, taking into account that + # X and Y can be 1-D rather than 2-D. This perfect + # match is required for Gouroud shading. For flat + # shading, X and Y specify boundaries, so we need + # one more boundary than color in each direction. + # For convenience, and consistent with Matlab, we + # discard the last row and/or column of C if necessary + # to meet this condition. This is done if allmatch + # is False. + + allmatch = kw.pop("allmatch", False) + + if len(args) == 1: + C = np.asanyarray(args[0]) + numRows, numCols = C.shape + if allmatch: + X, Y = np.meshgrid(np.arange(numCols), np.arange(numRows)) + else: + X, Y = np.meshgrid(np.arange(numCols + 1), + np.arange(numRows + 1)) + C = cbook.safe_masked_invalid(C) + return X, Y, C + + if len(args) == 3: + # Check x and y for bad data... + C = np.asanyarray(args[2]) + X, Y = [cbook.safe_masked_invalid(a) for a in args[:2]] + if funcname == 'pcolormesh': + if np.ma.is_masked(X) or np.ma.is_masked(Y): + raise ValueError( + 'x and y arguments to pcolormesh cannot have ' + 'non-finite values or be of type ' + 'numpy.ma.core.MaskedArray with masked values') + # safe_masked_invalid() returns an ndarray for dtypes other + # than floating point. + if isinstance(X, np.ma.core.MaskedArray): + X = X.data # strip mask as downstream doesn't like it... + if isinstance(Y, np.ma.core.MaskedArray): + Y = Y.data + numRows, numCols = C.shape + else: + raise TypeError( + 'Illegal arguments to %s; see help(%s)' % (funcname, funcname)) + + Nx = X.shape[-1] + Ny = Y.shape[0] + if X.ndim != 2 or X.shape[0] == 1: + x = X.reshape(1, Nx) + X = x.repeat(Ny, axis=0) + if Y.ndim != 2 or Y.shape[1] == 1: + y = Y.reshape(Ny, 1) + Y = y.repeat(Nx, axis=1) + if X.shape != Y.shape: + raise TypeError( + 'Incompatible X, Y inputs to %s; see help(%s)' % ( + funcname, funcname)) + if allmatch: + if not (Nx == numCols and Ny == numRows): + raise TypeError('Dimensions of C %s are incompatible with' + ' X (%d) and/or Y (%d); see help(%s)' % ( + C.shape, Nx, Ny, funcname)) + else: + if not (numCols in (Nx, Nx - 1) and numRows in (Ny, Ny - 1)): + raise TypeError('Dimensions of C %s are incompatible with' + ' X (%d) and/or Y (%d); see help(%s)' % ( + C.shape, Nx, Ny, funcname)) + C = C[:Ny - 1, :Nx - 1] + C = cbook.safe_masked_invalid(C) + return X, Y, C + + @_preprocess_data(label_namer=None) + @docstring.dedent_interpd + def pcolor(self, *args, **kwargs): + r""" + Create a pseudocolor plot with a non-regular rectangular grid. + + Call signature:: + + pcolor([X, Y,] C, **kwargs) + + *X* and *Y* can be used to specify the corners of the quadrilaterals. + + .. hint:: + + ``pcolor()`` can be very slow for large arrays. In most + cases you should use the the similar but much faster + `~.Axes.pcolormesh` instead. See there for a discussion of the + differences. + + Parameters + ---------- + C : array_like + A scalar 2-D array. The values will be color-mapped. + + X, Y : array_like, optional + The coordinates of the quadrilateral corners. The quadrilateral + for ``C[i,j]`` has corners at:: + + (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1]) + +--------+ + | C[i,j] | + +--------+ + (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1]), + + Note that the column index corresponds to the + x-coordinate, and the row index corresponds to y. For + details, see the :ref:`Notes ` + section below. + + The dimensions of *X* and *Y* should be one greater than those of + *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in + which case the last row and column of *C* will be ignored. + + If *X* and/or *Y* are 1-D arrays or column vectors they will be + expanded as needed into the appropriate 2-D arrays, making a + rectangular grid. + + cmap : str or `~matplotlib.colors.Colormap`, optional + A Colormap instance or registered colormap name. The colormap + maps the *C* values to colors. Defaults to :rc:`image.cmap`. + + norm : `~matplotlib.colors.Normalize`, optional + The Normalize instance scales the data values to the canonical + colormap range [0, 1] for mapping to colors. By default, the data + range is mapped to the colorbar range using linear scaling. + + vmin, vmax : scalar, optional, default: None + The colorbar range. If *None*, suitable min/max values are + automatically chosen by the `~.Normalize` instance (defaults to + the respective min/max values of *C* in case of the default linear + scaling). + + edgecolors : {'none', None, 'face', color, color sequence}, optional + The color of the edges. Defaults to 'none'. Possible values: + + - 'none' or '': No edge. + - *None*: :rc:`patch.edgecolor` will be used. Note that currently + :rc:`patch.force_edgecolor` has to be True for this to work. + - 'face': Use the adjacent face color. + - An mpl color or sequence of colors will set the edge color. + + The singular form *edgecolor* works as an alias. + + alpha : scalar, optional, default: None + The alpha blending value of the face color, between 0 (transparent) + and 1 (opaque). Note: The edgecolor is currently not affected by + this. + + snap : bool, optional, default: False + Whether to snap the mesh to pixel boundaries. + + Returns + ------- + collection : `matplotlib.collections.Collection` + + Other Parameters + ---------------- + antialiaseds : bool, optional, default: False + The default *antialiaseds* is False if the default + *edgecolors*\ ="none" is used. This eliminates artificial lines + at patch boundaries, and works regardless of the value of alpha. + If *edgecolors* is not "none", then the default *antialiaseds* + is taken from :rc:`patch.antialiased`, which defaults to True. + Stroking the edges may be preferred if *alpha* is 1, but will + cause artifacts otherwise. + + **kwargs : + Additionally, the following arguments are allowed. They are passed + along to the `~matplotlib.collections.PolyCollection` constructor: + + %(PolyCollection)s + + See Also + -------- + pcolormesh : for an explanation of the differences between + pcolor and pcolormesh. + imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a + faster alternative. + + Notes + ----- + + **Masked arrays** + + *X*, *Y* and *C* may be masked arrays. If either ``C[i, j]``, or one + of the vertices surrounding ``C[i,j]`` (*X* or *Y* at + ``[i, j], [i+1, j], [i, j+1], [i+1, j+1]``) is masked, nothing is + plotted. + + .. _axes-pcolor-grid-orientation: + + **Grid orientation** + + The grid orientation follows the standard matrix convention: An array + *C* with shape (nrows, ncolumns) is plotted with the column number as + *X* and the row number as *Y*. + + **Handling of pcolor() end-cases** + + ``pcolor()`` displays all columns of *C* if *X* and *Y* are not + specified, or if *X* and *Y* have one more column than *C*. + If *X* and *Y* have the same number of columns as *C* then the last + column of *C* is dropped. Similarly for the rows. + + Note: This behavior is different from MATLAB's ``pcolor()``, which + always discards the last row and column of *C*. + """ + + if not self._hold: + self.cla() + + alpha = kwargs.pop('alpha', None) + norm = kwargs.pop('norm', None) + cmap = kwargs.pop('cmap', None) + vmin = kwargs.pop('vmin', None) + vmax = kwargs.pop('vmax', None) + + X, Y, C = self._pcolorargs('pcolor', *args, allmatch=False) + Ny, Nx = X.shape + + # unit conversion allows e.g. datetime objects as axis values + self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs) + X = self.convert_xunits(X) + Y = self.convert_yunits(Y) + + # convert to MA, if necessary. + C = ma.asarray(C) + X = ma.asarray(X) + Y = ma.asarray(Y) + + mask = ma.getmaskarray(X) + ma.getmaskarray(Y) + xymask = (mask[0:-1, 0:-1] + mask[1:, 1:] + + mask[0:-1, 1:] + mask[1:, 0:-1]) + # don't plot if C or any of the surrounding vertices are masked. + mask = ma.getmaskarray(C) + xymask + + newaxis = np.newaxis + compress = np.compress + + ravelmask = (mask == 0).ravel() + X1 = compress(ravelmask, ma.filled(X[0:-1, 0:-1]).ravel()) + Y1 = compress(ravelmask, ma.filled(Y[0:-1, 0:-1]).ravel()) + X2 = compress(ravelmask, ma.filled(X[1:, 0:-1]).ravel()) + Y2 = compress(ravelmask, ma.filled(Y[1:, 0:-1]).ravel()) + X3 = compress(ravelmask, ma.filled(X[1:, 1:]).ravel()) + Y3 = compress(ravelmask, ma.filled(Y[1:, 1:]).ravel()) + X4 = compress(ravelmask, ma.filled(X[0:-1, 1:]).ravel()) + Y4 = compress(ravelmask, ma.filled(Y[0:-1, 1:]).ravel()) + npoly = len(X1) + + xy = np.concatenate((X1[:, newaxis], Y1[:, newaxis], + X2[:, newaxis], Y2[:, newaxis], + X3[:, newaxis], Y3[:, newaxis], + X4[:, newaxis], Y4[:, newaxis], + X1[:, newaxis], Y1[:, newaxis]), + axis=1) + verts = xy.reshape((npoly, 5, 2)) + + C = compress(ravelmask, ma.filled(C[0:Ny - 1, 0:Nx - 1]).ravel()) + + linewidths = (0.25,) + if 'linewidth' in kwargs: + kwargs['linewidths'] = kwargs.pop('linewidth') + kwargs.setdefault('linewidths', linewidths) + + if 'edgecolor' in kwargs: + kwargs['edgecolors'] = kwargs.pop('edgecolor') + ec = kwargs.setdefault('edgecolors', 'none') + + # aa setting will default via collections to patch.antialiased + # unless the boundary is not stroked, in which case the + # default will be False; with unstroked boundaries, aa + # makes artifacts that are often disturbing. + if 'antialiased' in kwargs: + kwargs['antialiaseds'] = kwargs.pop('antialiased') + if 'antialiaseds' not in kwargs and ( + isinstance(ec, six.string_types) and ec.lower() == "none"): + kwargs['antialiaseds'] = False + + kwargs.setdefault('snap', False) + + collection = mcoll.PolyCollection(verts, **kwargs) + + collection.set_alpha(alpha) + collection.set_array(C) + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + collection.set_cmap(cmap) + collection.set_norm(norm) + collection.set_clim(vmin, vmax) + collection.autoscale_None() + self.grid(False) + + x = X.compressed() + y = Y.compressed() + + # Transform from native to data coordinates? + t = collection._transform + if (not isinstance(t, mtransforms.Transform) and + hasattr(t, '_as_mpl_transform')): + t = t._as_mpl_transform(self.axes) + + if t and any(t.contains_branch_seperately(self.transData)): + trans_to_data = t - self.transData + pts = np.vstack([x, y]).T.astype(float) + transformed_pts = trans_to_data.transform(pts) + x = transformed_pts[..., 0] + y = transformed_pts[..., 1] + + self.add_collection(collection, autolim=False) + + minx = np.min(x) + maxx = np.max(x) + miny = np.min(y) + maxy = np.max(y) + collection.sticky_edges.x[:] = [minx, maxx] + collection.sticky_edges.y[:] = [miny, maxy] + corners = (minx, miny), (maxx, maxy) + self.update_datalim(corners) + self.autoscale_view() + return collection + + @_preprocess_data(label_namer=None) + @docstring.dedent_interpd + def pcolormesh(self, *args, **kwargs): + """ + Create a pseudocolor plot with a non-regular rectangular grid. + + Call signature:: + + pcolor([X, Y,] C, **kwargs) + + *X* and *Y* can be used to specify the corners of the quadrilaterals. + + .. note:: + + ``pcolormesh()`` is similar to :func:`~Axes.pcolor`. It's much + faster and preferred in most cases. For a detailed discussion on + the differences see + :ref:`Differences between pcolor() and pcolormesh() + `. + + Parameters + ---------- + C : array_like + A scalar 2-D array. The values will be color-mapped. + + X, Y : array_like, optional + The coordinates of the quadrilateral corners. The quadrilateral + for ``C[i,j]`` has corners at:: + + (X[i+1, j], Y[i+1, j]) (X[i+1, j+1], Y[i+1, j+1]) + +--------+ + | C[i,j] | + +--------+ + (X[i, j], Y[i, j]) (X[i, j+1], Y[i, j+1]), + + Note that the column index corresponds to the + x-coordinate, and the row index corresponds to y. For + details, see the :ref:`Notes ` + section below. + + The dimensions of *X* and *Y* should be one greater than those of + *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in + which case the last row and column of *C* will be ignored. + + If *X* and/or *Y* are 1-D arrays or column vectors they will be + expanded as needed into the appropriate 2-D arrays, making a + rectangular grid. + + cmap : str or `~matplotlib.colors.Colormap`, optional + A Colormap instance or registered colormap name. The colormap + maps the *C* values to colors. Defaults to :rc:`image.cmap`. + + norm : `~matplotlib.colors.Normalize`, optional + The Normalize instance scales the data values to the canonical + colormap range [0, 1] for mapping to colors. By default, the data + range is mapped to the colorbar range using linear scaling. + + vmin, vmax : scalar, optional, default: None + The colorbar range. If *None*, suitable min/max values are + automatically chosen by the `~.Normalize` instance (defaults to + the respective min/max values of *C* in case of the default linear + scaling). + + edgecolors : {'none', None, 'face', color, color sequence}, optional + The color of the edges. Defaults to 'none'. Possible values: + + - 'none' or '': No edge. + - *None*: :rc:`patch.edgecolor` will be used. Note that currently + :rc:`patch.force_edgecolor` has to be True for this to work. + - 'face': Use the adjacent face color. + - An mpl color or sequence of colors will set the edge color. + + The singular form *edgecolor* works as an alias. + + alpha : scalar, optional, default: None + The alpha blending value, between 0 (transparent) and 1 (opaque). + + shading : {'flat', 'gouraud'}, optional + The fill style, Possible values: + + - 'flat': A solid color is used for each quad. The color of the + quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by + ``C[i,j]``. + - 'gouraud': Each quad will be Gouraud shaded: The color of the + corners (i', j') are given by ``C[i',j']``. The color values of + the area in between is interpolated from the corner values. + When Gouraud shading is used, *edgecolors* is ignored. + + snap : bool, optional, default: False + Whether to snap the mesh to pixel boundaries. + + Returns + ------- + mesh : `matplotlib.collections.QuadMesh` + + Other Parameters + ---------------- + **kwargs + Additionally, the following arguments are allowed. They are passed + along to the `~matplotlib.collections.QuadMesh` constructor: + + %(QuadMesh)s + + + See Also + -------- + pcolor : An alternative implementation with slightly different + features. For a detailed discussion on the differences see + :ref:`Differences between pcolor() and pcolormesh() + `. + imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a + faster alternative. + + Notes + ----- + + **Masked arrays** + + *C* may be a masked array. If ``C[i, j]`` is masked, the corresponding + quadrilateral will be transparent. Masking of *X* and *Y* is not + supported. Use `~.Axes.pcolor` if you need this functionality. + + .. _axes-pcolormesh-grid-orientation: + + **Grid orientation** + + The grid orientation follows the standard matrix convention: An array + *C* with shape (nrows, ncolumns) is plotted with the column number as + *X* and the row number as *Y*. + + .. _differences-pcolor-pcolormesh: + + **Differences between pcolor() and pcolormesh()** + + Both methods are used to create a pseudocolor plot of a 2-D array + using quadrilaterals. + + The main difference lies in the created object and internal data + handling: + While `~.Axes.pcolor` returns a `.PolyCollection`, `~.Axes.pcolormesh` + returns a `.QuadMesh`. The latter is more specialized for the given + purpose and thus is faster. It should almost always be preferred. + + There is also a slight difference in the handling of masked arrays. + Both `~.Axes.pcolor` and `~.Axes.pcolormesh` support masked arrays + for *C*. However, only `~.Axes.pcolor` supports masked arrays for *X* + and *Y*. The reason lies in the internal handling of the masked values. + `~.Axes.pcolor` leaves out the respective polygons from the + PolyCollection. `~.Axes.pcolormesh` sets the facecolor of the masked + elements to transparent. You can see the difference when using + edgecolors. While all edges are drawn irrespective of masking in a + QuadMesh, the edge between two adjacent masked quadrilaterals in + `~.Axes.pcolor` is not drawn as the corresponding polygons do not + exist in the PolyCollection. + + Another difference is the support of Gouraud shading in + `~.Axes.pcolormesh`, which is not available with `~.Axes.pcolor`. + + """ + if not self._hold: + self.cla() + + alpha = kwargs.pop('alpha', None) + norm = kwargs.pop('norm', None) + cmap = kwargs.pop('cmap', None) + vmin = kwargs.pop('vmin', None) + vmax = kwargs.pop('vmax', None) + shading = kwargs.pop('shading', 'flat').lower() + antialiased = kwargs.pop('antialiased', False) + kwargs.setdefault('edgecolors', 'None') + + allmatch = (shading == 'gouraud') + + X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch) + Ny, Nx = X.shape + X = X.ravel() + Y = Y.ravel() + # unit conversion allows e.g. datetime objects as axis values + self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs) + X = self.convert_xunits(X) + Y = self.convert_yunits(Y) + + # convert to one dimensional arrays + C = C.ravel() + coords = np.column_stack((X, Y)).astype(float, copy=False) + collection = mcoll.QuadMesh(Nx - 1, Ny - 1, coords, + antialiased=antialiased, shading=shading, + **kwargs) + collection.set_alpha(alpha) + collection.set_array(C) + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + collection.set_cmap(cmap) + collection.set_norm(norm) + collection.set_clim(vmin, vmax) + collection.autoscale_None() + + self.grid(False) + + # Transform from native to data coordinates? + t = collection._transform + if (not isinstance(t, mtransforms.Transform) and + hasattr(t, '_as_mpl_transform')): + t = t._as_mpl_transform(self.axes) + + if t and any(t.contains_branch_seperately(self.transData)): + trans_to_data = t - self.transData + coords = trans_to_data.transform(coords) + + self.add_collection(collection, autolim=False) + + minx, miny = np.min(coords, axis=0) + maxx, maxy = np.max(coords, axis=0) + collection.sticky_edges.x[:] = [minx, maxx] + collection.sticky_edges.y[:] = [miny, maxy] + corners = (minx, miny), (maxx, maxy) + self.update_datalim(corners) + self.autoscale_view() + return collection + + @_preprocess_data(label_namer=None) + @docstring.dedent_interpd + def pcolorfast(self, *args, **kwargs): + """ + Create a pseudocolor plot with a non-regular rectangular grid. + + Call signatures:: + + ax.pcolorfast(C, **kwargs) + ax.pcolorfast(xr, yr, C, **kwargs) + ax.pcolorfast(x, y, C, **kwargs) + ax.pcolorfast(X, Y, C, **kwargs) + + This method is similar to ~.Axes.pcolor` and `~.Axes.pcolormesh`. + It's designed to provide the fastest pcolor-type plotting with the + Agg backend. To achieve this, it uses different algorithms internally + depending on the complexity of the input grid (regular rectangular, + non-regular rectangular or arbitrary quadrilateral). + + .. warning:: + + This method is experimental. Compared to `~.Axes.pcolor` or + `~.Axes.pcolormesh` it has some limitations: + + - It supports only flat shading (no outlines) + - It lacks support for log scaling of the axes. + - It does not have a have a pyplot wrapper. + + Parameters + ---------- + C : array-like(M, N) + A scalar 2D array. The values will be color-mapped. + *C* may be a masked array. + + x, y : tuple or array-like + *X* and *Y* are used to specify the coordinates of the + quadilaterals. There are different ways to do this: + + - Use tuples ``xr=(xmin, xmax)`` and ``yr=(ymin, ymax)`` to define + a *uniform rectiangular grid*. + + The tuples define the outer edges of the grid. All individual + quadrilaterals will be of the same size. This is the fastest + version. + + - Use 1D arrays *x*, *y* to specify a *non-uniform rectangular + grid*. + + In this case *x* and *y* have to be monotonic 1D arrays of length + *N+1* and *M+1*, specifying the x and y boundaries of the cells. + + The speed is intermediate. Note: The grid is checked, and if + found to be uniform the fast version is used. + + - Use 2D arrays *X*, *Y* if you need an *arbitrary quadrilateral + grid* (i.e. if the quadrilaterals are not rectangular). + + In this case *X* and *Y* are 2D arrays with shape (M, N), + specifying the x and y coordinates of the corners of the colored + quadrilaterals. See `~.Axes.pcolormesh` for details. + + This is the most general, but the slowest to render. It may + produce faster and more compact output using ps, pdf, and + svg backends, however. + + Leaving out *x* and *y* defaults to ``xr=(0, N)``, ``yr=(O, M)``. + + cmap : str or `~matplotlib.colors.Colormap`, optional + A Colormap instance or registered colormap name. The colormap + maps the *C* values to colors. Defaults to :rc:`image.cmap`. + + norm : `~matplotlib.colors.Normalize`, optional + The Normalize instance scales the data values to the canonical + colormap range [0, 1] for mapping to colors. By default, the data + range is mapped to the colorbar range using linear scaling. + + vmin, vmax : scalar, optional, default: None + The colorbar range. If *None*, suitable min/max values are + automatically chosen by the `~.Normalize` instance (defaults to + the respective min/max values of *C* in case of the default linear + scaling). + + alpha : scalar, optional, default: None + The alpha blending value, between 0 (transparent) and 1 (opaque). + + snap : bool, optional, default: False + Whether to snap the mesh to pixel boundaries. + + Returns + ------- + image : `.AxesImage` or `.PcolorImage` or `.QuadMesh` + The return type depends on the type of grid: + + - `.AxesImage` for a regular rectangular grid. + - `.PcolorImage` for a non-regular rectangular grid. + - `.QuadMesh` for a non-rectangular grid. + + Notes + ----- + .. [notes section required to get data note injection right] + + """ + + if not self._hold: + self.cla() + + alpha = kwargs.pop('alpha', None) + norm = kwargs.pop('norm', None) + cmap = kwargs.pop('cmap', None) + vmin = kwargs.pop('vmin', None) + vmax = kwargs.pop('vmax', None) + if norm is not None and not isinstance(norm, mcolors.Normalize): + raise ValueError( + "'norm' must be an instance of 'mcolors.Normalize'") + + C = args[-1] + nr, nc = C.shape + if len(args) == 1: + style = "image" + x = [0, nc] + y = [0, nr] + elif len(args) == 3: + x, y = args[:2] + x = np.asarray(x) + y = np.asarray(y) + if x.ndim == 1 and y.ndim == 1: + if x.size == 2 and y.size == 2: + style = "image" + else: + dx = np.diff(x) + dy = np.diff(y) + if (np.ptp(dx) < 0.01 * np.abs(dx.mean()) and + np.ptp(dy) < 0.01 * np.abs(dy.mean())): + style = "image" + else: + style = "pcolorimage" + elif x.ndim == 2 and y.ndim == 2: + style = "quadmesh" + else: + raise TypeError("arguments do not match valid signatures") + else: + raise TypeError("need 1 argument or 3 arguments") + + if style == "quadmesh": + + # convert to one dimensional arrays + # This should also be moved to the QuadMesh class + + # data point in each cell is value at lower left corner + C = ma.ravel(C) + X = x.ravel() + Y = y.ravel() + Nx = nc + 1 + Ny = nr + 1 + + # The following needs to be cleaned up; the renderer + # requires separate contiguous arrays for X and Y, + # but the QuadMesh class requires the 2D array. + coords = np.empty(((Nx * Ny), 2), np.float64) + coords[:, 0] = X + coords[:, 1] = Y + + # The QuadMesh class can also be changed to + # handle relevant superclass kwargs; the initializer + # should do much more than it does now. + collection = mcoll.QuadMesh(nc, nr, coords, 0, edgecolors="None") + collection.set_alpha(alpha) + collection.set_array(C) + collection.set_cmap(cmap) + collection.set_norm(norm) + self.add_collection(collection, autolim=False) + xl, xr, yb, yt = X.min(), X.max(), Y.min(), Y.max() + ret = collection + + else: # It's one of the two image styles. + xl, xr, yb, yt = x[0], x[-1], y[0], y[-1] + + if style == "image": + im = mimage.AxesImage(self, cmap, norm, + interpolation='nearest', + origin='lower', + extent=(xl, xr, yb, yt), + **kwargs) + im.set_data(C) + im.set_alpha(alpha) + elif style == "pcolorimage": + im = mimage.PcolorImage(self, x, y, C, + cmap=cmap, + norm=norm, + alpha=alpha, + **kwargs) + im.set_extent((xl, xr, yb, yt)) + self.add_image(im) + ret = im + + if vmin is not None or vmax is not None: + ret.set_clim(vmin, vmax) + else: + ret.autoscale_None() + + ret.sticky_edges.x[:] = [xl, xr] + ret.sticky_edges.y[:] = [yb, yt] + self.update_datalim(np.array([[xl, yb], [xr, yt]])) + self.autoscale_view(tight=True) + return ret + + @_preprocess_data() + def contour(self, *args, **kwargs): + if not self._hold: + self.cla() + kwargs['filled'] = False + contours = mcontour.QuadContourSet(self, *args, **kwargs) + self.autoscale_view() + return contours + contour.__doc__ = mcontour.QuadContourSet._contour_doc + + @_preprocess_data() + def contourf(self, *args, **kwargs): + if not self._hold: + self.cla() + kwargs['filled'] = True + contours = mcontour.QuadContourSet(self, *args, **kwargs) + self.autoscale_view() + return contours + contourf.__doc__ = mcontour.QuadContourSet._contour_doc + + def clabel(self, CS, *args, **kwargs): + return CS.clabel(*args, **kwargs) + clabel.__doc__ = mcontour.ContourSet.clabel.__doc__ + + @docstring.dedent_interpd + def table(self, **kwargs): + """ + Add a table to the current axes. + + Call signature:: + + table(cellText=None, cellColours=None, + cellLoc='right', colWidths=None, + rowLabels=None, rowColours=None, rowLoc='left', + colLabels=None, colColours=None, colLoc='center', + loc='bottom', bbox=None) + + Returns a :class:`matplotlib.table.Table` instance. Either `cellText` + or `cellColours` must be provided. For finer grained control over + tables, use the :class:`~matplotlib.table.Table` class and add it to + the axes with :meth:`~matplotlib.axes.Axes.add_table`. + + Thanks to John Gill for providing the class and table. + + kwargs control the :class:`~matplotlib.table.Table` + properties: + + %(Table)s + """ + return mtable.table(self, **kwargs) + + #### Data analysis + + @_preprocess_data(replace_names=["x", 'weights'], label_namer="x") + def hist(self, x, bins=None, range=None, density=None, weights=None, + cumulative=False, bottom=None, histtype='bar', align='mid', + orientation='vertical', rwidth=None, log=False, + color=None, label=None, stacked=False, normed=None, + **kwargs): + """ + Plot a histogram. + + Compute and draw the histogram of *x*. The return value is a + tuple (*n*, *bins*, *patches*) or ([*n0*, *n1*, ...], *bins*, + [*patches0*, *patches1*,...]) if the input contains multiple + data. + + Multiple data can be provided via *x* as a list of datasets + of potentially different length ([*x0*, *x1*, ...]), or as + a 2-D ndarray in which each column is a dataset. Note that + the ndarray form is transposed relative to the list form. + + Masked arrays are not supported at present. + + Parameters + ---------- + x : (n,) array or sequence of (n,) arrays + Input values, this takes either a single array or a sequence of + arrays which are not required to be of the same length + + bins : integer or sequence or 'auto', optional + If an integer is given, ``bins + 1`` bin edges are calculated and + returned, consistent with :func:`numpy.histogram`. + + If `bins` is a sequence, gives bin edges, including left edge of + first bin and right edge of last bin. In this case, `bins` is + returned unmodified. + + All but the last (righthand-most) bin is half-open. In other + words, if `bins` is:: + + [1, 2, 3, 4] + + then the first bin is ``[1, 2)`` (including 1, but excluding 2) and + the second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which + *includes* 4. + + Unequally spaced bins are supported if *bins* is a sequence. + + If Numpy 1.11 is installed, may also be ``'auto'``. + + Default is taken from the rcParam ``hist.bins``. + + range : tuple or None, optional + The lower and upper range of the bins. Lower and upper outliers + are ignored. If not provided, *range* is ``(x.min(), x.max())``. + Range has no effect if *bins* is a sequence. + + If *bins* is a sequence or *range* is specified, autoscaling + is based on the specified bin range instead of the + range of x. + + Default is ``None`` + + density : boolean, optional + If ``True``, the first element of the return tuple will + be the counts normalized to form a probability density, i.e., + the area (or integral) under the histogram will sum to 1. + This is achieved by dividing the count by the number of + observations times the bin width and not dividing by the total + number of observations. If *stacked* is also ``True``, the sum of + the histograms is normalized to 1. + + Default is ``None`` for both *normed* and *density*. If either is + set, then that value will be used. If neither are set, then the + args will be treated as ``False``. + + If both *density* and *normed* are set an error is raised. + + weights : (n, ) array_like or None, optional + An array of weights, of the same shape as *x*. Each value in *x* + only contributes its associated weight towards the bin count + (instead of 1). If *normed* or *density* is ``True``, + the weights are normalized, so that the integral of the density + over the range remains 1. + + Default is ``None`` + + cumulative : boolean, optional + If ``True``, then a histogram is computed where each bin gives the + counts in that bin plus all bins for smaller values. The last bin + gives the total number of datapoints. If *normed* or *density* + is also ``True`` then the histogram is normalized such that the + last bin equals 1. If *cumulative* evaluates to less than 0 + (e.g., -1), the direction of accumulation is reversed. + In this case, if *normed* and/or *density* is also ``True``, then + the histogram is normalized such that the first bin equals 1. + + Default is ``False`` + + bottom : array_like, scalar, or None + Location of the bottom baseline of each bin. If a scalar, + the base line for each bin is shifted by the same amount. + If an array, each bin is shifted independently and the length + of bottom must match the number of bins. If None, defaults to 0. + + Default is ``None`` + + histtype : {'bar', 'barstacked', 'step', 'stepfilled'}, optional + The type of histogram to draw. + + - 'bar' is a traditional bar-type histogram. If multiple data + are given the bars are arranged side by side. + + - 'barstacked' is a bar-type histogram where multiple + data are stacked on top of each other. + + - 'step' generates a lineplot that is by default + unfilled. + + - 'stepfilled' generates a lineplot that is by default + filled. + + Default is 'bar' + + align : {'left', 'mid', 'right'}, optional + Controls how the histogram is plotted. + + - 'left': bars are centered on the left bin edges. + + - 'mid': bars are centered between the bin edges. + + - 'right': bars are centered on the right bin edges. + + Default is 'mid' + + orientation : {'horizontal', 'vertical'}, optional + If 'horizontal', `~matplotlib.pyplot.barh` will be used for + bar-type histograms and the *bottom* kwarg will be the left edges. + + rwidth : scalar or None, optional + The relative width of the bars as a fraction of the bin width. If + ``None``, automatically compute the width. + + Ignored if *histtype* is 'step' or 'stepfilled'. + + Default is ``None`` + + log : boolean, optional + If ``True``, the histogram axis will be set to a log scale. If + *log* is ``True`` and *x* is a 1D array, empty bins will be + filtered out and only the non-empty ``(n, bins, patches)`` + will be returned. + + Default is ``False`` + + color : color or array_like of colors or None, optional + Color spec or sequence of color specs, one per dataset. Default + (``None``) uses the standard line color sequence. + + Default is ``None`` + + label : string or None, optional + String, or sequence of strings to match multiple datasets. Bar + charts yield multiple patches per dataset, but only the first gets + the label, so that the legend command will work as expected. + + default is ``None`` + + stacked : boolean, optional + If ``True``, multiple data are stacked on top of each other If + ``False`` multiple data are arranged side by side if histtype is + 'bar' or on top of each other if histtype is 'step' + + Default is ``False`` + + normed : bool, optional + Deprecated; use the density keyword argument instead. + + Returns + ------- + n : array or list of arrays + The values of the histogram bins. See *normed* or *density* + and *weights* for a description of the possible semantics. + If input *x* is an array, then this is an array of length + *nbins*. If input is a sequence arrays + ``[data1, data2,..]``, then this is a list of arrays with + the values of the histograms for each of the arrays in the + same order. + + bins : array + The edges of the bins. Length nbins + 1 (nbins left edges and right + edge of last bin). Always a single array even when multiple data + sets are passed in. + + patches : list or list of lists + Silent list of individual patches used to create the histogram + or list of such list if multiple input datasets. + + Other Parameters + ---------------- + **kwargs : `~matplotlib.patches.Patch` properties + + See also + -------- + hist2d : 2D histograms + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + # Avoid shadowing the builtin. + bin_range = range + del range + + if not self._hold: + self.cla() + + if np.isscalar(x): + x = [x] + + if bins is None: + bins = rcParams['hist.bins'] + + # Validate string inputs here so we don't have to clutter + # subsequent code. + if histtype not in ['bar', 'barstacked', 'step', 'stepfilled']: + raise ValueError("histtype %s is not recognized" % histtype) + + if align not in ['left', 'mid', 'right']: + raise ValueError("align kwarg %s is not recognized" % align) + + if orientation not in ['horizontal', 'vertical']: + raise ValueError( + "orientation kwarg %s is not recognized" % orientation) + + if histtype == 'barstacked' and not stacked: + stacked = True + + if density is not None and normed is not None: + raise ValueError("kwargs 'density' and 'normed' cannot be used " + "simultaneously. " + "Please only use 'density', since 'normed'" + "is deprecated.") + if normed is not None: + warnings.warn("The 'normed' kwarg is deprecated, and has been " + "replaced by the 'density' kwarg.") + + # basic input validation + input_empty = np.size(x) == 0 + # Massage 'x' for processing. + if input_empty: + x = [np.array([])] + else: + x = cbook._reshape_2D(x, 'x') + nx = len(x) # number of datasets + + # Process unit information + # Unit conversion is done individually on each dataset + self._process_unit_info(xdata=x[0], kwargs=kwargs) + x = [self.convert_xunits(xi) for xi in x] + + if bin_range is not None: + bin_range = self.convert_xunits(bin_range) + + # Check whether bins or range are given explicitly. + binsgiven = (cbook.iterable(bins) or bin_range is not None) + + # We need to do to 'weights' what was done to 'x' + if weights is not None: + w = cbook._reshape_2D(weights, 'weights') + else: + w = [None] * nx + + if len(w) != nx: + raise ValueError('weights should have the same shape as x') + + for xi, wi in zip(x, w): + if wi is not None and len(wi) != len(xi): + raise ValueError( + 'weights should have the same shape as x') + + if color is None: + color = [self._get_lines.get_next_color() for i in xrange(nx)] + else: + color = mcolors.to_rgba_array(color) + if len(color) != nx: + raise ValueError("color kwarg must have one color per dataset") + + # If bins are not specified either explicitly or via range, + # we need to figure out the range required for all datasets, + # and supply that to np.histogram. + if not binsgiven and not input_empty: + xmin = np.inf + xmax = -np.inf + for xi in x: + if len(xi) > 0: + xmin = min(xmin, xi.min()) + xmax = max(xmax, xi.max()) + bin_range = (xmin, xmax) + density = bool(density) or bool(normed) + if density and not stacked: + hist_kwargs = dict(range=bin_range, density=density) + else: + hist_kwargs = dict(range=bin_range) + + # List to store all the top coordinates of the histograms + tops = [] + mlast = None + # Loop through datasets + for i in xrange(nx): + # this will automatically overwrite bins, + # so that each histogram uses the same bins + m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs) + m = m.astype(float) # causes problems later if it's an int + if mlast is None: + mlast = np.zeros(len(bins)-1, m.dtype) + if stacked: + m += mlast + mlast[:] = m + tops.append(m) + + # If a stacked density plot, normalize so the area of all the stacked + # histograms together is 1 + if stacked and density: + db = np.diff(bins) + for m in tops: + m[:] = (m / db) / tops[-1].sum() + if cumulative: + slc = slice(None) + if cbook.is_numlike(cumulative) and cumulative < 0: + slc = slice(None, None, -1) + + if density: + tops = [(m * np.diff(bins))[slc].cumsum()[slc] for m in tops] + else: + tops = [m[slc].cumsum()[slc] for m in tops] + + patches = [] + + # Save autoscale state for later restoration; turn autoscaling + # off so we can do it all a single time at the end, instead + # of having it done by bar or fill and then having to be redone. + _saved_autoscalex = self.get_autoscalex_on() + _saved_autoscaley = self.get_autoscaley_on() + self.set_autoscalex_on(False) + self.set_autoscaley_on(False) + + if histtype.startswith('bar'): + + totwidth = np.diff(bins) + + if rwidth is not None: + dr = np.clip(rwidth, 0, 1) + elif (len(tops) > 1 and + ((not stacked) or rcParams['_internal.classic_mode'])): + dr = 0.8 + else: + dr = 1.0 + + if histtype == 'bar' and not stacked: + width = dr * totwidth / nx + dw = width + boffset = -0.5 * dr * totwidth * (1 - 1 / nx) + elif histtype == 'barstacked' or stacked: + width = dr * totwidth + boffset, dw = 0.0, 0.0 + + if align == 'mid' or align == 'edge': + boffset += 0.5 * totwidth + elif align == 'right': + boffset += totwidth + + if orientation == 'horizontal': + _barfunc = self.barh + bottom_kwarg = 'left' + else: # orientation == 'vertical' + _barfunc = self.bar + bottom_kwarg = 'bottom' + + for m, c in zip(tops, color): + if bottom is None: + bottom = np.zeros(len(m)) + if stacked: + height = m - bottom + else: + height = m + patch = _barfunc(bins[:-1]+boffset, height, width, + align='center', log=log, + color=c, **{bottom_kwarg: bottom}) + patches.append(patch) + if stacked: + bottom[:] = m + boffset += dw + + elif histtype.startswith('step'): + # these define the perimeter of the polygon + x = np.zeros(4 * len(bins) - 3) + y = np.zeros(4 * len(bins) - 3) + + x[0:2*len(bins)-1:2], x[1:2*len(bins)-1:2] = bins, bins[:-1] + x[2*len(bins)-1:] = x[1:2*len(bins)-1][::-1] + + if bottom is None: + bottom = np.zeros(len(bins) - 1) + + y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = bottom, bottom + y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1] + + if log: + if orientation == 'horizontal': + self.set_xscale('log', nonposx='clip') + logbase = self.xaxis._scale.base + else: # orientation == 'vertical' + self.set_yscale('log', nonposy='clip') + logbase = self.yaxis._scale.base + + # Setting a minimum of 0 results in problems for log plots + if np.min(bottom) > 0: + minimum = np.min(bottom) + elif density or weights is not None: + # For data that is normed to form a probability density, + # set to minimum data value / logbase + # (gives 1 full tick-label unit for the lowest filled bin) + ndata = np.array(tops) + minimum = (np.min(ndata[ndata > 0])) / logbase + else: + # For non-normed (density = False) data, + # set the min to 1 / log base, + # again so that there is 1 full tick-label unit + # for the lowest bin + minimum = 1.0 / logbase + + y[0], y[-1] = minimum, minimum + else: + minimum = 0 + + if align == 'left' or align == 'center': + x -= 0.5*(bins[1]-bins[0]) + elif align == 'right': + x += 0.5*(bins[1]-bins[0]) + + # If fill kwarg is set, it will be passed to the patch collection, + # overriding this + fill = (histtype == 'stepfilled') + + xvals, yvals = [], [] + for m in tops: + if stacked: + # starting point for drawing polygon + y[0] = y[1] + # top of the previous polygon becomes the bottom + y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1] + # set the top of this polygon + y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = (m + bottom, + m + bottom) + if log: + y[y < minimum] = minimum + if orientation == 'horizontal': + xvals.append(y.copy()) + yvals.append(x.copy()) + else: + xvals.append(x.copy()) + yvals.append(y.copy()) + + # stepfill is closed, step is not + split = -1 if fill else 2 * len(bins) + # add patches in reverse order so that when stacking, + # items lower in the stack are plotted on top of + # items higher in the stack + for x, y, c in reversed(list(zip(xvals, yvals, color))): + patches.append(self.fill( + x[:split], y[:split], + closed=True if fill else None, + facecolor=c, + edgecolor=None if fill else c, + fill=fill if fill else None)) + for patch_list in patches: + for patch in patch_list: + if orientation == 'vertical': + patch.sticky_edges.y.append(minimum) + elif orientation == 'horizontal': + patch.sticky_edges.x.append(minimum) + + # we return patches, so put it back in the expected order + patches.reverse() + + self.set_autoscalex_on(_saved_autoscalex) + self.set_autoscaley_on(_saved_autoscaley) + self.autoscale_view() + + if label is None: + labels = [None] + elif isinstance(label, six.string_types): + labels = [label] + else: + labels = [six.text_type(lab) for lab in label] + + for patch, lbl in zip_longest(patches, labels, fillvalue=None): + if patch: + p = patch[0] + p.update(kwargs) + if lbl is not None: + p.set_label(lbl) + + for p in patch[1:]: + p.update(kwargs) + p.set_label('_nolegend_') + + if nx == 1: + return tops[0], bins, cbook.silent_list('Patch', patches[0]) + else: + return tops, bins, cbook.silent_list('Lists of Patches', patches) + + @_preprocess_data(replace_names=["x", "y", "weights"], label_namer=None) + def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None, + cmin=None, cmax=None, **kwargs): + """ + Make a 2D histogram plot. + + Parameters + ---------- + x, y: array_like, shape (n, ) + Input values + + bins: [None | int | [int, int] | array_like | [array, array]] + + The bin specification: + + - If int, the number of bins for the two dimensions + (nx=ny=bins). + + - If ``[int, int]``, the number of bins in each dimension + (nx, ny = bins). + + - If array_like, the bin edges for the two dimensions + (x_edges=y_edges=bins). + + - If ``[array, array]``, the bin edges in each dimension + (x_edges, y_edges = bins). + + The default value is 10. + + range : array_like shape(2, 2), optional, default: None + The leftmost and rightmost edges of the bins along each dimension + (if not specified explicitly in the bins parameters): ``[[xmin, + xmax], [ymin, ymax]]``. All values outside of this range will be + considered outliers and not tallied in the histogram. + + normed : boolean, optional, default: False + Normalize histogram. + + weights : array_like, shape (n, ), optional, default: None + An array of values w_i weighing each sample (x_i, y_i). + + cmin : scalar, optional, default: None + All bins that has count less than cmin will not be displayed and + these count values in the return value count histogram will also + be set to nan upon return + + cmax : scalar, optional, default: None + All bins that has count more than cmax will not be displayed (set + to none before passing to imshow) and these count values in the + return value count histogram will also be set to nan upon return + + Returns + ------- + h : 2D array + The bi-dimensional histogram of samples x and y. Values in x are + histogrammed along the first dimension and values in y are + histogrammed along the second dimension. + xedges : 1D array + The bin edges along the x axis. + yedges : 1D array + The bin edges along the y axis. + image : AxesImage + + Other Parameters + ---------------- + cmap : Colormap or str, optional + A `.colors.Colormap` instance. If not set, use rc settings. + + norm : Normalize, optional + A `.colors.Normalize` instance is used to + scale luminance data to ``[0, 1]``. If not set, defaults to + `.colors.Normalize()`. + + vmin/vmax : None or scalar, optional + Arguments passed to the `~.colors.Normalize` instance. + + alpha : ``0 <= scalar <= 1`` or ``None``, optional + The alpha blending value. + + See also + -------- + hist : 1D histogram plotting + + Notes + ----- + - Currently ``hist2d`` calculates it's own axis limits, and any limits + previously set are ignored. + - Rendering the histogram with a logarithmic color scale is + accomplished by passing a `.colors.LogNorm` instance to the *norm* + keyword argument. Likewise, power-law normalization (similar + in effect to gamma correction) can be accomplished with + `.colors.PowerNorm`. + """ + + h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range, + normed=normed, weights=weights) + + if cmin is not None: + h[h < cmin] = None + if cmax is not None: + h[h > cmax] = None + + pc = self.pcolorfast(xedges, yedges, h.T, **kwargs) + self.set_xlim(xedges[0], xedges[-1]) + self.set_ylim(yedges[0], yedges[-1]) + + return h, xedges, yedges, pc + + @_preprocess_data(replace_names=["x"], label_namer=None) + @docstring.dedent_interpd + def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, + window=None, noverlap=None, pad_to=None, + sides=None, scale_by_freq=None, return_line=None, **kwargs): + r""" + Plot the power spectral density. + + Call signature:: + + psd(x, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, + window=mlab.window_hanning, noverlap=0, pad_to=None, + sides='default', scale_by_freq=None, return_line=None, **kwargs) + + The power spectral density :math:`P_{xx}` by Welch's average + periodogram method. The vector *x* is divided into *NFFT* length + segments. Each segment is detrended by function *detrend* and + windowed by function *window*. *noverlap* gives the length of + the overlap between segments. The :math:`|\mathrm{fft}(i)|^2` + of each segment :math:`i` are averaged to compute :math:`P_{xx}`, + with a scaling to correct for power loss due to windowing. + + If len(*x*) < *NFFT*, it will be zero padded to *NFFT*. + + Parameters + ---------- + x : 1-D array or sequence + Array or sequence containing the data + + %(Spectral)s + + %(PSD)s + + noverlap : integer + The number of points of overlap between segments. + The default value is 0 (no overlap). + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + return_line : bool + Whether to include the line object plotted in the returned values. + Default is False. + + Returns + ------- + Pxx : 1-D array + The values for the power spectrum `P_{xx}` before scaling + (real valued) + + freqs : 1-D array + The frequencies corresponding to the elements in *Pxx* + + line : a :class:`~matplotlib.lines.Line2D` instance + The line created by this function. + Only returned if *return_line* is True. + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + See Also + -------- + :func:`specgram` + :func:`specgram` differs in the default overlap; in not returning + the mean of the segment periodograms; in returning the times of the + segments; and in plotting a colormap instead of a line. + + :func:`magnitude_spectrum` + :func:`magnitude_spectrum` plots the magnitude spectrum. + + :func:`csd` + :func:`csd` plots the spectral density between two signals. + + Notes + ----- + For plotting, the power is plotted as + :math:`10\log_{10}(P_{xx})` for decibels, though *Pxx* itself + is returned. + + References + ---------- + Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, + John Wiley & Sons (1986) + """ + if not self._hold: + self.cla() + + if Fc is None: + Fc = 0 + + pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend, + window=window, noverlap=noverlap, pad_to=pad_to, + sides=sides, scale_by_freq=scale_by_freq) + freqs += Fc + + if scale_by_freq in (None, True): + psd_units = 'dB/Hz' + else: + psd_units = 'dB' + + line = self.plot(freqs, 10 * np.log10(pxx), **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Power Spectral Density (%s)' % psd_units) + self.grid(True) + vmin, vmax = self.viewLim.intervaly + intv = vmax - vmin + logi = int(np.log10(intv)) + if logi == 0: + logi = .1 + step = 10 * logi + ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step) + self.set_yticks(ticks) + + if return_line is None or not return_line: + return pxx, freqs + else: + return pxx, freqs, line + + @_preprocess_data(replace_names=["x", "y"], label_namer="y") + @docstring.dedent_interpd + def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None, + window=None, noverlap=None, pad_to=None, + sides=None, scale_by_freq=None, return_line=None, **kwargs): + """ + Plot the cross-spectral density. + + Call signature:: + + csd(x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, + window=mlab.window_hanning, noverlap=0, pad_to=None, + sides='default', scale_by_freq=None, return_line=None, **kwargs) + + The cross spectral density :math:`P_{xy}` by Welch's average + periodogram method. The vectors *x* and *y* are divided into + *NFFT* length segments. Each segment is detrended by function + *detrend* and windowed by function *window*. *noverlap* gives + the length of the overlap between segments. The product of + the direct FFTs of *x* and *y* are averaged over each segment + to compute :math:`P_{xy}`, with a scaling to correct for power + loss due to windowing. + + If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero + padded to *NFFT*. + + Parameters + ---------- + x, y : 1-D arrays or sequences + Arrays or sequences containing the data + + %(Spectral)s + + %(PSD)s + + noverlap : integer + The number of points of overlap between segments. + The default value is 0 (no overlap). + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + return_line : bool + Whether to include the line object plotted in the returned values. + Default is False. + + Returns + ------- + Pxy : 1-D array + The values for the cross spectrum `P_{xy}` before scaling + (complex valued) + + freqs : 1-D array + The frequencies corresponding to the elements in *Pxy* + + line : a :class:`~matplotlib.lines.Line2D` instance + The line created by this function. + Only returned if *return_line* is True. + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + See Also + -------- + :func:`psd` + :func:`psd` is the equivalent to setting y=x. + + Notes + ----- + For plotting, the power is plotted as + :math:`10\\log_{10}(P_{xy})` for decibels, though `P_{xy}` itself + is returned. + + References + ---------- + Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, + John Wiley & Sons (1986) + """ + if not self._hold: + self.cla() + + if Fc is None: + Fc = 0 + + pxy, freqs = mlab.csd(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend, + window=window, noverlap=noverlap, pad_to=pad_to, + sides=sides, scale_by_freq=scale_by_freq) + # pxy is complex + freqs += Fc + + line = self.plot(freqs, 10 * np.log10(np.abs(pxy)), **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Cross Spectrum Magnitude (dB)') + self.grid(True) + vmin, vmax = self.viewLim.intervaly + + intv = vmax - vmin + step = 10 * int(np.log10(intv)) + + ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step) + self.set_yticks(ticks) + + if return_line is None or not return_line: + return pxy, freqs + else: + return pxy, freqs, line + + @_preprocess_data(replace_names=["x"], label_namer=None) + @docstring.dedent_interpd + def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None, + pad_to=None, sides=None, scale=None, + **kwargs): + """ + Plot the magnitude spectrum. + + Call signature:: + + magnitude_spectrum(x, Fs=2, Fc=0, window=mlab.window_hanning, + pad_to=None, sides='default', **kwargs) + + Compute the magnitude spectrum of *x*. Data is padded to a + length of *pad_to* and the windowing function *window* is applied to + the signal. + + Parameters + ---------- + x : 1-D array or sequence + Array or sequence containing the data + + %(Spectral)s + + %(Single_Spectrum)s + + scale : [ 'default' | 'linear' | 'dB' ] + The scaling of the values in the *spec*. 'linear' is no scaling. + 'dB' returns the values in dB scale, i.e., the dB amplitude + (20 * log10). 'default' is 'linear'. + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + Returns + ------- + spectrum : 1-D array + The values for the magnitude spectrum before scaling (real valued) + + freqs : 1-D array + The frequencies corresponding to the elements in *spectrum* + + line : a :class:`~matplotlib.lines.Line2D` instance + The line created by this function + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + See Also + -------- + :func:`psd` + :func:`psd` plots the power spectral density.`. + + :func:`angle_spectrum` + :func:`angle_spectrum` plots the angles of the corresponding + frequencies. + + :func:`phase_spectrum` + :func:`phase_spectrum` plots the phase (unwrapped angle) of the + corresponding frequencies. + + :func:`specgram` + :func:`specgram` can plot the magnitude spectrum of segments within + the signal in a colormap. + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + if not self._hold: + self.cla() + + if Fc is None: + Fc = 0 + + if scale is None or scale == 'default': + scale = 'linear' + + spec, freqs = mlab.magnitude_spectrum(x=x, Fs=Fs, window=window, + pad_to=pad_to, sides=sides) + freqs += Fc + + if scale == 'linear': + Z = spec + yunits = 'energy' + elif scale == 'dB': + Z = 20. * np.log10(spec) + yunits = 'dB' + else: + raise ValueError('Unknown scale %s', scale) + + lines = self.plot(freqs, Z, **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Magnitude (%s)' % yunits) + + return spec, freqs, lines[0] + + @_preprocess_data(replace_names=["x"], label_namer=None) + @docstring.dedent_interpd + def angle_spectrum(self, x, Fs=None, Fc=None, window=None, + pad_to=None, sides=None, **kwargs): + """ + Plot the angle spectrum. + + Call signature:: + + angle_spectrum(x, Fs=2, Fc=0, window=mlab.window_hanning, + pad_to=None, sides='default', **kwargs) + + Compute the angle spectrum (wrapped phase spectrum) of *x*. + Data is padded to a length of *pad_to* and the windowing function + *window* is applied to the signal. + + Parameters + ---------- + x : 1-D array or sequence + Array or sequence containing the data + + %(Spectral)s + + %(Single_Spectrum)s + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + Returns + ------- + spectrum : 1-D array + The values for the angle spectrum in radians (real valued) + + freqs : 1-D array + The frequencies corresponding to the elements in *spectrum* + + line : a :class:`~matplotlib.lines.Line2D` instance + The line created by this function + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + See Also + -------- + :func:`magnitude_spectrum` + :func:`angle_spectrum` plots the magnitudes of the corresponding + frequencies. + + :func:`phase_spectrum` + :func:`phase_spectrum` plots the unwrapped version of this + function. + + :func:`specgram` + :func:`specgram` can plot the angle spectrum of segments within the + signal in a colormap. + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + if not self._hold: + self.cla() + + if Fc is None: + Fc = 0 + + spec, freqs = mlab.angle_spectrum(x=x, Fs=Fs, window=window, + pad_to=pad_to, sides=sides) + freqs += Fc + + lines = self.plot(freqs, spec, **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Angle (radians)') + + return spec, freqs, lines[0] + + @_preprocess_data(replace_names=["x"], label_namer=None) + @docstring.dedent_interpd + def phase_spectrum(self, x, Fs=None, Fc=None, window=None, + pad_to=None, sides=None, **kwargs): + """ + Plot the phase spectrum. + + Call signature:: + + phase_spectrum(x, Fs=2, Fc=0, window=mlab.window_hanning, + pad_to=None, sides='default', **kwargs) + + Compute the phase spectrum (unwrapped angle spectrum) of *x*. + Data is padded to a length of *pad_to* and the windowing function + *window* is applied to the signal. + + Parameters + ---------- + x : 1-D array or sequence + Array or sequence containing the data + + %(Spectral)s + + %(Single_Spectrum)s + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + Returns + ------- + spectrum : 1-D array + The values for the phase spectrum in radians (real valued) + + freqs : 1-D array + The frequencies corresponding to the elements in *spectrum* + + line : a :class:`~matplotlib.lines.Line2D` instance + The line created by this function + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + See Also + -------- + :func:`magnitude_spectrum` + :func:`magnitude_spectrum` plots the magnitudes of the + corresponding frequencies. + + :func:`angle_spectrum` + :func:`angle_spectrum` plots the wrapped version of this function. + + :func:`specgram` + :func:`specgram` can plot the phase spectrum of segments within the + signal in a colormap. + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + if not self._hold: + self.cla() + + if Fc is None: + Fc = 0 + + spec, freqs = mlab.phase_spectrum(x=x, Fs=Fs, window=window, + pad_to=pad_to, sides=sides) + freqs += Fc + + lines = self.plot(freqs, spec, **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Phase (radians)') + + return spec, freqs, lines[0] + + @_preprocess_data(replace_names=["x", "y"], label_namer=None) + @docstring.dedent_interpd + def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, + window=mlab.window_hanning, noverlap=0, pad_to=None, + sides='default', scale_by_freq=None, **kwargs): + """ + Plot the coherence between *x* and *y*. + + Plot the coherence between *x* and *y*. Coherence is the + normalized cross spectral density: + + .. math:: + + C_{xy} = \\frac{|P_{xy}|^2}{P_{xx}P_{yy}} + + Parameters + ---------- + %(Spectral)s + + %(PSD)s + + noverlap : integer + The number of points of overlap between blocks. The + default value is 0 (no overlap). + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + + Returns + ------- + The return value is a tuple (*Cxy*, *f*), where *f* are the + frequencies of the coherence vector. + + kwargs are applied to the lines. + + Other Parameters + ---------------- + **kwargs : + Keyword arguments control the :class:`~matplotlib.lines.Line2D` + properties: + + %(Line2D)s + + References + ---------- + Bendat & Piersol -- Random Data: Analysis and Measurement Procedures, + John Wiley & Sons (1986) + """ + if not self._hold: + self.cla() + cxy, freqs = mlab.cohere(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend, + window=window, noverlap=noverlap, + scale_by_freq=scale_by_freq) + freqs += Fc + + self.plot(freqs, cxy, **kwargs) + self.set_xlabel('Frequency') + self.set_ylabel('Coherence') + self.grid(True) + + return cxy, freqs + + @_preprocess_data(replace_names=["x"], label_namer=None) + @docstring.dedent_interpd + def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None, + window=None, noverlap=None, + cmap=None, xextent=None, pad_to=None, sides=None, + scale_by_freq=None, mode=None, scale=None, + vmin=None, vmax=None, **kwargs): + """ + Plot a spectrogram. + + Call signature:: + + specgram(x, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, + window=mlab.window_hanning, noverlap=128, + cmap=None, xextent=None, pad_to=None, sides='default', + scale_by_freq=None, mode='default', scale='default', + **kwargs) + + Compute and plot a spectrogram of data in *x*. Data are split into + *NFFT* length segments and the spectrum of each section is + computed. The windowing function *window* is applied to each + segment, and the amount of overlap of each segment is + specified with *noverlap*. The spectrogram is plotted as a colormap + (using imshow). + + Parameters + ---------- + x : 1-D array or sequence + Array or sequence containing the data. + + %(Spectral)s + + %(PSD)s + + mode : [ 'default' | 'psd' | 'magnitude' | 'angle' | 'phase' ] + What sort of spectrum to use. Default is 'psd', which takes + the power spectral density. 'complex' returns the complex-valued + frequency spectrum. 'magnitude' returns the magnitude spectrum. + 'angle' returns the phase spectrum without unwrapping. 'phase' + returns the phase spectrum with unwrapping. + + noverlap : integer + The number of points of overlap between blocks. The + default value is 128. + + scale : [ 'default' | 'linear' | 'dB' ] + The scaling of the values in the *spec*. 'linear' is no scaling. + 'dB' returns the values in dB scale. When *mode* is 'psd', + this is dB power (10 * log10). Otherwise this is dB amplitude + (20 * log10). 'default' is 'dB' if *mode* is 'psd' or + 'magnitude' and 'linear' otherwise. This must be 'linear' + if *mode* is 'angle' or 'phase'. + + Fc : integer + The center frequency of *x* (defaults to 0), which offsets + the x extents of the plot to reflect the frequency range used + when a signal is acquired and then filtered and downsampled to + baseband. + + cmap : + A :class:`matplotlib.colors.Colormap` instance; if *None*, use + default determined by rc + + xextent : [None | (xmin, xmax)] + The image extent along the x-axis. The default sets *xmin* to the + left border of the first bin (*spectrum* column) and *xmax* to the + right border of the last bin. Note that for *noverlap>0* the width + of the bins is smaller than those of the segments. + + **kwargs : + Additional kwargs are passed on to imshow which makes the + specgram image + + Returns + ------- + spectrum : 2-D array + Columns are the periodograms of successive segments. + + freqs : 1-D array + The frequencies corresponding to the rows in *spectrum*. + + t : 1-D array + The times corresponding to midpoints of segments (i.e., the columns + in *spectrum*). + + im : instance of class :class:`~matplotlib.image.AxesImage` + The image created by imshow containing the spectrogram + + See Also + -------- + :func:`psd` + :func:`psd` differs in the default overlap; in returning the mean + of the segment periodograms; in not returning times; and in + generating a line plot instead of colormap. + + :func:`magnitude_spectrum` + A single spectrum, similar to having a single segment when *mode* + is 'magnitude'. Plots a line instead of a colormap. + + :func:`angle_spectrum` + A single spectrum, similar to having a single segment when *mode* + is 'angle'. Plots a line instead of a colormap. + + :func:`phase_spectrum` + A single spectrum, similar to having a single segment when *mode* + is 'phase'. Plots a line instead of a colormap. + + Notes + ----- + The parameters *detrend* and *scale_by_freq* do only apply when *mode* + is set to 'psd'. + """ + if not self._hold: + self.cla() + + if NFFT is None: + NFFT = 256 # same default as in mlab.specgram() + if Fc is None: + Fc = 0 # same default as in mlab._spectral_helper() + if noverlap is None: + noverlap = 128 # same default as in mlab.specgram() + + if mode == 'complex': + raise ValueError('Cannot plot a complex specgram') + + if scale is None or scale == 'default': + if mode in ['angle', 'phase']: + scale = 'linear' + else: + scale = 'dB' + elif mode in ['angle', 'phase'] and scale == 'dB': + raise ValueError('Cannot use dB scale with angle or phase mode') + + spec, freqs, t = mlab.specgram(x=x, NFFT=NFFT, Fs=Fs, + detrend=detrend, window=window, + noverlap=noverlap, pad_to=pad_to, + sides=sides, + scale_by_freq=scale_by_freq, + mode=mode) + + if scale == 'linear': + Z = spec + elif scale == 'dB': + if mode is None or mode == 'default' or mode == 'psd': + Z = 10. * np.log10(spec) + else: + Z = 20. * np.log10(spec) + else: + raise ValueError('Unknown scale %s', scale) + + Z = np.flipud(Z) + + if xextent is None: + # padding is needed for first and last segment: + pad_xextent = (NFFT-noverlap) / Fs / 2 + xextent = np.min(t) - pad_xextent, np.max(t) + pad_xextent + xmin, xmax = xextent + freqs += Fc + extent = xmin, xmax, freqs[0], freqs[-1] + im = self.imshow(Z, cmap, extent=extent, vmin=vmin, vmax=vmax, + **kwargs) + self.axis('auto') + + return spec, freqs, t, im + + def spy(self, Z, precision=0, marker=None, markersize=None, + aspect='equal', origin="upper", **kwargs): + """ + Plot the sparsity pattern on a 2-D array. + + ``spy(Z)`` plots the sparsity pattern of the 2-D array *Z*. + + Parameters + ---------- + + Z : sparse array (n, m) + The array to be plotted. + + precision : float, optional, default: 0 + If *precision* is 0, any non-zero value will be plotted; else, + values of :math:`|Z| > precision` will be plotted. + + For :class:`scipy.sparse.spmatrix` instances, there is a special + case: if *precision* is 'present', any value present in the array + will be plotted, even if it is identically zero. + + origin : ["upper", "lower"], optional, default: "upper" + Place the [0,0] index of the array in the upper left or lower left + corner of the axes. + + aspect : ['auto' | 'equal' | scalar], optional, default: "equal" + + If 'equal', and `extent` is None, changes the axes aspect ratio to + match that of the image. If `extent` is not `None`, the axes + aspect ratio is changed to match that of the extent. + + + If 'auto', changes the image aspect ratio to match that of the + axes. + + If None, default to rc ``image.aspect`` value. + + Two plotting styles are available: image or marker. Both + are available for full arrays, but only the marker style + works for :class:`scipy.sparse.spmatrix` instances. + + If *marker* and *markersize* are *None*, an image will be + returned and any remaining kwargs are passed to + :func:`~matplotlib.pyplot.imshow`; else, a + :class:`~matplotlib.lines.Line2D` object will be returned with + the value of marker determining the marker type, and any + remaining kwargs passed to the + :meth:`~matplotlib.axes.Axes.plot` method. + + If *marker* and *markersize* are *None*, useful kwargs include: + + * *cmap* + * *alpha* + + See also + -------- + imshow : for image options. + plot : for plotting options + """ + if marker is None and markersize is None and hasattr(Z, 'tocoo'): + marker = 's' + if marker is None and markersize is None: + Z = np.asarray(Z) + mask = np.abs(Z) > precision + + if 'cmap' not in kwargs: + kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'], + name='binary') + nr, nc = Z.shape + extent = [-0.5, nc - 0.5, nr - 0.5, -0.5] + ret = self.imshow(mask, interpolation='nearest', aspect=aspect, + extent=extent, origin=origin, **kwargs) + else: + if hasattr(Z, 'tocoo'): + c = Z.tocoo() + if precision == 'present': + y = c.row + x = c.col + else: + nonzero = np.abs(c.data) > precision + y = c.row[nonzero] + x = c.col[nonzero] + else: + Z = np.asarray(Z) + nonzero = np.abs(Z) > precision + y, x = np.nonzero(nonzero) + if marker is None: + marker = 's' + if markersize is None: + markersize = 10 + marks = mlines.Line2D(x, y, linestyle='None', + marker=marker, markersize=markersize, **kwargs) + self.add_line(marks) + nr, nc = Z.shape + self.set_xlim(xmin=-0.5, xmax=nc - 0.5) + self.set_ylim(ymin=nr - 0.5, ymax=-0.5) + self.set_aspect(aspect) + ret = marks + self.title.set_y(1.05) + self.xaxis.tick_top() + self.xaxis.set_ticks_position('both') + self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9, + steps=[1, 2, 5, 10], + integer=True)) + self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9, + steps=[1, 2, 5, 10], + integer=True)) + return ret + + def matshow(self, Z, **kwargs): + """ + Plot the values of a 2D matrix or array as color-coded image. + + The matrix will be shown the way it would be printed, with the first + row at the top. Row and column numbering is zero-based. + + Parameters + ---------- + Z : array-like(N, M) + The matrix to be displayed. + + Returns + ------- + image : `~matplotlib.image.AxesImage` + + Other Parameters + ---------------- + **kwargs : `~matplotlib.axes.Axes.imshow` arguments + + See Also + -------- + imshow : More general function to plot data on a 2D regular raster. + + Notes + ----- + This is just a convenience function wrapping `.imshow` to set useful + defaults for a displaying a matrix. In particular: + + - Set ``origin='upper'``. + - Set ``interpolation='nearest'``. + - Set ``aspect='equal'``. + - Ticks are placed to the left and above. + - Ticks are formatted to show integer indices. + + """ + Z = np.asanyarray(Z) + nr, nc = Z.shape + kw = {'origin': 'upper', + 'interpolation': 'nearest', + 'aspect': 'equal'} # (already the imshow default) + kw.update(kwargs) + im = self.imshow(Z, **kw) + self.title.set_y(1.05) + self.xaxis.tick_top() + self.xaxis.set_ticks_position('both') + self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9, + steps=[1, 2, 5, 10], + integer=True)) + self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9, + steps=[1, 2, 5, 10], + integer=True)) + return im + + @_preprocess_data(replace_names=["dataset"], label_namer=None) + def violinplot(self, dataset, positions=None, vert=True, widths=0.5, + showmeans=False, showextrema=True, showmedians=False, + points=100, bw_method=None): + """ + Make a violin plot. + + Make a violin plot for each column of *dataset* or each vector in + sequence *dataset*. Each filled area extends to represent the + entire data range, with optional lines at the mean, the median, + the minimum, and the maximum. + + Parameters + ---------- + dataset : Array or a sequence of vectors. + The input data. + + positions : array-like, default = [1, 2, ..., n] + Sets the positions of the violins. The ticks and limits are + automatically set to match the positions. + + vert : bool, default = True. + If true, creates a vertical violin plot. + Otherwise, creates a horizontal violin plot. + + widths : array-like, default = 0.5 + Either a scalar or a vector that sets the maximal width of + each violin. The default is 0.5, which uses about half of the + available horizontal space. + + showmeans : bool, default = False + If `True`, will toggle rendering of the means. + + showextrema : bool, default = True + If `True`, will toggle rendering of the extrema. + + showmedians : bool, default = False + If `True`, will toggle rendering of the medians. + + points : scalar, default = 100 + Defines the number of points to evaluate each of the + gaussian kernel density estimations at. + + bw_method : str, scalar or callable, optional + The method used to calculate the estimator bandwidth. This can be + 'scott', 'silverman', a scalar constant or a callable. If a + scalar, this will be used directly as `kde.factor`. If a + callable, it should take a `GaussianKDE` instance as its only + parameter and return a scalar. If None (default), 'scott' is used. + + Returns + ------- + + result : dict + A dictionary mapping each component of the violinplot to a + list of the corresponding collection instances created. The + dictionary has the following keys: + + - ``bodies``: A list of the + :class:`matplotlib.collections.PolyCollection` instances + containing the filled area of each violin. + + - ``cmeans``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the mean values of each of the + violin's distribution. + + - ``cmins``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the bottom of each violin's + distribution. + + - ``cmaxes``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the top of each violin's + distribution. + + - ``cbars``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the centers of each violin's + distribution. + + - ``cmedians``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the median values of each of the + violin's distribution. + + Notes + ----- + .. [Notes section required for data comment. See #10189.] + + """ + + def _kde_method(X, coords): + # fallback gracefully if the vector contains only one value + if np.all(X[0] == X): + return (X[0] == coords).astype(float) + kde = mlab.GaussianKDE(X, bw_method) + return kde.evaluate(coords) + + vpstats = cbook.violin_stats(dataset, _kde_method, points=points) + return self.violin(vpstats, positions=positions, vert=vert, + widths=widths, showmeans=showmeans, + showextrema=showextrema, showmedians=showmedians) + + def violin(self, vpstats, positions=None, vert=True, widths=0.5, + showmeans=False, showextrema=True, showmedians=False): + """Drawing function for violin plots. + + Draw a violin plot for each column of `vpstats`. Each filled area + extends to represent the entire data range, with optional lines at the + mean, the median, the minimum, and the maximum. + + Parameters + ---------- + + vpstats : list of dicts + A list of dictionaries containing stats for each violin plot. + Required keys are: + + - ``coords``: A list of scalars containing the coordinates that + the violin's kernel density estimate were evaluated at. + + - ``vals``: A list of scalars containing the values of the + kernel density estimate at each of the coordinates given + in *coords*. + + - ``mean``: The mean value for this violin's dataset. + + - ``median``: The median value for this violin's dataset. + + - ``min``: The minimum value for this violin's dataset. + + - ``max``: The maximum value for this violin's dataset. + + positions : array-like, default = [1, 2, ..., n] + Sets the positions of the violins. The ticks and limits are + automatically set to match the positions. + + vert : bool, default = True. + If true, plots the violins veritcally. + Otherwise, plots the violins horizontally. + + widths : array-like, default = 0.5 + Either a scalar or a vector that sets the maximal width of + each violin. The default is 0.5, which uses about half of the + available horizontal space. + + showmeans : bool, default = False + If true, will toggle rendering of the means. + + showextrema : bool, default = True + If true, will toggle rendering of the extrema. + + showmedians : bool, default = False + If true, will toggle rendering of the medians. + + Returns + ------- + result : dict + A dictionary mapping each component of the violinplot to a + list of the corresponding collection instances created. The + dictionary has the following keys: + + - ``bodies``: A list of the + :class:`matplotlib.collections.PolyCollection` instances + containing the filled area of each violin. + + - ``cmeans``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the mean values of each of the + violin's distribution. + + - ``cmins``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the bottom of each violin's + distribution. + + - ``cmaxes``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the top of each violin's + distribution. + + - ``cbars``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the centers of each violin's + distribution. + + - ``cmedians``: A + :class:`matplotlib.collections.LineCollection` instance + created to identify the median values of each of the + violin's distribution. + + """ + + # Statistical quantities to be plotted on the violins + means = [] + mins = [] + maxes = [] + medians = [] + + # Collections to be returned + artists = {} + + N = len(vpstats) + datashape_message = ("List of violinplot statistics and `{0}` " + "values must have the same length") + + # Validate positions + if positions is None: + positions = range(1, N + 1) + elif len(positions) != N: + raise ValueError(datashape_message.format("positions")) + + # Validate widths + if np.isscalar(widths): + widths = [widths] * N + elif len(widths) != N: + raise ValueError(datashape_message.format("widths")) + + # Calculate ranges for statistics lines + pmins = -0.25 * np.array(widths) + positions + pmaxes = 0.25 * np.array(widths) + positions + + # Check whether we are rendering vertically or horizontally + if vert: + fill = self.fill_betweenx + perp_lines = self.hlines + par_lines = self.vlines + else: + fill = self.fill_between + perp_lines = self.vlines + par_lines = self.hlines + + if rcParams['_internal.classic_mode']: + fillcolor = 'y' + edgecolor = 'r' + else: + fillcolor = edgecolor = self._get_lines.get_next_color() + + # Render violins + bodies = [] + for stats, pos, width in zip(vpstats, positions, widths): + # The 0.5 factor reflects the fact that we plot from v-p to + # v+p + vals = np.array(stats['vals']) + vals = 0.5 * width * vals / vals.max() + bodies += [fill(stats['coords'], + -vals + pos, + vals + pos, + facecolor=fillcolor, + alpha=0.3)] + means.append(stats['mean']) + mins.append(stats['min']) + maxes.append(stats['max']) + medians.append(stats['median']) + artists['bodies'] = bodies + + # Render means + if showmeans: + artists['cmeans'] = perp_lines(means, pmins, pmaxes, + colors=edgecolor) + + # Render extrema + if showextrema: + artists['cmaxes'] = perp_lines(maxes, pmins, pmaxes, + colors=edgecolor) + artists['cmins'] = perp_lines(mins, pmins, pmaxes, + colors=edgecolor) + artists['cbars'] = par_lines(positions, mins, maxes, + colors=edgecolor) + + # Render medians + if showmedians: + artists['cmedians'] = perp_lines(medians, + pmins, + pmaxes, + colors=edgecolor) + + return artists + + def tricontour(self, *args, **kwargs): + return mtri.tricontour(self, *args, **kwargs) + tricontour.__doc__ = mtri.tricontour.__doc__ + + def tricontourf(self, *args, **kwargs): + return mtri.tricontourf(self, *args, **kwargs) + tricontourf.__doc__ = mtri.tricontour.__doc__ + + def tripcolor(self, *args, **kwargs): + return mtri.tripcolor(self, *args, **kwargs) + tripcolor.__doc__ = mtri.tripcolor.__doc__ + + def triplot(self, *args, **kwargs): + return mtri.triplot(self, *args, **kwargs) + triplot.__doc__ = mtri.triplot.__doc__ diff --git a/contrib/python/matplotlib/py2/matplotlib/axes/_base.py b/contrib/python/matplotlib/py2/matplotlib/axes/_base.py new file mode 100644 index 00000000000..5265f112701 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/axes/_base.py @@ -0,0 +1,4297 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from collections import OrderedDict + +import six +from six.moves import xrange + +import itertools +import warnings +import math +from operator import attrgetter + +import numpy as np + +import matplotlib + +from matplotlib import cbook +from matplotlib.cbook import (_check_1d, _string_to_bool, iterable, + index_of, get_label) +from matplotlib import docstring +import matplotlib.colors as mcolors +import matplotlib.lines as mlines +import matplotlib.patches as mpatches +import matplotlib.artist as martist +import matplotlib.transforms as mtransforms +import matplotlib.ticker as mticker +import matplotlib.axis as maxis +import matplotlib.scale as mscale +import matplotlib.spines as mspines +import matplotlib.font_manager as font_manager +import matplotlib.text as mtext +import matplotlib.image as mimage +from matplotlib.offsetbox import OffsetBox +from matplotlib.artist import allow_rasterization +from matplotlib.legend import Legend + +from matplotlib.rcsetup import cycler +from matplotlib.rcsetup import validate_axisbelow + +rcParams = matplotlib.rcParams + +is_string_like = cbook.is_string_like +is_sequence_of_strings = cbook.is_sequence_of_strings + +_hold_msg = """axes.hold is deprecated. + See the API Changes document (http://matplotlib.org/api/api_changes.html) + for more details.""" + + +def _process_plot_format(fmt): + """ + Process a MATLAB style color/line style format string. Return a + (*linestyle*, *color*) tuple as a result of the processing. Default + values are ('-', 'b'). Example format strings include: + + * 'ko': black circles + * '.b': blue dots + * 'r--': red dashed lines + * 'C2--': the third color in the color cycle, dashed lines + + .. seealso:: + + :func:`~matplotlib.Line2D.lineStyles` and + :func:`~matplotlib.pyplot.colors` + for all possible styles and color format string. + """ + + linestyle = None + marker = None + color = None + + # Is fmt just a colorspec? + try: + color = mcolors.to_rgba(fmt) + + # We need to differentiate grayscale '1.0' from tri_down marker '1' + try: + fmtint = str(int(fmt)) + except ValueError: + return linestyle, marker, color # Yes + else: + if fmt != fmtint: + # user definitely doesn't want tri_down marker + return linestyle, marker, color # Yes + else: + # ignore converted color + color = None + except ValueError: + pass # No, not just a color. + + # handle the multi char special cases and strip them from the + # string + if fmt.find('--') >= 0: + linestyle = '--' + fmt = fmt.replace('--', '') + if fmt.find('-.') >= 0: + linestyle = '-.' + fmt = fmt.replace('-.', '') + if fmt.find(' ') >= 0: + linestyle = 'None' + fmt = fmt.replace(' ', '') + + chars = [c for c in fmt] + + i = 0 + while i < len(chars): + c = chars[i] + if c in mlines.lineStyles: + if linestyle is not None: + raise ValueError( + 'Illegal format string "%s"; two linestyle symbols' % fmt) + linestyle = c + elif c in mlines.lineMarkers: + if marker is not None: + raise ValueError( + 'Illegal format string "%s"; two marker symbols' % fmt) + marker = c + elif c in mcolors.get_named_colors_mapping(): + if color is not None: + raise ValueError( + 'Illegal format string "%s"; two color symbols' % fmt) + color = c + elif c == 'C' and i < len(chars) - 1: + color_cycle_number = int(chars[i + 1]) + color = mcolors.to_rgba("C{}".format(color_cycle_number)) + i += 1 + else: + raise ValueError( + 'Unrecognized character %c in format string' % c) + i += 1 + + if linestyle is None and marker is None: + linestyle = rcParams['lines.linestyle'] + if linestyle is None: + linestyle = 'None' + if marker is None: + marker = 'None' + + return linestyle, marker, color + + +class _process_plot_var_args(object): + """ + Process variable length arguments to the plot command, so that + plot commands like the following are supported:: + + plot(t, s) + plot(t1, s1, t2, s2) + plot(t1, s1, 'ko', t2, s2) + plot(t1, s1, 'ko', t2, s2, 'r--', t3, e3) + + an arbitrary number of *x*, *y*, *fmt* are allowed + """ + def __init__(self, axes, command='plot'): + self.axes = axes + self.command = command + self.set_prop_cycle() + + def __getstate__(self): + # note: it is not possible to pickle a itertools.cycle instance + return {'axes': self.axes, 'command': self.command} + + def __setstate__(self, state): + self.__dict__ = state.copy() + self.set_prop_cycle() + + def set_prop_cycle(self, *args, **kwargs): + if not (args or kwargs) or (len(args) == 1 and args[0] is None): + prop_cycler = rcParams['axes.prop_cycle'] + else: + prop_cycler = cycler(*args, **kwargs) + + self.prop_cycler = itertools.cycle(prop_cycler) + # This should make a copy + self._prop_keys = prop_cycler.keys + + def __call__(self, *args, **kwargs): + if self.axes.xaxis is not None and self.axes.yaxis is not None: + xunits = kwargs.pop('xunits', self.axes.xaxis.units) + + if self.axes.name == 'polar': + xunits = kwargs.pop('thetaunits', xunits) + + yunits = kwargs.pop('yunits', self.axes.yaxis.units) + + if self.axes.name == 'polar': + yunits = kwargs.pop('runits', yunits) + + if xunits != self.axes.xaxis.units: + self.axes.xaxis.set_units(xunits) + + if yunits != self.axes.yaxis.units: + self.axes.yaxis.set_units(yunits) + + ret = self._grab_next_args(*args, **kwargs) + return ret + + def get_next_color(self): + """Return the next color in the cycle.""" + if 'color' not in self._prop_keys: + return 'k' + return next(self.prop_cycler)['color'] + + def set_lineprops(self, line, **kwargs): + assert self.command == 'plot', 'set_lineprops only works with "plot"' + line.set(**kwargs) + + def set_patchprops(self, fill_poly, **kwargs): + assert self.command == 'fill', 'set_patchprops only works with "fill"' + fill_poly.set(**kwargs) + + def _xy_from_xy(self, x, y): + if self.axes.xaxis is not None and self.axes.yaxis is not None: + bx = self.axes.xaxis.update_units(x) + by = self.axes.yaxis.update_units(y) + + if self.command != 'plot': + # the Line2D class can handle unitized data, with + # support for post hoc unit changes etc. Other mpl + # artists, e.g., Polygon which _process_plot_var_args + # also serves on calls to fill, cannot. So this is a + # hack to say: if you are not "plot", which is + # creating Line2D, then convert the data now to + # floats. If you are plot, pass the raw data through + # to Line2D which will handle the conversion. So + # polygons will not support post hoc conversions of + # the unit type since they are not storing the orig + # data. Hopefully we can rationalize this at a later + # date - JDH + if bx: + x = self.axes.convert_xunits(x) + if by: + y = self.axes.convert_yunits(y) + + # like asanyarray, but converts scalar to array, and doesn't change + # existing compatible sequences + x = _check_1d(x) + y = _check_1d(y) + if x.shape[0] != y.shape[0]: + raise ValueError("x and y must have same first dimension, but " + "have shapes {} and {}".format(x.shape, y.shape)) + if x.ndim > 2 or y.ndim > 2: + raise ValueError("x and y can be no greater than 2-D, but have " + "shapes {} and {}".format(x.shape, y.shape)) + + if x.ndim == 1: + x = x[:, np.newaxis] + if y.ndim == 1: + y = y[:, np.newaxis] + return x, y + + def _getdefaults(self, ignore, *kwargs): + """ + Only advance the cycler if the cycler has information that + is not specified in any of the supplied tuple of dicts. + Ignore any keys specified in the `ignore` set. + + Returns a copy of defaults dictionary if there are any + keys that are not found in any of the supplied dictionaries. + If the supplied dictionaries have non-None values for + everything the property cycler has, then just return + an empty dictionary. Ignored keys are excluded from the + returned dictionary. + + """ + prop_keys = self._prop_keys + if ignore is None: + ignore = set() + prop_keys = prop_keys - ignore + + if any(all(kw.get(k, None) is None for kw in kwargs) + for k in prop_keys): + # Need to copy this dictionary or else the next time around + # in the cycle, the dictionary could be missing entries. + default_dict = next(self.prop_cycler).copy() + for p in ignore: + default_dict.pop(p, None) + else: + default_dict = {} + return default_dict + + def _setdefaults(self, defaults, *kwargs): + """ + Given a defaults dictionary, and any other dictionaries, + update those other dictionaries with information in defaults if + none of the other dictionaries contains that information. + + """ + for k in defaults: + if all(kw.get(k, None) is None for kw in kwargs): + for kw in kwargs: + kw[k] = defaults[k] + + def _makeline(self, x, y, kw, kwargs): + kw = kw.copy() # Don't modify the original kw. + kw.update(kwargs) + default_dict = self._getdefaults(None, kw) + self._setdefaults(default_dict, kw) + seg = mlines.Line2D(x, y, **kw) + return seg + + def _makefill(self, x, y, kw, kwargs): + kw = kw.copy() # Don't modify the original kw. + kwargs = kwargs.copy() + + # Ignore 'marker'-related properties as they aren't Polygon + # properties, but they are Line2D properties, and so they are + # likely to appear in the default cycler construction. + # This is done here to the defaults dictionary as opposed to the + # other two dictionaries because we do want to capture when a + # *user* explicitly specifies a marker which should be an error. + # We also want to prevent advancing the cycler if there are no + # defaults needed after ignoring the given properties. + ignores = {'marker', 'markersize', 'markeredgecolor', + 'markerfacecolor', 'markeredgewidth'} + # Also ignore anything provided by *kwargs*. + for k, v in six.iteritems(kwargs): + if v is not None: + ignores.add(k) + + # Only using the first dictionary to use as basis + # for getting defaults for back-compat reasons. + # Doing it with both seems to mess things up in + # various places (probably due to logic bugs elsewhere). + default_dict = self._getdefaults(ignores, kw) + self._setdefaults(default_dict, kw) + + # Looks like we don't want "color" to be interpreted to + # mean both facecolor and edgecolor for some reason. + # So the "kw" dictionary is thrown out, and only its + # 'color' value is kept and translated as a 'facecolor'. + # This design should probably be revisited as it increases + # complexity. + facecolor = kw.get('color', None) + + # Throw out 'color' as it is now handled as a facecolor + default_dict.pop('color', None) + + # To get other properties set from the cycler + # modify the kwargs dictionary. + self._setdefaults(default_dict, kwargs) + + seg = mpatches.Polygon(np.hstack((x[:, np.newaxis], + y[:, np.newaxis])), + facecolor=facecolor, + fill=kwargs.get('fill', True), + closed=kw['closed']) + self.set_patchprops(seg, **kwargs) + return seg + + def _plot_args(self, tup, kwargs): + ret = [] + if len(tup) > 1 and isinstance(tup[-1], six.string_types): + linestyle, marker, color = _process_plot_format(tup[-1]) + tup = tup[:-1] + elif len(tup) == 3: + raise ValueError('third arg must be a format string') + else: + linestyle, marker, color = None, None, None + + # Don't allow any None value; These will be up-converted + # to one element array of None which causes problems + # downstream. + if any(v is None for v in tup): + raise ValueError("x and y must not be None") + + kw = {} + for k, v in zip(('linestyle', 'marker', 'color'), + (linestyle, marker, color)): + if v is not None: + kw[k] = v + + if 'label' not in kwargs or kwargs['label'] is None: + kwargs['label'] = get_label(tup[-1], None) + + if len(tup) == 2: + x = _check_1d(tup[0]) + y = _check_1d(tup[-1]) + else: + x, y = index_of(tup[-1]) + + x, y = self._xy_from_xy(x, y) + + if self.command == 'plot': + func = self._makeline + else: + kw['closed'] = kwargs.get('closed', True) + func = self._makefill + + ncx, ncy = x.shape[1], y.shape[1] + if ncx > 1 and ncy > 1 and ncx != ncy: + cbook.warn_deprecated("2.2", "cycling among columns of inputs " + "with non-matching shapes is deprecated.") + for j in xrange(max(ncx, ncy)): + seg = func(x[:, j % ncx], y[:, j % ncy], kw, kwargs) + ret.append(seg) + return ret + + def _grab_next_args(self, *args, **kwargs): + while args: + this, args = args[:2], args[2:] + if args and isinstance(args[0], six.string_types): + this += args[0], + args = args[1:] + for seg in self._plot_args(this, kwargs): + yield seg + + +class _AxesBase(martist.Artist): + """ + """ + name = "rectilinear" + + _shared_x_axes = cbook.Grouper() + _shared_y_axes = cbook.Grouper() + _twinned_axes = cbook.Grouper() + + def __str__(self): + return "{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})".format( + type(self).__name__, self._position.bounds) + + @docstring.Substitution(scale=' | '.join( + [repr(x) for x in mscale.get_scale_names()])) + def __init__(self, fig, rect, + facecolor=None, # defaults to rc axes.facecolor + frameon=True, + sharex=None, # use Axes instance's xaxis info + sharey=None, # use Axes instance's yaxis info + label='', + xscale=None, + yscale=None, + **kwargs + ): + """ + Build an `~axes.Axes` instance in + `~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* in + `~matplotlib.figure.Figure` coordinates + + Optional keyword arguments: + + ================ ========================================= + Keyword Description + ================ ========================================= + *adjustable* [ 'box' | 'datalim' ] + *alpha* float: the alpha transparency (can be None) + *anchor* [ 'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', + 'NW', 'W' ] + *aspect* [ 'auto' | 'equal' | aspect_ratio ] + *autoscale_on* bool; whether to autoscale the *viewlim* + *axisbelow* [ bool | 'line' ] draw the grids + and ticks below or above most other artists, + or below lines but above patches + *cursor_props* a (*float*, *color*) tuple + *figure* a :class:`~matplotlib.figure.Figure` + instance + *frame_on* bool; whether to draw the axes frame + *label* the axes label + *navigate* bool + *navigate_mode* [ 'PAN' | 'ZOOM' | None ] the navigation + toolbar button status + *position* [left, bottom, width, height] in + class:`~matplotlib.figure.Figure` coords + *sharex* an class:`~matplotlib.axes.Axes` instance + to share the x-axis with + *sharey* an class:`~matplotlib.axes.Axes` instance + to share the y-axis with + *title* the title string + *visible* bool, whether the axes is visible + *xlabel* the xlabel + *xlim* (*xmin*, *xmax*) view limits + *xscale* [%(scale)s] + *xticklabels* sequence of strings + *xticks* sequence of floats + *ylabel* the ylabel strings + *ylim* (*ymin*, *ymax*) view limits + *yscale* [%(scale)s] + *yticklabels* sequence of strings + *yticks* sequence of floats + ================ ========================================= + """ + + martist.Artist.__init__(self) + if isinstance(rect, mtransforms.Bbox): + self._position = rect + else: + self._position = mtransforms.Bbox.from_bounds(*rect) + if self._position.width < 0 or self._position.height < 0: + raise ValueError('Width and height specified must be non-negative') + self._originalPosition = self._position.frozen() + # self.set_axes(self) + self.axes = self + self._aspect = 'auto' + self._adjustable = 'box' + self._anchor = 'C' + self._sharex = sharex + self._sharey = sharey + if sharex is not None: + self._shared_x_axes.join(self, sharex) + if sharey is not None: + self._shared_y_axes.join(self, sharey) + self.set_label(label) + self.set_figure(fig) + + self.set_axes_locator(kwargs.get("axes_locator", None)) + + self.spines = self._gen_axes_spines() + + # this call may differ for non-sep axes, e.g., polar + self._init_axis() + if facecolor is None: + facecolor = rcParams['axes.facecolor'] + self._facecolor = facecolor + self._frameon = frameon + self._axisbelow = rcParams['axes.axisbelow'] + + self._rasterization_zorder = None + + self._hold = rcParams['axes.hold'] + if self._hold is None: + self._hold = True + + self._connected = {} # a dict from events to (id, func) + self.cla() + + # funcs used to format x and y - fall back on major formatters + self.fmt_xdata = None + self.fmt_ydata = None + + self._cachedRenderer = None + self.set_navigate(True) + self.set_navigate_mode(None) + + if xscale: + self.set_xscale(xscale) + if yscale: + self.set_yscale(yscale) + + if len(kwargs): + self.update(kwargs) + + if self.xaxis is not None: + self._xcid = self.xaxis.callbacks.connect( + 'units finalize', lambda: self._on_units_changed(scalex=True)) + + if self.yaxis is not None: + self._ycid = self.yaxis.callbacks.connect( + 'units finalize', lambda: self._on_units_changed(scaley=True)) + + self.tick_params( + top=rcParams['xtick.top'] and rcParams['xtick.minor.top'], + bottom=rcParams['xtick.bottom'] and rcParams['xtick.minor.bottom'], + labeltop=(rcParams['xtick.labeltop'] and + rcParams['xtick.minor.top']), + labelbottom=(rcParams['xtick.labelbottom'] and + rcParams['xtick.minor.bottom']), + left=rcParams['ytick.left'] and rcParams['ytick.minor.left'], + right=rcParams['ytick.right'] and rcParams['ytick.minor.right'], + labelleft=(rcParams['ytick.labelleft'] and + rcParams['ytick.minor.left']), + labelright=(rcParams['ytick.labelright'] and + rcParams['ytick.minor.right']), + which='minor') + + self.tick_params( + top=rcParams['xtick.top'] and rcParams['xtick.major.top'], + bottom=rcParams['xtick.bottom'] and rcParams['xtick.major.bottom'], + labeltop=(rcParams['xtick.labeltop'] and + rcParams['xtick.major.top']), + labelbottom=(rcParams['xtick.labelbottom'] and + rcParams['xtick.major.bottom']), + left=rcParams['ytick.left'] and rcParams['ytick.major.left'], + right=rcParams['ytick.right'] and rcParams['ytick.major.right'], + labelleft=(rcParams['ytick.labelleft'] and + rcParams['ytick.major.left']), + labelright=(rcParams['ytick.labelright'] and + rcParams['ytick.major.right']), + which='major') + + self._layoutbox = None + self._poslayoutbox = None + + def __getstate__(self): + # The renderer should be re-created by the figure, and then cached at + # that point. + state = super(_AxesBase, self).__getstate__() + state['_cachedRenderer'] = None + state.pop('_layoutbox') + state.pop('_poslayoutbox') + + return state + + def __setstate__(self, state): + self.__dict__ = state + # put the _remove_method back on all artists contained within the axes + for container_name in ['lines', 'collections', 'tables', 'patches', + 'texts', 'images']: + container = getattr(self, container_name) + for artist in container: + artist._remove_method = container.remove + self._stale = True + self._layoutbox = None + self._poslayoutbox = None + + def get_window_extent(self, *args, **kwargs): + """ + get the axes bounding box in display space; *args* and + *kwargs* are empty + """ + bbox = self.bbox + x_pad = self.xaxis.get_tick_padding() + y_pad = self.yaxis.get_tick_padding() + return mtransforms.Bbox([[bbox.x0 - x_pad, bbox.y0 - y_pad], + [bbox.x1 + x_pad, bbox.y1 + y_pad]]) + + def _init_axis(self): + "move this out of __init__ because non-separable axes don't use it" + self.xaxis = maxis.XAxis(self) + self.spines['bottom'].register_axis(self.xaxis) + self.spines['top'].register_axis(self.xaxis) + self.yaxis = maxis.YAxis(self) + self.spines['left'].register_axis(self.yaxis) + self.spines['right'].register_axis(self.yaxis) + self._update_transScale() + + def set_figure(self, fig): + """ + Set the `.Figure` for this `.Axes`. + + .. ACCEPTS: `.Figure` + + Parameters + ---------- + fig : `.Figure` + """ + martist.Artist.set_figure(self, fig) + + self.bbox = mtransforms.TransformedBbox(self._position, + fig.transFigure) + # these will be updated later as data is added + self.dataLim = mtransforms.Bbox.null() + self.viewLim = mtransforms.Bbox.unit() + self.transScale = mtransforms.TransformWrapper( + mtransforms.IdentityTransform()) + + self._set_lim_and_transforms() + + def _set_lim_and_transforms(self): + """ + set the *_xaxis_transform*, *_yaxis_transform*, + *transScale*, *transData*, *transLimits* and *transAxes* + transformations. + + .. note:: + + This method is primarily used by rectilinear projections + of the :class:`~matplotlib.axes.Axes` class, and is meant + to be overridden by new kinds of projection axes that need + different transformations and limits. (See + :class:`~matplotlib.projections.polar.PolarAxes` for an + example. + + """ + self.transAxes = mtransforms.BboxTransformTo(self.bbox) + + # Transforms the x and y axis separately by a scale factor. + # It is assumed that this part will have non-linear components + # (e.g., for a log scale). + self.transScale = mtransforms.TransformWrapper( + mtransforms.IdentityTransform()) + + # An affine transformation on the data, generally to limit the + # range of the axes + self.transLimits = mtransforms.BboxTransformFrom( + mtransforms.TransformedBbox(self.viewLim, self.transScale)) + + # The parentheses are important for efficiency here -- they + # group the last two (which are usually affines) separately + # from the first (which, with log-scaling can be non-affine). + self.transData = self.transScale + (self.transLimits + self.transAxes) + + self._xaxis_transform = mtransforms.blended_transform_factory( + self.transData, self.transAxes) + self._yaxis_transform = mtransforms.blended_transform_factory( + self.transAxes, self.transData) + + def get_xaxis_transform(self, which='grid'): + """ + Get the transformation used for drawing x-axis labels, ticks + and gridlines. The x-direction is in data coordinates and the + y-direction is in axis coordinates. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + if which == 'grid': + return self._xaxis_transform + elif which == 'tick1': + # for cartesian projection, this is bottom spine + return self.spines['bottom'].get_spine_transform() + elif which == 'tick2': + # for cartesian projection, this is top spine + return self.spines['top'].get_spine_transform() + else: + raise ValueError('unknown value for which') + + def get_xaxis_text1_transform(self, pad_points): + """ + Get the transformation used for drawing x-axis labels, which + will add the given amount of padding (in points) between the + axes and the label. The x-direction is in data coordinates + and the y-direction is in axis coordinates. Returns a + 3-tuple of the form:: + + (transform, valign, halign) + + where *valign* and *halign* are requested alignments for the + text. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + labels_align = matplotlib.rcParams["xtick.alignment"] + + return (self.get_xaxis_transform(which='tick1') + + mtransforms.ScaledTranslation(0, -1 * pad_points / 72.0, + self.figure.dpi_scale_trans), + "top", labels_align) + + def get_xaxis_text2_transform(self, pad_points): + """ + Get the transformation used for drawing the secondary x-axis + labels, which will add the given amount of padding (in points) + between the axes and the label. The x-direction is in data + coordinates and the y-direction is in axis coordinates. + Returns a 3-tuple of the form:: + + (transform, valign, halign) + + where *valign* and *halign* are requested alignments for the + text. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + labels_align = matplotlib.rcParams["xtick.alignment"] + return (self.get_xaxis_transform(which='tick2') + + mtransforms.ScaledTranslation(0, pad_points / 72.0, + self.figure.dpi_scale_trans), + "bottom", labels_align) + + def get_yaxis_transform(self, which='grid'): + """ + Get the transformation used for drawing y-axis labels, ticks + and gridlines. The x-direction is in axis coordinates and the + y-direction is in data coordinates. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + if which == 'grid': + return self._yaxis_transform + elif which == 'tick1': + # for cartesian projection, this is bottom spine + return self.spines['left'].get_spine_transform() + elif which == 'tick2': + # for cartesian projection, this is top spine + return self.spines['right'].get_spine_transform() + else: + raise ValueError('unknown value for which') + + def get_yaxis_text1_transform(self, pad_points): + """ + Get the transformation used for drawing y-axis labels, which + will add the given amount of padding (in points) between the + axes and the label. The x-direction is in axis coordinates + and the y-direction is in data coordinates. Returns a 3-tuple + of the form:: + + (transform, valign, halign) + + where *valign* and *halign* are requested alignments for the + text. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + labels_align = matplotlib.rcParams["ytick.alignment"] + return (self.get_yaxis_transform(which='tick1') + + mtransforms.ScaledTranslation(-1 * pad_points / 72.0, 0, + self.figure.dpi_scale_trans), + labels_align, "right") + + def get_yaxis_text2_transform(self, pad_points): + """ + Get the transformation used for drawing the secondary y-axis + labels, which will add the given amount of padding (in points) + between the axes and the label. The x-direction is in axis + coordinates and the y-direction is in data coordinates. + Returns a 3-tuple of the form:: + + (transform, valign, halign) + + where *valign* and *halign* are requested alignments for the + text. + + .. note:: + + This transformation is primarily used by the + :class:`~matplotlib.axis.Axis` class, and is meant to be + overridden by new kinds of projections that may need to + place axis elements in different locations. + + """ + labels_align = matplotlib.rcParams["ytick.alignment"] + + return (self.get_yaxis_transform(which='tick2') + + mtransforms.ScaledTranslation(pad_points / 72.0, 0, + self.figure.dpi_scale_trans), + labels_align, "left") + + def _update_transScale(self): + self.transScale.set( + mtransforms.blended_transform_factory( + self.xaxis.get_transform(), self.yaxis.get_transform())) + if hasattr(self, "lines"): + for line in self.lines: + try: + line._transformed_path.invalidate() + except AttributeError: + pass + + def get_position(self, original=False): + """ + Get a copy of the axes rectangle as a `.Bbox`. + + Parameters + ---------- + original : bool + If ``True``, return the original position. Otherwise return the + active position. For an explanation of the positions see + `.set_position`. + + Returns + ------- + pos : `.Bbox` + + """ + if original: + return self._originalPosition.frozen() + else: + return self._position.frozen() + + def set_position(self, pos, which='both'): + """ + Set the axes position. + + Axes have two position attributes. The 'original' position is the + position allocated for the Axes. The 'active' position is the + position the Axes is actually drawn at. These positions are usually + the same unless a fixed aspect is set to the Axes. See `.set_aspect` + for details. + + Parameters + ---------- + pos : [left, bottom, width, height] or `~matplotlib.transforms.Bbox` + The new position of the in `.Figure` coordinates. + + which : ['both' | 'active' | 'original'], optional + Determines which position variables to change. + + """ + self._set_position(pos, which='both') + # because this is being called externally to the library we + # zero the constrained layout parts. + self._layoutbox = None + self._poslayoutbox = None + + def _set_position(self, pos, which='both'): + """ + private version of set_position. Call this internally + to get the same functionality of `get_position`, but not + to take the axis out of the constrained_layout + hierarchy. + """ + if not isinstance(pos, mtransforms.BboxBase): + pos = mtransforms.Bbox.from_bounds(*pos) + for ax in self._twinned_axes.get_siblings(self): + if which in ('both', 'active'): + ax._position.set(pos) + if which in ('both', 'original'): + ax._originalPosition.set(pos) + self.stale = True + + def reset_position(self): + """ + Reset the active position to the original position. + + This resets the a possible position change due to aspect constraints. + For an explanation of the positions see `.set_position`. + """ + for ax in self._twinned_axes.get_siblings(self): + pos = ax.get_position(original=True) + ax.set_position(pos, which='active') + + def set_axes_locator(self, locator): + """ + Set the axes locator. + + .. ACCEPTS: a callable object which takes an axes instance and + renderer and returns a bbox. + + Parameters + ---------- + locator : callable + A locator function, which takes an axes and a renderer and returns + a bbox. + """ + self._axes_locator = locator + self.stale = True + + def get_axes_locator(self): + """ + Return the axes_locator. + """ + return self._axes_locator + + def _set_artist_props(self, a): + """set the boilerplate props for artists added to axes""" + a.set_figure(self.figure) + if not a.is_transform_set(): + a.set_transform(self.transData) + + a.axes = self + if a.mouseover: + self.mouseover_set.add(a) + + def _gen_axes_patch(self): + """ + Returns the patch used to draw the background of the axes. It + is also used as the clipping path for any data elements on the + axes. + + In the standard axes, this is a rectangle, but in other + projections it may not be. + + .. note:: + + Intended to be overridden by new projection types. + + """ + return mpatches.Rectangle((0.0, 0.0), 1.0, 1.0) + + def _gen_axes_spines(self, locations=None, offset=0.0, units='inches'): + """ + Returns a dict whose keys are spine names and values are + Line2D or Patch instances. Each element is used to draw a + spine of the axes. + + In the standard axes, this is a single line segment, but in + other projections it may not be. + + .. note:: + + Intended to be overridden by new projection types. + + """ + return OrderedDict([ + ('left', mspines.Spine.linear_spine(self, 'left')), + ('right', mspines.Spine.linear_spine(self, 'right')), + ('bottom', mspines.Spine.linear_spine(self, 'bottom')), + ('top', mspines.Spine.linear_spine(self, 'top'))]) + + def cla(self): + """Clear the current axes.""" + # Note: this is called by Axes.__init__() + + # stash the current visibility state + if hasattr(self, 'patch'): + patch_visible = self.patch.get_visible() + else: + patch_visible = True + + xaxis_visible = self.xaxis.get_visible() + yaxis_visible = self.yaxis.get_visible() + + self.xaxis.cla() + self.yaxis.cla() + + for name, spine in six.iteritems(self.spines): + spine.cla() + + self.ignore_existing_data_limits = True + self.callbacks = cbook.CallbackRegistry() + + if self._sharex is not None: + # major and minor are axis.Ticker class instances with + # locator and formatter attributes + self.xaxis.major = self._sharex.xaxis.major + self.xaxis.minor = self._sharex.xaxis.minor + x0, x1 = self._sharex.get_xlim() + self.set_xlim(x0, x1, emit=False, auto=None) + self.xaxis._scale = mscale.scale_factory( + self._sharex.xaxis.get_scale(), self.xaxis) + else: + self.xaxis._set_scale('linear') + try: + self.set_xlim(0, 1) + except TypeError: + pass + + if self._sharey is not None: + self.yaxis.major = self._sharey.yaxis.major + self.yaxis.minor = self._sharey.yaxis.minor + y0, y1 = self._sharey.get_ylim() + self.set_ylim(y0, y1, emit=False, auto=None) + self.yaxis._scale = mscale.scale_factory( + self._sharey.yaxis.get_scale(), self.yaxis) + else: + self.yaxis._set_scale('linear') + try: + self.set_ylim(0, 1) + except TypeError: + pass + # update the minor locator for x and y axis based on rcParams + if (rcParams['xtick.minor.visible']): + self.xaxis.set_minor_locator(mticker.AutoMinorLocator()) + + if (rcParams['ytick.minor.visible']): + self.yaxis.set_minor_locator(mticker.AutoMinorLocator()) + + self._autoscaleXon = True + self._autoscaleYon = True + self._xmargin = rcParams['axes.xmargin'] + self._ymargin = rcParams['axes.ymargin'] + self._tight = None + self._use_sticky_edges = True + self._update_transScale() # needed? + + self._get_lines = _process_plot_var_args(self) + self._get_patches_for_fill = _process_plot_var_args(self, 'fill') + + self._gridOn = rcParams['axes.grid'] + self.lines = [] + self.patches = [] + self.texts = [] + self.tables = [] + self.artists = [] + self.images = [] + self.mouseover_set = set() + self._current_image = None # strictly for pyplot via _sci, _gci + self.legend_ = None + self.collections = [] # collection.Collection instances + self.containers = [] + + self.grid(False) # Disable grid on init to use rcParameter + self.grid(self._gridOn, which=rcParams['axes.grid.which'], + axis=rcParams['axes.grid.axis']) + props = font_manager.FontProperties( + size=rcParams['axes.titlesize'], + weight=rcParams['axes.titleweight']) + + self.title = mtext.Text( + x=0.5, y=1.0, text='', + fontproperties=props, + verticalalignment='baseline', + horizontalalignment='center', + ) + self._left_title = mtext.Text( + x=0.0, y=1.0, text='', + fontproperties=props.copy(), + verticalalignment='baseline', + horizontalalignment='left', ) + self._right_title = mtext.Text( + x=1.0, y=1.0, text='', + fontproperties=props.copy(), + verticalalignment='baseline', + horizontalalignment='right', + ) + title_offset_points = rcParams['axes.titlepad'] + # refactor this out so it can be called in ax.set_title if + # pad argument used... + self._set_title_offset_trans(title_offset_points) + + for _title in (self.title, self._left_title, self._right_title): + self._set_artist_props(_title) + + # The patch draws the background of the axes. We want this to be below + # the other artists. We use the frame to draw the edges so we are + # setting the edgecolor to None. + self.patch = self._gen_axes_patch() + self.patch.set_figure(self.figure) + self.patch.set_facecolor(self._facecolor) + self.patch.set_edgecolor('None') + self.patch.set_linewidth(0) + self.patch.set_transform(self.transAxes) + + self.set_axis_on() + + self.xaxis.set_clip_path(self.patch) + self.yaxis.set_clip_path(self.patch) + + self._shared_x_axes.clean() + self._shared_y_axes.clean() + if self._sharex: + self.xaxis.set_visible(xaxis_visible) + self.patch.set_visible(patch_visible) + + if self._sharey: + self.yaxis.set_visible(yaxis_visible) + self.patch.set_visible(patch_visible) + + self.stale = True + + @property + @cbook.deprecated("2.1", alternative="Axes.patch") + def axesPatch(self): + return self.patch + + def clear(self): + """Clear the axes.""" + self.cla() + + def get_facecolor(self): + """Get the Axes facecolor.""" + return self.patch.get_facecolor() + get_fc = get_facecolor + + def set_facecolor(self, color): + """Set the Axes facecolor. + + .. ACCEPTS: color + + Parameters + ---------- + color : color + """ + self._facecolor = color + self.stale = True + return self.patch.set_facecolor(color) + set_fc = set_facecolor + + def _set_title_offset_trans(self, title_offset_points): + """ + Set the offset for the title either from rcParams['axes.titlepad'] + or from set_title kwarg ``pad``. + """ + self.titleOffsetTrans = mtransforms.ScaledTranslation( + 0.0, title_offset_points / 72.0, + self.figure.dpi_scale_trans) + for _title in (self.title, self._left_title, self._right_title): + _title.set_transform(self.transAxes + self.titleOffsetTrans) + _title.set_clip_box(None) + + def set_prop_cycle(self, *args, **kwargs): + """ + Set the property cycle of the Axes. + + The property cycle controls the style properties such as color, + marker and linestyle of future plot commands. The style properties + of data already added to the Axes are not modified. + + Call signatures:: + + set_prop_cycle(cycler) + set_prop_cycle(label=values[, label2=values2[, ...]]) + set_prop_cycle(label, values) + + Form 1 sets given `~cycler.Cycler` object. + + Form 2 creates a `~cycler.Cycler` which cycles over one or more + properties simultaneously and set it as the property cycle of the + axes. If multiple properties are given, their value lists must have + the same length. This is just a shortcut for explicitly creating a + cycler and passing it to the function, i.e. it's short for + ``set_prop_cycle(cycler(label=values label2=values2, ...))``. + + Form 3 creates a `~cycler.Cycler` for a single property and set it + as the property cycle of the axes. This form exists for compatibility + with the original `cycler.cycler` interface. Its use is discouraged + in favor of the kwarg form, i.e. ``set_prop_cycle(label=values)``. + + Parameters + ---------- + cycler : Cycler + Set the given Cycler. *None* resets to the cycle defined by the + current style. + + label : str + The property key. Must be a valid `.Artist` property. + For example, 'color' or 'linestyle'. Aliases are allowed, + such as 'c' for 'color' and 'lw' for 'linewidth'. + + values : iterable + Finite-length iterable of the property values. These values + are validated and will raise a ValueError if invalid. + + Examples + -------- + Setting the property cycle for a single property: + + >>> ax.set_prop_cycle(color=['red', 'green', 'blue']) + + Setting the property cycle for simultaneously cycling over multiple + properties (e.g. red circle, green plus, blue cross): + + >>> ax.set_prop_cycle(color=['red', 'green', 'blue'], + ... marker=['o', '+', 'x']) + + See Also + -------- + matplotlib.rcsetup.cycler + Convenience function for creating validated cyclers for properties. + cycler.cycler + The original function for creating unvalidated cyclers. + + """ + if args and kwargs: + raise TypeError("Cannot supply both positional and keyword " + "arguments to this method.") + if len(args) == 1 and args[0] is None: + prop_cycle = None + else: + prop_cycle = cycler(*args, **kwargs) + self._get_lines.set_prop_cycle(prop_cycle) + self._get_patches_for_fill.set_prop_cycle(prop_cycle) + + @cbook.deprecated('1.5', alternative='`.set_prop_cycle`') + def set_color_cycle(self, clist): + """ + Set the color cycle for any future plot commands on this Axes. + + Parameters + ---------- + clist + A list of mpl color specifiers. + """ + if clist is None: + # Calling set_color_cycle() or set_prop_cycle() with None + # effectively resets the cycle, but you can't do + # set_prop_cycle('color', None). So we are special-casing this. + self.set_prop_cycle(None) + else: + self.set_prop_cycle('color', clist) + + @cbook.deprecated("2.0") + def ishold(self): + """return the HOLD status of the axes + + The `hold` mechanism is deprecated and will be removed in + v3.0. + """ + + return self._hold + + @cbook.deprecated("2.0", message=_hold_msg) + def hold(self, b=None): + """ + Set the hold state. + + The ``hold`` mechanism is deprecated and will be removed in + v3.0. The behavior will remain consistent with the + long-time default value of True. + + If *hold* is *None* (default), toggle the *hold* state. Else + set the *hold* state to boolean value *b*. + + Examples:: + + # toggle hold + hold() + + # turn hold on + hold(True) + + # turn hold off + hold(False) + + When hold is *True*, subsequent plot commands will be added to + the current axes. When hold is *False*, the current axes and + figure will be cleared on the next plot command + + """ + if b is None: + self._hold = not self._hold + else: + self._hold = b + + def get_aspect(self): + return self._aspect + + def set_aspect(self, aspect, adjustable=None, anchor=None, share=False): + """ + Set the aspect of the axis scaling, i.e. the ratio of y-unit to x-unit. + + Parameters + ---------- + aspect : ['auto' | 'equal'] or num + Possible values: + + ======== ================================================ + value description + ======== ================================================ + 'auto' automatic; fill the position rectangle with data + 'equal' same scaling from data to plot units for x and y + num a circle will be stretched such that the height + is num times the width. aspect=1 is the same as + aspect='equal'. + ======== ================================================ + + adjustable : None or ['box' | 'datalim'], optional + If not ``None``, this defines which parameter will be adjusted to + meet the required aspect. See `.set_adjustable` for further + details. + + anchor : None or str or 2-tuple of float, optional + If not ``None``, this defines where the Axes will be drawn if there + is extra space due to aspect constraints. The most common way to + to specify the anchor are abbreviations of cardinal directions: + + ===== ===================== + value description + ===== ===================== + 'C' centered + 'SW' lower left corner + 'S' middle of bottom edge + 'SE' lower right corner + etc. + ===== ===================== + + See `.set_anchor` for further details. + + share : bool, optional + If ``True``, apply the settings to all shared Axes. + Default is ``False``. + + See Also + -------- + matplotlib.axes.Axes.set_adjustable + defining the parameter to adjust in order to meet the required + aspect. + matplotlib.axes.Axes.set_anchor + defining the position in case of extra space. + """ + if not (isinstance(aspect, six.string_types) + and aspect in ('equal', 'auto')): + aspect = float(aspect) # raise ValueError if necessary + if share: + axes = set(self._shared_x_axes.get_siblings(self) + + self._shared_y_axes.get_siblings(self)) + else: + axes = [self] + for ax in axes: + ax._aspect = aspect + + if adjustable is None: + adjustable = self._adjustable + self.set_adjustable(adjustable, share=share) # Handle sharing. + + if anchor is not None: + self.set_anchor(anchor, share=share) + self.stale = True + + def get_adjustable(self): + return self._adjustable + + def set_adjustable(self, adjustable, share=False): + """ + Define which parameter the Axes will change to achieve a given aspect. + + Parameters + ---------- + adjustable : ['box' | 'datalim'] + If 'box', change the physical dimensions of the Axes. + If 'datalim', change the ``x`` or ``y`` data limits. + + share : bool, optional + If ``True``, apply the settings to all shared Axes. + Default is ``False``. + + .. ACCEPTS: [ 'box' | 'datalim'] + + See Also + -------- + matplotlib.axes.Axes.set_aspect + for a description of aspect handling. + + Notes + ----- + Shared Axes (of which twinned Axes are a special case) + impose restrictions on how aspect ratios can be imposed. + For twinned Axes, use 'datalim'. For Axes that share both + x and y, use 'box'. Otherwise, either 'datalim' or 'box' + may be used. These limitations are partly a requirement + to avoid over-specification, and partly a result of the + particular implementation we are currently using, in + which the adjustments for aspect ratios are done sequentially + and independently on each Axes as it is drawn. + """ + if adjustable == 'box-forced': + warnings.warn("The 'box-forced' keyword argument is deprecated" + " since 2.2.", cbook.mplDeprecation) + if adjustable not in ('box', 'datalim', 'box-forced'): + raise ValueError("argument must be 'box', or 'datalim'") + if share: + axes = set(self._shared_x_axes.get_siblings(self) + + self._shared_y_axes.get_siblings(self)) + else: + axes = [self] + for ax in axes: + ax._adjustable = adjustable + self.stale = True + + def get_anchor(self): + """ + Get the anchor location. + + See Also + -------- + matplotlib.axes.Axes.set_anchor + for a description of the anchor. + matplotlib.axes.Axes.set_aspect + for a description of aspect handling. + """ + return self._anchor + + def set_anchor(self, anchor, share=False): + """ + Define the anchor location. + + The actual drawing area (active position) of the Axes may be smaller + than the Bbox (original position) when a fixed aspect is required. The + anchor defines where the drawing area will be located within the + available space. + + .. ACCEPTS: [ 'C' | 'SW' | 'S' | 'SE' | 'E' | 'NE' | 'N' | 'NW' | 'W' ] + + Parameters + ---------- + anchor : str or 2-tuple of floats + The anchor position may be either: + + - a sequence (*cx*, *cy*). *cx* and *cy* may range from 0 + to 1, where 0 is left or bottom and 1 is right or top. + + - a string using cardinal directions as abbreviation: + + - 'C' for centered + - 'S' (south) for bottom-center + - 'SW' (south west) for bottom-left + - etc. + + Here is an overview of the possible positions: + + +------+------+------+ + | 'NW' | 'N' | 'NE' | + +------+------+------+ + | 'W' | 'C' | 'E' | + +------+------+------+ + | 'SW' | 'S' | 'SE' | + +------+------+------+ + + share : bool, optional + If ``True``, apply the settings to all shared Axes. + Default is ``False``. + + See Also + -------- + matplotlib.axes.Axes.set_aspect + for a description of aspect handling. + """ + if not (anchor in mtransforms.Bbox.coefs or len(anchor) == 2): + raise ValueError('argument must be among %s' % + ', '.join(mtransforms.Bbox.coefs)) + if share: + axes = set(self._shared_x_axes.get_siblings(self) + + self._shared_y_axes.get_siblings(self)) + else: + axes = [self] + for ax in axes: + ax._anchor = anchor + + self.stale = True + + def get_data_ratio(self): + """ + Returns the aspect ratio of the raw data. + + This method is intended to be overridden by new projection + types. + """ + xmin, xmax = self.get_xbound() + ymin, ymax = self.get_ybound() + + xsize = max(abs(xmax - xmin), 1e-30) + ysize = max(abs(ymax - ymin), 1e-30) + + return ysize / xsize + + def get_data_ratio_log(self): + """ + Returns the aspect ratio of the raw data in log scale. + Will be used when both axis scales are in log. + """ + xmin, xmax = self.get_xbound() + ymin, ymax = self.get_ybound() + + xsize = max(abs(math.log10(xmax) - math.log10(xmin)), 1e-30) + ysize = max(abs(math.log10(ymax) - math.log10(ymin)), 1e-30) + + return ysize / xsize + + def apply_aspect(self, position=None): + """ + Adjust the Axes for a specified data aspect ratio. + + Depending on `.get_adjustable` this will modify either the Axes box + (position) or the view limits. In the former case, `.get_anchor` + will affect the position. + + Notes + ----- + This is called automatically when each Axes is drawn. You may need + to call it yourself if you need to update the Axes position and/or + view limits before the Figure is drawn. + + See Also + -------- + matplotlib.axes.Axes.set_aspect + for a description of aspect ratio handling. + matplotlib.axes.Axes.set_adjustable + defining the parameter to adjust in order to meet the required + aspect. + matplotlib.axes.Axes.set_anchor + defining the position in case of extra space. + """ + if position is None: + position = self.get_position(original=True) + + aspect = self.get_aspect() + + if self.name != 'polar': + xscale, yscale = self.get_xscale(), self.get_yscale() + if xscale == "linear" and yscale == "linear": + aspect_scale_mode = "linear" + elif xscale == "log" and yscale == "log": + aspect_scale_mode = "log" + elif ((xscale == "linear" and yscale == "log") or + (xscale == "log" and yscale == "linear")): + if aspect != "auto": + warnings.warn( + 'aspect is not supported for Axes with xscale=%s, ' + 'yscale=%s' % (xscale, yscale)) + aspect = "auto" + else: # some custom projections have their own scales. + pass + else: + aspect_scale_mode = "linear" + + if aspect == 'auto': + self._set_position(position, which='active') + return + + if aspect == 'equal': + A = 1 + else: + A = aspect + + figW, figH = self.get_figure().get_size_inches() + fig_aspect = figH / figW + if self._adjustable in ['box', 'box-forced']: + if self in self._twinned_axes: + raise RuntimeError("Adjustable 'box' is not allowed in a" + " twinned Axes. Use 'datalim' instead.") + if aspect_scale_mode == "log": + box_aspect = A * self.get_data_ratio_log() + else: + box_aspect = A * self.get_data_ratio() + pb = position.frozen() + pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect) + self._set_position(pb1.anchored(self.get_anchor(), pb), 'active') + return + + # reset active to original in case it had been changed + # by prior use of 'box' + self._set_position(position, which='active') + + xmin, xmax = self.get_xbound() + ymin, ymax = self.get_ybound() + + if aspect_scale_mode == "log": + xmin, xmax = math.log10(xmin), math.log10(xmax) + ymin, ymax = math.log10(ymin), math.log10(ymax) + + xsize = max(abs(xmax - xmin), 1e-30) + ysize = max(abs(ymax - ymin), 1e-30) + + l, b, w, h = position.bounds + box_aspect = fig_aspect * (h / w) + data_ratio = box_aspect / A + + y_expander = (data_ratio * xsize / ysize - 1.0) + # If y_expander > 0, the dy/dx viewLim ratio needs to increase + if abs(y_expander) < 0.005: + return + + if aspect_scale_mode == "log": + dL = self.dataLim + dL_width = math.log10(dL.x1) - math.log10(dL.x0) + dL_height = math.log10(dL.y1) - math.log10(dL.y0) + xr = 1.05 * dL_width + yr = 1.05 * dL_height + else: + dL = self.dataLim + xr = 1.05 * dL.width + yr = 1.05 * dL.height + + xmarg = xsize - xr + ymarg = ysize - yr + Ysize = data_ratio * xsize + Xsize = ysize / data_ratio + Xmarg = Xsize - xr + Ymarg = Ysize - yr + # Setting these targets to, e.g., 0.05*xr does not seem to + # help. + xm = 0 + ym = 0 + + shared_x = self in self._shared_x_axes + shared_y = self in self._shared_y_axes + # Not sure whether we need this check: + if shared_x and shared_y: + raise RuntimeError("adjustable='datalim' is not allowed when both" + " axes are shared.") + + # If y is shared, then we are only allowed to change x, etc. + if shared_y: + adjust_y = False + else: + if xmarg > xm and ymarg > ym: + adjy = ((Ymarg > 0 and y_expander < 0) or + (Xmarg < 0 and y_expander > 0)) + else: + adjy = y_expander > 0 + adjust_y = shared_x or adjy # (Ymarg > xmarg) + + if adjust_y: + yc = 0.5 * (ymin + ymax) + y0 = yc - Ysize / 2.0 + y1 = yc + Ysize / 2.0 + if aspect_scale_mode == "log": + self.set_ybound((10. ** y0, 10. ** y1)) + else: + self.set_ybound((y0, y1)) + else: + xc = 0.5 * (xmin + xmax) + x0 = xc - Xsize / 2.0 + x1 = xc + Xsize / 2.0 + if aspect_scale_mode == "log": + self.set_xbound((10. ** x0, 10. ** x1)) + else: + self.set_xbound((x0, x1)) + + def axis(self, *v, **kwargs): + """Set axis properties. + + Valid signatures:: + + xmin, xmax, ymin, ymax = axis() + xmin, xmax, ymin, ymax = axis(list_arg) + xmin, xmax, ymin, ymax = axis(string_arg) + xmin, xmax, ymin, ymax = axis(**kwargs) + + Parameters + ---------- + v : list of float or {'on', 'off', 'equal', 'tight', 'scaled',\ + 'normal', 'auto', 'image', 'square'} + Optional positional argument + + Axis data limits set from a list; or a command relating to axes: + + ========== ================================================ + Value Description + ========== ================================================ + 'on' Toggle axis lines and labels on + 'off' Toggle axis lines and labels off + 'equal' Equal scaling by changing limits + 'scaled' Equal scaling by changing box dimensions + 'tight' Limits set such that all data is shown + 'auto' Automatic scaling, fill rectangle with data + 'normal' Same as 'auto'; deprecated + 'image' 'scaled' with axis limits equal to data limits + 'square' Square plot; similar to 'scaled', but initially\ + forcing xmax-xmin = ymax-ymin + ========== ================================================ + + emit : bool, optional + Passed to set_{x,y}lim functions, if observers + are notified of axis limit change + + xmin, ymin, xmax, ymax : float, optional + The axis limits to be set + + Returns + ------- + xmin, xmax, ymin, ymax : float + The axis limits + + """ + + if len(v) == 0 and len(kwargs) == 0: + xmin, xmax = self.get_xlim() + ymin, ymax = self.get_ylim() + return xmin, xmax, ymin, ymax + + emit = kwargs.get('emit', True) + + if len(v) == 1 and isinstance(v[0], six.string_types): + s = v[0].lower() + if s == 'on': + self.set_axis_on() + elif s == 'off': + self.set_axis_off() + elif s in ('equal', 'tight', 'scaled', 'normal', + 'auto', 'image', 'square'): + self.set_autoscale_on(True) + self.set_aspect('auto') + self.autoscale_view(tight=False) + # self.apply_aspect() + if s == 'equal': + self.set_aspect('equal', adjustable='datalim') + elif s == 'scaled': + self.set_aspect('equal', adjustable='box', anchor='C') + self.set_autoscale_on(False) # Req. by Mark Bakker + elif s == 'tight': + self.autoscale_view(tight=True) + self.set_autoscale_on(False) + elif s == 'image': + self.autoscale_view(tight=True) + self.set_autoscale_on(False) + self.set_aspect('equal', adjustable='box', anchor='C') + elif s == 'square': + self.set_aspect('equal', adjustable='box', anchor='C') + self.set_autoscale_on(False) + xlim = self.get_xlim() + ylim = self.get_ylim() + edge_size = max(np.diff(xlim), np.diff(ylim)) + self.set_xlim([xlim[0], xlim[0] + edge_size], + emit=emit, auto=False) + self.set_ylim([ylim[0], ylim[0] + edge_size], + emit=emit, auto=False) + else: + raise ValueError('Unrecognized string %s to axis; ' + 'try on or off' % s) + xmin, xmax = self.get_xlim() + ymin, ymax = self.get_ylim() + return xmin, xmax, ymin, ymax + + try: + v[0] + except IndexError: + xmin = kwargs.get('xmin', None) + xmax = kwargs.get('xmax', None) + auto = False # turn off autoscaling, unless... + if xmin is None and xmax is None: + auto = None # leave autoscaling state alone + xmin, xmax = self.set_xlim(xmin, xmax, emit=emit, auto=auto) + + ymin = kwargs.get('ymin', None) + ymax = kwargs.get('ymax', None) + auto = False # turn off autoscaling, unless... + if ymin is None and ymax is None: + auto = None # leave autoscaling state alone + ymin, ymax = self.set_ylim(ymin, ymax, emit=emit, auto=auto) + return xmin, xmax, ymin, ymax + + v = v[0] + if len(v) != 4: + raise ValueError('v must contain [xmin xmax ymin ymax]') + + self.set_xlim([v[0], v[1]], emit=emit, auto=False) + self.set_ylim([v[2], v[3]], emit=emit, auto=False) + + return v + + def get_legend(self): + """Return the `Legend` instance, or None if no legend is defined.""" + return self.legend_ + + def get_images(self): + """return a list of Axes images contained by the Axes""" + return cbook.silent_list('AxesImage', self.images) + + def get_lines(self): + """Return a list of lines contained by the Axes""" + return cbook.silent_list('Line2D', self.lines) + + def get_xaxis(self): + """Return the XAxis instance.""" + return self.xaxis + + def get_xgridlines(self): + """Get the x grid lines as a list of `Line2D` instances.""" + return cbook.silent_list('Line2D xgridline', + self.xaxis.get_gridlines()) + + def get_xticklines(self): + """Get the x tick lines as a list of `Line2D` instances.""" + return cbook.silent_list('Line2D xtickline', + self.xaxis.get_ticklines()) + + def get_yaxis(self): + """Return the YAxis instance.""" + return self.yaxis + + def get_ygridlines(self): + """Get the y grid lines as a list of `Line2D` instances.""" + return cbook.silent_list('Line2D ygridline', + self.yaxis.get_gridlines()) + + def get_yticklines(self): + """Get the y tick lines as a list of `Line2D` instances.""" + return cbook.silent_list('Line2D ytickline', + self.yaxis.get_ticklines()) + + # Adding and tracking artists + + def _sci(self, im): + """ + helper for :func:`~matplotlib.pyplot.sci`; + do not use elsewhere. + """ + if isinstance(im, matplotlib.contour.ContourSet): + if im.collections[0] not in self.collections: + raise ValueError( + "ContourSet must be in current Axes") + elif im not in self.images and im not in self.collections: + raise ValueError( + "Argument must be an image, collection, or ContourSet in " + "this Axes") + self._current_image = im + + def _gci(self): + """ + Helper for :func:`~matplotlib.pyplot.gci`; + do not use elsewhere. + """ + return self._current_image + + def has_data(self): + """ + Return *True* if any artists have been added to axes. + + This should not be used to determine whether the *dataLim* + need to be updated, and may not actually be useful for + anything. + """ + return ( + len(self.collections) + + len(self.images) + + len(self.lines) + + len(self.patches)) > 0 + + def add_artist(self, a): + """Add any :class:`~matplotlib.artist.Artist` to the axes. + + Use `add_artist` only for artists for which there is no dedicated + "add" method; and if necessary, use a method such as `update_datalim` + to manually update the dataLim if the artist is to be included in + autoscaling. + + Returns the artist. + """ + a.axes = self + self.artists.append(a) + self._set_artist_props(a) + a.set_clip_path(self.patch) + a._remove_method = lambda h: self.artists.remove(h) + self.stale = True + return a + + def add_collection(self, collection, autolim=True): + """ + Add a :class:`~matplotlib.collections.Collection` instance + to the axes. + + Returns the collection. + """ + label = collection.get_label() + if not label: + collection.set_label('_collection%d' % len(self.collections)) + self.collections.append(collection) + self._set_artist_props(collection) + + if collection.get_clip_path() is None: + collection.set_clip_path(self.patch) + + if autolim: + self.update_datalim(collection.get_datalim(self.transData)) + + collection._remove_method = lambda h: self.collections.remove(h) + self.stale = True + return collection + + def add_image(self, image): + """ + Add a :class:`~matplotlib.image.AxesImage` to the axes. + + Returns the image. + """ + self._set_artist_props(image) + if not image.get_label(): + image.set_label('_image%d' % len(self.images)) + self.images.append(image) + image._remove_method = lambda h: self.images.remove(h) + self.stale = True + return image + + def _update_image_limits(self, image): + xmin, xmax, ymin, ymax = image.get_extent() + self.axes.update_datalim(((xmin, ymin), (xmax, ymax))) + + def add_line(self, line): + """ + Add a :class:`~matplotlib.lines.Line2D` to the list of plot + lines + + Returns the line. + """ + self._set_artist_props(line) + if line.get_clip_path() is None: + line.set_clip_path(self.patch) + + self._update_line_limits(line) + if not line.get_label(): + line.set_label('_line%d' % len(self.lines)) + self.lines.append(line) + line._remove_method = lambda h: self.lines.remove(h) + self.stale = True + return line + + def _add_text(self, txt): + """ + + """ + self._set_artist_props(txt) + self.texts.append(txt) + txt._remove_method = lambda h: self.texts.remove(h) + self.stale = True + return txt + + def _update_line_limits(self, line): + """ + Figures out the data limit of the given line, updating self.dataLim. + """ + path = line.get_path() + if path.vertices.size == 0: + return + + line_trans = line.get_transform() + + if line_trans == self.transData: + data_path = path + + elif any(line_trans.contains_branch_seperately(self.transData)): + # identify the transform to go from line's coordinates + # to data coordinates + trans_to_data = line_trans - self.transData + + # if transData is affine we can use the cached non-affine component + # of line's path. (since the non-affine part of line_trans is + # entirely encapsulated in trans_to_data). + if self.transData.is_affine: + line_trans_path = line._get_transformed_path() + na_path, _ = line_trans_path.get_transformed_path_and_affine() + data_path = trans_to_data.transform_path_affine(na_path) + else: + data_path = trans_to_data.transform_path(path) + else: + # for backwards compatibility we update the dataLim with the + # coordinate range of the given path, even though the coordinate + # systems are completely different. This may occur in situations + # such as when ax.transAxes is passed through for absolute + # positioning. + data_path = path + + if data_path.vertices.size > 0: + updatex, updatey = line_trans.contains_branch_seperately( + self.transData) + self.dataLim.update_from_path(data_path, + self.ignore_existing_data_limits, + updatex=updatex, + updatey=updatey) + self.ignore_existing_data_limits = False + + def add_patch(self, p): + """ + Add a :class:`~matplotlib.patches.Patch` *p* to the list of + axes patches; the clipbox will be set to the Axes clipping + box. If the transform is not set, it will be set to + :attr:`transData`. + + Returns the patch. + """ + + self._set_artist_props(p) + if p.get_clip_path() is None: + p.set_clip_path(self.patch) + self._update_patch_limits(p) + self.patches.append(p) + p._remove_method = lambda h: self.patches.remove(h) + return p + + def _update_patch_limits(self, patch): + """update the data limits for patch *p*""" + # hist can add zero height Rectangles, which is useful to keep + # the bins, counts and patches lined up, but it throws off log + # scaling. We'll ignore rects with zero height or width in + # the auto-scaling + + # cannot check for '==0' since unitized data may not compare to zero + # issue #2150 - we update the limits if patch has non zero width + # or height. + if (isinstance(patch, mpatches.Rectangle) and + ((not patch.get_width()) and (not patch.get_height()))): + return + vertices = patch.get_path().vertices + if vertices.size > 0: + xys = patch.get_patch_transform().transform(vertices) + if patch.get_data_transform() != self.transData: + patch_to_data = (patch.get_data_transform() - + self.transData) + xys = patch_to_data.transform(xys) + + updatex, updatey = patch.get_transform().\ + contains_branch_seperately(self.transData) + self.update_datalim(xys, updatex=updatex, + updatey=updatey) + + def add_table(self, tab): + """ + Add a :class:`~matplotlib.table.Table` instance to the + list of axes tables + + Parameters + ---------- + tab: `matplotlib.table.Table` + Table instance + + Returns + ------- + `matplotlib.table.Table`: the table. + """ + self._set_artist_props(tab) + self.tables.append(tab) + tab.set_clip_path(self.patch) + tab._remove_method = lambda h: self.tables.remove(h) + return tab + + def add_container(self, container): + """ + Add a :class:`~matplotlib.container.Container` instance + to the axes. + + Returns the collection. + """ + label = container.get_label() + if not label: + container.set_label('_container%d' % len(self.containers)) + self.containers.append(container) + container.set_remove_method(lambda h: self.containers.remove(h)) + return container + + def _on_units_changed(self, scalex=False, scaley=False): + """ + Callback for processing changes to axis units. + + Currently forces updates of data limits and view limits. + """ + self.relim() + self.autoscale_view(scalex=scalex, scaley=scaley) + + def relim(self, visible_only=False): + """ + Recompute the data limits based on current artists. If you want to + exclude invisible artists from the calculation, set + ``visible_only=True`` + + At present, :class:`~matplotlib.collections.Collection` + instances are not supported. + """ + # Collections are deliberately not supported (yet); see + # the TODO note in artists.py. + self.dataLim.ignore(True) + self.dataLim.set_points(mtransforms.Bbox.null().get_points()) + self.ignore_existing_data_limits = True + + for line in self.lines: + if not visible_only or line.get_visible(): + self._update_line_limits(line) + + for p in self.patches: + if not visible_only or p.get_visible(): + self._update_patch_limits(p) + + for image in self.images: + if not visible_only or image.get_visible(): + self._update_image_limits(image) + + def update_datalim(self, xys, updatex=True, updatey=True): + """ + Update the data lim bbox with seq of xy tups or equiv. 2-D array + """ + # if no data is set currently, the bbox will ignore its + # limits and set the bound to be the bounds of the xydata. + # Otherwise, it will compute the bounds of it's current data + # and the data in xydata + xys = np.asarray(xys) + if not len(xys): + return + self.dataLim.update_from_data_xy(xys, self.ignore_existing_data_limits, + updatex=updatex, updatey=updatey) + self.ignore_existing_data_limits = False + + def update_datalim_bounds(self, bounds): + """ + Update the datalim to include the given + :class:`~matplotlib.transforms.Bbox` *bounds* + """ + self.dataLim.set(mtransforms.Bbox.union([self.dataLim, bounds])) + + def _process_unit_info(self, xdata=None, ydata=None, kwargs=None): + """Look for unit *kwargs* and update the axis instances as necessary""" + + if self.xaxis is None or self.yaxis is None: + return + + if xdata is not None: + # we only need to update if there is nothing set yet. + if not self.xaxis.have_units(): + self.xaxis.update_units(xdata) + + if ydata is not None: + # we only need to update if there is nothing set yet. + if not self.yaxis.have_units(): + self.yaxis.update_units(ydata) + + # process kwargs 2nd since these will override default units + if kwargs is not None: + xunits = kwargs.pop('xunits', self.xaxis.units) + if self.name == 'polar': + xunits = kwargs.pop('thetaunits', xunits) + if xunits != self.xaxis.units: + self.xaxis.set_units(xunits) + # If the units being set imply a different converter, + # we need to update. + if xdata is not None: + self.xaxis.update_units(xdata) + + yunits = kwargs.pop('yunits', self.yaxis.units) + if self.name == 'polar': + yunits = kwargs.pop('runits', yunits) + if yunits != self.yaxis.units: + self.yaxis.set_units(yunits) + # If the units being set imply a different converter, + # we need to update. + if ydata is not None: + self.yaxis.update_units(ydata) + return kwargs + + def in_axes(self, mouseevent): + """ + Return *True* if the given *mouseevent* (in display coords) + is in the Axes + """ + return self.patch.contains(mouseevent)[0] + + def get_autoscale_on(self): + """ + Get whether autoscaling is applied for both axes on plot commands + """ + return self._autoscaleXon and self._autoscaleYon + + def get_autoscalex_on(self): + """ + Get whether autoscaling for the x-axis is applied on plot commands + """ + return self._autoscaleXon + + def get_autoscaley_on(self): + """ + Get whether autoscaling for the y-axis is applied on plot commands + """ + return self._autoscaleYon + + def set_autoscale_on(self, b): + """ + Set whether autoscaling is applied on plot commands + + .. ACCEPTS: bool + + Parameters + ---------- + b : bool + """ + self._autoscaleXon = b + self._autoscaleYon = b + + def set_autoscalex_on(self, b): + """ + Set whether autoscaling for the x-axis is applied on plot commands + + .. ACCEPTS: bool + + Parameters + ---------- + b : bool + """ + self._autoscaleXon = b + + def set_autoscaley_on(self, b): + """ + Set whether autoscaling for the y-axis is applied on plot commands + + .. ACCEPTS: bool + + Parameters + ---------- + b : bool + """ + self._autoscaleYon = b + + @property + def use_sticky_edges(self): + """ + When autoscaling, whether to obey all `Artist.sticky_edges`. + + Default is ``True``. + + Setting this to ``False`` ensures that the specified margins + will be applied, even if the plot includes an image, for + example, which would otherwise force a view limit to coincide + with its data limit. + + The changing this property does not change the plot until + `autoscale` or `autoscale_view` is called. + """ + return self._use_sticky_edges + + @use_sticky_edges.setter + def use_sticky_edges(self, b): + self._use_sticky_edges = bool(b) + # No effect until next autoscaling, which will mark the axes as stale. + + def set_xmargin(self, m): + """ + Set padding of X data limits prior to autoscaling. + + *m* times the data interval will be added to each + end of that interval before it is used in autoscaling. + For example, if your data is in the range [0, 2], a factor of + ``m = 0.1`` will result in a range [-0.2, 2.2]. + + Negative values -0.5 < m < 0 will result in clipping of the data range. + I.e. for a data range [0, 2], a factor of ``m = -0.1`` will result in + a range [0.2, 1.8]. + + .. ACCEPTS: float greater than -0.5 + + Parameters + ---------- + m : float greater than -0.5 + """ + if m <= -0.5: + raise ValueError("margin must be greater than -0.5") + self._xmargin = m + self.stale = True + + def set_ymargin(self, m): + """ + Set padding of Y data limits prior to autoscaling. + + *m* times the data interval will be added to each + end of that interval before it is used in autoscaling. + For example, if your data is in the range [0, 2], a factor of + ``m = 0.1`` will result in a range [-0.2, 2.2]. + + Negative values -0.5 < m < 0 will result in clipping of the data range. + I.e. for a data range [0, 2], a factor of ``m = -0.1`` will result in + a range [0.2, 1.8]. + + .. ACCEPTS: float greater than -0.5 + + Parameters + ---------- + m : float greater than -0.5 + """ + if m <= -0.5: + raise ValueError("margin must be greater than -0.5") + self._ymargin = m + self.stale = True + + def margins(self, *args, **kw): + """ + Set or retrieve autoscaling margins. + + signatures:: + + margins() + + returns xmargin, ymargin + + :: + + margins(margin) + + margins(xmargin, ymargin) + + margins(x=xmargin, y=ymargin) + + margins(..., tight=False) + + All three forms above set the xmargin and ymargin parameters. + All keyword parameters are optional. A single argument + specifies both xmargin and ymargin. The padding added to the end of + each interval is *margin* times the data interval. The *margin* must + be a float in the range [0, 1]. + + The *tight* parameter is passed to :meth:`autoscale_view` + , which is executed after a margin is changed; the default here is + *True*, on the assumption that when margins are specified, no + additional padding to match tick marks is usually desired. Setting + *tight* to *None* will preserve the previous setting. + + Specifying any margin changes only the autoscaling; for example, + if *xmargin* is not None, then *xmargin* times the X data + interval will be added to each end of that interval before + it is used in autoscaling. + + """ + if not args and not kw: + return self._xmargin, self._ymargin + + tight = kw.pop('tight', True) + mx = kw.pop('x', None) + my = kw.pop('y', None) + if len(args) == 1: + mx = my = args[0] + elif len(args) == 2: + mx, my = args + elif len(args) > 2: + raise ValueError("more than two arguments were supplied") + if mx is not None: + self.set_xmargin(mx) + if my is not None: + self.set_ymargin(my) + + scalex = (mx is not None) + scaley = (my is not None) + + self.autoscale_view(tight=tight, scalex=scalex, scaley=scaley) + + def set_rasterization_zorder(self, z): + """ + Parameters + ---------- + z : float or None + zorder below which artists are rasterized. ``None`` means that + artists do not get rasterized based on zorder. + + .. ACCEPTS: float or None + """ + self._rasterization_zorder = z + self.stale = True + + def get_rasterization_zorder(self): + """Return the zorder value below which artists will be rasterized.""" + return self._rasterization_zorder + + def autoscale(self, enable=True, axis='both', tight=None): + """ + Autoscale the axis view to the data (toggle). + + Convenience method for simple axis view autoscaling. + It turns autoscaling on or off, and then, + if autoscaling for either axis is on, it performs + the autoscaling on the specified axis or axes. + + Parameters + ---------- + enable : bool or None, optional + True (default) turns autoscaling on, False turns it off. + None leaves the autoscaling state unchanged. + + axis : ['both' | 'x' | 'y'], optional + which axis to operate on; default is 'both' + + tight: bool or None, optional + If True, set view limits to data limits; + if False, let the locator and margins expand the view limits; + if None, use tight scaling if the only artist is an image, + otherwise treat *tight* as False. + The *tight* setting is retained for future autoscaling + until it is explicitly changed. + + """ + if enable is None: + scalex = True + scaley = True + else: + scalex = False + scaley = False + if axis in ['x', 'both']: + self._autoscaleXon = bool(enable) + scalex = self._autoscaleXon + if axis in ['y', 'both']: + self._autoscaleYon = bool(enable) + scaley = self._autoscaleYon + if tight and scalex: + self._xmargin = 0 + if tight and scaley: + self._ymargin = 0 + self.autoscale_view(tight=tight, scalex=scalex, scaley=scaley) + + def autoscale_view(self, tight=None, scalex=True, scaley=True): + """ + Autoscale the view limits using the data limits. + + You can selectively autoscale only a single axis, e.g., the xaxis by + setting *scaley* to *False*. The autoscaling preserves any + axis direction reversal that has already been done. + + If *tight* is *False*, the axis major locator will be used + to expand the view limits if rcParams['axes.autolimit_mode'] + is 'round_numbers'. Note that any margins that are in effect + will be applied first, regardless of whether *tight* is + *True* or *False*. Specifying *tight* as *True* or *False* + saves the setting as a private attribute of the Axes; specifying + it as *None* (the default) applies the previously saved value. + + The data limits are not updated automatically when artist data are + changed after the artist has been added to an Axes instance. In that + case, use :meth:`matplotlib.axes.Axes.relim` prior to calling + autoscale_view. + """ + if tight is not None: + self._tight = bool(tight) + + if self.use_sticky_edges and (self._xmargin or self._ymargin): + stickies = [artist.sticky_edges for artist in self.get_children()] + x_stickies = sum([sticky.x for sticky in stickies], []) + y_stickies = sum([sticky.y for sticky in stickies], []) + if self.get_xscale().lower() == 'log': + x_stickies = [xs for xs in x_stickies if xs > 0] + if self.get_yscale().lower() == 'log': + y_stickies = [ys for ys in y_stickies if ys > 0] + else: # Small optimization. + x_stickies, y_stickies = [], [] + + def handle_single_axis(scale, autoscaleon, shared_axes, interval, + minpos, axis, margin, stickies, set_bound): + + if not (scale and autoscaleon): + return # nothing to do... + + shared = shared_axes.get_siblings(self) + dl = [ax.dataLim for ax in shared] + # ignore non-finite data limits if good limits exist + finite_dl = [d for d in dl if np.isfinite(d).all()] + if len(finite_dl): + # if finite limits exist for atleast one axis (and the + # other is infinite), restore the finite limits + x_finite = [d for d in dl + if (np.isfinite(d.intervalx).all() and + (d not in finite_dl))] + y_finite = [d for d in dl + if (np.isfinite(d.intervaly).all() and + (d not in finite_dl))] + + dl = finite_dl + dl.extend(x_finite) + dl.extend(y_finite) + + bb = mtransforms.BboxBase.union(dl) + x0, x1 = getattr(bb, interval) + locator = axis.get_major_locator() + try: + # e.g., DateLocator has its own nonsingular() + x0, x1 = locator.nonsingular(x0, x1) + except AttributeError: + # Default nonsingular for, e.g., MaxNLocator + x0, x1 = mtransforms.nonsingular( + x0, x1, increasing=False, expander=0.05) + + # Add the margin in figure space and then transform back, to handle + # non-linear scales. + minpos = getattr(bb, minpos) + transform = axis.get_transform() + inverse_trans = transform.inverted() + # We cannot use exact equality due to floating point issues e.g. + # with streamplot. + do_lower_margin = not np.any(np.isclose(x0, stickies)) + do_upper_margin = not np.any(np.isclose(x1, stickies)) + x0, x1 = axis._scale.limit_range_for_scale(x0, x1, minpos) + x0t, x1t = transform.transform([x0, x1]) + delta = (x1t - x0t) * margin + if do_lower_margin: + x0t -= delta + if do_upper_margin: + x1t += delta + x0, x1 = inverse_trans.transform([x0t, x1t]) + + if not self._tight: + x0, x1 = locator.view_limits(x0, x1) + set_bound(x0, x1) + # End of definition of internal function 'handle_single_axis'. + + handle_single_axis( + scalex, self._autoscaleXon, self._shared_x_axes, 'intervalx', + 'minposx', self.xaxis, self._xmargin, x_stickies, self.set_xbound) + handle_single_axis( + scaley, self._autoscaleYon, self._shared_y_axes, 'intervaly', + 'minposy', self.yaxis, self._ymargin, y_stickies, self.set_ybound) + + def _get_axis_list(self): + return (self.xaxis, self.yaxis) + + # Drawing + + @allow_rasterization + def draw(self, renderer=None, inframe=False): + """Draw everything (plot lines, axes, labels)""" + if renderer is None: + renderer = self._cachedRenderer + + if renderer is None: + raise RuntimeError('No renderer defined') + if not self.get_visible(): + return + renderer.open_group('axes') + # prevent triggering call backs during the draw process + self._stale = True + locator = self.get_axes_locator() + if locator: + pos = locator(self, renderer) + self.apply_aspect(pos) + else: + self.apply_aspect() + + artists = self.get_children() + artists.remove(self.patch) + + # the frame draws the edges around the axes patch -- we + # decouple these so the patch can be in the background and the + # frame in the foreground. Do this before drawing the axis + # objects so that the spine has the opportunity to update them. + if not (self.axison and self._frameon): + for spine in six.itervalues(self.spines): + artists.remove(spine) + + if self.axison and not inframe: + if self._axisbelow is True: + self.xaxis.set_zorder(0.5) + self.yaxis.set_zorder(0.5) + elif self._axisbelow is False: + self.xaxis.set_zorder(2.5) + self.yaxis.set_zorder(2.5) + else: + # 'line': above patches, below lines + self.xaxis.set_zorder(1.5) + self.yaxis.set_zorder(1.5) + else: + for _axis in self._get_axis_list(): + artists.remove(_axis) + + if inframe: + artists.remove(self.title) + artists.remove(self._left_title) + artists.remove(self._right_title) + + if not self.figure.canvas.is_saving(): + artists = [a for a in artists + if not a.get_animated() or a in self.images] + artists = sorted(artists, key=attrgetter('zorder')) + + # rasterize artists with negative zorder + # if the minimum zorder is negative, start rasterization + rasterization_zorder = self._rasterization_zorder + if (rasterization_zorder is not None and + artists and artists[0].zorder < rasterization_zorder): + renderer.start_rasterizing() + artists_rasterized = [a for a in artists + if a.zorder < rasterization_zorder] + artists = [a for a in artists + if a.zorder >= rasterization_zorder] + else: + artists_rasterized = [] + + # the patch draws the background rectangle -- the frame below + # will draw the edges + if self.axison and self._frameon: + self.patch.draw(renderer) + + if artists_rasterized: + for a in artists_rasterized: + a.draw(renderer) + renderer.stop_rasterizing() + + mimage._draw_list_compositing_images(renderer, self, artists) + + renderer.close_group('axes') + self._cachedRenderer = renderer + self.stale = False + + def draw_artist(self, a): + """ + This method can only be used after an initial draw which + caches the renderer. It is used to efficiently update Axes + data (axis ticks, labels, etc are not updated) + """ + if self._cachedRenderer is None: + raise AttributeError("draw_artist can only be used after an " + "initial draw which caches the renderer") + a.draw(self._cachedRenderer) + + def redraw_in_frame(self): + """ + This method can only be used after an initial draw which + caches the renderer. It is used to efficiently update Axes + data (axis ticks, labels, etc are not updated) + """ + if self._cachedRenderer is None: + raise AttributeError("redraw_in_frame can only be used after an " + "initial draw which caches the renderer") + self.draw(self._cachedRenderer, inframe=True) + + def get_renderer_cache(self): + return self._cachedRenderer + + # Axes rectangle characteristics + + def get_frame_on(self): + """ + Get whether the axes rectangle patch is drawn. + """ + return self._frameon + + def set_frame_on(self, b): + """ + Set whether the axes rectangle patch is drawn. + + .. ACCEPTS: bool + + Parameters + ---------- + b : bool + """ + self._frameon = b + self.stale = True + + def get_axisbelow(self): + """ + Get whether axis ticks and gridlines are above or below most artists. + """ + return self._axisbelow + + def set_axisbelow(self, b): + """ + Set whether axis ticks and gridlines are above or below most artists. + + .. ACCEPTS: [ bool | 'line' ] + + Parameters + ---------- + b : bool or 'line' + """ + self._axisbelow = validate_axisbelow(b) + self.stale = True + + @docstring.dedent_interpd + def grid(self, b=None, which='major', axis='both', **kwargs): + """ + Turn the axes grids on or off. + + Set the axes grids on or off; *b* is a boolean. + + If *b* is *None* and ``len(kwargs)==0``, toggle the grid state. If + *kwargs* are supplied, it is assumed that you want a grid and *b* + is thus set to *True*. + + *which* can be 'major' (default), 'minor', or 'both' to control + whether major tick grids, minor tick grids, or both are affected. + + *axis* can be 'both' (default), 'x', or 'y' to control which + set of gridlines are drawn. + + *kwargs* are used to set the grid line properties, e.g.,:: + + ax.grid(color='r', linestyle='-', linewidth=2) + + Valid :class:`~matplotlib.lines.Line2D` kwargs are + + %(Line2D)s + + """ + if len(kwargs): + b = True + elif b is not None: + b = _string_to_bool(b) + + if axis == 'x' or axis == 'both': + self.xaxis.grid(b, which=which, **kwargs) + if axis == 'y' or axis == 'both': + self.yaxis.grid(b, which=which, **kwargs) + + def ticklabel_format(self, **kwargs): + """ + Change the `~matplotlib.ticker.ScalarFormatter` used by + default for linear axes. + + Optional keyword arguments: + + ============== ========================================= + Keyword Description + ============== ========================================= + *style* [ 'sci' (or 'scientific') | 'plain' ] + plain turns off scientific notation + *scilimits* (m, n), pair of integers; if *style* + is 'sci', scientific notation will + be used for numbers outside the range + 10`m`:sup: to 10`n`:sup:. + Use (0,0) to include all numbers. + *useOffset* [ bool | offset ]; if True, + the offset will be calculated as needed; + if False, no offset will be used; if a + numeric offset is specified, it will be + used. + *axis* [ 'x' | 'y' | 'both' ] + *useLocale* If True, format the number according to + the current locale. This affects things + such as the character used for the + decimal separator. If False, use + C-style (English) formatting. The + default setting is controlled by the + axes.formatter.use_locale rcparam. + *useMathText* If True, render the offset and scientific + notation in mathtext + ============== ========================================= + + Only the major ticks are affected. + If the method is called when the + :class:`~matplotlib.ticker.ScalarFormatter` is not the + :class:`~matplotlib.ticker.Formatter` being used, an + :exc:`AttributeError` will be raised. + + """ + style = kwargs.pop('style', '').lower() + scilimits = kwargs.pop('scilimits', None) + useOffset = kwargs.pop('useOffset', None) + useLocale = kwargs.pop('useLocale', None) + useMathText = kwargs.pop('useMathText', None) + axis = kwargs.pop('axis', 'both').lower() + if scilimits is not None: + try: + m, n = scilimits + m + n + 1 # check that both are numbers + except (ValueError, TypeError): + raise ValueError("scilimits must be a sequence of 2 integers") + if style[:3] == 'sci': + sb = True + elif style == 'plain': + sb = False + elif style == 'comma': + raise NotImplementedError("comma style remains to be added") + elif style == '': + sb = None + else: + raise ValueError("%s is not a valid style value") + try: + if sb is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_scientific(sb) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_scientific(sb) + if scilimits is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_powerlimits(scilimits) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_powerlimits(scilimits) + if useOffset is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_useOffset(useOffset) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_useOffset(useOffset) + if useLocale is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_useLocale(useLocale) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_useLocale(useLocale) + if useMathText is not None: + if axis == 'both' or axis == 'x': + self.xaxis.major.formatter.set_useMathText(useMathText) + if axis == 'both' or axis == 'y': + self.yaxis.major.formatter.set_useMathText(useMathText) + except AttributeError: + raise AttributeError( + "This method only works with the ScalarFormatter.") + + def locator_params(self, axis='both', tight=None, **kwargs): + """ + Control behavior of tick locators. + + Parameters + ---------- + axis : ['both' | 'x' | 'y'], optional + The axis on which to operate. + + tight : bool or None, optional + Parameter passed to :meth:`autoscale_view`. + Default is None, for no change. + + Other Parameters + ---------------- + **kw : + Remaining keyword arguments are passed to directly to the + :meth:`~matplotlib.ticker.MaxNLocator.set_params` method. + + Typically one might want to reduce the maximum number + of ticks and use tight bounds when plotting small + subplots, for example:: + + ax.locator_params(tight=True, nbins=4) + + Because the locator is involved in autoscaling, + :meth:`autoscale_view` is called automatically after + the parameters are changed. + + This presently works only for the + :class:`~matplotlib.ticker.MaxNLocator` used + by default on linear axes, but it may be generalized. + """ + _x = axis in ['x', 'both'] + _y = axis in ['y', 'both'] + if _x: + self.xaxis.get_major_locator().set_params(**kwargs) + if _y: + self.yaxis.get_major_locator().set_params(**kwargs) + self.autoscale_view(tight=tight, scalex=_x, scaley=_y) + + def tick_params(self, axis='both', **kwargs): + """Change the appearance of ticks, tick labels, and gridlines. + + Parameters + ---------- + axis : {'x', 'y', 'both'}, optional + Which axis to apply the parameters to. + + Other Parameters + ---------------- + + axis : {'x', 'y', 'both'} + Axis on which to operate; default is 'both'. + + reset : bool + If *True*, set all parameters to defaults + before processing other keyword arguments. Default is + *False*. + + which : {'major', 'minor', 'both'} + Default is 'major'; apply arguments to *which* ticks. + + direction : {'in', 'out', 'inout'} + Puts ticks inside the axes, outside the axes, or both. + + length : float + Tick length in points. + + width : float + Tick width in points. + + color : color + Tick color; accepts any mpl color spec. + + pad : float + Distance in points between tick and label. + + labelsize : float or str + Tick label font size in points or as a string (e.g., 'large'). + + labelcolor : color + Tick label color; mpl color spec. + + colors : color + Changes the tick color and the label color to the same value: + mpl color spec. + + zorder : float + Tick and label zorder. + + bottom, top, left, right : bool + Whether to draw the respective ticks. + + labelbottom, labeltop, labelleft, labelright : bool + Whether to draw the respective tick labels. + + labelrotation : float + Tick label rotation + + grid_color : color + Changes the gridline color to the given mpl color spec. + + grid_alpha : float + Transparency of gridlines: 0 (transparent) to 1 (opaque). + + grid_linewidth : float + Width of gridlines in points. + + grid_linestyle : string + Any valid :class:`~matplotlib.lines.Line2D` line style spec. + + Examples + -------- + + Usage :: + + ax.tick_params(direction='out', length=6, width=2, colors='r', + grid_color='r', grid_alpha=0.5) + + This will make all major ticks be red, pointing out of the box, + and with dimensions 6 points by 2 points. Tick labels will + also be red. Gridlines will be red and translucent. + + """ + if axis in ['x', 'both']: + xkw = dict(kwargs) + xkw.pop('left', None) + xkw.pop('right', None) + xkw.pop('labelleft', None) + xkw.pop('labelright', None) + self.xaxis.set_tick_params(**xkw) + if axis in ['y', 'both']: + ykw = dict(kwargs) + ykw.pop('top', None) + ykw.pop('bottom', None) + ykw.pop('labeltop', None) + ykw.pop('labelbottom', None) + self.yaxis.set_tick_params(**ykw) + + def set_axis_off(self): + """Turn off the axis.""" + self.axison = False + self.stale = True + + def set_axis_on(self): + """Turn on the axis.""" + self.axison = True + self.stale = True + + # data limits, ticks, tick labels, and formatting + + def invert_xaxis(self): + """Invert the x-axis.""" + self.set_xlim(self.get_xlim()[::-1], auto=None) + + def xaxis_inverted(self): + """Return whether the x-axis is inverted.""" + left, right = self.get_xlim() + return right < left + + def get_xbound(self): + """Return the lower and upper x-axis bounds, in increasing order.""" + left, right = self.get_xlim() + if left < right: + return left, right + else: + return right, left + + def set_xbound(self, lower=None, upper=None): + """ + Set the lower and upper numerical bounds of the x-axis. + + This method will honor axes inversion regardless of parameter order. + It will not change the _autoscaleXon attribute. + + .. ACCEPTS: (lower: float, upper: float) + """ + if upper is None and iterable(lower): + lower, upper = lower + + old_lower, old_upper = self.get_xbound() + + if lower is None: + lower = old_lower + if upper is None: + upper = old_upper + + if self.xaxis_inverted(): + if lower < upper: + self.set_xlim(upper, lower, auto=None) + else: + self.set_xlim(lower, upper, auto=None) + else: + if lower < upper: + self.set_xlim(lower, upper, auto=None) + else: + self.set_xlim(upper, lower, auto=None) + + def get_xlim(self): + """ + Get the x-axis range + + Returns + ------- + xlimits : tuple + Returns the current x-axis limits as the tuple + (`left`, `right`). + + Notes + ----- + The x-axis may be inverted, in which case the `left` value will + be greater than the `right` value. + + """ + return tuple(self.viewLim.intervalx) + + def _validate_converted_limits(self, limit, convert): + """ + Raise ValueError if converted limits are non-finite. + + Note that this function also accepts None as a limit argument. + + Returns + ------- + The limit value after call to convert(), or None if limit is None. + + """ + if limit is not None: + converted_limit = convert(limit) + if (isinstance(converted_limit, float) and + (not np.isreal(converted_limit) or + not np.isfinite(converted_limit))): + raise ValueError("Axis limits cannot be NaN or Inf") + return converted_limit + + def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw): + """ + Set the data limits for the x-axis + + .. ACCEPTS: (left: float, right: float) + + Parameters + ---------- + left : scalar, optional + The left xlim (default: None, which leaves the left limit + unchanged). + + right : scalar, optional + The right xlim (default: None, which leaves the right limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of the x-axis. True turns on, + False turns off (default action), None leaves unchanged. + + xlimits : tuple, optional + The left and right xlims may be passed as the tuple + (`left`, `right`) as the first positional argument (or as + the `left` keyword argument). + + Returns + ------- + xlimits : tuple + Returns the new x-axis limits as (`left`, `right`). + + Notes + ----- + The `left` value may be greater than the `right` value, in which + case the x-axis values will decrease from left to right. + + Examples + -------- + >>> set_xlim(left, right) + >>> set_xlim((left, right)) + >>> left, right = set_xlim(left, right) + + One limit may be left unchanged. + + >>> set_xlim(right=right_lim) + + Limits may be passed in reverse order to flip the direction of + the x-axis. For example, suppose `x` represents the number of + years before present. The x-axis limits might be set like the + following so 5000 years ago is on the left of the plot and the + present is on the right. + + >>> set_xlim(5000, 0) + + """ + if 'xmin' in kw: + left = kw.pop('xmin') + if 'xmax' in kw: + right = kw.pop('xmax') + if kw: + raise ValueError("unrecognized kwargs: %s" % list(kw)) + + if right is None and iterable(left): + left, right = left + + self._process_unit_info(xdata=(left, right)) + left = self._validate_converted_limits(left, self.convert_xunits) + right = self._validate_converted_limits(right, self.convert_xunits) + + old_left, old_right = self.get_xlim() + if left is None: + left = old_left + if right is None: + right = old_right + + if left == right: + warnings.warn( + ('Attempting to set identical left==right results\n' + 'in singular transformations; automatically expanding.\n' + 'left=%s, right=%s') % (left, right)) + left, right = mtransforms.nonsingular(left, right, increasing=False) + + if self.get_xscale() == 'log' and (left <= 0.0 or right <= 0.0): + warnings.warn( + 'Attempted to set non-positive xlimits for log-scale axis; ' + 'invalid limits will be ignored.') + left, right = self.xaxis.limit_range_for_scale(left, right) + + self.viewLim.intervalx = (left, right) + if auto is not None: + self._autoscaleXon = bool(auto) + + if emit: + self.callbacks.process('xlim_changed', self) + # Call all of the other x-axes that are shared with this one + for other in self._shared_x_axes.get_siblings(self): + if other is not self: + other.set_xlim(self.viewLim.intervalx, + emit=False, auto=auto) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return left, right + + def get_xscale(self): + return self.xaxis.get_scale() + get_xscale.__doc__ = "Return the xaxis scale string: %s""" % ( + ", ".join(mscale.get_scale_names())) + + def set_xscale(self, value, **kwargs): + """ + Set the x-axis scale. + + .. ACCEPTS: [ 'linear' | 'log' | 'symlog' | 'logit' | ... ] + + Parameters + ---------- + value : {"linear", "log", "symlog", "logit"} + scaling strategy to apply + + Notes + ----- + Different kwargs are accepted, depending on the scale. See + the `~matplotlib.scale` module for more information. + + See also + -------- + matplotlib.scale.LinearScale : linear transform + + matplotlib.scale.LogTransform : log transform + + matplotlib.scale.SymmetricalLogTransform : symlog transform + + matplotlib.scale.LogisticTransform : logit transform + """ + g = self.get_shared_x_axes() + for ax in g.get_siblings(self): + ax.xaxis._set_scale(value, **kwargs) + ax._update_transScale() + ax.stale = True + + self.autoscale_view(scaley=False) + + def get_xticks(self, minor=False): + """Return the x ticks as a list of locations""" + return self.xaxis.get_ticklocs(minor=minor) + + def set_xticks(self, ticks, minor=False): + """ + Set the x ticks with list of *ticks* + + .. ACCEPTS: list of tick locations. + + Parameters + ---------- + ticks : list + List of x-axis tick locations. + + minor : bool, optional + If ``False`` sets major ticks, if ``True`` sets minor ticks. + Default is ``False``. + """ + ret = self.xaxis.set_ticks(ticks, minor=minor) + self.stale = True + return ret + + def get_xmajorticklabels(self): + """ + Get the major x tick labels. + + Returns + ------- + labels : list + List of :class:`~matplotlib.text.Text` instances + """ + return cbook.silent_list('Text xticklabel', + self.xaxis.get_majorticklabels()) + + def get_xminorticklabels(self): + """ + Get the minor x tick labels. + + Returns + ------- + labels : list + List of :class:`~matplotlib.text.Text` instances + """ + return cbook.silent_list('Text xticklabel', + self.xaxis.get_minorticklabels()) + + def get_xticklabels(self, minor=False, which=None): + """ + Get the x tick labels as a list of :class:`~matplotlib.text.Text` + instances. + + Parameters + ---------- + minor : bool, optional + If True return the minor ticklabels, + else return the major ticklabels. + + which : None, ('minor', 'major', 'both') + Overrides `minor`. + + Selects which ticklabels to return + + Returns + ------- + ret : list + List of :class:`~matplotlib.text.Text` instances. + """ + return cbook.silent_list('Text xticklabel', + self.xaxis.get_ticklabels(minor=minor, + which=which)) + + def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs): + """ + Set the x-tick labels with list of string labels. + + .. ACCEPTS: list of string labels + + Parameters + ---------- + labels : list of str + List of string labels. + + fontdict : dict, optional + A dictionary controlling the appearance of the ticklabels. + The default `fontdict` is:: + + {'fontsize': rcParams['axes.titlesize'], + 'fontweight': rcParams['axes.titleweight'], + 'verticalalignment': 'baseline', + 'horizontalalignment': loc} + + minor : bool, optional + Whether to set the minor ticklabels rather than the major ones. + + Returns + ------- + A list of `~.text.Text` instances. + + Other Parameters + ----------------- + **kwargs : `~.text.Text` properties. + """ + if fontdict is not None: + kwargs.update(fontdict) + ret = self.xaxis.set_ticklabels(labels, + minor=minor, **kwargs) + self.stale = True + return ret + + def invert_yaxis(self): + """Invert the y-axis.""" + self.set_ylim(self.get_ylim()[::-1], auto=None) + + def yaxis_inverted(self): + """Return whether the y-axis is inverted.""" + bottom, top = self.get_ylim() + return top < bottom + + def get_ybound(self): + """Return the lower and upper y-axis bounds, in increasing order.""" + bottom, top = self.get_ylim() + if bottom < top: + return bottom, top + else: + return top, bottom + + def set_ybound(self, lower=None, upper=None): + """ + Set the lower and upper numerical bounds of the y-axis. + This method will honor axes inversion regardless of parameter order. + It will not change the _autoscaleYon attribute. + + .. ACCEPTS: (lower: float, upper: float) + """ + if upper is None and iterable(lower): + lower, upper = lower + + old_lower, old_upper = self.get_ybound() + + if lower is None: + lower = old_lower + if upper is None: + upper = old_upper + + if self.yaxis_inverted(): + if lower < upper: + self.set_ylim(upper, lower, auto=None) + else: + self.set_ylim(lower, upper, auto=None) + else: + if lower < upper: + self.set_ylim(lower, upper, auto=None) + else: + self.set_ylim(upper, lower, auto=None) + + def get_ylim(self): + """ + Get the y-axis range + + Returns + ------- + ylimits : tuple + Returns the current y-axis limits as the tuple + (`bottom`, `top`). + + Notes + ----- + The y-axis may be inverted, in which case the `bottom` value + will be greater than the `top` value. + + """ + return tuple(self.viewLim.intervaly) + + def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw): + """ + Set the data limits for the y-axis + + .. ACCEPTS: (bottom: float, top: float) + + Parameters + ---------- + bottom : scalar, optional + The bottom ylim (default: None, which leaves the bottom + limit unchanged). + + top : scalar, optional + The top ylim (default: None, which leaves the top limit + unchanged). + + emit : bool, optional + Whether to notify observers of limit change (default: True). + + auto : bool or None, optional + Whether to turn on autoscaling of the y-axis. True turns on, + False turns off (default action), None leaves unchanged. + + ylimits : tuple, optional + The bottom and top yxlims may be passed as the tuple + (`bottom`, `top`) as the first positional argument (or as + the `bottom` keyword argument). + + Returns + ------- + ylimits : tuple + Returns the new y-axis limits as (`bottom`, `top`). + + Notes + ----- + The `bottom` value may be greater than the `top` value, in which + case the y-axis values will decrease from bottom to top. + + Examples + -------- + >>> set_ylim(bottom, top) + >>> set_ylim((bottom, top)) + >>> bottom, top = set_ylim(bottom, top) + + One limit may be left unchanged. + + >>> set_ylim(top=top_lim) + + Limits may be passed in reverse order to flip the direction of + the y-axis. For example, suppose `y` represents depth of the + ocean in m. The y-axis limits might be set like the following + so 5000 m depth is at the bottom of the plot and the surface, + 0 m, is at the top. + + >>> set_ylim(5000, 0) + """ + if 'ymin' in kw: + bottom = kw.pop('ymin') + if 'ymax' in kw: + top = kw.pop('ymax') + if kw: + raise ValueError("unrecognized kwargs: %s" % list(kw)) + + if top is None and iterable(bottom): + bottom, top = bottom + + bottom = self._validate_converted_limits(bottom, self.convert_yunits) + top = self._validate_converted_limits(top, self.convert_yunits) + + old_bottom, old_top = self.get_ylim() + + if bottom is None: + bottom = old_bottom + if top is None: + top = old_top + + if bottom == top: + warnings.warn( + ('Attempting to set identical bottom==top results\n' + 'in singular transformations; automatically expanding.\n' + 'bottom=%s, top=%s') % (bottom, top)) + + bottom, top = mtransforms.nonsingular(bottom, top, increasing=False) + + if self.get_yscale() == 'log' and (bottom <= 0.0 or top <= 0.0): + warnings.warn( + 'Attempted to set non-positive ylimits for log-scale axis; ' + 'invalid limits will be ignored.') + bottom, top = self.yaxis.limit_range_for_scale(bottom, top) + + self.viewLim.intervaly = (bottom, top) + if auto is not None: + self._autoscaleYon = bool(auto) + + if emit: + self.callbacks.process('ylim_changed', self) + # Call all of the other y-axes that are shared with this one + for other in self._shared_y_axes.get_siblings(self): + if other is not self: + other.set_ylim(self.viewLim.intervaly, + emit=False, auto=auto) + if (other.figure != self.figure and + other.figure.canvas is not None): + other.figure.canvas.draw_idle() + self.stale = True + return bottom, top + + def get_yscale(self): + return self.yaxis.get_scale() + get_yscale.__doc__ = "Return the yaxis scale string: %s""" % ( + ", ".join(mscale.get_scale_names())) + + def set_yscale(self, value, **kwargs): + """ + Set the y-axis scale. + + .. ACCEPTS: [ 'linear' | 'log' | 'symlog' | 'logit' | ... ] + + Parameters + ---------- + value : {"linear", "log", "symlog", "logit"} + scaling strategy to apply + + Notes + ----- + Different kwargs are accepted, depending on the scale. See + the `~matplotlib.scale` module for more information. + + See also + -------- + matplotlib.scale.LinearScale : linear transform + + matplotlib.scale.LogTransform : log transform + + matplotlib.scale.SymmetricalLogTransform : symlog transform + + matplotlib.scale.LogisticTransform : logit transform + """ + g = self.get_shared_y_axes() + for ax in g.get_siblings(self): + ax.yaxis._set_scale(value, **kwargs) + ax._update_transScale() + ax.stale = True + self.autoscale_view(scalex=False) + + def get_yticks(self, minor=False): + """Return the y ticks as a list of locations""" + return self.yaxis.get_ticklocs(minor=minor) + + def set_yticks(self, ticks, minor=False): + """ + Set the y ticks with list of *ticks* + + .. ACCEPTS: list of tick locations. + + Parameters + ---------- + ticks : sequence + List of y-axis tick locations + + minor : bool, optional + If ``False`` sets major ticks, if ``True`` sets minor ticks. + Default is ``False``. + """ + ret = self.yaxis.set_ticks(ticks, minor=minor) + return ret + + def get_ymajorticklabels(self): + """ + Get the major y tick labels. + + Returns + ------- + labels : list + List of :class:`~matplotlib.text.Text` instances + """ + return cbook.silent_list('Text yticklabel', + self.yaxis.get_majorticklabels()) + + def get_yminorticklabels(self): + """ + Get the minor y tick labels. + + Returns + ------- + labels : list + List of :class:`~matplotlib.text.Text` instances + """ + return cbook.silent_list('Text yticklabel', + self.yaxis.get_minorticklabels()) + + def get_yticklabels(self, minor=False, which=None): + """ + Get the y tick labels as a list of :class:`~matplotlib.text.Text` + instances. + + Parameters + ---------- + minor : bool + If True return the minor ticklabels, + else return the major ticklabels + + which : None, ('minor', 'major', 'both') + Overrides `minor`. + + Selects which ticklabels to return + + Returns + ------- + ret : list + List of :class:`~matplotlib.text.Text` instances. + """ + return cbook.silent_list('Text yticklabel', + self.yaxis.get_ticklabels(minor=minor, + which=which)) + + def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs): + """ + Set the y-tick labels with list of strings labels. + + .. ACCEPTS: list of string labels + + Parameters + ---------- + labels : list of str + list of string labels + + fontdict : dict, optional + A dictionary controlling the appearance of the ticklabels. + The default `fontdict` is:: + + {'fontsize': rcParams['axes.titlesize'], + 'fontweight': rcParams['axes.titleweight'], + 'verticalalignment': 'baseline', + 'horizontalalignment': loc} + + minor : bool, optional + Whether to set the minor ticklabels rather than the major ones. + + Returns + ------- + A list of `~.text.Text` instances. + + Other Parameters + ---------------- + **kwargs : `~.text.Text` properties. + """ + if fontdict is not None: + kwargs.update(fontdict) + return self.yaxis.set_ticklabels(labels, + minor=minor, **kwargs) + + def xaxis_date(self, tz=None): + """ + Sets up x-axis ticks and labels that treat the x data as dates. + + Parameters + ---------- + tz : string or :class:`tzinfo` instance, optional + Timezone string or timezone. Defaults to rc value. + """ + # should be enough to inform the unit conversion interface + # dates are coming in + self.xaxis.axis_date(tz) + + def yaxis_date(self, tz=None): + """ + Sets up y-axis ticks and labels that treat the y data as dates. + + Parameters + ---------- + tz : string or :class:`tzinfo` instance, optional + Timezone string or timezone. Defaults to rc value. + """ + self.yaxis.axis_date(tz) + + def format_xdata(self, x): + """ + Return *x* string formatted. This function will use the attribute + self.fmt_xdata if it is callable, else will fall back on the xaxis + major formatter + """ + try: + return self.fmt_xdata(x) + except TypeError: + func = self.xaxis.get_major_formatter().format_data_short + val = func(x) + return val + + def format_ydata(self, y): + """ + Return y string formatted. This function will use the + :attr:`fmt_ydata` attribute if it is callable, else will fall + back on the yaxis major formatter + """ + try: + return self.fmt_ydata(y) + except TypeError: + func = self.yaxis.get_major_formatter().format_data_short + val = func(y) + return val + + def format_coord(self, x, y): + """Return a format string formatting the *x*, *y* coord""" + if x is None: + xs = '???' + else: + xs = self.format_xdata(x) + if y is None: + ys = '???' + else: + ys = self.format_ydata(y) + return 'x=%s y=%s' % (xs, ys) + + def minorticks_on(self): + 'Add autoscaling minor ticks to the axes.' + for ax in (self.xaxis, self.yaxis): + scale = ax.get_scale() + if scale == 'log': + s = ax._scale + ax.set_minor_locator(mticker.LogLocator(s.base, s.subs)) + elif scale == 'symlog': + s = ax._scale + ax.set_minor_locator( + mticker.SymmetricalLogLocator(s._transform, s.subs)) + else: + ax.set_minor_locator(mticker.AutoMinorLocator()) + + def minorticks_off(self): + """Remove minor ticks from the axes.""" + self.xaxis.set_minor_locator(mticker.NullLocator()) + self.yaxis.set_minor_locator(mticker.NullLocator()) + + # Interactive manipulation + + def can_zoom(self): + """ + Return *True* if this axes supports the zoom box button functionality. + """ + return True + + def can_pan(self): + """ + Return *True* if this axes supports any pan/zoom button functionality. + """ + return True + + def get_navigate(self): + """ + Get whether the axes responds to navigation commands + """ + return self._navigate + + def set_navigate(self, b): + """ + Set whether the axes responds to navigation toolbar commands + + .. ACCEPTS: bool + + Parameters + ---------- + b : bool + """ + self._navigate = b + + def get_navigate_mode(self): + """ + Get the navigation toolbar button status: 'PAN', 'ZOOM', or None + """ + return self._navigate_mode + + def set_navigate_mode(self, b): + """ + Set the navigation toolbar button status; + + .. warning:: + this is not a user-API function. + + """ + self._navigate_mode = b + + def _get_view(self): + """ + Save information required to reproduce the current view. + + Called before a view is changed, such as during a pan or zoom + initiated by the user. You may return any information you deem + necessary to describe the view. + + .. note:: + + Intended to be overridden by new projection types, but if not, the + default implementation saves the view limits. You *must* implement + :meth:`_set_view` if you implement this method. + """ + xmin, xmax = self.get_xlim() + ymin, ymax = self.get_ylim() + return (xmin, xmax, ymin, ymax) + + def _set_view(self, view): + """ + Apply a previously saved view. + + Called when restoring a view, such as with the navigation buttons. + + .. note:: + + Intended to be overridden by new projection types, but if not, the + default implementation restores the view limits. You *must* + implement :meth:`_get_view` if you implement this method. + """ + xmin, xmax, ymin, ymax = view + self.set_xlim((xmin, xmax)) + self.set_ylim((ymin, ymax)) + + def _set_view_from_bbox(self, bbox, direction='in', + mode=None, twinx=False, twiny=False): + """ + Update view from a selection bbox. + + .. note:: + + Intended to be overridden by new projection types, but if not, the + default implementation sets the view limits to the bbox directly. + + Parameters + ---------- + + bbox : 4-tuple or 3 tuple + * If bbox is a 4 tuple, it is the selected bounding box limits, + in *display* coordinates. + * If bbox is a 3 tuple, it is an (xp, yp, scl) triple, where + (xp,yp) is the center of zooming and scl the scale factor to + zoom by. + + direction : str + The direction to apply the bounding box. + * `'in'` - The bounding box describes the view directly, i.e., + it zooms in. + * `'out'` - The bounding box describes the size to make the + existing view, i.e., it zooms out. + + mode : str or None + The selection mode, whether to apply the bounding box in only the + `'x'` direction, `'y'` direction or both (`None`). + + twinx : bool + Whether this axis is twinned in the *x*-direction. + + twiny : bool + Whether this axis is twinned in the *y*-direction. + """ + Xmin, Xmax = self.get_xlim() + Ymin, Ymax = self.get_ylim() + + if len(bbox) == 3: + # Zooming code + xp, yp, scl = bbox + + # Should not happen + if scl == 0: + scl = 1. + + # direction = 'in' + if scl > 1: + direction = 'in' + else: + direction = 'out' + scl = 1/scl + + # get the limits of the axes + tranD2C = self.transData.transform + xmin, ymin = tranD2C((Xmin, Ymin)) + xmax, ymax = tranD2C((Xmax, Ymax)) + + # set the range + xwidth = xmax - xmin + ywidth = ymax - ymin + xcen = (xmax + xmin)*.5 + ycen = (ymax + ymin)*.5 + xzc = (xp*(scl - 1) + xcen)/scl + yzc = (yp*(scl - 1) + ycen)/scl + + bbox = [xzc - xwidth/2./scl, yzc - ywidth/2./scl, + xzc + xwidth/2./scl, yzc + ywidth/2./scl] + elif len(bbox) != 4: + # should be len 3 or 4 but nothing else + warnings.warn( + "Warning in _set_view_from_bbox: bounding box is not a tuple " + "of length 3 or 4. Ignoring the view change.") + return + + # Just grab bounding box + lastx, lasty, x, y = bbox + + # zoom to rect + inverse = self.transData.inverted() + lastx, lasty = inverse.transform_point((lastx, lasty)) + x, y = inverse.transform_point((x, y)) + + if twinx: + x0, x1 = Xmin, Xmax + else: + if Xmin < Xmax: + if x < lastx: + x0, x1 = x, lastx + else: + x0, x1 = lastx, x + if x0 < Xmin: + x0 = Xmin + if x1 > Xmax: + x1 = Xmax + else: + if x > lastx: + x0, x1 = x, lastx + else: + x0, x1 = lastx, x + if x0 > Xmin: + x0 = Xmin + if x1 < Xmax: + x1 = Xmax + + if twiny: + y0, y1 = Ymin, Ymax + else: + if Ymin < Ymax: + if y < lasty: + y0, y1 = y, lasty + else: + y0, y1 = lasty, y + if y0 < Ymin: + y0 = Ymin + if y1 > Ymax: + y1 = Ymax + else: + if y > lasty: + y0, y1 = y, lasty + else: + y0, y1 = lasty, y + if y0 > Ymin: + y0 = Ymin + if y1 < Ymax: + y1 = Ymax + + if direction == 'in': + if mode == 'x': + self.set_xlim((x0, x1)) + elif mode == 'y': + self.set_ylim((y0, y1)) + else: + self.set_xlim((x0, x1)) + self.set_ylim((y0, y1)) + elif direction == 'out': + if self.get_xscale() == 'log': + alpha = np.log(Xmax / Xmin) / np.log(x1 / x0) + rx1 = pow(Xmin / x0, alpha) * Xmin + rx2 = pow(Xmax / x0, alpha) * Xmin + else: + alpha = (Xmax - Xmin) / (x1 - x0) + rx1 = alpha * (Xmin - x0) + Xmin + rx2 = alpha * (Xmax - x0) + Xmin + if self.get_yscale() == 'log': + alpha = np.log(Ymax / Ymin) / np.log(y1 / y0) + ry1 = pow(Ymin / y0, alpha) * Ymin + ry2 = pow(Ymax / y0, alpha) * Ymin + else: + alpha = (Ymax - Ymin) / (y1 - y0) + ry1 = alpha * (Ymin - y0) + Ymin + ry2 = alpha * (Ymax - y0) + Ymin + + if mode == 'x': + self.set_xlim((rx1, rx2)) + elif mode == 'y': + self.set_ylim((ry1, ry2)) + else: + self.set_xlim((rx1, rx2)) + self.set_ylim((ry1, ry2)) + + def start_pan(self, x, y, button): + """ + Called when a pan operation has started. + + *x*, *y* are the mouse coordinates in display coords. + button is the mouse button number: + + * 1: LEFT + * 2: MIDDLE + * 3: RIGHT + + .. note:: + + Intended to be overridden by new projection types. + + """ + self._pan_start = cbook.Bunch( + lim=self.viewLim.frozen(), + trans=self.transData.frozen(), + trans_inverse=self.transData.inverted().frozen(), + bbox=self.bbox.frozen(), + x=x, + y=y) + + def end_pan(self): + """ + Called when a pan operation completes (when the mouse button + is up.) + + .. note:: + + Intended to be overridden by new projection types. + + """ + del self._pan_start + + def drag_pan(self, button, key, x, y): + """ + Called when the mouse moves during a pan operation. + + *button* is the mouse button number: + + * 1: LEFT + * 2: MIDDLE + * 3: RIGHT + + *key* is a "shift" key + + *x*, *y* are the mouse coordinates in display coords. + + .. note:: + + Intended to be overridden by new projection types. + + """ + def format_deltas(key, dx, dy): + if key == 'control': + if abs(dx) > abs(dy): + dy = dx + else: + dx = dy + elif key == 'x': + dy = 0 + elif key == 'y': + dx = 0 + elif key == 'shift': + if 2 * abs(dx) < abs(dy): + dx = 0 + elif 2 * abs(dy) < abs(dx): + dy = 0 + elif abs(dx) > abs(dy): + dy = dy / abs(dy) * abs(dx) + else: + dx = dx / abs(dx) * abs(dy) + return dx, dy + + p = self._pan_start + dx = x - p.x + dy = y - p.y + if dx == 0 and dy == 0: + return + if button == 1: + dx, dy = format_deltas(key, dx, dy) + result = p.bbox.translated(-dx, -dy).transformed(p.trans_inverse) + elif button == 3: + try: + dx = -dx / self.bbox.width + dy = -dy / self.bbox.height + dx, dy = format_deltas(key, dx, dy) + if self.get_aspect() != 'auto': + dx = dy = 0.5 * (dx + dy) + alpha = np.power(10.0, (dx, dy)) + start = np.array([p.x, p.y]) + oldpoints = p.lim.transformed(p.trans) + newpoints = start + alpha * (oldpoints - start) + result = (mtransforms.Bbox(newpoints) + .transformed(p.trans_inverse)) + except OverflowError: + warnings.warn('Overflow while panning') + return + + valid = np.isfinite(result.transformed(p.trans)) + points = result.get_points().astype(object) + # Just ignore invalid limits (typically, underflow in log-scale). + points[~valid] = None + self.set_xlim(points[:, 0]) + self.set_ylim(points[:, 1]) + + @cbook.deprecated("2.1") + def get_cursor_props(self): + """ + Return the cursor propertiess as a (*linewidth*, *color*) + tuple, where *linewidth* is a float and *color* is an RGBA + tuple + """ + return self._cursorProps + + @cbook.deprecated("2.1") + def set_cursor_props(self, *args): + """Set the cursor property as + + Call signature :: + + ax.set_cursor_props(linewidth, color) + + or:: + + ax.set_cursor_props((linewidth, color)) + + ACCEPTS: a (*float*, *color*) tuple + """ + if len(args) == 1: + lw, c = args[0] + elif len(args) == 2: + lw, c = args + else: + raise ValueError('args must be a (linewidth, color) tuple') + c = mcolors.to_rgba(c) + self._cursorProps = lw, c + + def get_children(self): + """return a list of child artists""" + children = [] + children.extend(self.collections) + children.extend(self.patches) + children.extend(self.lines) + children.extend(self.texts) + children.extend(self.artists) + children.extend(six.itervalues(self.spines)) + children.append(self.xaxis) + children.append(self.yaxis) + children.append(self.title) + children.append(self._left_title) + children.append(self._right_title) + children.extend(self.tables) + children.extend(self.images) + if self.legend_ is not None: + children.append(self.legend_) + children.append(self.patch) + return children + + def contains(self, mouseevent): + """ + Test whether the mouse event occurred in the axes. + + Returns *True* / *False*, {} + """ + if callable(self._contains): + return self._contains(self, mouseevent) + return self.patch.contains(mouseevent) + + def contains_point(self, point): + """ + Returns *True* if the point (tuple of x,y) is inside the axes + (the area defined by the its patch). A pixel coordinate is + required. + + """ + return self.patch.contains_point(point, radius=1.0) + + def pick(self, *args): + """Trigger pick event + + Call signature:: + + pick(mouseevent) + + each child artist will fire a pick event if mouseevent is over + the artist and the artist has picker set + """ + martist.Artist.pick(self, args[0]) + + def get_default_bbox_extra_artists(self): + return [artist for artist in self.get_children() + if artist.get_visible()] + + def get_tightbbox(self, renderer, call_axes_locator=True): + """ + Return the tight bounding box of the axes. + The dimension of the Bbox in canvas coordinate. + + If *call_axes_locator* is *False*, it does not call the + _axes_locator attribute, which is necessary to get the correct + bounding box. ``call_axes_locator==False`` can be used if the + caller is only intereted in the relative size of the tightbbox + compared to the axes bbox. + """ + + bb = [] + + if not self.get_visible(): + return None + + locator = self.get_axes_locator() + if locator and call_axes_locator: + pos = locator(self, renderer) + self.apply_aspect(pos) + else: + self.apply_aspect() + + bb.append(self.get_window_extent(renderer)) + + if self.title.get_visible(): + bb.append(self.title.get_window_extent(renderer)) + if self._left_title.get_visible(): + bb.append(self._left_title.get_window_extent(renderer)) + if self._right_title.get_visible(): + bb.append(self._right_title.get_window_extent(renderer)) + + bb_xaxis = self.xaxis.get_tightbbox(renderer) + if bb_xaxis: + bb.append(bb_xaxis) + + bb_yaxis = self.yaxis.get_tightbbox(renderer) + if bb_yaxis: + bb.append(bb_yaxis) + + for child in self.get_children(): + if isinstance(child, OffsetBox) and child.get_visible(): + bb.append(child.get_window_extent(renderer)) + elif isinstance(child, Legend) and child.get_visible(): + bb.append(child._legend_box.get_window_extent(renderer)) + + _bbox = mtransforms.Bbox.union( + [b for b in bb if b.width != 0 or b.height != 0]) + + return _bbox + + def _make_twin_axes(self, *kl, **kwargs): + """ + Make a twinx axes of self. This is used for twinx and twiny. + """ + # Typically, SubplotBase._make_twin_axes is called instead of this. + # There is also an override in axes_grid1/axes_divider.py. + if 'sharex' in kwargs and 'sharey' in kwargs: + raise ValueError("Twinned Axes may share only one axis.") + ax2 = self.figure.add_axes(self.get_position(True), *kl, **kwargs) + self.set_adjustable('datalim') + ax2.set_adjustable('datalim') + self._twinned_axes.join(self, ax2) + return ax2 + + def twinx(self): + """ + Create a twin Axes sharing the xaxis + + Create a new Axes instance with an invisible x-axis and an independent + y-axis positioned opposite to the original one (i.e. at right). The + x-axis autoscale setting will be inherited from the original Axes. + To ensure that the tick marks of both y-axes align, see + `~matplotlib.ticker.LinearLocator` + + Returns + ------- + ax_twin : Axes + The newly created Axes instance + + Notes + ----- + For those who are 'picking' artists while using twinx, pick + events are only called for the artists in the top-most axes. + """ + ax2 = self._make_twin_axes(sharex=self) + ax2.yaxis.tick_right() + ax2.yaxis.set_label_position('right') + ax2.yaxis.set_offset_position('right') + ax2.set_autoscalex_on(self.get_autoscalex_on()) + self.yaxis.tick_left() + ax2.xaxis.set_visible(False) + ax2.patch.set_visible(False) + return ax2 + + def twiny(self): + """ + Create a twin Axes sharing the yaxis + + Create a new Axes instance with an invisible y-axis and an independent + x-axis positioned opposite to the original one (i.e. at top). The + y-axis autoscale setting will be inherited from the original Axes. + To ensure that the tick marks of both x-axes align, see + `~matplotlib.ticker.LinearLocator` + + Returns + ------- + ax_twin : Axes + The newly created Axes instance + + Notes + ----- + For those who are 'picking' artists while using twiny, pick + events are only called for the artists in the top-most axes. + """ + + ax2 = self._make_twin_axes(sharey=self) + ax2.xaxis.tick_top() + ax2.xaxis.set_label_position('top') + ax2.set_autoscaley_on(self.get_autoscaley_on()) + self.xaxis.tick_bottom() + ax2.yaxis.set_visible(False) + ax2.patch.set_visible(False) + return ax2 + + def get_shared_x_axes(self): + """Return a reference to the shared axes Grouper object for x axes.""" + return self._shared_x_axes + + def get_shared_y_axes(self): + """Return a reference to the shared axes Grouper object for y axes.""" + return self._shared_y_axes diff --git a/contrib/python/matplotlib/py2/matplotlib/axes/_subplots.py b/contrib/python/matplotlib/py2/matplotlib/axes/_subplots.py new file mode 100644 index 00000000000..4c93ed996a1 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/axes/_subplots.py @@ -0,0 +1,267 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import map + +from matplotlib.gridspec import GridSpec, SubplotSpec +from matplotlib import docstring +import matplotlib.artist as martist +from matplotlib.axes._axes import Axes + +import matplotlib._layoutbox as layoutbox + +import warnings +from matplotlib.cbook import mplDeprecation + + +class SubplotBase(object): + """ + Base class for subplots, which are :class:`Axes` instances with + additional methods to facilitate generating and manipulating a set + of :class:`Axes` within a figure. + """ + + def __init__(self, fig, *args, **kwargs): + """ + *fig* is a :class:`matplotlib.figure.Figure` instance. + + *args* is the tuple (*numRows*, *numCols*, *plotNum*), where + the array of subplots in the figure has dimensions *numRows*, + *numCols*, and where *plotNum* is the number of the subplot + being created. *plotNum* starts at 1 in the upper left + corner and increases to the right. + + If *numRows* <= *numCols* <= *plotNum* < 10, *args* can be the + decimal integer *numRows* * 100 + *numCols* * 10 + *plotNum*. + """ + + self.figure = fig + + if len(args) == 1: + if isinstance(args[0], SubplotSpec): + self._subplotspec = args[0] + else: + try: + s = str(int(args[0])) + rows, cols, num = map(int, s) + except ValueError: + raise ValueError('Single argument to subplot must be ' + 'a 3-digit integer') + self._subplotspec = GridSpec(rows, cols, + figure=self.figure)[num - 1] + # num - 1 for converting from MATLAB to python indexing + elif len(args) == 3: + rows, cols, num = args + rows = int(rows) + cols = int(cols) + if isinstance(num, tuple) and len(num) == 2: + num = [int(n) for n in num] + self._subplotspec = GridSpec( + rows, cols, + figure=self.figure)[(num[0] - 1):num[1]] + else: + if num < 1 or num > rows*cols: + raise ValueError( + ("num must be 1 <= num <= {maxn}, not {num}" + ).format(maxn=rows*cols, num=num)) + self._subplotspec = GridSpec( + rows, cols, figure=self.figure)[int(num) - 1] + # num - 1 for converting from MATLAB to python indexing + else: + raise ValueError('Illegal argument(s) to subplot: %s' % (args,)) + + self.update_params() + + # _axes_class is set in the subplot_class_factory + self._axes_class.__init__(self, fig, self.figbox, **kwargs) + # add a layout box to this, for both the full axis, and the poss + # of the axis. We need both because the axes may become smaller + # due to parasitic axes and hence no longer fill the subplotspec. + if self._subplotspec._layoutbox is None: + self._layoutbox = None + self._poslayoutbox = None + else: + name = self._subplotspec._layoutbox.name + '.ax' + name = name + layoutbox.seq_id() + self._layoutbox = layoutbox.LayoutBox( + parent=self._subplotspec._layoutbox, + name=name, + artist=self) + self._poslayoutbox = layoutbox.LayoutBox( + parent=self._layoutbox, + name=self._layoutbox.name+'.pos', + pos=True, subplot=True, artist=self) + + def __reduce__(self): + # get the first axes class which does not + # inherit from a subplotbase + + def not_subplotbase(c): + return issubclass(c, Axes) and not issubclass(c, SubplotBase) + + axes_class = [c for c in self.__class__.mro() + if not_subplotbase(c)][0] + r = [_PicklableSubplotClassConstructor(), + (axes_class,), + self.__getstate__()] + return tuple(r) + + def get_geometry(self): + """get the subplot geometry, e.g., 2,2,3""" + rows, cols, num1, num2 = self.get_subplotspec().get_geometry() + return rows, cols, num1 + 1 # for compatibility + + # COVERAGE NOTE: Never used internally or from examples + def change_geometry(self, numrows, numcols, num): + """change subplot geometry, e.g., from 1,1,1 to 2,2,3""" + self._subplotspec = GridSpec(numrows, numcols, + figure=self.figure)[num - 1] + self.update_params() + self.set_position(self.figbox) + + def get_subplotspec(self): + """get the SubplotSpec instance associated with the subplot""" + return self._subplotspec + + def set_subplotspec(self, subplotspec): + """set the SubplotSpec instance associated with the subplot""" + self._subplotspec = subplotspec + + def update_params(self): + """update the subplot position from fig.subplotpars""" + + self.figbox, self.rowNum, self.colNum, self.numRows, self.numCols = \ + self.get_subplotspec().get_position(self.figure, + return_all=True) + + def is_first_col(self): + return self.colNum == 0 + + def is_first_row(self): + return self.rowNum == 0 + + def is_last_row(self): + return self.rowNum == self.numRows - 1 + + def is_last_col(self): + return self.colNum == self.numCols - 1 + + # COVERAGE NOTE: Never used internally. + def label_outer(self): + """Only show "outer" labels and tick labels. + + x-labels are only kept for subplots on the last row; y-labels only for + subplots on the first column. + """ + lastrow = self.is_last_row() + firstcol = self.is_first_col() + if not lastrow: + for label in self.get_xticklabels(which="both"): + label.set_visible(False) + self.get_xaxis().get_offset_text().set_visible(False) + self.set_xlabel("") + if not firstcol: + for label in self.get_yticklabels(which="both"): + label.set_visible(False) + self.get_yaxis().get_offset_text().set_visible(False) + self.set_ylabel("") + + def _make_twin_axes(self, *kl, **kwargs): + """ + Make a twinx axes of self. This is used for twinx and twiny. + """ + from matplotlib.projections import process_projection_requirements + if 'sharex' in kwargs and 'sharey' in kwargs: + # The following line is added in v2.2 to avoid breaking Seaborn, + # which currently uses this internal API. + if kwargs["sharex"] is not self and kwargs["sharey"] is not self: + raise ValueError("Twinned Axes may share only one axis.") + kl = (self.get_subplotspec(),) + kl + projection_class, kwargs, key = process_projection_requirements( + self.figure, *kl, **kwargs) + + ax2 = subplot_class_factory(projection_class)(self.figure, + *kl, **kwargs) + self.figure.add_subplot(ax2) + self.set_adjustable('datalim') + ax2.set_adjustable('datalim') + + if self._layoutbox is not None and ax2._layoutbox is not None: + # make the layout boxes be explicitly the same + ax2._layoutbox.constrain_same(self._layoutbox) + ax2._poslayoutbox.constrain_same(self._poslayoutbox) + + self._twinned_axes.join(self, ax2) + return ax2 + +_subplot_classes = {} + + +def subplot_class_factory(axes_class=None): + # This makes a new class that inherits from SubplotBase and the + # given axes_class (which is assumed to be a subclass of Axes). + # This is perhaps a little bit roundabout to make a new class on + # the fly like this, but it means that a new Subplot class does + # not have to be created for every type of Axes. + if axes_class is None: + axes_class = Axes + + new_class = _subplot_classes.get(axes_class) + if new_class is None: + new_class = type(str("%sSubplot") % (axes_class.__name__), + (SubplotBase, axes_class), + {'_axes_class': axes_class}) + _subplot_classes[axes_class] = new_class + + return new_class + +# This is provided for backward compatibility +Subplot = subplot_class_factory() + + +class _PicklableSubplotClassConstructor(object): + """ + This stub class exists to return the appropriate subplot + class when __call__-ed with an axes class. This is purely to + allow Pickling of Axes and Subplots. + """ + def __call__(self, axes_class): + # create a dummy object instance + subplot_instance = _PicklableSubplotClassConstructor() + subplot_class = subplot_class_factory(axes_class) + # update the class to the desired subplot class + subplot_instance.__class__ = subplot_class + return subplot_instance + + +docstring.interpd.update(Axes=martist.kwdoc(Axes)) +docstring.interpd.update(Subplot=martist.kwdoc(Axes)) + +""" +# this is some discarded code I was using to find the minimum positive +# data point for some log scaling fixes. I realized there was a +# cleaner way to do it, but am keeping this around as an example for +# how to get the data out of the axes. Might want to make something +# like this a method one day, or better yet make get_verts an Artist +# method + + minx, maxx = self.get_xlim() + if minx<=0 or maxx<=0: + # find the min pos value in the data + xs = [] + for line in self.lines: + xs.extend(line.get_xdata(orig=False)) + for patch in self.patches: + xs.extend([x for x,y in patch.get_verts()]) + for collection in self.collections: + xs.extend([x for x,y in collection.get_verts()]) + posx = [x for x in xs if x>0] + if len(posx): + + minx = min(posx) + maxx = max(posx) + # warning, probably breaks inverted axis + self.set_xlim((0.1*minx, maxx)) + +""" diff --git a/contrib/python/matplotlib/py2/matplotlib/axis.py b/contrib/python/matplotlib/py2/matplotlib/axis.py new file mode 100644 index 00000000000..48c31ae6c0c --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/axis.py @@ -0,0 +1,2509 @@ +""" +Classes for the ticks and x and y axis +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import logging + +from matplotlib import rcParams +import matplotlib.artist as artist +from matplotlib.artist import allow_rasterization +import matplotlib.cbook as cbook +from matplotlib.cbook import _string_to_bool +import matplotlib.font_manager as font_manager +import matplotlib.lines as mlines +import matplotlib.patches as mpatches +import matplotlib.scale as mscale +import matplotlib.text as mtext +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import matplotlib.units as munits +import numpy as np +import warnings + +_log = logging.getLogger(__name__) + +GRIDLINE_INTERPOLATION_STEPS = 180 + +# This list is being used for compatibility with Axes.grid, which +# allows all Line2D kwargs. +_line_AI = artist.ArtistInspector(mlines.Line2D) +_line_param_names = _line_AI.get_setters() +_line_param_aliases = [list(d.keys())[0] for d in _line_AI.aliasd.values()] +_gridline_param_names = ['grid_' + name + for name in _line_param_names + _line_param_aliases] + + +class Tick(artist.Artist): + """ + Abstract base class for the axis ticks, grid lines and labels + + 1 refers to the bottom of the plot for xticks and the left for yticks + 2 refers to the top of the plot for xticks and the right for yticks + + Attributes + ---------- + tick1line : Line2D + + tick2line : Line2D + + gridline : Line2D + + label1 : Text + + label2 : Text + + gridOn : bool + Determines whether to draw the tickline. + + tick1On : bool + Determines whether to draw the first tickline. + + tick2On : bool + Determines whether to draw the second tickline. + + label1On : bool + Determines whether to draw the first tick label. + + label2On : bool + Determines whether to draw the second tick label. + """ + def __init__(self, axes, loc, label, + size=None, # points + width=None, + color=None, + tickdir=None, + pad=None, + labelsize=None, + labelcolor=None, + zorder=None, + gridOn=None, # defaults to axes.grid depending on + # axes.grid.which + tick1On=True, + tick2On=True, + label1On=True, + label2On=False, + major=True, + labelrotation=0, + grid_color=None, + grid_linestyle=None, + grid_linewidth=None, + grid_alpha=None, + **kw # Other Line2D kwargs applied to gridlines. + ): + """ + bbox is the Bound2D bounding box in display coords of the Axes + loc is the tick location in data coords + size is the tick size in points + """ + artist.Artist.__init__(self) + + if gridOn is None: + if major and (rcParams['axes.grid.which'] in ('both', 'major')): + gridOn = rcParams['axes.grid'] + elif (not major) and (rcParams['axes.grid.which'] + in ('both', 'minor')): + gridOn = rcParams['axes.grid'] + else: + gridOn = False + + self.set_figure(axes.figure) + self.axes = axes + + name = self.__name__.lower() + self._name = name + + self._loc = loc + + if size is None: + if major: + size = rcParams['%s.major.size' % name] + else: + size = rcParams['%s.minor.size' % name] + self._size = size + + if width is None: + if major: + width = rcParams['%s.major.width' % name] + else: + width = rcParams['%s.minor.width' % name] + self._width = width + + if color is None: + color = rcParams['%s.color' % name] + self._color = color + + if pad is None: + if major: + pad = rcParams['%s.major.pad' % name] + else: + pad = rcParams['%s.minor.pad' % name] + self._base_pad = pad + + if labelcolor is None: + labelcolor = rcParams['%s.color' % name] + self._labelcolor = labelcolor + + if labelsize is None: + labelsize = rcParams['%s.labelsize' % name] + self._labelsize = labelsize + + self._set_labelrotation(labelrotation) + + if zorder is None: + if major: + zorder = mlines.Line2D.zorder + 0.01 + else: + zorder = mlines.Line2D.zorder + self._zorder = zorder + + self._grid_color = (rcParams['grid.color'] + if grid_color is None else grid_color) + self._grid_linestyle = (rcParams['grid.linestyle'] + if grid_linestyle is None else grid_linestyle) + self._grid_linewidth = (rcParams['grid.linewidth'] + if grid_linewidth is None else grid_linewidth) + self._grid_alpha = (rcParams['grid.alpha'] + if grid_alpha is None else grid_alpha) + + self._grid_kw = {k[5:]: v for k, v in kw.items()} + + self.apply_tickdir(tickdir) + + self.tick1line = self._get_tick1line() + self.tick2line = self._get_tick2line() + self.gridline = self._get_gridline() + + self.label1 = self._get_text1() + self.label = self.label1 # legacy name + self.label2 = self._get_text2() + + self.gridOn = gridOn + self.tick1On = tick1On + self.tick2On = tick2On + self.label1On = label1On + self.label2On = label2On + + self.update_position(loc) + + def _set_labelrotation(self, labelrotation): + if isinstance(labelrotation, six.string_types): + mode = labelrotation + angle = 0 + elif isinstance(labelrotation, (tuple, list)): + mode, angle = labelrotation + else: + mode = 'default' + angle = labelrotation + if mode not in ('auto', 'default'): + raise ValueError("Label rotation mode must be 'default' or " + "'auto', not '{}'.".format(mode)) + self._labelrotation = (mode, angle) + + def apply_tickdir(self, tickdir): + """ + Calculate self._pad and self._tickmarkers + """ + pass + + def get_tickdir(self): + return self._tickdir + + def get_tick_padding(self): + """ + Get the length of the tick outside of the axes. + """ + padding = { + 'in': 0.0, + 'inout': 0.5, + 'out': 1.0 + } + return self._size * padding[self._tickdir] + + def get_children(self): + children = [self.tick1line, self.tick2line, + self.gridline, self.label1, self.label2] + return children + + def set_clip_path(self, clippath, transform=None): + artist.Artist.set_clip_path(self, clippath, transform) + self.gridline.set_clip_path(clippath, transform) + self.stale = True + + set_clip_path.__doc__ = artist.Artist.set_clip_path.__doc__ + + def get_pad_pixels(self): + return self.figure.dpi * self._base_pad / 72.0 + + def contains(self, mouseevent): + """ + Test whether the mouse event occurred in the Tick marks. + + This function always returns false. It is more useful to test if the + axis as a whole contains the mouse rather than the set of tick marks. + """ + if callable(self._contains): + return self._contains(self, mouseevent) + return False, {} + + def set_pad(self, val): + """ + Set the tick label pad in points + + ACCEPTS: float + """ + self._apply_params(pad=val) + self.stale = True + + def get_pad(self): + 'Get the value of the tick label pad in points' + return self._base_pad + + def _get_text1(self): + 'Get the default Text 1 instance' + pass + + def _get_text2(self): + 'Get the default Text 2 instance' + pass + + def _get_tick1line(self): + 'Get the default line2D instance for tick1' + pass + + def _get_tick2line(self): + 'Get the default line2D instance for tick2' + pass + + def _get_gridline(self): + 'Get the default grid Line2d instance for this tick' + pass + + def get_loc(self): + 'Return the tick location (data coords) as a scalar' + return self._loc + + @allow_rasterization + def draw(self, renderer): + if not self.get_visible(): + self.stale = False + return + + renderer.open_group(self.__name__) + if self.gridOn: + self.gridline.draw(renderer) + if self.tick1On: + self.tick1line.draw(renderer) + if self.tick2On: + self.tick2line.draw(renderer) + + if self.label1On: + self.label1.draw(renderer) + if self.label2On: + self.label2.draw(renderer) + renderer.close_group(self.__name__) + + self.stale = False + + def set_label1(self, s): + """ + Set the text of ticklabel + + ACCEPTS: str + """ + self.label1.set_text(s) + self.stale = True + + set_label = set_label1 + + def set_label2(self, s): + """ + Set the text of ticklabel2 + + ACCEPTS: str + """ + self.label2.set_text(s) + self.stale = True + + def _set_artist_props(self, a): + a.set_figure(self.figure) + + def get_view_interval(self): + 'return the view Interval instance for the axis this tick is ticking' + raise NotImplementedError('Derived must override') + + def _apply_params(self, **kw): + switchkw = ['gridOn', 'tick1On', 'tick2On', 'label1On', 'label2On'] + switches = [k for k in kw if k in switchkw] + for k in switches: + setattr(self, k, kw.pop(k)) + newmarker = [k for k in kw if k in ['size', 'width', 'pad', 'tickdir']] + if newmarker: + self._size = kw.pop('size', self._size) + # Width could be handled outside this block, but it is + # convenient to leave it here. + self._width = kw.pop('width', self._width) + self._base_pad = kw.pop('pad', self._base_pad) + # apply_tickdir uses _size and _base_pad to make _pad, + # and also makes _tickmarkers. + self.apply_tickdir(kw.pop('tickdir', self._tickdir)) + self.tick1line.set_marker(self._tickmarkers[0]) + self.tick2line.set_marker(self._tickmarkers[1]) + for line in (self.tick1line, self.tick2line): + line.set_markersize(self._size) + line.set_markeredgewidth(self._width) + # _get_text1_transform uses _pad from apply_tickdir. + trans = self._get_text1_transform()[0] + self.label1.set_transform(trans) + trans = self._get_text2_transform()[0] + self.label2.set_transform(trans) + tick_kw = {k: v for k, v in six.iteritems(kw) + if k in ['color', 'zorder']} + if tick_kw: + self.tick1line.set(**tick_kw) + self.tick2line.set(**tick_kw) + for k, v in six.iteritems(tick_kw): + setattr(self, '_' + k, v) + + if 'labelrotation' in kw: + self._set_labelrotation(kw.pop('labelrotation')) + self.label1.set(rotation=self._labelrotation[1]) + self.label2.set(rotation=self._labelrotation[1]) + + label_list = [k for k in six.iteritems(kw) + if k[0] in ['labelsize', 'labelcolor']] + if label_list: + label_kw = {k[5:]: v for k, v in label_list} + self.label1.set(**label_kw) + self.label2.set(**label_kw) + for k, v in six.iteritems(label_kw): + # for labelsize the text objects covert str ('small') + # -> points. grab the integer from the `Text` object + # instead of saving the string representation + v = getattr(self.label1, 'get_' + k)() + setattr(self, '_label' + k, v) + + grid_list = [k for k in six.iteritems(kw) + if k[0] in _gridline_param_names] + if grid_list: + grid_kw = {k[5:]: v for k, v in grid_list} + self.gridline.set(**grid_kw) + for k, v in six.iteritems(grid_kw): + setattr(self, '_grid_' + k, v) + + def update_position(self, loc): + 'Set the location of tick in data coords with scalar *loc*' + raise NotImplementedError('Derived must override') + + def _get_text1_transform(self): + raise NotImplementedError('Derived must override') + + def _get_text2_transform(self): + raise NotImplementedError('Derived must override') + + +class XTick(Tick): + """ + Contains all the Artists needed to make an x tick - the tick line, + the label text and the grid line + """ + __name__ = 'xtick' + + def _get_text1_transform(self): + return self.axes.get_xaxis_text1_transform(self._pad) + + def _get_text2_transform(self): + return self.axes.get_xaxis_text2_transform(self._pad) + + def apply_tickdir(self, tickdir): + if tickdir is None: + tickdir = rcParams['%s.direction' % self._name] + self._tickdir = tickdir + + if self._tickdir == 'in': + self._tickmarkers = (mlines.TICKUP, mlines.TICKDOWN) + elif self._tickdir == 'inout': + self._tickmarkers = ('|', '|') + else: + self._tickmarkers = (mlines.TICKDOWN, mlines.TICKUP) + self._pad = self._base_pad + self.get_tick_padding() + self.stale = True + + def _get_text1(self): + 'Get the default Text instance' + # the y loc is 3 points below the min of y axis + # get the affine as an a,b,c,d,tx,ty list + # x in data coords, y in axes coords + trans, vert, horiz = self._get_text1_transform() + t = mtext.Text( + x=0, y=0, + fontproperties=font_manager.FontProperties(size=self._labelsize), + color=self._labelcolor, + verticalalignment=vert, + horizontalalignment=horiz, + ) + t.set_transform(trans) + self._set_artist_props(t) + return t + + def _get_text2(self): + + 'Get the default Text 2 instance' + # x in data coords, y in axes coords + trans, vert, horiz = self._get_text2_transform() + t = mtext.Text( + x=0, y=1, + fontproperties=font_manager.FontProperties(size=self._labelsize), + color=self._labelcolor, + verticalalignment=vert, + horizontalalignment=horiz, + ) + t.set_transform(trans) + self._set_artist_props(t) + return t + + def _get_tick1line(self): + 'Get the default line2D instance' + # x in data coords, y in axes coords + l = mlines.Line2D(xdata=(0,), ydata=(0,), color=self._color, + linestyle='None', marker=self._tickmarkers[0], + markersize=self._size, + markeredgewidth=self._width, zorder=self._zorder) + l.set_transform(self.axes.get_xaxis_transform(which='tick1')) + self._set_artist_props(l) + return l + + def _get_tick2line(self): + 'Get the default line2D instance' + # x in data coords, y in axes coords + l = mlines.Line2D(xdata=(0,), ydata=(1,), + color=self._color, + linestyle='None', + marker=self._tickmarkers[1], + markersize=self._size, + markeredgewidth=self._width, + zorder=self._zorder) + + l.set_transform(self.axes.get_xaxis_transform(which='tick2')) + self._set_artist_props(l) + return l + + def _get_gridline(self): + 'Get the default line2D instance' + # x in data coords, y in axes coords + l = mlines.Line2D(xdata=(0.0, 0.0), ydata=(0, 1.0), + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, + markersize=0, + **self._grid_kw) + l.set_transform(self.axes.get_xaxis_transform(which='grid')) + l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS + self._set_artist_props(l) + + return l + + def update_position(self, loc): + 'Set the location of tick in data coords with scalar *loc*' + if self.tick1On: + self.tick1line.set_xdata((loc,)) + if self.tick2On: + self.tick2line.set_xdata((loc,)) + if self.gridOn: + self.gridline.set_xdata((loc,)) + if self.label1On: + self.label1.set_x(loc) + if self.label2On: + self.label2.set_x(loc) + + self._loc = loc + self.stale = True + + def get_view_interval(self): + 'return the Interval instance for this axis view limits' + return self.axes.viewLim.intervalx + + +class YTick(Tick): + """ + Contains all the Artists needed to make a Y tick - the tick line, + the label text and the grid line + """ + __name__ = 'ytick' + + def _get_text1_transform(self): + return self.axes.get_yaxis_text1_transform(self._pad) + + def _get_text2_transform(self): + return self.axes.get_yaxis_text2_transform(self._pad) + + def apply_tickdir(self, tickdir): + if tickdir is None: + tickdir = rcParams['%s.direction' % self._name] + self._tickdir = tickdir + + if self._tickdir == 'in': + self._tickmarkers = (mlines.TICKRIGHT, mlines.TICKLEFT) + elif self._tickdir == 'inout': + self._tickmarkers = ('_', '_') + else: + self._tickmarkers = (mlines.TICKLEFT, mlines.TICKRIGHT) + self._pad = self._base_pad + self.get_tick_padding() + self.stale = True + + # how far from the y axis line the right of the ticklabel are + def _get_text1(self): + 'Get the default Text instance' + # x in axes coords, y in data coords + trans, vert, horiz = self._get_text1_transform() + t = mtext.Text( + x=0, y=0, + fontproperties=font_manager.FontProperties(size=self._labelsize), + color=self._labelcolor, + verticalalignment=vert, + horizontalalignment=horiz, + ) + t.set_transform(trans) + self._set_artist_props(t) + return t + + def _get_text2(self): + 'Get the default Text instance' + # x in axes coords, y in data coords + trans, vert, horiz = self._get_text2_transform() + t = mtext.Text( + x=1, y=0, + fontproperties=font_manager.FontProperties(size=self._labelsize), + color=self._labelcolor, + verticalalignment=vert, + horizontalalignment=horiz, + ) + t.set_transform(trans) + self._set_artist_props(t) + return t + + def _get_tick1line(self): + 'Get the default line2D instance' + # x in axes coords, y in data coords + + l = mlines.Line2D((0,), (0,), + color=self._color, + marker=self._tickmarkers[0], + linestyle='None', + markersize=self._size, + markeredgewidth=self._width, + zorder=self._zorder) + l.set_transform(self.axes.get_yaxis_transform(which='tick1')) + self._set_artist_props(l) + return l + + def _get_tick2line(self): + 'Get the default line2D instance' + # x in axes coords, y in data coords + l = mlines.Line2D((1,), (0,), + color=self._color, + marker=self._tickmarkers[1], + linestyle='None', + markersize=self._size, + markeredgewidth=self._width, + zorder=self._zorder) + l.set_transform(self.axes.get_yaxis_transform(which='tick2')) + self._set_artist_props(l) + return l + + def _get_gridline(self): + 'Get the default line2D instance' + # x in axes coords, y in data coords + l = mlines.Line2D(xdata=(0, 1), ydata=(0, 0), + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, + markersize=0, + **self._grid_kw) + l.set_transform(self.axes.get_yaxis_transform(which='grid')) + l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS + self._set_artist_props(l) + return l + + def update_position(self, loc): + 'Set the location of tick in data coords with scalar *loc*' + if self.tick1On: + self.tick1line.set_ydata((loc,)) + if self.tick2On: + self.tick2line.set_ydata((loc,)) + if self.gridOn: + self.gridline.set_ydata((loc,)) + if self.label1On: + self.label1.set_y(loc) + if self.label2On: + self.label2.set_y(loc) + + self._loc = loc + self.stale = True + + def get_view_interval(self): + 'return the Interval instance for this axis view limits' + return self.axes.viewLim.intervaly + + +class Ticker(object): + locator = None + formatter = None + + +class _LazyTickList(object): + """ + A descriptor for lazy instantiation of tick lists. + + See comment above definition of the ``majorTicks`` and ``minorTicks`` + attributes. + """ + + def __init__(self, major): + self._major = major + + def __get__(self, instance, cls): + if instance is None: + return self + else: + # instance._get_tick() can itself try to access the majorTicks + # attribute (e.g. in certain projection classes which override + # e.g. get_xaxis_text1_transform). In order to avoid infinite + # recursion, first set the majorTicks on the instance to an empty + # list, then create the tick and append it. + if self._major: + instance.majorTicks = [] + tick = instance._get_tick(major=True) + instance.majorTicks.append(tick) + return instance.majorTicks + else: + instance.minorTicks = [] + tick = instance._get_tick(major=False) + instance.minorTicks.append(tick) + return instance.minorTicks + + +class Axis(artist.Artist): + """ + Public attributes + + * :attr:`axes.transData` - transform data coords to display coords + * :attr:`axes.transAxes` - transform axis coords to display coords + * :attr:`labelpad` - number of points between the axis and its label + """ + OFFSETTEXTPAD = 3 + + def __str__(self): + return self.__class__.__name__ \ + + "(%f,%f)" % tuple(self.axes.transAxes.transform_point((0, 0))) + + def __init__(self, axes, pickradius=15): + """ + Init the axis with the parent Axes instance + """ + artist.Artist.__init__(self) + self.set_figure(axes.figure) + + self.isDefault_label = True + + self.axes = axes + self.major = Ticker() + self.minor = Ticker() + self.callbacks = cbook.CallbackRegistry() + + self._autolabelpos = True + self._smart_bounds = False + + self.label = self._get_label() + self.labelpad = rcParams['axes.labelpad'] + self.offsetText = self._get_offset_text() + + self.pickradius = pickradius + + # Initialize here for testing; later add API + self._major_tick_kw = dict() + self._minor_tick_kw = dict() + + self.cla() + self._set_scale('linear') + + # During initialization, Axis objects often create ticks that are later + # unused; this turns out to be a very slow step. Instead, use a custom + # descriptor to make the tick lists lazy and instantiate them as needed. + majorTicks = _LazyTickList(major=True) + minorTicks = _LazyTickList(major=False) + + def set_label_coords(self, x, y, transform=None): + """ + Set the coordinates of the label. By default, the x + coordinate of the y label is determined by the tick label + bounding boxes, but this can lead to poor alignment of + multiple ylabels if there are multiple axes. Ditto for the y + coordinate of the x label. + + You can also specify the coordinate system of the label with + the transform. If None, the default coordinate system will be + the axes coordinate system (0,0) is (left,bottom), (0.5, 0.5) + is middle, etc + + """ + + self._autolabelpos = False + if transform is None: + transform = self.axes.transAxes + + self.label.set_transform(transform) + self.label.set_position((x, y)) + self.stale = True + + def get_transform(self): + return self._scale.get_transform() + + def get_scale(self): + return self._scale.name + + def _set_scale(self, value, **kwargs): + self._scale = mscale.scale_factory(value, self, **kwargs) + self._scale.set_default_locators_and_formatters(self) + + self.isDefault_majloc = True + self.isDefault_minloc = True + self.isDefault_majfmt = True + self.isDefault_minfmt = True + + def limit_range_for_scale(self, vmin, vmax): + return self._scale.limit_range_for_scale(vmin, vmax, self.get_minpos()) + + @property + @cbook.deprecated("2.2.0") + def unit_data(self): + return self.units + + @unit_data.setter + @cbook.deprecated("2.2.0") + def unit_data(self, unit_data): + self.set_units(unit_data) + + def get_children(self): + children = [self.label, self.offsetText] + majorticks = self.get_major_ticks() + minorticks = self.get_minor_ticks() + + children.extend(majorticks) + children.extend(minorticks) + return children + + def cla(self): + 'clear the current axis' + + self.label.set_text('') # self.set_label_text would change isDefault_ + + self._set_scale('linear') + + # Clear the callback registry for this axis, or it may "leak" + self.callbacks = cbook.CallbackRegistry() + + # whether the grids are on + self._gridOnMajor = (rcParams['axes.grid'] and + rcParams['axes.grid.which'] in ('both', 'major')) + self._gridOnMinor = (rcParams['axes.grid'] and + rcParams['axes.grid.which'] in ('both', 'minor')) + + self.reset_ticks() + + self.converter = None + self.units = None + self.set_units(None) + self.stale = True + + def reset_ticks(self): + """ + Re-initialize the major and minor Tick lists. + + Each list starts with a single fresh Tick. + """ + # Restore the lazy tick lists. + try: + del self.majorTicks + except AttributeError: + pass + try: + del self.minorTicks + except AttributeError: + pass + try: + self.set_clip_path(self.axes.patch) + except AttributeError: + pass + + def set_tick_params(self, which='major', reset=False, **kw): + """ + Set appearance parameters for ticks, ticklabels, and gridlines. + + For documentation of keyword arguments, see + :meth:`matplotlib.axes.Axes.tick_params`. + """ + dicts = [] + if which == 'major' or which == 'both': + dicts.append(self._major_tick_kw) + if which == 'minor' or which == 'both': + dicts.append(self._minor_tick_kw) + kwtrans = self._translate_tick_kw(kw, to_init_kw=True) + for d in dicts: + if reset: + d.clear() + d.update(kwtrans) + + if reset: + self.reset_ticks() + else: + if which == 'major' or which == 'both': + for tick in self.majorTicks: + tick._apply_params(**self._major_tick_kw) + if which == 'minor' or which == 'both': + for tick in self.minorTicks: + tick._apply_params(**self._minor_tick_kw) + if 'labelcolor' in kwtrans: + self.offsetText.set_color(kwtrans['labelcolor']) + self.stale = True + + @staticmethod + def _translate_tick_kw(kw, to_init_kw=True): + # The following lists may be moved to a more + # accessible location. + kwkeys0 = ['size', 'width', 'color', 'tickdir', 'pad', + 'labelsize', 'labelcolor', 'zorder', 'gridOn', + 'tick1On', 'tick2On', 'label1On', 'label2On'] + kwkeys1 = ['length', 'direction', 'left', 'bottom', 'right', 'top', + 'labelleft', 'labelbottom', 'labelright', 'labeltop', + 'labelrotation'] + kwkeys2 = _gridline_param_names + kwkeys = kwkeys0 + kwkeys1 + kwkeys2 + kwtrans = dict() + if to_init_kw: + if 'length' in kw: + kwtrans['size'] = kw.pop('length') + if 'direction' in kw: + kwtrans['tickdir'] = kw.pop('direction') + if 'rotation' in kw: + kwtrans['labelrotation'] = kw.pop('rotation') + if 'left' in kw: + kwtrans['tick1On'] = _string_to_bool(kw.pop('left')) + if 'bottom' in kw: + kwtrans['tick1On'] = _string_to_bool(kw.pop('bottom')) + if 'right' in kw: + kwtrans['tick2On'] = _string_to_bool(kw.pop('right')) + if 'top' in kw: + kwtrans['tick2On'] = _string_to_bool(kw.pop('top')) + + if 'labelleft' in kw: + kwtrans['label1On'] = _string_to_bool(kw.pop('labelleft')) + if 'labelbottom' in kw: + kwtrans['label1On'] = _string_to_bool(kw.pop('labelbottom')) + if 'labelright' in kw: + kwtrans['label2On'] = _string_to_bool(kw.pop('labelright')) + if 'labeltop' in kw: + kwtrans['label2On'] = _string_to_bool(kw.pop('labeltop')) + if 'colors' in kw: + c = kw.pop('colors') + kwtrans['color'] = c + kwtrans['labelcolor'] = c + # Maybe move the checking up to the caller of this method. + for key in kw: + if key not in kwkeys: + raise ValueError( + "keyword %s is not recognized; valid keywords are %s" + % (key, kwkeys)) + kwtrans.update(kw) + else: + raise NotImplementedError("Inverse translation is deferred") + return kwtrans + + def set_clip_path(self, clippath, transform=None): + artist.Artist.set_clip_path(self, clippath, transform) + for child in self.majorTicks + self.minorTicks: + child.set_clip_path(clippath, transform) + self.stale = True + + def get_view_interval(self): + 'return the Interval instance for this axis view limits' + raise NotImplementedError('Derived must override') + + def set_view_interval(self, vmin, vmax, ignore=False): + raise NotImplementedError('Derived must override') + + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + raise NotImplementedError('Derived must override') + + def set_data_interval(self): + '''set the axis data limits''' + raise NotImplementedError('Derived must override') + + def set_default_intervals(self): + '''set the default limits for the axis data and view interval if they + are not mutated''' + + # this is mainly in support of custom object plotting. For + # example, if someone passes in a datetime object, we do not + # know automagically how to set the default min/max of the + # data and view limits. The unit conversion AxisInfo + # interface provides a hook for custom types to register + # default limits through the AxisInfo.default_limits + # attribute, and the derived code below will check for that + # and use it if is available (else just use 0..1) + pass + + def _set_artist_props(self, a): + if a is None: + return + a.set_figure(self.figure) + + def iter_ticks(self): + """ + Iterate through all of the major and minor ticks. + """ + majorLocs = self.major.locator() + majorTicks = self.get_major_ticks(len(majorLocs)) + self.major.formatter.set_locs(majorLocs) + majorLabels = [self.major.formatter(val, i) + for i, val in enumerate(majorLocs)] + + minorLocs = self.minor.locator() + minorTicks = self.get_minor_ticks(len(minorLocs)) + self.minor.formatter.set_locs(minorLocs) + minorLabels = [self.minor.formatter(val, i) + for i, val in enumerate(minorLocs)] + + major_minor = [ + (majorTicks, majorLocs, majorLabels), + (minorTicks, minorLocs, minorLabels)] + + for group in major_minor: + for tick in zip(*group): + yield tick + + def get_ticklabel_extents(self, renderer): + """ + Get the extents of the tick labels on either side + of the axes. + """ + + ticks_to_draw = self._update_ticks(renderer) + ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw, + renderer) + + if len(ticklabelBoxes): + bbox = mtransforms.Bbox.union(ticklabelBoxes) + else: + bbox = mtransforms.Bbox.from_extents(0, 0, 0, 0) + if len(ticklabelBoxes2): + bbox2 = mtransforms.Bbox.union(ticklabelBoxes2) + else: + bbox2 = mtransforms.Bbox.from_extents(0, 0, 0, 0) + return bbox, bbox2 + + def set_smart_bounds(self, value): + """set the axis to have smart bounds""" + self._smart_bounds = value + self.stale = True + + def get_smart_bounds(self): + """get whether the axis has smart bounds""" + return self._smart_bounds + + def _update_ticks(self, renderer): + """ + Update ticks (position and labels) using the current data + interval of the axes. Returns a list of ticks that will be + drawn. + """ + + interval = self.get_view_interval() + tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator + if self._smart_bounds and tick_tups: + # handle inverted limits + view_low, view_high = sorted(interval) + data_low, data_high = sorted(self.get_data_interval()) + locs = np.sort([ti[1] for ti in tick_tups]) + if data_low <= view_low: + # data extends beyond view, take view as limit + ilow = view_low + else: + # data stops within view, take best tick + good_locs = locs[locs <= data_low] + if len(good_locs): + # last tick prior or equal to first data point + ilow = good_locs[-1] + else: + # No ticks (why not?), take first tick + ilow = locs[0] + if data_high >= view_high: + # data extends beyond view, take view as limit + ihigh = view_high + else: + # data stops within view, take best tick + good_locs = locs[locs >= data_high] + if len(good_locs): + # first tick after or equal to last data point + ihigh = good_locs[0] + else: + # No ticks (why not?), take last tick + ihigh = locs[-1] + tick_tups = [ti for ti in tick_tups if ilow <= ti[1] <= ihigh] + + # so that we don't lose ticks on the end, expand out the interval ever + # so slightly. The "ever so slightly" is defined to be the width of a + # half of a pixel. We don't want to draw a tick that even one pixel + # outside of the defined axis interval. + if interval[0] <= interval[1]: + interval_expanded = interval + else: + interval_expanded = interval[1], interval[0] + + if hasattr(self, '_get_pixel_distance_along_axis'): + # normally, one does not want to catch all exceptions that + # could possibly happen, but it is not clear exactly what + # exceptions might arise from a user's projection (their + # rendition of the Axis object). So, we catch all, with + # the idea that one would rather potentially lose a tick + # from one side of the axis or another, rather than see a + # stack trace. + # We also catch users warnings here. These are the result of + # invalid numpy calculations that may be the result of out of + # bounds on axis with finite allowed intervals such as geo + # projections i.e. Mollweide. + with np.errstate(invalid='ignore'): + try: + ds1 = self._get_pixel_distance_along_axis( + interval_expanded[0], -0.5) + except: + warnings.warn("Unable to find pixel distance along axis " + "for interval padding of ticks; assuming no " + "interval padding needed.") + ds1 = 0.0 + if np.isnan(ds1): + ds1 = 0.0 + try: + ds2 = self._get_pixel_distance_along_axis( + interval_expanded[1], +0.5) + except: + warnings.warn("Unable to find pixel distance along axis " + "for interval padding of ticks; assuming no " + "interval padding needed.") + ds2 = 0.0 + if np.isnan(ds2): + ds2 = 0.0 + interval_expanded = (interval_expanded[0] - ds1, + interval_expanded[1] + ds2) + + ticks_to_draw = [] + for tick, loc, label in tick_tups: + if tick is None: + continue + # NB: always update labels and position to avoid issues like #9397 + tick.update_position(loc) + tick.set_label1(label) + tick.set_label2(label) + if not mtransforms.interval_contains(interval_expanded, loc): + continue + ticks_to_draw.append(tick) + + return ticks_to_draw + + def _get_tick_bboxes(self, ticks, renderer): + """ + Given the list of ticks, return two lists of bboxes. One for + tick lable1's and another for tick label2's. + """ + + ticklabelBoxes = [] + ticklabelBoxes2 = [] + + for tick in ticks: + if tick.label1On and tick.label1.get_visible(): + extent = tick.label1.get_window_extent(renderer) + ticklabelBoxes.append(extent) + if tick.label2On and tick.label2.get_visible(): + extent = tick.label2.get_window_extent(renderer) + ticklabelBoxes2.append(extent) + return ticklabelBoxes, ticklabelBoxes2 + + def get_tightbbox(self, renderer): + """ + Return a bounding box that encloses the axis. It only accounts + tick labels, axis label, and offsetText. + """ + if not self.get_visible(): + return + + ticks_to_draw = self._update_ticks(renderer) + + self._update_label_position(renderer) + + # go back to just this axis's tick labels + ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes( + ticks_to_draw, renderer) + + self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) + self.offsetText.set_text(self.major.formatter.get_offset()) + + bb = [] + + for a in [self.label, self.offsetText]: + if a.get_visible(): + bb.append(a.get_window_extent(renderer)) + + bb.extend(ticklabelBoxes) + bb.extend(ticklabelBoxes2) + + bb = [b for b in bb if b.width != 0 or b.height != 0] + if bb: + _bbox = mtransforms.Bbox.union(bb) + return _bbox + else: + return None + + def get_tick_padding(self): + values = [] + if len(self.majorTicks): + values.append(self.majorTicks[0].get_tick_padding()) + if len(self.minorTicks): + values.append(self.minorTicks[0].get_tick_padding()) + if len(values): + return max(values) + return 0.0 + + @allow_rasterization + def draw(self, renderer, *args, **kwargs): + 'Draw the axis lines, grid lines, tick lines and labels' + + if not self.get_visible(): + return + renderer.open_group(__name__) + + ticks_to_draw = self._update_ticks(renderer) + ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw, + renderer) + + for tick in ticks_to_draw: + tick.draw(renderer) + + # scale up the axis label box to also find the neighbors, not + # just the tick labels that actually overlap note we need a + # *copy* of the axis label box because we don't wan't to scale + # the actual bbox + + self._update_label_position(renderer) + + self.label.draw(renderer) + + self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2) + self.offsetText.set_text(self.major.formatter.get_offset()) + self.offsetText.draw(renderer) + + if 0: # draw the bounding boxes around the text for debug + for tick in self.majorTicks: + label = tick.label1 + mpatches.bbox_artist(label, renderer) + mpatches.bbox_artist(self.label, renderer) + + renderer.close_group(__name__) + self.stale = False + + def _get_label(self): + raise NotImplementedError('Derived must override') + + def _get_offset_text(self): + raise NotImplementedError('Derived must override') + + def get_gridlines(self): + 'Return the grid lines as a list of Line2D instance' + ticks = self.get_major_ticks() + return cbook.silent_list('Line2D gridline', + [tick.gridline for tick in ticks]) + + def get_label(self): + 'Return the axis label as a Text instance' + return self.label + + def get_offset_text(self): + 'Return the axis offsetText as a Text instance' + return self.offsetText + + def get_pickradius(self): + 'Return the depth of the axis used by the picker' + return self.pickradius + + def get_majorticklabels(self): + 'Return a list of Text instances for the major ticklabels' + ticks = self.get_major_ticks() + labels1 = [tick.label1 for tick in ticks if tick.label1On] + labels2 = [tick.label2 for tick in ticks if tick.label2On] + return cbook.silent_list('Text major ticklabel', labels1 + labels2) + + def get_minorticklabels(self): + 'Return a list of Text instances for the minor ticklabels' + ticks = self.get_minor_ticks() + labels1 = [tick.label1 for tick in ticks if tick.label1On] + labels2 = [tick.label2 for tick in ticks if tick.label2On] + return cbook.silent_list('Text minor ticklabel', labels1 + labels2) + + def get_ticklabels(self, minor=False, which=None): + """ + Get the tick labels as a list of :class:`~matplotlib.text.Text` + instances. + + Parameters + ---------- + minor : bool + If True return the minor ticklabels, + else return the major ticklabels + + which : None, ('minor', 'major', 'both') + Overrides `minor`. + + Selects which ticklabels to return + + Returns + ------- + ret : list + List of :class:`~matplotlib.text.Text` instances. + """ + + if which is not None: + if which == 'minor': + return self.get_minorticklabels() + elif which == 'major': + return self.get_majorticklabels() + elif which == 'both': + return self.get_majorticklabels() + self.get_minorticklabels() + else: + raise ValueError("`which` must be one of ('minor', 'major', " + "'both') not " + str(which)) + if minor: + return self.get_minorticklabels() + return self.get_majorticklabels() + + def get_majorticklines(self): + 'Return the major tick lines as a list of Line2D instances' + lines = [] + ticks = self.get_major_ticks() + for tick in ticks: + lines.append(tick.tick1line) + lines.append(tick.tick2line) + return cbook.silent_list('Line2D ticklines', lines) + + def get_minorticklines(self): + 'Return the minor tick lines as a list of Line2D instances' + lines = [] + ticks = self.get_minor_ticks() + for tick in ticks: + lines.append(tick.tick1line) + lines.append(tick.tick2line) + return cbook.silent_list('Line2D ticklines', lines) + + def get_ticklines(self, minor=False): + 'Return the tick lines as a list of Line2D instances' + if minor: + return self.get_minorticklines() + return self.get_majorticklines() + + def get_majorticklocs(self): + "Get the major tick locations in data coordinates as a numpy array" + return self.major.locator() + + def get_minorticklocs(self): + "Get the minor tick locations in data coordinates as a numpy array" + return self.minor.locator() + + def get_ticklocs(self, minor=False): + "Get the tick locations in data coordinates as a numpy array" + if minor: + return self.minor.locator() + return self.major.locator() + + def get_ticks_direction(self, minor=False): + """ + Get the tick directions as a numpy array + + Parameters + ---------- + minor : boolean + True to return the minor tick directions, + False to return the major tick directions, + Default is False + + Returns + ------- + numpy array of tick directions + """ + if minor: + return np.array( + [tick._tickdir for tick in self.get_minor_ticks()]) + else: + return np.array( + [tick._tickdir for tick in self.get_major_ticks()]) + + def _get_tick(self, major): + 'return the default tick instance' + raise NotImplementedError('derived must override') + + def _copy_tick_props(self, src, dest): + 'Copy the props from src tick to dest tick' + if src is None or dest is None: + return + dest.label1.update_from(src.label1) + dest.label2.update_from(src.label2) + + dest.tick1line.update_from(src.tick1line) + dest.tick2line.update_from(src.tick2line) + dest.gridline.update_from(src.gridline) + + dest.tick1On = src.tick1On + dest.tick2On = src.tick2On + dest.label1On = src.label1On + dest.label2On = src.label2On + + def get_label_text(self): + 'Get the text of the label' + return self.label.get_text() + + def get_major_locator(self): + 'Get the locator of the major ticker' + return self.major.locator + + def get_minor_locator(self): + 'Get the locator of the minor ticker' + return self.minor.locator + + def get_major_formatter(self): + 'Get the formatter of the major ticker' + return self.major.formatter + + def get_minor_formatter(self): + 'Get the formatter of the minor ticker' + return self.minor.formatter + + def get_major_ticks(self, numticks=None): + 'get the tick instances; grow as necessary' + if numticks is None: + numticks = len(self.get_major_locator()()) + + while len(self.majorTicks) < numticks: + # update the new tick label properties from the old + tick = self._get_tick(major=True) + self.majorTicks.append(tick) + if self._gridOnMajor: + tick.gridOn = True + self._copy_tick_props(self.majorTicks[0], tick) + + return self.majorTicks[:numticks] + + def get_minor_ticks(self, numticks=None): + 'get the minor tick instances; grow as necessary' + if numticks is None: + numticks = len(self.get_minor_locator()()) + + while len(self.minorTicks) < numticks: + # update the new tick label properties from the old + tick = self._get_tick(major=False) + self.minorTicks.append(tick) + if self._gridOnMinor: + tick.gridOn = True + self._copy_tick_props(self.minorTicks[0], tick) + + return self.minorTicks[:numticks] + + def grid(self, b=None, which='major', **kwargs): + """ + Set the axis grid on or off; b is a boolean. Use *which* = + 'major' | 'minor' | 'both' to set the grid for major or minor ticks. + + If *b* is *None* and len(kwargs)==0, toggle the grid state. If + *kwargs* are supplied, it is assumed you want the grid on and *b* + will be set to True. + + *kwargs* are used to set the line properties of the grids, e.g., + + xax.grid(color='r', linestyle='-', linewidth=2) + """ + if len(kwargs): + b = True + which = which.lower() + gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()} + if which in ['minor', 'both']: + if b is None: + self._gridOnMinor = not self._gridOnMinor + else: + self._gridOnMinor = b + self.set_tick_params(which='minor', gridOn=self._gridOnMinor, + **gridkw) + if which in ['major', 'both']: + if b is None: + self._gridOnMajor = not self._gridOnMajor + else: + self._gridOnMajor = b + self.set_tick_params(which='major', gridOn=self._gridOnMajor, + **gridkw) + self.stale = True + + def update_units(self, data): + """ + introspect *data* for units converter and update the + axis.converter instance if necessary. Return *True* + if *data* is registered for unit conversion. + """ + + converter = munits.registry.get_converter(data) + if converter is None: + return False + + neednew = self.converter != converter + self.converter = converter + default = self.converter.default_units(data, self) + if default is not None and self.units is None: + self.set_units(default) + + if neednew: + self._update_axisinfo() + self.stale = True + return True + + def _update_axisinfo(self): + """ + check the axis converter for the stored units to see if the + axis info needs to be updated + """ + if self.converter is None: + return + + info = self.converter.axisinfo(self.units, self) + + if info is None: + return + if info.majloc is not None and \ + self.major.locator != info.majloc and self.isDefault_majloc: + self.set_major_locator(info.majloc) + self.isDefault_majloc = True + if info.minloc is not None and \ + self.minor.locator != info.minloc and self.isDefault_minloc: + self.set_minor_locator(info.minloc) + self.isDefault_minloc = True + if info.majfmt is not None and \ + self.major.formatter != info.majfmt and self.isDefault_majfmt: + self.set_major_formatter(info.majfmt) + self.isDefault_majfmt = True + if info.minfmt is not None and \ + self.minor.formatter != info.minfmt and self.isDefault_minfmt: + self.set_minor_formatter(info.minfmt) + self.isDefault_minfmt = True + if info.label is not None and self.isDefault_label: + self.set_label_text(info.label) + self.isDefault_label = True + + self.set_default_intervals() + + def have_units(self): + return self.converter is not None or self.units is not None + + def convert_units(self, x): + # If x is already a number, doesn't need converting + if munits.ConversionInterface.is_numlike(x): + return x + + if self.converter is None: + self.converter = munits.registry.get_converter(x) + + if self.converter is None: + return x + + ret = self.converter.convert(x, self.units, self) + return ret + + def set_units(self, u): + """ + set the units for axis + + ACCEPTS: a units tag + """ + pchanged = False + if u is None: + self.units = None + pchanged = True + else: + if u != self.units: + self.units = u + pchanged = True + if pchanged: + self._update_axisinfo() + self.callbacks.process('units') + self.callbacks.process('units finalize') + self.stale = True + + def get_units(self): + 'return the units for axis' + return self.units + + def set_label_text(self, label, fontdict=None, **kwargs): + """ Sets the text value of the axis label + + ACCEPTS: A string value for the label + """ + self.isDefault_label = False + self.label.set_text(label) + if fontdict is not None: + self.label.update(fontdict) + self.label.update(kwargs) + self.stale = True + return self.label + + def set_major_formatter(self, formatter): + """ + Set the formatter of the major ticker + + ACCEPTS: A :class:`~matplotlib.ticker.Formatter` instance + """ + self.isDefault_majfmt = False + self.major.formatter = formatter + formatter.set_axis(self) + self.stale = True + + def set_minor_formatter(self, formatter): + """ + Set the formatter of the minor ticker + + ACCEPTS: A :class:`~matplotlib.ticker.Formatter` instance + """ + self.isDefault_minfmt = False + self.minor.formatter = formatter + formatter.set_axis(self) + self.stale = True + + def set_major_locator(self, locator): + """ + Set the locator of the major ticker + + ACCEPTS: a :class:`~matplotlib.ticker.Locator` instance + """ + self.isDefault_majloc = False + self.major.locator = locator + locator.set_axis(self) + self.stale = True + + def set_minor_locator(self, locator): + """ + Set the locator of the minor ticker + + ACCEPTS: a :class:`~matplotlib.ticker.Locator` instance + """ + self.isDefault_minloc = False + self.minor.locator = locator + locator.set_axis(self) + self.stale = True + + def set_pickradius(self, pickradius): + """ + Set the depth of the axis used by the picker + + ACCEPTS: a distance in points + """ + self.pickradius = pickradius + + def set_ticklabels(self, ticklabels, *args, **kwargs): + """ + Set the text values of the tick labels. Return a list of Text + instances. Use *kwarg* *minor=True* to select minor ticks. + All other kwargs are used to update the text object properties. + As for get_ticklabels, label1 (left or bottom) is + affected for a given tick only if its label1On attribute + is True, and similarly for label2. The list of returned + label text objects consists of all such label1 objects followed + by all such label2 objects. + + The input *ticklabels* is assumed to match the set of + tick locations, regardless of the state of label1On and + label2On. + + ACCEPTS: sequence of strings or Text objects + """ + get_labels = [] + for t in ticklabels: + # try calling get_text() to check whether it is Text object + # if it is Text, get label content + try: + get_labels.append(t.get_text()) + # otherwise add the label to the list directly + except AttributeError: + get_labels.append(t) + # replace the ticklabels list with the processed one + ticklabels = get_labels + + minor = kwargs.pop('minor', False) + if minor: + self.set_minor_formatter(mticker.FixedFormatter(ticklabels)) + ticks = self.get_minor_ticks() + else: + self.set_major_formatter(mticker.FixedFormatter(ticklabels)) + ticks = self.get_major_ticks() + ret = [] + for tick_label, tick in zip(ticklabels, ticks): + # deal with label1 + tick.label1.set_text(tick_label) + tick.label1.update(kwargs) + # deal with label2 + tick.label2.set_text(tick_label) + tick.label2.update(kwargs) + # only return visible tick labels + if tick.label1On: + ret.append(tick.label1) + if tick.label2On: + ret.append(tick.label2) + + self.stale = True + return ret + + def set_ticks(self, ticks, minor=False): + """ + Set the locations of the tick marks from sequence ticks + + ACCEPTS: sequence of floats + """ + # XXX if the user changes units, the information will be lost here + ticks = self.convert_units(ticks) + if len(ticks) > 1: + xleft, xright = self.get_view_interval() + if xright > xleft: + self.set_view_interval(min(ticks), max(ticks)) + else: + self.set_view_interval(max(ticks), min(ticks)) + if minor: + self.set_minor_locator(mticker.FixedLocator(ticks)) + return self.get_minor_ticks(len(ticks)) + else: + self.set_major_locator(mticker.FixedLocator(ticks)) + return self.get_major_ticks(len(ticks)) + + def _get_tick_boxes_siblings(self, xdir, renderer): + """ + Get the bounding boxes for this `.axis` and its siblings + as set by `.Figure.align_xlabels` or `.Figure.align_ylablels`. + + By default it just gets bboxes for self. + """ + raise NotImplementedError('Derived must override') + + def _update_label_position(self, renderer): + """ + Update the label position based on the bounding box enclosing + all the ticklabels and axis spine + """ + raise NotImplementedError('Derived must override') + + def _update_offset_text_position(self, bboxes, bboxes2): + """ + Update the label position based on the sequence of bounding + boxes of all the ticklabels + """ + raise NotImplementedError('Derived must override') + + def pan(self, numsteps): + 'Pan *numsteps* (can be positive or negative)' + self.major.locator.pan(numsteps) + + def zoom(self, direction): + "Zoom in/out on axis; if *direction* is >0 zoom in, else zoom out" + self.major.locator.zoom(direction) + + def axis_date(self, tz=None): + """ + Sets up x-axis ticks and labels that treat the x data as dates. + *tz* is a :class:`tzinfo` instance or a timezone string. + This timezone is used to create date labels. + """ + # By providing a sample datetime instance with the desired + # timezone, the registered converter can be selected, + # and the "units" attribute, which is the timezone, can + # be set. + import datetime + if isinstance(tz, six.string_types): + import pytz + tz = pytz.timezone(tz) + self.update_units(datetime.datetime(2009, 1, 1, 0, 0, 0, 0, tz)) + + def get_tick_space(self): + """ + Return the estimated number of ticks that can fit on the axis. + """ + # Must be overridden in the subclass + raise NotImplementedError() + + def get_label_position(self): + """ + Return the label position (top or bottom) + """ + return self.label_position + + def set_label_position(self, position): + """ + Set the label position (top or bottom) + + ACCEPTS: [ 'top' | 'bottom' ] + """ + raise NotImplementedError() + + def get_minpos(self): + raise NotImplementedError() + + +class XAxis(Axis): + __name__ = 'xaxis' + axis_name = 'x' + + def contains(self, mouseevent): + """Test whether the mouse event occurred in the x axis. + """ + if callable(self._contains): + return self._contains(self, mouseevent) + + x, y = mouseevent.x, mouseevent.y + try: + trans = self.axes.transAxes.inverted() + xaxes, yaxes = trans.transform_point((x, y)) + except ValueError: + return False, {} + l, b = self.axes.transAxes.transform_point((0, 0)) + r, t = self.axes.transAxes.transform_point((1, 1)) + inaxis = xaxes >= 0 and xaxes <= 1 and ( + (y < b and y > b - self.pickradius) or + (y > t and y < t + self.pickradius)) + return inaxis, {} + + def _get_tick(self, major): + if major: + tick_kw = self._major_tick_kw + else: + tick_kw = self._minor_tick_kw + return XTick(self.axes, 0, '', major=major, **tick_kw) + + def _get_label(self): + # x in axes coords, y in display coords (to be updated at draw + # time by _update_label_positions) + label = mtext.Text(x=0.5, y=0, + fontproperties=font_manager.FontProperties( + size=rcParams['axes.labelsize'], + weight=rcParams['axes.labelweight']), + color=rcParams['axes.labelcolor'], + verticalalignment='top', + horizontalalignment='center') + + label.set_transform(mtransforms.blended_transform_factory( + self.axes.transAxes, mtransforms.IdentityTransform())) + + self._set_artist_props(label) + self.label_position = 'bottom' + return label + + def _get_offset_text(self): + # x in axes coords, y in display coords (to be updated at draw time) + offsetText = mtext.Text(x=1, y=0, + fontproperties=font_manager.FontProperties( + size=rcParams['xtick.labelsize']), + color=rcParams['xtick.color'], + verticalalignment='top', + horizontalalignment='right') + offsetText.set_transform(mtransforms.blended_transform_factory( + self.axes.transAxes, mtransforms.IdentityTransform()) + ) + self._set_artist_props(offsetText) + self.offset_text_position = 'bottom' + return offsetText + + def _get_pixel_distance_along_axis(self, where, perturb): + """ + Returns the amount, in data coordinates, that a single pixel + corresponds to in the locality given by "where", which is also given + in data coordinates, and is an x coordinate. "perturb" is the amount + to perturb the pixel. Usually +0.5 or -0.5. + + Implementing this routine for an axis is optional; if present, it will + ensure that no ticks are lost due to round-off at the extreme ends of + an axis. + """ + + # Note that this routine does not work for a polar axis, because of + # the 1e-10 below. To do things correctly, we need to use rmax + # instead of 1e-10 for a polar axis. But since we do not have that + # kind of information at this point, we just don't try to pad anything + # for the theta axis of a polar plot. + if self.axes.name == 'polar': + return 0.0 + + # + # first figure out the pixel location of the "where" point. We use + # 1e-10 for the y point, so that we remain compatible with log axes. + + # transformation from data coords to display coords + trans = self.axes.transData + # transformation from display coords to data coords + transinv = trans.inverted() + pix = trans.transform_point((where, 1e-10)) + # perturb the pixel + ptp = transinv.transform_point((pix[0] + perturb, pix[1])) + dx = abs(ptp[0] - where) + + return dx + + def set_label_position(self, position): + """ + Set the label position (top or bottom) + + ACCEPTS: [ 'top' | 'bottom' ] + """ + if position == 'top': + self.label.set_verticalalignment('baseline') + elif position == 'bottom': + self.label.set_verticalalignment('top') + else: + raise ValueError("Position accepts only 'top' or 'bottom'") + self.label_position = position + self.stale = True + + def _get_tick_boxes_siblings(self, renderer): + """ + Get the bounding boxes for this `.axis` and its siblings + as set by `.Figure.align_xlabels` or `.Figure.align_ylablels`. + + By default it just gets bboxes for self. + """ + bboxes = [] + bboxes2 = [] + # get the Grouper that keeps track of x-label groups for this figure + grp = self.figure._align_xlabel_grp + # if we want to align labels from other axes: + for nn, axx in enumerate(grp.get_siblings(self.axes)): + ticks_to_draw = axx.xaxis._update_ticks(renderer) + tlb, tlb2 = axx.xaxis._get_tick_bboxes(ticks_to_draw, renderer) + bboxes.extend(tlb) + bboxes2.extend(tlb2) + return bboxes, bboxes2 + + def _update_label_position(self, renderer): + """ + Update the label position based on the bounding box enclosing + all the ticklabels and axis spine + """ + if not self._autolabelpos: + return + + # get bounding boxes for this axis and any siblings + # that have been set by `fig.align_xlabels()` + bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer) + + x, y = self.label.get_position() + if self.label_position == 'bottom': + try: + spine = self.axes.spines['bottom'] + spinebbox = spine.get_transform().transform_path( + spine.get_path()).get_extents() + except KeyError: + # use axes if spine doesn't exist + spinebbox = self.axes.bbox + bbox = mtransforms.Bbox.union(bboxes + [spinebbox]) + bottom = bbox.y0 + + self.label.set_position( + (x, bottom - self.labelpad * self.figure.dpi / 72.0) + ) + + else: + try: + spine = self.axes.spines['top'] + spinebbox = spine.get_transform().transform_path( + spine.get_path()).get_extents() + except KeyError: + # use axes if spine doesn't exist + spinebbox = self.axes.bbox + bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox]) + top = bbox.y1 + + self.label.set_position( + (x, top + self.labelpad * self.figure.dpi / 72.0) + ) + + def _update_offset_text_position(self, bboxes, bboxes2): + """ + Update the offset_text position based on the sequence of bounding + boxes of all the ticklabels + """ + x, y = self.offsetText.get_position() + if not len(bboxes): + bottom = self.axes.bbox.ymin + else: + bbox = mtransforms.Bbox.union(bboxes) + bottom = bbox.y0 + self.offsetText.set_position( + (x, bottom - self.OFFSETTEXTPAD * self.figure.dpi / 72.0) + ) + + def get_text_heights(self, renderer): + """ + Returns the amount of space one should reserve for text + above and below the axes. Returns a tuple (above, below) + """ + bbox, bbox2 = self.get_ticklabel_extents(renderer) + # MGDTODO: Need a better way to get the pad + padPixels = self.majorTicks[0].get_pad_pixels() + + above = 0.0 + if bbox2.height: + above += bbox2.height + padPixels + below = 0.0 + if bbox.height: + below += bbox.height + padPixels + + if self.get_label_position() == 'top': + above += self.label.get_window_extent(renderer).height + padPixels + else: + below += self.label.get_window_extent(renderer).height + padPixels + return above, below + + def set_ticks_position(self, position): + """ + Set the ticks position (top, bottom, both, default or none) + both sets the ticks to appear on both positions, but does not + change the tick labels. 'default' resets the tick positions to + the default: ticks on both positions, labels at bottom. 'none' + can be used if you don't want any ticks. 'none' and 'both' + affect only the ticks, not the labels. + + ACCEPTS: [ 'top' | 'bottom' | 'both' | 'default' | 'none' ] + """ + if position == 'top': + self.set_tick_params(which='both', top=True, labeltop=True, + bottom=False, labelbottom=False) + elif position == 'bottom': + self.set_tick_params(which='both', top=False, labeltop=False, + bottom=True, labelbottom=True) + elif position == 'both': + self.set_tick_params(which='both', top=True, + bottom=True) + elif position == 'none': + self.set_tick_params(which='both', top=False, + bottom=False) + elif position == 'default': + self.set_tick_params(which='both', top=True, labeltop=False, + bottom=True, labelbottom=True) + else: + raise ValueError("invalid position: %s" % position) + self.stale = True + + def tick_top(self): + """ + Move ticks and ticklabels (if present) to the top of the axes. + """ + label = True + if 'label1On' in self._major_tick_kw: + label = (self._major_tick_kw['label1On'] + or self._major_tick_kw['label2On']) + self.set_ticks_position('top') + # if labels were turned off before this was called + # leave them off + self.set_tick_params(which='both', labeltop=label) + + def tick_bottom(self): + """ + Move ticks and ticklabels (if present) to the bottom of the axes. + """ + label = True + if 'label1On' in self._major_tick_kw: + label = (self._major_tick_kw['label1On'] + or self._major_tick_kw['label2On']) + self.set_ticks_position('bottom') + # if labels were turned off before this was called + # leave them off + self.set_tick_params(which='both', labelbottom=label) + + def get_ticks_position(self): + """ + Return the ticks position (top, bottom, default or unknown) + """ + majt = self.majorTicks[0] + mT = self.minorTicks[0] + + majorTop = ((not majt.tick1On) and majt.tick2On and + (not majt.label1On) and majt.label2On) + minorTop = ((not mT.tick1On) and mT.tick2On and + (not mT.label1On) and mT.label2On) + if majorTop and minorTop: + return 'top' + + MajorBottom = (majt.tick1On and (not majt.tick2On) and + majt.label1On and (not majt.label2On)) + MinorBottom = (mT.tick1On and (not mT.tick2On) and + mT.label1On and (not mT.label2On)) + if MajorBottom and MinorBottom: + return 'bottom' + + majorDefault = (majt.tick1On and majt.tick2On and + majt.label1On and (not majt.label2On)) + minorDefault = (mT.tick1On and mT.tick2On and + mT.label1On and (not mT.label2On)) + if majorDefault and minorDefault: + return 'default' + + return 'unknown' + + def get_view_interval(self): + 'return the Interval instance for this axis view limits' + return self.axes.viewLim.intervalx + + def set_view_interval(self, vmin, vmax, ignore=False): + """ + If *ignore* is *False*, the order of vmin, vmax + does not matter; the original axis orientation will + be preserved. In addition, the view limits can be + expanded, but will not be reduced. This method is + for mpl internal use; for normal use, see + :meth:`~matplotlib.axes.Axes.set_xlim`. + + """ + if ignore: + self.axes.viewLim.intervalx = vmin, vmax + else: + Vmin, Vmax = self.get_view_interval() + if Vmin < Vmax: + self.axes.viewLim.intervalx = (min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) + else: + self.axes.viewLim.intervalx = (max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) + + def get_minpos(self): + return self.axes.dataLim.minposx + + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + return self.axes.dataLim.intervalx + + def set_data_interval(self, vmin, vmax, ignore=False): + 'set the axis data limits' + if ignore: + self.axes.dataLim.intervalx = vmin, vmax + else: + Vmin, Vmax = self.get_data_interval() + self.axes.dataLim.intervalx = min(vmin, Vmin), max(vmax, Vmax) + self.stale = True + + def set_default_intervals(self): + 'set the default limits for the axis interval if they are not mutated' + xmin, xmax = 0., 1. + dataMutated = self.axes.dataLim.mutatedx() + viewMutated = self.axes.viewLim.mutatedx() + if not dataMutated or not viewMutated: + if self.converter is not None: + info = self.converter.axisinfo(self.units, self) + if info.default_limits is not None: + valmin, valmax = info.default_limits + xmin = self.converter.convert(valmin, self.units, self) + xmax = self.converter.convert(valmax, self.units, self) + if not dataMutated: + self.axes.dataLim.intervalx = xmin, xmax + if not viewMutated: + self.axes.viewLim.intervalx = xmin, xmax + self.stale = True + + def get_tick_space(self): + ends = self.axes.transAxes.transform([[0, 0], [1, 0]]) + length = ((ends[1][0] - ends[0][0]) / self.axes.figure.dpi) * 72.0 + tick = self._get_tick(True) + # There is a heuristic here that the aspect ratio of tick text + # is no more than 3:1 + size = tick.label1.get_size() * 3 + if size > 0: + return int(np.floor(length / size)) + else: + return 2**31 - 1 + + +class YAxis(Axis): + __name__ = 'yaxis' + axis_name = 'y' + + def contains(self, mouseevent): + """Test whether the mouse event occurred in the y axis. + + Returns *True* | *False* + """ + if callable(self._contains): + return self._contains(self, mouseevent) + + x, y = mouseevent.x, mouseevent.y + try: + trans = self.axes.transAxes.inverted() + xaxes, yaxes = trans.transform_point((x, y)) + except ValueError: + return False, {} + l, b = self.axes.transAxes.transform_point((0, 0)) + r, t = self.axes.transAxes.transform_point((1, 1)) + inaxis = yaxes >= 0 and yaxes <= 1 and ( + (x < l and x > l - self.pickradius) or + (x > r and x < r + self.pickradius)) + return inaxis, {} + + def _get_tick(self, major): + if major: + tick_kw = self._major_tick_kw + else: + tick_kw = self._minor_tick_kw + return YTick(self.axes, 0, '', major=major, **tick_kw) + + def _get_label(self): + # x in display coords (updated by _update_label_position) + # y in axes coords + label = mtext.Text(x=0, y=0.5, + # todo: get the label position + fontproperties=font_manager.FontProperties( + size=rcParams['axes.labelsize'], + weight=rcParams['axes.labelweight']), + color=rcParams['axes.labelcolor'], + verticalalignment='bottom', + horizontalalignment='center', + rotation='vertical', + rotation_mode='anchor') + label.set_transform(mtransforms.blended_transform_factory( + mtransforms.IdentityTransform(), self.axes.transAxes)) + + self._set_artist_props(label) + self.label_position = 'left' + return label + + def _get_offset_text(self): + # x in display coords, y in axes coords (to be updated at draw time) + offsetText = mtext.Text(x=0, y=0.5, + fontproperties=font_manager.FontProperties( + size=rcParams['ytick.labelsize'] + ), + color=rcParams['ytick.color'], + verticalalignment='baseline', + horizontalalignment='left') + offsetText.set_transform(mtransforms.blended_transform_factory( + self.axes.transAxes, mtransforms.IdentityTransform()) + ) + self._set_artist_props(offsetText) + self.offset_text_position = 'left' + return offsetText + + def _get_pixel_distance_along_axis(self, where, perturb): + """ + Returns the amount, in data coordinates, that a single pixel + corresponds to in the locality given by *where*, which is also given + in data coordinates, and is a y coordinate. + + *perturb* is the amount to perturb the pixel. Usually +0.5 or -0.5. + + Implementing this routine for an axis is optional; if present, it will + ensure that no ticks are lost due to round-off at the extreme ends of + an axis. + """ + + # + # first figure out the pixel location of the "where" point. We use + # 1e-10 for the x point, so that we remain compatible with log axes. + + # transformation from data coords to display coords + trans = self.axes.transData + # transformation from display coords to data coords + transinv = trans.inverted() + pix = trans.transform_point((1e-10, where)) + # perturb the pixel + ptp = transinv.transform_point((pix[0], pix[1] + perturb)) + dy = abs(ptp[1] - where) + return dy + + def set_label_position(self, position): + """ + Set the label position (left or right) + + ACCEPTS: [ 'left' | 'right' ] + """ + self.label.set_rotation_mode('anchor') + self.label.set_horizontalalignment('center') + if position == 'left': + self.label.set_verticalalignment('bottom') + elif position == 'right': + self.label.set_verticalalignment('top') + else: + raise ValueError("Position accepts only 'left' or 'right'") + self.label_position = position + self.stale = True + + def _get_tick_boxes_siblings(self, renderer): + """ + Get the bounding boxes for this `.axis` and its siblings + as set by `.Figure.align_xlabels` or `.Figure.align_ylablels`. + + By default it just gets bboxes for self. + """ + bboxes = [] + bboxes2 = [] + # get the Grouper that keeps track of y-label groups for this figure + grp = self.figure._align_ylabel_grp + # if we want to align labels from other axes: + for axx in grp.get_siblings(self.axes): + ticks_to_draw = axx.yaxis._update_ticks(renderer) + tlb, tlb2 = axx.yaxis._get_tick_bboxes(ticks_to_draw, renderer) + bboxes.extend(tlb) + bboxes2.extend(tlb2) + return bboxes, bboxes2 + + def _update_label_position(self, renderer): + """ + Update the label position based on the bounding box enclosing + all the ticklabels and axis spine + """ + if not self._autolabelpos: + return + + # get bounding boxes for this axis and any siblings + # that have been set by `fig.align_ylabels()` + bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer) + + x, y = self.label.get_position() + if self.label_position == 'left': + try: + spine = self.axes.spines['left'] + spinebbox = spine.get_transform().transform_path( + spine.get_path()).get_extents() + except KeyError: + # use axes if spine doesn't exist + spinebbox = self.axes.bbox + bbox = mtransforms.Bbox.union(bboxes + [spinebbox]) + left = bbox.x0 + self.label.set_position( + (left - self.labelpad * self.figure.dpi / 72.0, y) + ) + + else: + try: + spine = self.axes.spines['right'] + spinebbox = spine.get_transform().transform_path( + spine.get_path()).get_extents() + except KeyError: + # use axes if spine doesn't exist + spinebbox = self.axes.bbox + bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox]) + right = bbox.x1 + + self.label.set_position( + (right + self.labelpad * self.figure.dpi / 72.0, y) + ) + + def _update_offset_text_position(self, bboxes, bboxes2): + """ + Update the offset_text position based on the sequence of bounding + boxes of all the ticklabels + """ + x, y = self.offsetText.get_position() + top = self.axes.bbox.ymax + self.offsetText.set_position( + (x, top + self.OFFSETTEXTPAD * self.figure.dpi / 72.0) + ) + + def set_offset_position(self, position): + """ + .. ACCEPTS: [ 'left' | 'right' ] + """ + x, y = self.offsetText.get_position() + if position == 'left': + x = 0 + elif position == 'right': + x = 1 + else: + raise ValueError("Position accepts only [ 'left' | 'right' ]") + + self.offsetText.set_ha(position) + self.offsetText.set_position((x, y)) + self.stale = True + + def get_text_widths(self, renderer): + bbox, bbox2 = self.get_ticklabel_extents(renderer) + # MGDTODO: Need a better way to get the pad + padPixels = self.majorTicks[0].get_pad_pixels() + + left = 0.0 + if bbox.width: + left += bbox.width + padPixels + right = 0.0 + if bbox2.width: + right += bbox2.width + padPixels + + if self.get_label_position() == 'left': + left += self.label.get_window_extent(renderer).width + padPixels + else: + right += self.label.get_window_extent(renderer).width + padPixels + return left, right + + def set_ticks_position(self, position): + """ + Set the ticks position (left, right, both, default or none) + 'both' sets the ticks to appear on both positions, but does not + change the tick labels. 'default' resets the tick positions to + the default: ticks on both positions, labels at left. 'none' + can be used if you don't want any ticks. 'none' and 'both' + affect only the ticks, not the labels. + + ACCEPTS: [ 'left' | 'right' | 'both' | 'default' | 'none' ] + """ + if position == 'right': + self.set_tick_params(which='both', right=True, labelright=True, + left=False, labelleft=False) + self.set_offset_position(position) + elif position == 'left': + self.set_tick_params(which='both', right=False, labelright=False, + left=True, labelleft=True) + self.set_offset_position(position) + elif position == 'both': + self.set_tick_params(which='both', right=True, + left=True) + elif position == 'none': + self.set_tick_params(which='both', right=False, + left=False) + elif position == 'default': + self.set_tick_params(which='both', right=True, labelright=False, + left=True, labelleft=True) + else: + raise ValueError("invalid position: %s" % position) + self.stale = True + + def tick_right(self): + """ + Move ticks and ticklabels (if present) to the right of the axes. + """ + label = True + if 'label1On' in self._major_tick_kw: + label = (self._major_tick_kw['label1On'] + or self._major_tick_kw['label2On']) + self.set_ticks_position('right') + # if labels were turned off before this was called + # leave them off + self.set_tick_params(which='both', labelright=label) + + def tick_left(self): + """ + Move ticks and ticklabels (if present) to the left of the axes. + """ + label = True + if 'label1On' in self._major_tick_kw: + label = (self._major_tick_kw['label1On'] + or self._major_tick_kw['label2On']) + self.set_ticks_position('left') + # if labels were turned off before this was called + # leave them off + self.set_tick_params(which='both', labelleft=label) + + def get_ticks_position(self): + """ + Return the ticks position (left, right, both or unknown) + """ + majt = self.majorTicks[0] + mT = self.minorTicks[0] + + majorRight = ((not majt.tick1On) and majt.tick2On and + (not majt.label1On) and majt.label2On) + minorRight = ((not mT.tick1On) and mT.tick2On and + (not mT.label1On) and mT.label2On) + if majorRight and minorRight: + return 'right' + + majorLeft = (majt.tick1On and (not majt.tick2On) and + majt.label1On and (not majt.label2On)) + minorLeft = (mT.tick1On and (not mT.tick2On) and + mT.label1On and (not mT.label2On)) + if majorLeft and minorLeft: + return 'left' + + majorDefault = (majt.tick1On and majt.tick2On and + majt.label1On and (not majt.label2On)) + minorDefault = (mT.tick1On and mT.tick2On and + mT.label1On and (not mT.label2On)) + if majorDefault and minorDefault: + return 'default' + + return 'unknown' + + def get_view_interval(self): + 'return the Interval instance for this axis view limits' + return self.axes.viewLim.intervaly + + def set_view_interval(self, vmin, vmax, ignore=False): + """ + If *ignore* is *False*, the order of vmin, vmax + does not matter; the original axis orientation will + be preserved. In addition, the view limits can be + expanded, but will not be reduced. This method is + for mpl internal use; for normal use, see + :meth:`~matplotlib.axes.Axes.set_ylim`. + + """ + if ignore: + self.axes.viewLim.intervaly = vmin, vmax + else: + Vmin, Vmax = self.get_view_interval() + if Vmin < Vmax: + self.axes.viewLim.intervaly = (min(vmin, vmax, Vmin), + max(vmin, vmax, Vmax)) + else: + self.axes.viewLim.intervaly = (max(vmin, vmax, Vmin), + min(vmin, vmax, Vmax)) + self.stale = True + + def get_minpos(self): + return self.axes.dataLim.minposy + + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + return self.axes.dataLim.intervaly + + def set_data_interval(self, vmin, vmax, ignore=False): + 'set the axis data limits' + if ignore: + self.axes.dataLim.intervaly = vmin, vmax + else: + Vmin, Vmax = self.get_data_interval() + self.axes.dataLim.intervaly = min(vmin, Vmin), max(vmax, Vmax) + self.stale = True + + def set_default_intervals(self): + 'set the default limits for the axis interval if they are not mutated' + ymin, ymax = 0., 1. + dataMutated = self.axes.dataLim.mutatedy() + viewMutated = self.axes.viewLim.mutatedy() + if not dataMutated or not viewMutated: + if self.converter is not None: + info = self.converter.axisinfo(self.units, self) + if info.default_limits is not None: + valmin, valmax = info.default_limits + ymin = self.converter.convert(valmin, self.units, self) + ymax = self.converter.convert(valmax, self.units, self) + if not dataMutated: + self.axes.dataLim.intervaly = ymin, ymax + if not viewMutated: + self.axes.viewLim.intervaly = ymin, ymax + self.stale = True + + def get_tick_space(self): + ends = self.axes.transAxes.transform([[0, 0], [0, 1]]) + length = ((ends[1][1] - ends[0][1]) / self.axes.figure.dpi) * 72.0 + tick = self._get_tick(True) + # Having a spacing of at least 2 just looks good. + size = tick.label1.get_size() * 2.0 + if size > 0: + return int(np.floor(length / size)) + else: + return 2**31 - 1 diff --git a/contrib/python/matplotlib/py2/matplotlib/backend_bases.py b/contrib/python/matplotlib/py2/matplotlib/backend_bases.py new file mode 100644 index 00000000000..136f567ebcd --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backend_bases.py @@ -0,0 +1,3383 @@ +""" +Abstract base classes define the primitives that renderers and +graphics contexts must implement to serve as a matplotlib backend + +:class:`RendererBase` + An abstract base class to handle drawing/rendering operations. + +:class:`FigureCanvasBase` + The abstraction layer that separates the + :class:`matplotlib.figure.Figure` from the backend specific + details like a user interface drawing area + +:class:`GraphicsContextBase` + An abstract base class that provides color, line styles, etc... + +:class:`Event` + The base class for all of the matplotlib event + handling. Derived classes such as :class:`KeyEvent` and + :class:`MouseEvent` store the meta data like keys and buttons + pressed, x and y locations in pixel and + :class:`~matplotlib.axes.Axes` coordinates. + +:class:`ShowBase` + The base class for the Show class of each interactive backend; + the 'show' callable is then set to Show.__call__, inherited from + ShowBase. + +:class:`ToolContainerBase` + The base class for the Toolbar class of each interactive backend. + +:class:`StatusbarBase` + The base class for the messaging area. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import xrange + +from contextlib import contextmanager +from functools import partial +import importlib +import io +import os +import sys +import time +import warnings +from weakref import WeakKeyDictionary + +import numpy as np + +from matplotlib import ( + backend_tools as tools, cbook, colors, textpath, tight_bbox, transforms, + widgets, get_backend, is_interactive, rcParams) +from matplotlib._pylab_helpers import Gcf +from matplotlib.transforms import Bbox, TransformedBbox, Affine2D +from matplotlib.path import Path + +try: + from PIL import Image + _has_pil = True + del Image +except ImportError: + _has_pil = False + + +_default_filetypes = { + 'ps': 'Postscript', + 'eps': 'Encapsulated Postscript', + 'pdf': 'Portable Document Format', + 'pgf': 'PGF code for LaTeX', + 'png': 'Portable Network Graphics', + 'raw': 'Raw RGBA bitmap', + 'rgba': 'Raw RGBA bitmap', + 'svg': 'Scalable Vector Graphics', + 'svgz': 'Scalable Vector Graphics' +} + + +_default_backends = { + 'ps': 'matplotlib.backends.backend_ps', + 'eps': 'matplotlib.backends.backend_ps', + 'pdf': 'matplotlib.backends.backend_pdf', + 'pgf': 'matplotlib.backends.backend_pgf', + 'png': 'matplotlib.backends.backend_agg', + 'raw': 'matplotlib.backends.backend_agg', + 'rgba': 'matplotlib.backends.backend_agg', + 'svg': 'matplotlib.backends.backend_svg', + 'svgz': 'matplotlib.backends.backend_svg', +} + + +def register_backend(format, backend, description=None): + """ + Register a backend for saving to a given file format. + + Parameters + ---------- + format : str + File extension + + backend : module string or canvas class + Backend for handling file output + + description : str, optional + Description of the file type. Defaults to an empty string + """ + if description is None: + description = '' + _default_backends[format] = backend + _default_filetypes[format] = description + + +def get_registered_canvas_class(format): + """ + Return the registered default canvas for given file format. + Handles deferred import of required backend. + """ + if format not in _default_backends: + return None + backend_class = _default_backends[format] + if isinstance(backend_class, six.string_types): + backend_class = importlib.import_module(backend_class).FigureCanvas + _default_backends[format] = backend_class + return backend_class + + +class _Backend(object): + # A backend can be defined by using the following pattern: + # + # @_Backend.export + # class FooBackend(_Backend): + # # override the attributes and methods documented below. + + # The following attributes and methods must be overridden by subclasses. + + # The `FigureCanvas` and `FigureManager` classes must be defined. + FigureCanvas = None + FigureManager = None + + # The following methods must be left as None for non-interactive backends. + # For interactive backends, `trigger_manager_draw` should be a function + # taking a manager as argument and triggering a canvas draw, and `mainloop` + # should be a function taking no argument and starting the backend main + # loop. + trigger_manager_draw = None + mainloop = None + + # The following methods will be automatically defined and exported, but + # can be overridden. + + @classmethod + def new_figure_manager(cls, num, *args, **kwargs): + """Create a new figure manager instance. + """ + # This import needs to happen here due to circular imports. + from matplotlib.figure import Figure + fig_cls = kwargs.pop('FigureClass', Figure) + fig = fig_cls(*args, **kwargs) + return cls.new_figure_manager_given_figure(num, fig) + + @classmethod + def new_figure_manager_given_figure(cls, num, figure): + """Create a new figure manager instance for the given figure. + """ + canvas = cls.FigureCanvas(figure) + manager = cls.FigureManager(canvas, num) + return manager + + @classmethod + def draw_if_interactive(cls): + if cls.trigger_manager_draw is not None and is_interactive(): + manager = Gcf.get_active() + if manager: + cls.trigger_manager_draw(manager) + + @classmethod + def show(cls, block=None): + """Show all figures. + + `show` blocks by calling `mainloop` if *block* is ``True``, or if it + is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in + `interactive` mode. + """ + if cls.mainloop is None: + return + managers = Gcf.get_all_fig_managers() + if not managers: + return + for manager in managers: + manager.show() + if block is None: + # Hack: Are we in IPython's pylab mode? + from matplotlib import pyplot + try: + # IPython versions >= 0.10 tack the _needmain attribute onto + # pyplot.show, and always set it to False, when in %pylab mode. + ipython_pylab = not pyplot.show._needmain + except AttributeError: + ipython_pylab = False + block = not ipython_pylab and not is_interactive() + # TODO: The above is a hack to get the WebAgg backend working with + # ipython's `%pylab` mode until proper integration is implemented. + if get_backend() == "WebAgg": + block = True + if block: + cls.mainloop() + + # This method is the one actually exporting the required methods. + + @staticmethod + def export(cls): + for name in ["FigureCanvas", + "FigureManager", + "new_figure_manager", + "new_figure_manager_given_figure", + "draw_if_interactive", + "show"]: + setattr(sys.modules[cls.__module__], name, getattr(cls, name)) + + # For back-compatibility, generate a shim `Show` class. + + class Show(ShowBase): + def mainloop(self): + return cls.mainloop() + + setattr(sys.modules[cls.__module__], "Show", Show) + return cls + + +class ShowBase(_Backend): + """ + Simple base class to generate a show() callable in backends. + + Subclass must override mainloop() method. + """ + + def __call__(self, block=None): + return self.show(block=block) + + +class RendererBase(object): + """An abstract base class to handle drawing/rendering operations. + + The following methods must be implemented in the backend for full + functionality (though just implementing :meth:`draw_path` alone would + give a highly capable backend): + + * :meth:`draw_path` + * :meth:`draw_image` + * :meth:`draw_gouraud_triangle` + + The following methods *should* be implemented in the backend for + optimization reasons: + + * :meth:`draw_text` + * :meth:`draw_markers` + * :meth:`draw_path_collection` + * :meth:`draw_quad_mesh` + + """ + def __init__(self): + self._texmanager = None + self._text2path = textpath.TextToPath() + + def open_group(self, s, gid=None): + """ + Open a grouping element with label *s*. If *gid* is given, use + *gid* as the id of the group. Is only currently used by + :mod:`~matplotlib.backends.backend_svg`. + """ + + def close_group(self, s): + """ + Close a grouping element with label *s* + Is only currently used by :mod:`~matplotlib.backends.backend_svg` + """ + + def draw_path(self, gc, path, transform, rgbFace=None): + """ + Draws a :class:`~matplotlib.path.Path` instance using the + given affine transform. + """ + raise NotImplementedError + + def draw_markers(self, gc, marker_path, marker_trans, path, + trans, rgbFace=None): + """ + Draws a marker at each of the vertices in path. This includes + all vertices, including control points on curves. To avoid + that behavior, those vertices should be removed before calling + this function. + + This provides a fallback implementation of draw_markers that + makes multiple calls to :meth:`draw_path`. Some backends may + want to override this method in order to draw the marker only + once and reuse it multiple times. + + Parameters + ---------- + gc : `GraphicsContextBase` + The graphics context + + marker_trans : `matplotlib.transforms.Transform` + An affine transform applied to the marker. + + trans : `matplotlib.transforms.Transform` + An affine transform applied to the path. + + """ + for vertices, codes in path.iter_segments(trans, simplify=False): + if len(vertices): + x, y = vertices[-2:] + self.draw_path(gc, marker_path, + marker_trans + + transforms.Affine2D().translate(x, y), + rgbFace) + + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position): + """ + Draws a collection of paths selecting drawing properties from + the lists *facecolors*, *edgecolors*, *linewidths*, + *linestyles* and *antialiaseds*. *offsets* is a list of + offsets to apply to each of the paths. The offsets in + *offsets* are first transformed by *offsetTrans* before being + applied. *offset_position* may be either "screen" or "data" + depending on the space that the offsets are in. + + This provides a fallback implementation of + :meth:`draw_path_collection` that makes multiple calls to + :meth:`draw_path`. Some backends may want to override this in + order to render each set of path data only once, and then + reference that path multiple times with the different offsets, + colors, styles etc. The generator methods + :meth:`_iter_collection_raw_paths` and + :meth:`_iter_collection` are provided to help with (and + standardize) the implementation across backends. It is highly + recommended to use those generators, so that changes to the + behavior of :meth:`draw_path_collection` can be made globally. + """ + path_ids = [] + for path, transform in self._iter_collection_raw_paths( + master_transform, paths, all_transforms): + path_ids.append((path, transforms.Affine2D(transform))) + + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, master_transform, all_transforms, path_ids, offsets, + offsetTrans, facecolors, edgecolors, linewidths, linestyles, + antialiaseds, urls, offset_position): + path, transform = path_id + transform = transforms.Affine2D( + transform.get_matrix()).translate(xo, yo) + self.draw_path(gc0, path, transform, rgbFace) + + def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, + coordinates, offsets, offsetTrans, facecolors, + antialiased, edgecolors): + """ + This provides a fallback implementation of + :meth:`draw_quad_mesh` that generates paths and then calls + :meth:`draw_path_collection`. + """ + + from matplotlib.collections import QuadMesh + paths = QuadMesh.convert_mesh_to_paths( + meshWidth, meshHeight, coordinates) + + if edgecolors is None: + edgecolors = facecolors + linewidths = np.array([gc.get_linewidth()], float) + + return self.draw_path_collection( + gc, master_transform, paths, [], offsets, offsetTrans, facecolors, + edgecolors, linewidths, [], [antialiased], [None], 'screen') + + def draw_gouraud_triangle(self, gc, points, colors, transform): + """ + Draw a Gouraud-shaded triangle. + + Parameters + ---------- + points : array_like, shape=(3, 2) + Array of (x, y) points for the triangle. + + colors : array_like, shape=(3, 4) + RGBA colors for each point of the triangle. + + transform : `matplotlib.transforms.Transform` + An affine transform to apply to the points. + + """ + raise NotImplementedError + + def draw_gouraud_triangles(self, gc, triangles_array, colors_array, + transform): + """ + Draws a series of Gouraud triangles. + + Parameters + ---------- + points : array_like, shape=(N, 3, 2) + Array of *N* (x, y) points for the triangles. + + colors : array_like, shape=(N, 3, 4) + Array of *N* RGBA colors for each point of the triangles. + + transform : `matplotlib.transforms.Transform` + An affine transform to apply to the points. + """ + transform = transform.frozen() + for tri, col in zip(triangles_array, colors_array): + self.draw_gouraud_triangle(gc, tri, col, transform) + + def _iter_collection_raw_paths(self, master_transform, paths, + all_transforms): + """ + This is a helper method (along with :meth:`_iter_collection`) to make + it easier to write a space-efficient :meth:`draw_path_collection` + implementation in a backend. + + This method yields all of the base path/transform + combinations, given a master transform, a list of paths and + list of transforms. + + The arguments should be exactly what is passed in to + :meth:`draw_path_collection`. + + The backend should take each yielded path and transform and + create an object that can be referenced (reused) later. + """ + Npaths = len(paths) + Ntransforms = len(all_transforms) + N = max(Npaths, Ntransforms) + + if Npaths == 0: + return + + transform = transforms.IdentityTransform() + for i in xrange(N): + path = paths[i % Npaths] + if Ntransforms: + transform = Affine2D(all_transforms[i % Ntransforms]) + yield path, transform + master_transform + + def _iter_collection_uses_per_path(self, paths, all_transforms, + offsets, facecolors, edgecolors): + """ + Compute how many times each raw path object returned by + _iter_collection_raw_paths would be used when calling + _iter_collection. This is intended for the backend to decide + on the tradeoff between using the paths in-line and storing + them once and reusing. Rounds up in case the number of uses + is not the same for every path. + """ + Npaths = len(paths) + if Npaths == 0 or (len(facecolors) == 0 and len(edgecolors) == 0): + return 0 + Npath_ids = max(Npaths, len(all_transforms)) + N = max(Npath_ids, len(offsets)) + return (N + Npath_ids - 1) // Npath_ids + + def _iter_collection(self, gc, master_transform, all_transforms, + path_ids, offsets, offsetTrans, facecolors, + edgecolors, linewidths, linestyles, + antialiaseds, urls, offset_position): + """ + This is a helper method (along with + :meth:`_iter_collection_raw_paths`) to make it easier to write + a space-efficient :meth:`draw_path_collection` implementation in a + backend. + + This method yields all of the path, offset and graphics + context combinations to draw the path collection. The caller + should already have looped over the results of + :meth:`_iter_collection_raw_paths` to draw this collection. + + The arguments should be the same as that passed into + :meth:`draw_path_collection`, with the exception of + *path_ids*, which is a list of arbitrary objects that the + backend will use to reference one of the paths created in the + :meth:`_iter_collection_raw_paths` stage. + + Each yielded result is of the form:: + + xo, yo, path_id, gc, rgbFace + + where *xo*, *yo* is an offset; *path_id* is one of the elements of + *path_ids*; *gc* is a graphics context and *rgbFace* is a color to + use for filling the path. + """ + Ntransforms = len(all_transforms) + Npaths = len(path_ids) + Noffsets = len(offsets) + N = max(Npaths, Noffsets) + Nfacecolors = len(facecolors) + Nedgecolors = len(edgecolors) + Nlinewidths = len(linewidths) + Nlinestyles = len(linestyles) + Naa = len(antialiaseds) + Nurls = len(urls) + + if (Nfacecolors == 0 and Nedgecolors == 0) or Npaths == 0: + return + if Noffsets: + toffsets = offsetTrans.transform(offsets) + + gc0 = self.new_gc() + gc0.copy_properties(gc) + + if Nfacecolors == 0: + rgbFace = None + + if Nedgecolors == 0: + gc0.set_linewidth(0.0) + + xo, yo = 0, 0 + for i in xrange(N): + path_id = path_ids[i % Npaths] + if Noffsets: + xo, yo = toffsets[i % Noffsets] + if offset_position == 'data': + if Ntransforms: + transform = ( + Affine2D(all_transforms[i % Ntransforms]) + + master_transform) + else: + transform = master_transform + xo, yo = transform.transform_point((xo, yo)) + xp, yp = transform.transform_point((0, 0)) + xo = -(xp - xo) + yo = -(yp - yo) + if not (np.isfinite(xo) and np.isfinite(yo)): + continue + if Nfacecolors: + rgbFace = facecolors[i % Nfacecolors] + if Nedgecolors: + if Nlinewidths: + gc0.set_linewidth(linewidths[i % Nlinewidths]) + if Nlinestyles: + gc0.set_dashes(*linestyles[i % Nlinestyles]) + fg = edgecolors[i % Nedgecolors] + if len(fg) == 4: + if fg[3] == 0.0: + gc0.set_linewidth(0) + else: + gc0.set_foreground(fg) + else: + gc0.set_foreground(fg) + if rgbFace is not None and len(rgbFace) == 4: + if rgbFace[3] == 0: + rgbFace = None + gc0.set_antialiased(antialiaseds[i % Naa]) + if Nurls: + gc0.set_url(urls[i % Nurls]) + + yield xo, yo, path_id, gc0, rgbFace + gc0.restore() + + def get_image_magnification(self): + """ + Get the factor by which to magnify images passed to :meth:`draw_image`. + Allows a backend to have images at a different resolution to other + artists. + """ + return 1.0 + + def draw_image(self, gc, x, y, im, transform=None): + """ + Draw an RGBA image. + + Parameters + ---------- + gc : `GraphicsContextBase` + a graphics context with clipping information. + + x : scalar + the distance in physical units (i.e., dots or pixels) from the left + hand side of the canvas. + + y : scalar + the distance in physical units (i.e., dots or pixels) from the + bottom side of the canvas. + + im : array_like, shape=(N, M, 4), dtype=np.uint8 + An array of RGBA pixels. + + transform : `matplotlib.transforms.Affine2DBase` + If and only if the concrete backend is written such that + :meth:`option_scale_image` returns ``True``, an affine + transformation *may* be passed to :meth:`draw_image`. It takes the + form of a :class:`~matplotlib.transforms.Affine2DBase` instance. + The translation vector of the transformation is given in physical + units (i.e., dots or pixels). Note that the transformation does not + override `x` and `y`, and has to be applied *before* translating + the result by `x` and `y` (this can be accomplished by adding `x` + and `y` to the translation vector defined by `transform`). + """ + raise NotImplementedError + + def option_image_nocomposite(self): + """ + override this method for renderers that do not necessarily always + want to rescale and composite raster images. (like SVG, PDF, or PS) + """ + return False + + def option_scale_image(self): + """ + override this method for renderers that support arbitrary affine + transformations in :meth:`draw_image` (most vector backends). + """ + return False + + def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None): + """ + """ + self._draw_text_as_path(gc, x, y, s, prop, angle, ismath="TeX") + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + """ + Draw the text instance + + Parameters + ---------- + gc : `GraphicsContextBase` + the graphics context + + x : scalar + the x location of the text in display coords + + y : scalar + the y location of the text baseline in display coords + + s : str + the text string + + prop : `matplotlib.font_manager.FontProperties` + font properties + + angle : scalar + the rotation angle in degrees + + mtext : `matplotlib.text.Text` + the original text object to be rendered + + Notes + ----- + **backend implementers note** + + When you are trying to determine if you have gotten your bounding box + right (which is what enables the text layout/alignment to work + properly), it helps to change the line in text.py:: + + if 0: bbox_artist(self, renderer) + + to if 1, and then the actual bounding box will be plotted along with + your text. + """ + + self._draw_text_as_path(gc, x, y, s, prop, angle, ismath) + + def _get_text_path_transform(self, x, y, s, prop, angle, ismath): + """ + return the text path and transform + + Parameters + ---------- + prop : `matplotlib.font_manager.FontProperties` + font property + + s : str + text to be converted + + usetex : bool + If True, use matplotlib usetex mode. + + ismath : bool + If True, use mathtext parser. If "TeX", use *usetex* mode. + """ + + text2path = self._text2path + fontsize = self.points_to_pixels(prop.get_size_in_points()) + + if ismath == "TeX": + verts, codes = text2path.get_text_path(prop, s, ismath=False, + usetex=True) + else: + verts, codes = text2path.get_text_path(prop, s, ismath=ismath, + usetex=False) + + path = Path(verts, codes) + angle = np.deg2rad(angle) + if self.flipy(): + transform = Affine2D().scale(fontsize / text2path.FONT_SCALE, + fontsize / text2path.FONT_SCALE) + transform = transform.rotate(angle).translate(x, self.height - y) + else: + transform = Affine2D().scale(fontsize / text2path.FONT_SCALE, + fontsize / text2path.FONT_SCALE) + transform = transform.rotate(angle).translate(x, y) + + return path, transform + + def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath): + """ + draw the text by converting them to paths using textpath module. + + Parameters + ---------- + prop : `matplotlib.font_manager.FontProperties` + font property + + s : str + text to be converted + + usetex : bool + If True, use matplotlib usetex mode. + + ismath : bool + If True, use mathtext parser. If "TeX", use *usetex* mode. + """ + path, transform = self._get_text_path_transform( + x, y, s, prop, angle, ismath) + color = gc.get_rgb() + + gc.set_linewidth(0.0) + self.draw_path(gc, path, transform, rgbFace=color) + + def get_text_width_height_descent(self, s, prop, ismath): + """ + Get the width, height, and descent (offset from the bottom + to the baseline), in display coords, of the string *s* with + :class:`~matplotlib.font_manager.FontProperties` *prop* + """ + if ismath == 'TeX': + # todo: handle props + size = prop.get_size_in_points() + texmanager = self._text2path.get_texmanager() + fontsize = prop.get_size_in_points() + w, h, d = texmanager.get_text_width_height_descent( + s, fontsize, renderer=self) + return w, h, d + + dpi = self.points_to_pixels(72) + if ismath: + dims = self._text2path.mathtext_parser.parse(s, dpi, prop) + return dims[0:3] # return width, height, descent + + flags = self._text2path._get_hinting_flag() + font = self._text2path._get_font(prop) + size = prop.get_size_in_points() + font.set_size(size, dpi) + # the width and height of unrotated string + font.set_text(s, 0.0, flags=flags) + w, h = font.get_width_height() + d = font.get_descent() + w /= 64.0 # convert from subpixels + h /= 64.0 + d /= 64.0 + return w, h, d + + def flipy(self): + """ + Return true if y small numbers are top for renderer Is used + for drawing text (:mod:`matplotlib.text`) and images + (:mod:`matplotlib.image`) only + """ + return True + + def get_canvas_width_height(self): + 'return the canvas width and height in display coords' + return 1, 1 + + def get_texmanager(self): + """ + return the :class:`matplotlib.texmanager.TexManager` instance + """ + if self._texmanager is None: + from matplotlib.texmanager import TexManager + self._texmanager = TexManager() + return self._texmanager + + def new_gc(self): + """ + Return an instance of a :class:`GraphicsContextBase` + """ + return GraphicsContextBase() + + def points_to_pixels(self, points): + """ + Convert points to display units + + You need to override this function (unless your backend + doesn't have a dpi, e.g., postscript or svg). Some imaging + systems assume some value for pixels per inch:: + + points to pixels = points * pixels_per_inch/72.0 * dpi/72.0 + + Parameters + ---------- + points : scalar or array_like + a float or a numpy array of float + + Returns + ------- + Points converted to pixels + """ + return points + + def strip_math(self, s): + return cbook.strip_math(s) + + def start_rasterizing(self): + """ + Used in MixedModeRenderer. Switch to the raster renderer. + """ + + def stop_rasterizing(self): + """ + Used in MixedModeRenderer. Switch back to the vector renderer + and draw the contents of the raster renderer as an image on + the vector renderer. + """ + + def start_filter(self): + """ + Used in AggRenderer. Switch to a temporary renderer for image + filtering effects. + """ + + def stop_filter(self, filter_func): + """ + Used in AggRenderer. Switch back to the original renderer. + The contents of the temporary renderer is processed with the + *filter_func* and is drawn on the original renderer as an + image. + """ + + +class GraphicsContextBase(object): + """ + An abstract base class that provides color, line styles, etc... + """ + + def __init__(self): + self._alpha = 1.0 + self._forced_alpha = False # if True, _alpha overrides A from RGBA + self._antialiased = 1 # use 0,1 not True, False for extension code + self._capstyle = 'butt' + self._cliprect = None + self._clippath = None + self._dashes = None, None + self._joinstyle = 'round' + self._linestyle = 'solid' + self._linewidth = 1 + self._rgb = (0.0, 0.0, 0.0, 1.0) + self._hatch = None + self._hatch_color = colors.to_rgba(rcParams['hatch.color']) + self._hatch_linewidth = rcParams['hatch.linewidth'] + self._url = None + self._gid = None + self._snap = None + self._sketch = None + + def copy_properties(self, gc): + 'Copy properties from gc to self' + self._alpha = gc._alpha + self._forced_alpha = gc._forced_alpha + self._antialiased = gc._antialiased + self._capstyle = gc._capstyle + self._cliprect = gc._cliprect + self._clippath = gc._clippath + self._dashes = gc._dashes + self._joinstyle = gc._joinstyle + self._linestyle = gc._linestyle + self._linewidth = gc._linewidth + self._rgb = gc._rgb + self._hatch = gc._hatch + self._hatch_color = gc._hatch_color + self._hatch_linewidth = gc._hatch_linewidth + self._url = gc._url + self._gid = gc._gid + self._snap = gc._snap + self._sketch = gc._sketch + + def restore(self): + """ + Restore the graphics context from the stack - needed only + for backends that save graphics contexts on a stack + """ + + def get_alpha(self): + """ + Return the alpha value used for blending - not supported on + all backends + """ + return self._alpha + + def get_antialiased(self): + "Return true if the object should try to do antialiased rendering" + return self._antialiased + + def get_capstyle(self): + """ + Return the capstyle as a string in ('butt', 'round', 'projecting') + """ + return self._capstyle + + def get_clip_rectangle(self): + """ + Return the clip rectangle as a :class:`~matplotlib.transforms.Bbox` + instance + """ + return self._cliprect + + def get_clip_path(self): + """ + Return the clip path in the form (path, transform), where path + is a :class:`~matplotlib.path.Path` instance, and transform is + an affine transform to apply to the path before clipping. + """ + if self._clippath is not None: + return self._clippath.get_transformed_path_and_affine() + return None, None + + def get_dashes(self): + """ + Return the dash information as an offset dashlist tuple. + + The dash list is a even size list that gives the ink on, ink + off in pixels. + + See p107 of to PostScript `BLUEBOOK + `_ + for more info. + + Default value is None + """ + return self._dashes + + def get_forced_alpha(self): + """ + Return whether the value given by get_alpha() should be used to + override any other alpha-channel values. + """ + return self._forced_alpha + + def get_joinstyle(self): + """ + Return the line join style as one of ('miter', 'round', 'bevel') + """ + return self._joinstyle + + @cbook.deprecated("2.1") + def get_linestyle(self): + """ + Return the linestyle: one of ('solid', 'dashed', 'dashdot', + 'dotted'). + """ + return self._linestyle + + def get_linewidth(self): + """ + Return the line width in points as a scalar + """ + return self._linewidth + + def get_rgb(self): + """ + returns a tuple of three or four floats from 0-1. + """ + return self._rgb + + def get_url(self): + """ + returns a url if one is set, None otherwise + """ + return self._url + + def get_gid(self): + """ + Return the object identifier if one is set, None otherwise. + """ + return self._gid + + def get_snap(self): + """ + returns the snap setting which may be: + + * True: snap vertices to the nearest pixel center + + * False: leave vertices as-is + + * None: (auto) If the path contains only rectilinear line + segments, round to the nearest pixel center + """ + return self._snap + + def set_alpha(self, alpha): + """ + Set the alpha value used for blending - not supported on all backends. + If ``alpha=None`` (the default), the alpha components of the + foreground and fill colors will be used to set their respective + transparencies (where applicable); otherwise, ``alpha`` will override + them. + """ + if alpha is not None: + self._alpha = alpha + self._forced_alpha = True + else: + self._alpha = 1.0 + self._forced_alpha = False + self.set_foreground(self._rgb, isRGBA=True) + + def set_antialiased(self, b): + """ + True if object should be drawn with antialiased rendering + """ + + # use 0, 1 to make life easier on extension code trying to read the gc + if b: + self._antialiased = 1 + else: + self._antialiased = 0 + + def set_capstyle(self, cs): + """ + Set the capstyle as a string in ('butt', 'round', 'projecting') + """ + if cs in ('butt', 'round', 'projecting'): + self._capstyle = cs + else: + raise ValueError('Unrecognized cap style. Found %s' % cs) + + def set_clip_rectangle(self, rectangle): + """ + Set the clip rectangle with sequence (left, bottom, width, height) + """ + self._cliprect = rectangle + + def set_clip_path(self, path): + """ + Set the clip path and transformation. Path should be a + :class:`~matplotlib.transforms.TransformedPath` instance. + """ + if (path is not None + and not isinstance(path, transforms.TransformedPath)): + raise ValueError("Path should be a " + "matplotlib.transforms.TransformedPath instance") + self._clippath = path + + def set_dashes(self, dash_offset, dash_list): + """ + Set the dash style for the gc. + + Parameters + ---------- + dash_offset : float + is the offset (usually 0). + + dash_list : array_like + specifies the on-off sequence as points. + ``(None, None)`` specifies a solid line + + """ + if dash_list is not None: + dl = np.asarray(dash_list) + if np.any(dl < 0.0): + raise ValueError( + "All values in the dash list must be positive") + self._dashes = dash_offset, dash_list + + def set_foreground(self, fg, isRGBA=False): + """ + Set the foreground color. fg can be a MATLAB format string, a + html hex color string, an rgb or rgba unit tuple, or a float between 0 + and 1. In the latter case, grayscale is used. + + If you know fg is rgba, set ``isRGBA=True`` for efficiency. + """ + if self._forced_alpha and isRGBA: + self._rgb = fg[:3] + (self._alpha,) + elif self._forced_alpha: + self._rgb = colors.to_rgba(fg, self._alpha) + elif isRGBA: + self._rgb = fg + else: + self._rgb = colors.to_rgba(fg) + + def set_joinstyle(self, js): + """ + Set the join style to be one of ('miter', 'round', 'bevel') + """ + if js in ('miter', 'round', 'bevel'): + self._joinstyle = js + else: + raise ValueError('Unrecognized join style. Found %s' % js) + + def set_linewidth(self, w): + """ + Set the linewidth in points + """ + self._linewidth = float(w) + + @cbook.deprecated("2.1") + def set_linestyle(self, style): + """ + Set the linestyle to be one of ('solid', 'dashed', 'dashdot', + 'dotted'). These are defined in the rcParams + `lines.dashed_pattern`, `lines.dashdot_pattern` and + `lines.dotted_pattern`. One may also specify customized dash + styles by providing a tuple of (offset, dash pairs). + """ + self._linestyle = style + + def set_url(self, url): + """ + Sets the url for links in compatible backends + """ + self._url = url + + def set_gid(self, id): + """ + Sets the id. + """ + self._gid = id + + def set_snap(self, snap): + """ + Sets the snap setting which may be: + + * True: snap vertices to the nearest pixel center + + * False: leave vertices as-is + + * None: (auto) If the path contains only rectilinear line + segments, round to the nearest pixel center + """ + self._snap = snap + + def set_hatch(self, hatch): + """ + Sets the hatch style for filling + """ + self._hatch = hatch + + def get_hatch(self): + """ + Gets the current hatch style + """ + return self._hatch + + def get_hatch_path(self, density=6.0): + """ + Returns a Path for the current hatch. + """ + hatch = self.get_hatch() + if hatch is None: + return None + return Path.hatch(hatch, density) + + def get_hatch_color(self): + """ + Gets the color to use for hatching. + """ + return self._hatch_color + + def set_hatch_color(self, hatch_color): + """ + sets the color to use for hatching. + """ + self._hatch_color = hatch_color + + def get_hatch_linewidth(self): + """ + Gets the linewidth to use for hatching. + """ + return self._hatch_linewidth + + def get_sketch_params(self): + """ + Returns the sketch parameters for the artist. + + Returns + ------- + sketch_params : tuple or `None` + + A 3-tuple with the following elements: + + * `scale`: The amplitude of the wiggle perpendicular to the + source line. + + * `length`: The length of the wiggle along the line. + + * `randomness`: The scale factor by which the length is + shrunken or expanded. + + May return `None` if no sketch parameters were set. + """ + return self._sketch + + def set_sketch_params(self, scale=None, length=None, randomness=None): + """ + Sets the sketch parameters. + + Parameters + ---------- + + scale : float, optional + The amplitude of the wiggle perpendicular to the source + line, in pixels. If scale is `None`, or not provided, no + sketch filter will be provided. + + length : float, optional + The length of the wiggle along the line, in pixels + (default 128) + + randomness : float, optional + The scale factor by which the length is shrunken or + expanded (default 16) + """ + self._sketch = ( + None if scale is None + else (scale, length or 128., randomness or 16.)) + + +class TimerBase(object): + ''' + A base class for providing timer events, useful for things animations. + Backends need to implement a few specific methods in order to use their + own timing mechanisms so that the timer events are integrated into their + event loops. + + Mandatory functions that must be implemented: + + * `_timer_start`: Contains backend-specific code for starting + the timer + + * `_timer_stop`: Contains backend-specific code for stopping + the timer + + Optional overrides: + + * `_timer_set_single_shot`: Code for setting the timer to + single shot operating mode, if supported by the timer + object. If not, the `Timer` class itself will store the flag + and the `_on_timer` method should be overridden to support + such behavior. + + * `_timer_set_interval`: Code for setting the interval on the + timer, if there is a method for doing so on the timer + object. + + * `_on_timer`: This is the internal function that any timer + object should call, which will handle the task of running + all callbacks that have been set. + + Attributes + ---------- + interval : scalar + The time between timer events in milliseconds. Default is 1000 ms. + + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to `False`. + + callbacks : List[Tuple[callable, Tuple, Dict]] + Stores list of (func, args, kwargs) tuples that will be called upon + timer events. This list can be manipulated directly, or the + functions `add_callback` and `remove_callback` can be used. + + ''' + def __init__(self, interval=None, callbacks=None): + #Initialize empty callbacks list and setup default settings if necssary + if callbacks is None: + self.callbacks = [] + else: + self.callbacks = callbacks[:] # Create a copy + + if interval is None: + self._interval = 1000 + else: + self._interval = interval + + self._single = False + + # Default attribute for holding the GUI-specific timer object + self._timer = None + + def __del__(self): + 'Need to stop timer and possibly disconnect timer.' + self._timer_stop() + + def start(self, interval=None): + ''' + Start the timer object. `interval` is optional and will be used + to reset the timer interval first if provided. + ''' + if interval is not None: + self._set_interval(interval) + self._timer_start() + + def stop(self): + ''' + Stop the timer. + ''' + self._timer_stop() + + def _timer_start(self): + pass + + def _timer_stop(self): + pass + + def _get_interval(self): + return self._interval + + def _set_interval(self, interval): + # Force to int since none of the backends actually support fractional + # milliseconds, and some error or give warnings. + interval = int(interval) + self._interval = interval + self._timer_set_interval() + + interval = property(_get_interval, _set_interval) + + def _get_single_shot(self): + return self._single + + def _set_single_shot(self, ss=True): + self._single = ss + self._timer_set_single_shot() + + single_shot = property(_get_single_shot, _set_single_shot) + + def add_callback(self, func, *args, **kwargs): + ''' + Register `func` to be called by timer when the event fires. Any + additional arguments provided will be passed to `func`. + ''' + self.callbacks.append((func, args, kwargs)) + + def remove_callback(self, func, *args, **kwargs): + ''' + Remove `func` from list of callbacks. `args` and `kwargs` are optional + and used to distinguish between copies of the same function registered + to be called with different arguments. + ''' + if args or kwargs: + self.callbacks.remove((func, args, kwargs)) + else: + funcs = [c[0] for c in self.callbacks] + if func in funcs: + self.callbacks.pop(funcs.index(func)) + + def _timer_set_interval(self): + """Used to set interval on underlying timer object.""" + + def _timer_set_single_shot(self): + """Used to set single shot on underlying timer object.""" + + def _on_timer(self): + ''' + Runs all function that have been registered as callbacks. Functions + can return False (or 0) if they should not be called any more. If there + are no callbacks, the timer is automatically stopped. + ''' + for func, args, kwargs in self.callbacks: + ret = func(*args, **kwargs) + # docstring above explains why we use `if ret == 0` here, + # instead of `if not ret`. + # This will also catch `ret == False` as `False == 0` + # but does not annoy the linters + # https://docs.python.org/3/library/stdtypes.html#boolean-values + if ret == 0: + self.callbacks.remove((func, args, kwargs)) + + if len(self.callbacks) == 0: + self.stop() + + +class Event(object): + """ + A matplotlib event. Attach additional attributes as defined in + :meth:`FigureCanvasBase.mpl_connect`. The following attributes + are defined and shown with their default values + + Attributes + ---------- + name : str + the event name + + canvas : `FigureCanvasBase` + the backend-specific canvas instance generating the event + + guiEvent + the GUI event that triggered the matplotlib event + + """ + def __init__(self, name, canvas, guiEvent=None): + self.name = name + self.canvas = canvas + self.guiEvent = guiEvent + + +@cbook.deprecated("2.1") +class IdleEvent(Event): + """ + An event triggered by the GUI backend when it is idle -- useful + for passive animation + """ + + +class DrawEvent(Event): + """ + An event triggered by a draw operation on the canvas + + In most backends callbacks subscribed to this callback will be + fired after the rendering is complete but before the screen is + updated. Any extra artists drawn to the canvas's renderer will + be reflected without an explicit call to ``blit``. + + .. warning :: + + Calling ``canvas.draw`` and ``canvas.blit`` in these callbacks may + not be safe with all backends and may cause infinite recursion. + + In addition to the :class:`Event` attributes, the following event + attributes are defined: + + Attributes + ---------- + renderer : `RendererBase` + the renderer for the draw event + + """ + def __init__(self, name, canvas, renderer): + Event.__init__(self, name, canvas) + self.renderer = renderer + + +class ResizeEvent(Event): + """ + An event triggered by a canvas resize + + In addition to the :class:`Event` attributes, the following event + attributes are defined: + + Attributes + ---------- + width : scalar + width of the canvas in pixels + + height : scalar + height of the canvas in pixels + + """ + def __init__(self, name, canvas): + Event.__init__(self, name, canvas) + self.width, self.height = canvas.get_width_height() + + +class CloseEvent(Event): + """ + An event triggered by a figure being closed + + """ + def __init__(self, name, canvas, guiEvent=None): + Event.__init__(self, name, canvas, guiEvent) + + +class LocationEvent(Event): + """ + An event that has a screen location + + The following additional attributes are defined and shown with + their default values. + + In addition to the :class:`Event` attributes, the following + event attributes are defined: + + Attributes + ---------- + x : scalar + x position - pixels from left of canvas + + y : scalar + y position - pixels from bottom of canvas + + inaxes : bool + the :class:`~matplotlib.axes.Axes` instance if mouse is over axes + + xdata : scalar + x coord of mouse in data coords + + ydata : scalar + y coord of mouse in data coords + + """ + x = None # x position - pixels from left of canvas + y = None # y position - pixels from right of canvas + inaxes = None # the Axes instance if mouse us over axes + xdata = None # x coord of mouse in data coords + ydata = None # y coord of mouse in data coords + + # the last event that was triggered before this one + lastevent = None + + def __init__(self, name, canvas, x, y, guiEvent=None): + """ + *x*, *y* in figure coords, 0,0 = bottom, left + """ + Event.__init__(self, name, canvas, guiEvent=guiEvent) + self.x = x + self.y = y + + if x is None or y is None: + # cannot check if event was in axes if no x,y info + self.inaxes = None + self._update_enter_leave() + return + + # Find all axes containing the mouse + if self.canvas.mouse_grabber is None: + axes_list = [a for a in self.canvas.figure.get_axes() + if a.in_axes(self)] + else: + axes_list = [self.canvas.mouse_grabber] + + if axes_list: + self.inaxes = cbook._topmost_artist(axes_list) + try: + trans = self.inaxes.transData.inverted() + xdata, ydata = trans.transform_point((x, y)) + except ValueError: + self.xdata = None + self.ydata = None + else: + self.xdata = xdata + self.ydata = ydata + else: + self.inaxes = None + + self._update_enter_leave() + + def _update_enter_leave(self): + 'process the figure/axes enter leave events' + if LocationEvent.lastevent is not None: + last = LocationEvent.lastevent + if last.inaxes != self.inaxes: + # process axes enter/leave events + try: + if last.inaxes is not None: + last.canvas.callbacks.process('axes_leave_event', last) + except: + pass + # See ticket 2901582. + # I think this is a valid exception to the rule + # against catching all exceptions; if anything goes + # wrong, we simply want to move on and process the + # current event. + if self.inaxes is not None: + self.canvas.callbacks.process('axes_enter_event', self) + + else: + # process a figure enter event + if self.inaxes is not None: + self.canvas.callbacks.process('axes_enter_event', self) + + LocationEvent.lastevent = self + + +class MouseEvent(LocationEvent): + """ + A mouse event ('button_press_event', + 'button_release_event', + 'scroll_event', + 'motion_notify_event'). + + In addition to the :class:`Event` and :class:`LocationEvent` + attributes, the following attributes are defined: + + Attributes + ---------- + button : None, scalar, or str + button pressed None, 1, 2, 3, 'up', 'down' (up and down are used + for scroll events). Note that in the nbagg backend, both the + middle and right clicks return 3 since right clicking will bring + up the context menu in some browsers. + + key : None, or str + the key depressed when the mouse event triggered (see + :class:`KeyEvent`) + + step : scalar + number of scroll steps (positive for 'up', negative for 'down') + + Examples + -------- + Usage:: + + def on_press(event): + print('you pressed', event.button, event.xdata, event.ydata) + + cid = fig.canvas.mpl_connect('button_press_event', on_press) + + """ + x = None # x position - pixels from left of canvas + y = None # y position - pixels from right of canvas + button = None # button pressed None, 1, 2, 3 + dblclick = None # whether or not the event is the result of a double click + inaxes = None # the Axes instance if mouse us over axes + xdata = None # x coord of mouse in data coords + ydata = None # y coord of mouse in data coords + step = None # scroll steps for scroll events + + def __init__(self, name, canvas, x, y, button=None, key=None, + step=0, dblclick=False, guiEvent=None): + """ + x, y in figure coords, 0,0 = bottom, left + button pressed None, 1, 2, 3, 'up', 'down' + """ + LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent) + self.button = button + self.key = key + self.step = step + self.dblclick = dblclick + + def __str__(self): + return ("MPL MouseEvent: xy=(%d,%d) xydata=(%s,%s) button=%s " + + "dblclick=%s inaxes=%s") % (self.x, self.y, self.xdata, + self.ydata, self.button, + self.dblclick, self.inaxes) + + +class PickEvent(Event): + """ + a pick event, fired when the user picks a location on the canvas + sufficiently close to an artist. + + Attrs: all the :class:`Event` attributes plus + + Attributes + ---------- + mouseevent : `MouseEvent` + the mouse event that generated the pick + + artist : `matplotlib.artist.Artist` + the picked artist + + other + extra class dependent attrs -- e.g., a + :class:`~matplotlib.lines.Line2D` pick may define different + extra attributes than a + :class:`~matplotlib.collections.PatchCollection` pick event + + Examples + -------- + Usage:: + + ax.plot(np.rand(100), 'o', picker=5) # 5 points tolerance + + def on_pick(event): + line = event.artist + xdata, ydata = line.get_data() + ind = event.ind + print('on pick line:', np.array([xdata[ind], ydata[ind]]).T) + + cid = fig.canvas.mpl_connect('pick_event', on_pick) + + """ + def __init__(self, name, canvas, mouseevent, artist, + guiEvent=None, **kwargs): + Event.__init__(self, name, canvas, guiEvent) + self.mouseevent = mouseevent + self.artist = artist + self.__dict__.update(kwargs) + + +class KeyEvent(LocationEvent): + """ + A key event (key press, key release). + + Attach additional attributes as defined in + :meth:`FigureCanvasBase.mpl_connect`. + + In addition to the :class:`Event` and :class:`LocationEvent` + attributes, the following attributes are defined: + + Attributes + ---------- + key : None or str + the key(s) pressed. Could be **None**, a single case sensitive ascii + character ("g", "G", "#", etc.), a special key + ("control", "shift", "f1", "up", etc.) or a + combination of the above (e.g., "ctrl+alt+g", "ctrl+alt+G"). + + Notes + ----- + Modifier keys will be prefixed to the pressed key and will be in the order + "ctrl", "alt", "super". The exception to this rule is when the pressed key + is itself a modifier key, therefore "ctrl+alt" and "alt+control" can both + be valid key values. + + Examples + -------- + Usage:: + + def on_key(event): + print('you pressed', event.key, event.xdata, event.ydata) + + cid = fig.canvas.mpl_connect('key_press_event', on_key) + + """ + def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None): + LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent) + self.key = key + + +class FigureCanvasBase(object): + """ + The canvas the figure renders into. + + Public attributes + + Attributes + ---------- + figure : `matplotlib.figure.Figure` + A high-level figure instance + + """ + events = [ + 'resize_event', + 'draw_event', + 'key_press_event', + 'key_release_event', + 'button_press_event', + 'button_release_event', + 'scroll_event', + 'motion_notify_event', + 'pick_event', + 'idle_event', + 'figure_enter_event', + 'figure_leave_event', + 'axes_enter_event', + 'axes_leave_event', + 'close_event' + ] + + supports_blit = True + fixed_dpi = None + + filetypes = _default_filetypes + if _has_pil: + # JPEG support + register_backend('jpg', 'matplotlib.backends.backend_agg', + 'Joint Photographic Experts Group') + register_backend('jpeg', 'matplotlib.backends.backend_agg', + 'Joint Photographic Experts Group') + # TIFF support + register_backend('tif', 'matplotlib.backends.backend_agg', + 'Tagged Image File Format') + register_backend('tiff', 'matplotlib.backends.backend_agg', + 'Tagged Image File Format') + + def __init__(self, figure): + self._is_idle_drawing = True + self._is_saving = False + figure.set_canvas(self) + self.figure = figure + # a dictionary from event name to a dictionary that maps cid->func + self.callbacks = cbook.CallbackRegistry() + self.widgetlock = widgets.LockDraw() + self._button = None # the button pressed + self._key = None # the key pressed + self._lastx, self._lasty = None, None + self.button_pick_id = self.mpl_connect('button_press_event', self.pick) + self.scroll_pick_id = self.mpl_connect('scroll_event', self.pick) + self.mouse_grabber = None # the axes currently grabbing mouse + self.toolbar = None # NavigationToolbar2 will set me + self._is_idle_drawing = False + + @contextmanager + def _idle_draw_cntx(self): + self._is_idle_drawing = True + yield + self._is_idle_drawing = False + + def is_saving(self): + """ + Returns whether the renderer is in the process of saving + to a file, rather than rendering for an on-screen buffer. + """ + return self._is_saving + + @cbook.deprecated("2.2") + def onRemove(self, ev): + """ + Mouse event processor which removes the top artist + under the cursor. Connect this to the 'mouse_press_event' + using:: + + canvas.mpl_connect('mouse_press_event',canvas.onRemove) + """ + # Find the top artist under the cursor + under = cbook._topmost_artist(self.figure.hitlist(ev)) + h = None + if under: + h = under[-1] + + # Try deleting that artist, or its parent if you + # can't delete the artist + while h: + if h.remove(): + self.draw_idle() + break + parent = None + for p in under: + if h in p.get_children(): + parent = p + break + h = parent + + def pick(self, mouseevent): + if not self.widgetlock.locked(): + self.figure.pick(mouseevent) + + def blit(self, bbox=None): + """Blit the canvas in bbox (default entire canvas).""" + + def resize(self, w, h): + """Set the canvas size in pixels.""" + + def draw_event(self, renderer): + """Pass a `DrawEvent` to all functions connected to ``draw_event``.""" + s = 'draw_event' + event = DrawEvent(s, self, renderer) + self.callbacks.process(s, event) + + def resize_event(self): + """Pass a `ResizeEvent` to all functions connected to ``resize_event``. + """ + s = 'resize_event' + event = ResizeEvent(s, self) + self.callbacks.process(s, event) + self.draw_idle() + + def close_event(self, guiEvent=None): + """Pass a `CloseEvent` to all functions connected to ``close_event``. + """ + s = 'close_event' + try: + event = CloseEvent(s, self, guiEvent=guiEvent) + self.callbacks.process(s, event) + except (TypeError, AttributeError): + pass + # Suppress the TypeError when the python session is being killed. + # It may be that a better solution would be a mechanism to + # disconnect all callbacks upon shutdown. + # AttributeError occurs on OSX with qt4agg upon exiting + # with an open window; 'callbacks' attribute no longer exists. + + def key_press_event(self, key, guiEvent=None): + """Pass a `KeyEvent` to all functions connected to ``key_press_event``. + """ + self._key = key + s = 'key_press_event' + event = KeyEvent( + s, self, key, self._lastx, self._lasty, guiEvent=guiEvent) + self.callbacks.process(s, event) + + def key_release_event(self, key, guiEvent=None): + """ + Pass a `KeyEvent` to all functions connected to ``key_release_event``. + """ + s = 'key_release_event' + event = KeyEvent( + s, self, key, self._lastx, self._lasty, guiEvent=guiEvent) + self.callbacks.process(s, event) + self._key = None + + def pick_event(self, mouseevent, artist, **kwargs): + """ + This method will be called by artists who are picked and will + fire off :class:`PickEvent` callbacks registered listeners + """ + s = 'pick_event' + event = PickEvent(s, self, mouseevent, artist, + guiEvent=mouseevent.guiEvent, + **kwargs) + self.callbacks.process(s, event) + + def scroll_event(self, x, y, step, guiEvent=None): + """ + Backend derived classes should call this function on any + scroll wheel event. x,y are the canvas coords: 0,0 is lower, + left. button and key are as defined in MouseEvent. + + This method will be call all functions connected to the + 'scroll_event' with a :class:`MouseEvent` instance. + """ + if step >= 0: + self._button = 'up' + else: + self._button = 'down' + s = 'scroll_event' + mouseevent = MouseEvent(s, self, x, y, self._button, self._key, + step=step, guiEvent=guiEvent) + self.callbacks.process(s, mouseevent) + + def button_press_event(self, x, y, button, dblclick=False, guiEvent=None): + """ + Backend derived classes should call this function on any mouse + button press. x,y are the canvas coords: 0,0 is lower, left. + button and key are as defined in :class:`MouseEvent`. + + This method will be call all functions connected to the + 'button_press_event' with a :class:`MouseEvent` instance. + """ + self._button = button + s = 'button_press_event' + mouseevent = MouseEvent(s, self, x, y, button, self._key, + dblclick=dblclick, guiEvent=guiEvent) + self.callbacks.process(s, mouseevent) + + def button_release_event(self, x, y, button, guiEvent=None): + """ + Backend derived classes should call this function on any mouse + button release. + + This method will call all functions connected to the + 'button_release_event' with a :class:`MouseEvent` instance. + + Parameters + ---------- + x : scalar + the canvas coordinates where 0=left + + y : scalar + the canvas coordinates where 0=bottom + + guiEvent + the native UI event that generated the mpl event + + """ + s = 'button_release_event' + event = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent) + self.callbacks.process(s, event) + self._button = None + + def motion_notify_event(self, x, y, guiEvent=None): + """ + Backend derived classes should call this function on any + motion-notify-event. + + This method will call all functions connected to the + 'motion_notify_event' with a :class:`MouseEvent` instance. + + Parameters + ---------- + x : scalar + the canvas coordinates where 0=left + + y : scalar + the canvas coordinates where 0=bottom + + guiEvent + the native UI event that generated the mpl event + + """ + self._lastx, self._lasty = x, y + s = 'motion_notify_event' + event = MouseEvent(s, self, x, y, self._button, self._key, + guiEvent=guiEvent) + self.callbacks.process(s, event) + + def leave_notify_event(self, guiEvent=None): + """ + Backend derived classes should call this function when leaving + canvas + + Parameters + ---------- + guiEvent + the native UI event that generated the mpl event + + """ + + self.callbacks.process('figure_leave_event', LocationEvent.lastevent) + LocationEvent.lastevent = None + self._lastx, self._lasty = None, None + + def enter_notify_event(self, guiEvent=None, xy=None): + """ + Backend derived classes should call this function when entering + canvas + + Parameters + ---------- + guiEvent + the native UI event that generated the mpl event + xy : tuple of 2 scalars + the coordinate location of the pointer when the canvas is + entered + + """ + if xy is not None: + x, y = xy + self._lastx, self._lasty = x, y + + event = Event('figure_enter_event', self, guiEvent) + self.callbacks.process('figure_enter_event', event) + + @cbook.deprecated("2.1") + def idle_event(self, guiEvent=None): + """Called when GUI is idle.""" + s = 'idle_event' + event = IdleEvent(s, self, guiEvent=guiEvent) + self.callbacks.process(s, event) + + def grab_mouse(self, ax): + """ + Set the child axes which are currently grabbing the mouse events. + Usually called by the widgets themselves. + It is an error to call this if the mouse is already grabbed by + another axes. + """ + if self.mouse_grabber not in (None, ax): + raise RuntimeError("Another Axes already grabs mouse input") + self.mouse_grabber = ax + + def release_mouse(self, ax): + """ + Release the mouse grab held by the axes, ax. + Usually called by the widgets. + It is ok to call this even if you ax doesn't have the mouse + grab currently. + """ + if self.mouse_grabber is ax: + self.mouse_grabber = None + + def draw(self, *args, **kwargs): + """Render the :class:`~matplotlib.figure.Figure`.""" + + def draw_idle(self, *args, **kwargs): + """ + :meth:`draw` only if idle; defaults to draw but backends can override + """ + if not self._is_idle_drawing: + with self._idle_draw_cntx(): + self.draw(*args, **kwargs) + + def draw_cursor(self, event): + """ + Draw a cursor in the event.axes if inaxes is not None. Use + native GUI drawing for efficiency if possible + """ + + def get_width_height(self): + """ + Return the figure width and height in points or pixels + (depending on the backend), truncated to integers + """ + return int(self.figure.bbox.width), int(self.figure.bbox.height) + + @classmethod + def get_supported_filetypes(cls): + """Return dict of savefig file formats supported by this backend""" + return cls.filetypes + + @classmethod + def get_supported_filetypes_grouped(cls): + """Return a dict of savefig file formats supported by this backend, + where the keys are a file type name, such as 'Joint Photographic + Experts Group', and the values are a list of filename extensions used + for that filetype, such as ['jpg', 'jpeg'].""" + groupings = {} + for ext, name in six.iteritems(cls.filetypes): + groupings.setdefault(name, []).append(ext) + groupings[name].sort() + return groupings + + def _get_output_canvas(self, fmt): + """ + Return a canvas suitable for saving figures to a specified file format. + + If necessary, this function will switch to a registered backend that + supports the format. + """ + method_name = 'print_%s' % fmt + # Return the current canvas if it supports the requested format. + if hasattr(self, method_name): + return self + # Return a default canvas for the requested format, if it exists. + canvas_class = get_registered_canvas_class(fmt) + if canvas_class: + return self.switch_backends(canvas_class) + # Else report error for unsupported format. + raise ValueError( + "Format {!r} is not supported (supported formats: {})" + .format(fmt, ", ".join(sorted(self.get_supported_filetypes())))) + + def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None, + orientation='portrait', format=None, **kwargs): + """ + Render the figure to hardcopy. Set the figure patch face and edge + colors. This is useful because some of the GUIs have a gray figure + face color background and you'll probably want to override this on + hardcopy. + + Parameters + ---------- + filename + can also be a file object on image backends + + orientation : {'landscape', 'portrait'}, optional + only currently applies to PostScript printing. + + dpi : scalar, optional + the dots per inch to save the figure in; if None, use savefig.dpi + + facecolor : color spec or None, optional + the facecolor of the figure; if None, defaults to savefig.facecolor + + edgecolor : color spec or None, optional + the edgecolor of the figure; if None, defaults to savefig.edgecolor + + format : str, optional + when set, forcibly set the file format to save to + + bbox_inches : str or `~matplotlib.transforms.Bbox`, optional + Bbox in inches. Only the given portion of the figure is + saved. If 'tight', try to figure out the tight bbox of + the figure. If None, use savefig.bbox + + pad_inches : scalar, optional + Amount of padding around the figure when bbox_inches is + 'tight'. If None, use savefig.pad_inches + + bbox_extra_artists : list of `~matplotlib.artist.Artist`, optional + A list of extra artists that will be considered when the + tight bbox is calculated. + + """ + self._is_saving = True + # Remove the figure manager, if any, to avoid resizing the GUI widget. + # Having *no* manager and a *None* manager are currently different (see + # Figure.show); should probably be normalized to None at some point. + _no_manager = object() + if hasattr(self, 'manager'): + manager = self.manager + del self.manager + else: + manager = _no_manager + + if format is None: + # get format from filename, or from backend's default filetype + if isinstance(filename, getattr(os, "PathLike", ())): + filename = os.fspath(filename) + if isinstance(filename, six.string_types): + format = os.path.splitext(filename)[1][1:] + if format is None or format == '': + format = self.get_default_filetype() + if isinstance(filename, six.string_types): + filename = filename.rstrip('.') + '.' + format + format = format.lower() + + # get canvas object and print method for format + canvas = self._get_output_canvas(format) + print_method = getattr(canvas, 'print_%s' % format) + + if dpi is None: + dpi = rcParams['savefig.dpi'] + + if dpi == 'figure': + dpi = getattr(self.figure, '_original_dpi', self.figure.dpi) + + if facecolor is None: + facecolor = rcParams['savefig.facecolor'] + if edgecolor is None: + edgecolor = rcParams['savefig.edgecolor'] + + origDPI = self.figure.dpi + origfacecolor = self.figure.get_facecolor() + origedgecolor = self.figure.get_edgecolor() + + self.figure.dpi = dpi + self.figure.set_facecolor(facecolor) + self.figure.set_edgecolor(edgecolor) + + bbox_inches = kwargs.pop("bbox_inches", None) + if bbox_inches is None: + bbox_inches = rcParams['savefig.bbox'] + + if bbox_inches: + # call adjust_bbox to save only the given area + if bbox_inches == "tight": + # When bbox_inches == "tight", it saves the figure twice. The + # first save command (to a BytesIO) is just to estimate the + # bounding box of the figure. + result = print_method( + io.BytesIO(), + dpi=dpi, + facecolor=facecolor, + edgecolor=edgecolor, + orientation=orientation, + dryrun=True, + **kwargs) + renderer = self.figure._cachedRenderer + bbox_inches = self.figure.get_tightbbox(renderer) + + bbox_artists = kwargs.pop("bbox_extra_artists", None) + if bbox_artists is None: + bbox_artists = self.figure.get_default_bbox_extra_artists() + + bbox_filtered = [] + for a in bbox_artists: + bbox = a.get_window_extent(renderer) + if a.get_clip_on(): + clip_box = a.get_clip_box() + if clip_box is not None: + bbox = Bbox.intersection(bbox, clip_box) + clip_path = a.get_clip_path() + if clip_path is not None and bbox is not None: + clip_path = clip_path.get_fully_transformed_path() + bbox = Bbox.intersection(bbox, + clip_path.get_extents()) + if bbox is not None and (bbox.width != 0 or + bbox.height != 0): + bbox_filtered.append(bbox) + + if bbox_filtered: + _bbox = Bbox.union(bbox_filtered) + trans = Affine2D().scale(1.0 / self.figure.dpi) + bbox_extra = TransformedBbox(_bbox, trans) + bbox_inches = Bbox.union([bbox_inches, bbox_extra]) + + pad = kwargs.pop("pad_inches", None) + if pad is None: + pad = rcParams['savefig.pad_inches'] + + bbox_inches = bbox_inches.padded(pad) + + restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches, + canvas.fixed_dpi) + + _bbox_inches_restore = (bbox_inches, restore_bbox) + else: + _bbox_inches_restore = None + + try: + result = print_method( + filename, + dpi=dpi, + facecolor=facecolor, + edgecolor=edgecolor, + orientation=orientation, + bbox_inches_restore=_bbox_inches_restore, + **kwargs) + finally: + if bbox_inches and restore_bbox: + restore_bbox() + + self.figure.dpi = origDPI + self.figure.set_facecolor(origfacecolor) + self.figure.set_edgecolor(origedgecolor) + self.figure.set_canvas(self) + if manager is not _no_manager: + self.manager = manager + self._is_saving = False + return result + + @classmethod + def get_default_filetype(cls): + """ + Get the default savefig file format as specified in rcParam + ``savefig.format``. Returned string excludes period. Overridden + in backends that only support a single file type. + """ + return rcParams['savefig.format'] + + def get_window_title(self): + """ + Get the title text of the window containing the figure. + Return None if there is no window (e.g., a PS backend). + """ + if hasattr(self, "manager"): + return self.manager.get_window_title() + + def set_window_title(self, title): + """ + Set the title text of the window containing the figure. Note that + this has no effect if there is no window (e.g., a PS backend). + """ + if hasattr(self, "manager"): + self.manager.set_window_title(title) + + def get_default_filename(self): + """ + Return a string, which includes extension, suitable for use as + a default filename. + """ + default_basename = self.get_window_title() or 'image' + default_basename = default_basename.replace(' ', '_') + default_filetype = self.get_default_filetype() + default_filename = default_basename + '.' + default_filetype + + save_dir = os.path.expanduser(rcParams['savefig.directory']) + + # ensure non-existing filename in save dir + i = 1 + while os.path.isfile(os.path.join(save_dir, default_filename)): + # attach numerical count to basename + default_filename = ( + '{}-{}.{}'.format(default_basename, i, default_filetype)) + i += 1 + + return default_filename + + def switch_backends(self, FigureCanvasClass): + """ + Instantiate an instance of FigureCanvasClass + + This is used for backend switching, e.g., to instantiate a + FigureCanvasPS from a FigureCanvasGTK. Note, deep copying is + not done, so any changes to one of the instances (e.g., setting + figure size or line props), will be reflected in the other + """ + newCanvas = FigureCanvasClass(self.figure) + newCanvas._is_saving = self._is_saving + return newCanvas + + def mpl_connect(self, s, func): + """ + Connect event with string *s* to *func*. The signature of *func* is:: + + def func(event) + + where event is a :class:`matplotlib.backend_bases.Event`. The + following events are recognized + + - 'button_press_event' + - 'button_release_event' + - 'draw_event' + - 'key_press_event' + - 'key_release_event' + - 'motion_notify_event' + - 'pick_event' + - 'resize_event' + - 'scroll_event' + - 'figure_enter_event', + - 'figure_leave_event', + - 'axes_enter_event', + - 'axes_leave_event' + - 'close_event' + + For the location events (button and key press/release), if the + mouse is over the axes, the variable ``event.inaxes`` will be + set to the :class:`~matplotlib.axes.Axes` the event occurs is + over, and additionally, the variables ``event.xdata`` and + ``event.ydata`` will be defined. This is the mouse location + in data coords. See + :class:`~matplotlib.backend_bases.KeyEvent` and + :class:`~matplotlib.backend_bases.MouseEvent` for more info. + + Return value is a connection id that can be used with + :meth:`~matplotlib.backend_bases.Event.mpl_disconnect`. + + Examples + -------- + Usage:: + + def on_press(event): + print('you pressed', event.button, event.xdata, event.ydata) + + cid = canvas.mpl_connect('button_press_event', on_press) + + """ + if s == 'idle_event': + cbook.warn_deprecated(1.5, + "idle_event is only implemented for the wx backend, and will " + "be removed in matplotlib 2.1. Use the animations module " + "instead.") + + return self.callbacks.connect(s, func) + + def mpl_disconnect(self, cid): + """ + Disconnect callback id cid + + Examples + -------- + Usage:: + + cid = canvas.mpl_connect('button_press_event', on_press) + #...later + canvas.mpl_disconnect(cid) + """ + return self.callbacks.disconnect(cid) + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of + :class:`backend_bases.Timer`. This is useful for getting periodic + events through the backend's native event loop. Implemented only for + backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + + callbacks : List[Tuple[callable, Tuple, Dict]] + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + + callbacks which return ``False`` or ``0`` will be removed from the + timer. + + Examples + -------- + + >>> timer = fig.canvas.new_timer(callbacks=[(f1, (1, ), {'a': 3}),]) + + """ + return TimerBase(*args, **kwargs) + + def flush_events(self): + """Flush the GUI events for the figure. + + Interactive backends need to reimplement this method. + """ + + def start_event_loop(self, timeout=0): + """Start a blocking event loop. + + Such an event loop is used by interactive functions, such as `ginput` + and `waitforbuttonpress`, to wait for events. + + The event loop blocks until a callback function triggers + `stop_event_loop`, or *timeout* is reached. + + If *timeout* is negative, never timeout. + + Only interactive backends need to reimplement this method and it relies + on `flush_events` being properly implemented. + + Interactive backends should implement this in a more native way. + """ + if timeout <= 0: + timeout = np.inf + timestep = 0.01 + counter = 0 + self._looping = True + while self._looping and counter * timestep < timeout: + self.flush_events() + time.sleep(timestep) + counter += 1 + + def stop_event_loop(self): + """Stop the current blocking event loop. + + Interactive backends need to reimplement this to match + `start_event_loop` + """ + self._looping = False + + start_event_loop_default = cbook.deprecated( + "2.1", name="start_event_loop_default")(start_event_loop) + stop_event_loop_default = cbook.deprecated( + "2.1", name="stop_event_loop_default")(stop_event_loop) + + +def key_press_handler(event, canvas, toolbar=None): + """ + Implement the default mpl key bindings for the canvas and toolbar + described at :ref:`key-event-handling` + + Parameters + ---------- + event : :class:`KeyEvent` + a key press/release event + canvas : :class:`FigureCanvasBase` + the backend-specific canvas instance + toolbar : :class:`NavigationToolbar2` + the navigation cursor toolbar + + """ + # these bindings happen whether you are over an axes or not + + if event.key is None: + return + + # Load key-mappings from your matplotlibrc file. + fullscreen_keys = rcParams['keymap.fullscreen'] + home_keys = rcParams['keymap.home'] + back_keys = rcParams['keymap.back'] + forward_keys = rcParams['keymap.forward'] + pan_keys = rcParams['keymap.pan'] + zoom_keys = rcParams['keymap.zoom'] + save_keys = rcParams['keymap.save'] + quit_keys = rcParams['keymap.quit'] + grid_keys = rcParams['keymap.grid'] + grid_minor_keys = rcParams['keymap.grid_minor'] + toggle_yscale_keys = rcParams['keymap.yscale'] + toggle_xscale_keys = rcParams['keymap.xscale'] + all_keys = rcParams['keymap.all_axes'] + + # toggle fullscreen mode ('f', 'ctrl + f') + if event.key in fullscreen_keys: + try: + canvas.manager.full_screen_toggle() + except AttributeError: + pass + + # quit the figure (default key 'ctrl+w') + if event.key in quit_keys: + Gcf.destroy_fig(canvas.figure) + + if toolbar is not None: + # home or reset mnemonic (default key 'h', 'home' and 'r') + if event.key in home_keys: + toolbar.home() + # forward / backward keys to enable left handed quick navigation + # (default key for backward: 'left', 'backspace' and 'c') + elif event.key in back_keys: + toolbar.back() + # (default key for forward: 'right' and 'v') + elif event.key in forward_keys: + toolbar.forward() + # pan mnemonic (default key 'p') + elif event.key in pan_keys: + toolbar.pan() + toolbar._set_cursor(event) + # zoom mnemonic (default key 'o') + elif event.key in zoom_keys: + toolbar.zoom() + toolbar._set_cursor(event) + # saving current figure (default key 's') + elif event.key in save_keys: + toolbar.save_figure() + + if event.inaxes is None: + return + + # these bindings require the mouse to be over an axes to trigger + def _get_uniform_gridstate(ticks): + # Return True/False if all grid lines are on or off, None if they are + # not all in the same state. + if all(tick.gridOn for tick in ticks): + return True + elif not any(tick.gridOn for tick in ticks): + return False + else: + return None + + ax = event.inaxes + # toggle major grids in current axes (default key 'g') + # Both here and below (for 'G'), we do nothing if *any* grid (major or + # minor, x or y) is not in a uniform state, to avoid messing up user + # customization. + if (event.key in grid_keys + # Exclude minor grids not in a uniform state. + and None not in [_get_uniform_gridstate(ax.xaxis.minorTicks), + _get_uniform_gridstate(ax.yaxis.minorTicks)]): + x_state = _get_uniform_gridstate(ax.xaxis.majorTicks) + y_state = _get_uniform_gridstate(ax.yaxis.majorTicks) + cycle = [(False, False), (True, False), (True, True), (False, True)] + try: + x_state, y_state = ( + cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)]) + except ValueError: + # Exclude major grids not in a uniform state. + pass + else: + # If turning major grids off, also turn minor grids off. + ax.grid(x_state, which="major" if x_state else "both", axis="x") + ax.grid(y_state, which="major" if y_state else "both", axis="y") + canvas.draw_idle() + # toggle major and minor grids in current axes (default key 'G') + if (event.key in grid_minor_keys + # Exclude major grids not in a uniform state. + and None not in [_get_uniform_gridstate(ax.xaxis.majorTicks), + _get_uniform_gridstate(ax.yaxis.majorTicks)]): + x_state = _get_uniform_gridstate(ax.xaxis.minorTicks) + y_state = _get_uniform_gridstate(ax.yaxis.minorTicks) + cycle = [(False, False), (True, False), (True, True), (False, True)] + try: + x_state, y_state = ( + cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)]) + except ValueError: + # Exclude minor grids not in a uniform state. + pass + else: + ax.grid(x_state, which="both", axis="x") + ax.grid(y_state, which="both", axis="y") + canvas.draw_idle() + # toggle scaling of y-axes between 'log and 'linear' (default key 'l') + elif event.key in toggle_yscale_keys: + scale = ax.get_yscale() + if scale == 'log': + ax.set_yscale('linear') + ax.figure.canvas.draw_idle() + elif scale == 'linear': + try: + ax.set_yscale('log') + except ValueError as exc: + warnings.warn(str(exc)) + ax.set_yscale('linear') + ax.figure.canvas.draw_idle() + # toggle scaling of x-axes between 'log and 'linear' (default key 'k') + elif event.key in toggle_xscale_keys: + scalex = ax.get_xscale() + if scalex == 'log': + ax.set_xscale('linear') + ax.figure.canvas.draw_idle() + elif scalex == 'linear': + try: + ax.set_xscale('log') + except ValueError as exc: + warnings.warn(str(exc)) + ax.set_xscale('linear') + ax.figure.canvas.draw_idle() + + elif (event.key.isdigit() and event.key != '0') or event.key in all_keys: + # keys in list 'all' enables all axes (default key 'a'), + # otherwise if key is a number only enable this particular axes + # if it was the axes, where the event was raised + if not (event.key in all_keys): + n = int(event.key) - 1 + for i, a in enumerate(canvas.figure.get_axes()): + # consider axes, in which the event was raised + # FIXME: Why only this axes? + if event.x is not None and event.y is not None \ + and a.in_axes(event): + if event.key in all_keys: + a.set_navigate(True) + else: + a.set_navigate(i == n) + + +class NonGuiException(Exception): + pass + + +class FigureManagerBase(object): + """ + Helper class for pyplot mode, wraps everything up into a neat bundle + + Attributes + ---------- + canvas : :class:`FigureCanvasBase` + The backend-specific canvas instance + + num : int or str + The figure number + + key_press_handler_id : int + The default key handler cid, when using the toolmanager. Can be used + to disable default key press handling :: + + figure.canvas.mpl_disconnect( + figure.canvas.manager.key_press_handler_id) + """ + def __init__(self, canvas, num): + self.canvas = canvas + canvas.manager = self # store a pointer to parent + self.num = num + + self.key_press_handler_id = None + if rcParams['toolbar'] != 'toolmanager': + self.key_press_handler_id = self.canvas.mpl_connect( + 'key_press_event', + self.key_press) + + def show(self): + """ + For GUI backends, show the figure window and redraw. + For non-GUI backends, raise an exception to be caught + by :meth:`~matplotlib.figure.Figure.show`, for an + optional warning. + """ + raise NonGuiException() + + def destroy(self): + pass + + def full_screen_toggle(self): + pass + + def resize(self, w, h): + """"For GUI backends, resize the window (in pixels).""" + + def key_press(self, event): + """ + Implement the default mpl key bindings defined at + :ref:`key-event-handling` + """ + if rcParams['toolbar'] != 'toolmanager': + key_press_handler(event, self.canvas, self.canvas.toolbar) + + @cbook.deprecated("2.2") + def show_popup(self, msg): + """Display message in a popup -- GUI only.""" + + def get_window_title(self): + """Get the title text of the window containing the figure. + + Return None for non-GUI (e.g., PS) backends. + """ + return 'image' + + def set_window_title(self, title): + """Set the title text of the window containing the figure. + + This has no effect for non-GUI (e.g., PS) backends. + """ + + +cursors = tools.cursors + + +class NavigationToolbar2(object): + """ + Base class for the navigation cursor, version 2 + + backends must implement a canvas that handles connections for + 'button_press_event' and 'button_release_event'. See + :meth:`FigureCanvasBase.mpl_connect` for more information + + + They must also define + + :meth:`save_figure` + save the current figure + + :meth:`set_cursor` + if you want the pointer icon to change + + :meth:`_init_toolbar` + create your toolbar widget + + :meth:`draw_rubberband` (optional) + draw the zoom to rect "rubberband" rectangle + + :meth:`press` (optional) + whenever a mouse button is pressed, you'll be notified with + the event + + :meth:`release` (optional) + whenever a mouse button is released, you'll be notified with + the event + + :meth:`set_message` (optional) + display message + + :meth:`set_history_buttons` (optional) + you can change the history back / forward buttons to + indicate disabled / enabled state. + + That's it, we'll do the rest! + """ + + # list of toolitems to add to the toolbar, format is: + # ( + # text, # the text of the button (often not visible to users) + # tooltip_text, # the tooltip shown on hover (where possible) + # image_file, # name of the image for the button (without the extension) + # name_of_method, # name of the method in NavigationToolbar2 to call + # ) + toolitems = ( + ('Home', 'Reset original view', 'home', 'home'), + ('Back', 'Back to previous view', 'back', 'back'), + ('Forward', 'Forward to next view', 'forward', 'forward'), + (None, None, None, None), + ('Pan', 'Pan axes with left mouse, zoom with right', 'move', 'pan'), + ('Zoom', 'Zoom to rectangle', 'zoom_to_rect', 'zoom'), + ('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'), + (None, None, None, None), + ('Save', 'Save the figure', 'filesave', 'save_figure'), + ) + + def __init__(self, canvas): + self.canvas = canvas + canvas.toolbar = self + self._nav_stack = cbook.Stack() + self._xypress = None # the location and axis info at the time + # of the press + self._idPress = None + self._idRelease = None + self._active = None + # This cursor will be set after the initial draw. + self._lastCursor = cursors.POINTER + self._init_toolbar() + self._idDrag = self.canvas.mpl_connect( + 'motion_notify_event', self.mouse_move) + + self._ids_zoom = [] + self._zoom_mode = None + + self._button_pressed = None # determined by the button pressed + # at start + + self.mode = '' # a mode string for the status bar + self.set_history_buttons() + + def set_message(self, s): + """Display a message on toolbar or in status bar.""" + + def back(self, *args): + """move back up the view lim stack""" + self._nav_stack.back() + self.set_history_buttons() + self._update_view() + + @cbook.deprecated("2.1", alternative="canvas.draw_idle") + def dynamic_update(self): + self.canvas.draw_idle() + + def draw_rubberband(self, event, x0, y0, x1, y1): + """Draw a rectangle rubberband to indicate zoom limits. + + Note that it is not guaranteed that ``x0 <= x1`` and ``y0 <= y1``. + """ + + def remove_rubberband(self): + """Remove the rubberband.""" + + def forward(self, *args): + """Move forward in the view lim stack.""" + self._nav_stack.forward() + self.set_history_buttons() + self._update_view() + + def home(self, *args): + """Restore the original view.""" + self._nav_stack.home() + self.set_history_buttons() + self._update_view() + + def _init_toolbar(self): + """ + This is where you actually build the GUI widgets (called by + __init__). The icons ``home.xpm``, ``back.xpm``, ``forward.xpm``, + ``hand.xpm``, ``zoom_to_rect.xpm`` and ``filesave.xpm`` are standard + across backends (there are ppm versions in CVS also). + + You just need to set the callbacks + + home : self.home + back : self.back + forward : self.forward + hand : self.pan + zoom_to_rect : self.zoom + filesave : self.save_figure + + You only need to define the last one - the others are in the base + class implementation. + + """ + raise NotImplementedError + + def _set_cursor(self, event): + if not event.inaxes or not self._active: + if self._lastCursor != cursors.POINTER: + self.set_cursor(cursors.POINTER) + self._lastCursor = cursors.POINTER + else: + if (self._active == 'ZOOM' + and self._lastCursor != cursors.SELECT_REGION): + self.set_cursor(cursors.SELECT_REGION) + self._lastCursor = cursors.SELECT_REGION + elif (self._active == 'PAN' and + self._lastCursor != cursors.MOVE): + self.set_cursor(cursors.MOVE) + self._lastCursor = cursors.MOVE + + def mouse_move(self, event): + self._set_cursor(event) + + if event.inaxes and event.inaxes.get_navigate(): + + try: + s = event.inaxes.format_coord(event.xdata, event.ydata) + except (ValueError, OverflowError): + pass + else: + artists = [a for a in event.inaxes.mouseover_set + if a.contains(event) and a.get_visible()] + + if artists: + a = cbook._topmost_artist(artists) + if a is not event.inaxes.patch: + data = a.get_cursor_data(event) + if data is not None: + s += ' [%s]' % a.format_cursor_data(data) + + if len(self.mode): + self.set_message('%s, %s' % (self.mode, s)) + else: + self.set_message(s) + else: + self.set_message(self.mode) + + def pan(self, *args): + """Activate the pan/zoom tool. pan with left button, zoom with right""" + # set the pointer icon and button press funcs to the + # appropriate callbacks + + if self._active == 'PAN': + self._active = None + else: + self._active = 'PAN' + if self._idPress is not None: + self._idPress = self.canvas.mpl_disconnect(self._idPress) + self.mode = '' + + if self._idRelease is not None: + self._idRelease = self.canvas.mpl_disconnect(self._idRelease) + self.mode = '' + + if self._active: + self._idPress = self.canvas.mpl_connect( + 'button_press_event', self.press_pan) + self._idRelease = self.canvas.mpl_connect( + 'button_release_event', self.release_pan) + self.mode = 'pan/zoom' + self.canvas.widgetlock(self) + else: + self.canvas.widgetlock.release(self) + + for a in self.canvas.figure.get_axes(): + a.set_navigate_mode(self._active) + + self.set_message(self.mode) + + def press(self, event): + """Called whenever a mouse button is pressed.""" + + def press_pan(self, event): + """Callback for mouse button press in pan/zoom mode.""" + + if event.button == 1: + self._button_pressed = 1 + elif event.button == 3: + self._button_pressed = 3 + else: + self._button_pressed = None + return + + if self._nav_stack() is None: + # set the home button to this view + self.push_current() + + x, y = event.x, event.y + self._xypress = [] + for i, a in enumerate(self.canvas.figure.get_axes()): + if (x is not None and y is not None and a.in_axes(event) and + a.get_navigate() and a.can_pan()): + a.start_pan(x, y, event.button) + self._xypress.append((a, i)) + self.canvas.mpl_disconnect(self._idDrag) + self._idDrag = self.canvas.mpl_connect('motion_notify_event', + self.drag_pan) + + self.press(event) + + def press_zoom(self, event): + """Callback for mouse button press in zoom to rect mode.""" + # If we're already in the middle of a zoom, pressing another + # button works to "cancel" + if self._ids_zoom != []: + for zoom_id in self._ids_zoom: + self.canvas.mpl_disconnect(zoom_id) + self.release(event) + self.draw() + self._xypress = None + self._button_pressed = None + self._ids_zoom = [] + return + + if event.button == 1: + self._button_pressed = 1 + elif event.button == 3: + self._button_pressed = 3 + else: + self._button_pressed = None + return + + if self._nav_stack() is None: + # set the home button to this view + self.push_current() + + x, y = event.x, event.y + self._xypress = [] + for i, a in enumerate(self.canvas.figure.get_axes()): + if (x is not None and y is not None and a.in_axes(event) and + a.get_navigate() and a.can_zoom()): + self._xypress.append((x, y, a, i, a._get_view())) + + id1 = self.canvas.mpl_connect('motion_notify_event', self.drag_zoom) + id2 = self.canvas.mpl_connect('key_press_event', + self._switch_on_zoom_mode) + id3 = self.canvas.mpl_connect('key_release_event', + self._switch_off_zoom_mode) + + self._ids_zoom = id1, id2, id3 + self._zoom_mode = event.key + + self.press(event) + + def _switch_on_zoom_mode(self, event): + self._zoom_mode = event.key + self.mouse_move(event) + + def _switch_off_zoom_mode(self, event): + self._zoom_mode = None + self.mouse_move(event) + + def push_current(self): + """Push the current view limits and position onto the stack.""" + self._nav_stack.push( + WeakKeyDictionary( + {ax: (ax._get_view(), + # Store both the original and modified positions. + (ax.get_position(True).frozen(), + ax.get_position().frozen())) + for ax in self.canvas.figure.axes})) + self.set_history_buttons() + + def release(self, event): + """Callback for mouse button release.""" + + def release_pan(self, event): + """Callback for mouse button release in pan/zoom mode.""" + + if self._button_pressed is None: + return + self.canvas.mpl_disconnect(self._idDrag) + self._idDrag = self.canvas.mpl_connect( + 'motion_notify_event', self.mouse_move) + for a, ind in self._xypress: + a.end_pan() + if not self._xypress: + return + self._xypress = [] + self._button_pressed = None + self.push_current() + self.release(event) + self.draw() + + def drag_pan(self, event): + """Callback for dragging in pan/zoom mode.""" + for a, ind in self._xypress: + #safer to use the recorded button at the press than current button: + #multiple button can get pressed during motion... + a.drag_pan(self._button_pressed, event.key, event.x, event.y) + self.canvas.draw_idle() + + def drag_zoom(self, event): + """Callback for dragging in zoom mode.""" + if self._xypress: + x, y = event.x, event.y + lastx, lasty, a, ind, view = self._xypress[0] + (x1, y1), (x2, y2) = np.clip( + [[lastx, lasty], [x, y]], a.bbox.min, a.bbox.max) + if self._zoom_mode == "x": + y1, y2 = a.bbox.intervaly + elif self._zoom_mode == "y": + x1, x2 = a.bbox.intervalx + self.draw_rubberband(event, x1, y1, x2, y2) + + def release_zoom(self, event): + """Callback for mouse button release in zoom to rect mode.""" + for zoom_id in self._ids_zoom: + self.canvas.mpl_disconnect(zoom_id) + self._ids_zoom = [] + + self.remove_rubberband() + + if not self._xypress: + return + + last_a = [] + + for cur_xypress in self._xypress: + x, y = event.x, event.y + lastx, lasty, a, ind, view = cur_xypress + # ignore singular clicks - 5 pixels is a threshold + # allows the user to "cancel" a zoom action + # by zooming by less than 5 pixels + if ((abs(x - lastx) < 5 and self._zoom_mode!="y") or + (abs(y - lasty) < 5 and self._zoom_mode!="x")): + self._xypress = None + self.release(event) + self.draw() + return + + # detect twinx,y axes and avoid double zooming + twinx, twiny = False, False + if last_a: + for la in last_a: + if a.get_shared_x_axes().joined(a, la): + twinx = True + if a.get_shared_y_axes().joined(a, la): + twiny = True + last_a.append(a) + + if self._button_pressed == 1: + direction = 'in' + elif self._button_pressed == 3: + direction = 'out' + else: + continue + + a._set_view_from_bbox((lastx, lasty, x, y), direction, + self._zoom_mode, twinx, twiny) + + self.draw() + self._xypress = None + self._button_pressed = None + + self._zoom_mode = None + + self.push_current() + self.release(event) + + def draw(self): + """Redraw the canvases, update the locators.""" + for a in self.canvas.figure.get_axes(): + xaxis = getattr(a, 'xaxis', None) + yaxis = getattr(a, 'yaxis', None) + locators = [] + if xaxis is not None: + locators.append(xaxis.get_major_locator()) + locators.append(xaxis.get_minor_locator()) + if yaxis is not None: + locators.append(yaxis.get_major_locator()) + locators.append(yaxis.get_minor_locator()) + + for loc in locators: + loc.refresh() + self.canvas.draw_idle() + + def _update_view(self): + """Update the viewlim and position from the view and + position stack for each axes. + """ + nav_info = self._nav_stack() + if nav_info is None: + return + # Retrieve all items at once to avoid any risk of GC deleting an Axes + # while in the middle of the loop below. + items = list(nav_info.items()) + for ax, (view, (pos_orig, pos_active)) in items: + ax._set_view(view) + # Restore both the original and modified positions + ax._set_position(pos_orig, 'original') + ax._set_position(pos_active, 'active') + self.canvas.draw_idle() + + def save_figure(self, *args): + """Save the current figure.""" + raise NotImplementedError + + def set_cursor(self, cursor): + """Set the current cursor to one of the :class:`Cursors` enums values. + + If required by the backend, this method should trigger an update in + the backend event loop after the cursor is set, as this method may be + called e.g. before a long-running task during which the GUI is not + updated. + """ + + def update(self): + """Reset the axes stack.""" + self._nav_stack.clear() + self.set_history_buttons() + + def zoom(self, *args): + """Activate zoom to rect mode.""" + if self._active == 'ZOOM': + self._active = None + else: + self._active = 'ZOOM' + + if self._idPress is not None: + self._idPress = self.canvas.mpl_disconnect(self._idPress) + self.mode = '' + + if self._idRelease is not None: + self._idRelease = self.canvas.mpl_disconnect(self._idRelease) + self.mode = '' + + if self._active: + self._idPress = self.canvas.mpl_connect('button_press_event', + self.press_zoom) + self._idRelease = self.canvas.mpl_connect('button_release_event', + self.release_zoom) + self.mode = 'zoom rect' + self.canvas.widgetlock(self) + else: + self.canvas.widgetlock.release(self) + + for a in self.canvas.figure.get_axes(): + a.set_navigate_mode(self._active) + + self.set_message(self.mode) + + def set_history_buttons(self): + """Enable or disable the back/forward button.""" + + +class ToolContainerBase(object): + """ + Base class for all tool containers, e.g. toolbars. + + Attributes + ---------- + toolmanager : `ToolManager` + The tools with which this `ToolContainer` wants to communicate. + """ + + _icon_extension = '.png' + """ + Toolcontainer button icon image format extension + + **String**: Image extension + """ + + def __init__(self, toolmanager): + self.toolmanager = toolmanager + self.toolmanager.toolmanager_connect('tool_removed_event', + self._remove_tool_cbk) + + def _tool_toggled_cbk(self, event): + """ + Captures the 'tool_trigger_[name]' + + This only gets used for toggled tools + """ + self.toggle_toolitem(event.tool.name, event.tool.toggled) + + def add_tool(self, tool, group, position=-1): + """ + Adds a tool to this container + + Parameters + ---------- + tool : tool_like + The tool to add, see `ToolManager.get_tool`. + group : str + The name of the group to add this tool to. + position : int (optional) + The position within the group to place this tool. Defaults to end. + """ + tool = self.toolmanager.get_tool(tool) + image = self._get_image_filename(tool.image) + toggle = getattr(tool, 'toggled', None) is not None + self.add_toolitem(tool.name, group, position, + image, tool.description, toggle) + if toggle: + self.toolmanager.toolmanager_connect('tool_trigger_%s' % tool.name, + self._tool_toggled_cbk) + # If initially toggled + if tool.toggled: + self.toggle_toolitem(tool.name, True) + + def _remove_tool_cbk(self, event): + """Captures the 'tool_removed_event' signal and removes the tool.""" + self.remove_toolitem(event.tool.name) + + def _get_image_filename(self, image): + """Find the image based on its name.""" + if not image: + return None + + basedir = os.path.join(rcParams['datapath'], 'images') + possible_images = ( + image, + image + self._icon_extension, + os.path.join(basedir, image), + os.path.join(basedir, image) + self._icon_extension) + + for fname in possible_images: + if os.path.isfile(fname): + return fname + + def trigger_tool(self, name): + """ + Trigger the tool + + Parameters + ---------- + name : String + Name (id) of the tool triggered from within the container + """ + self.toolmanager.trigger_tool(name, sender=self) + + def add_toolitem(self, name, group, position, image, description, toggle): + """ + Add a toolitem to the container + + This method must get implemented per backend + + The callback associated with the button click event, + must be **EXACTLY** `self.trigger_tool(name)` + + Parameters + ---------- + name : string + Name of the tool to add, this gets used as the tool's ID and as the + default label of the buttons + group : String + Name of the group that this tool belongs to + position : Int + Position of the tool within its group, if -1 it goes at the End + image_file : String + Filename of the image for the button or `None` + description : String + Description of the tool, used for the tooltips + toggle : Bool + * `True` : The button is a toggle (change the pressed/unpressed + state between consecutive clicks) + * `False` : The button is a normal button (returns to unpressed + state after release) + """ + raise NotImplementedError + + def toggle_toolitem(self, name, toggled): + """ + Toggle the toolitem without firing event + + Parameters + ---------- + name : String + Id of the tool to toggle + toggled : bool + Whether to set this tool as toggled or not. + """ + raise NotImplementedError + + def remove_toolitem(self, name): + """ + Remove a toolitem from the `ToolContainer` + + This method must get implemented per backend + + Called when `ToolManager` emits a `tool_removed_event` + + Parameters + ---------- + name : string + Name of the tool to remove + """ + raise NotImplementedError + + +class StatusbarBase(object): + """Base class for the statusbar""" + def __init__(self, toolmanager): + self.toolmanager = toolmanager + self.toolmanager.toolmanager_connect('tool_message_event', + self._message_cbk) + + def _message_cbk(self, event): + """Captures the 'tool_message_event' and set the message""" + self.set_message(event.message) + + def set_message(self, s): + """ + Display a message on toolbar or in status bar + + Parameters + ---------- + s : str + Message text + """ + pass diff --git a/contrib/python/matplotlib/py2/matplotlib/backend_managers.py b/contrib/python/matplotlib/py2/matplotlib/backend_managers.py new file mode 100644 index 00000000000..ab9a503fab8 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backend_managers.py @@ -0,0 +1,436 @@ +""" +`ToolManager` + Class that makes the bridge between user interaction (key press, + toolbar clicks, ..) and the actions in response to the user inputs. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) +import six +import warnings + +import matplotlib.cbook as cbook +import matplotlib.widgets as widgets +from matplotlib.rcsetup import validate_stringlist +import matplotlib.backend_tools as tools + + +class ToolEvent(object): + """Event for tool manipulation (add/remove)""" + def __init__(self, name, sender, tool, data=None): + self.name = name + self.sender = sender + self.tool = tool + self.data = data + + +class ToolTriggerEvent(ToolEvent): + """Event to inform that a tool has been triggered""" + def __init__(self, name, sender, tool, canvasevent=None, data=None): + ToolEvent.__init__(self, name, sender, tool, data) + self.canvasevent = canvasevent + + +class ToolManagerMessageEvent(object): + """ + Event carrying messages from toolmanager + + Messages usually get displayed to the user by the toolbar + """ + def __init__(self, name, sender, message): + self.name = name + self.sender = sender + self.message = message + + +class ToolManager(object): + """ + Helper class that groups all the user interactions for a Figure + + Attributes + ---------- + figure: `Figure` + keypresslock: `widgets.LockDraw` + `LockDraw` object to know if the `canvas` key_press_event is locked + messagelock: `widgets.LockDraw` + `LockDraw` object to know if the message is available to write + """ + + def __init__(self, figure=None): + warnings.warn('Treat the new Tool classes introduced in v1.5 as ' + + 'experimental for now, the API will likely change in ' + + 'version 2.1 and perhaps the rcParam as well') + + self._key_press_handler_id = None + + self._tools = {} + self._keys = {} + self._toggled = {} + self._callbacks = cbook.CallbackRegistry() + + # to process keypress event + self.keypresslock = widgets.LockDraw() + self.messagelock = widgets.LockDraw() + + self._figure = None + self.set_figure(figure) + + @property + def canvas(self): + """Canvas managed by FigureManager""" + if not self._figure: + return None + return self._figure.canvas + + @property + def figure(self): + """Figure that holds the canvas""" + return self._figure + + @figure.setter + def figure(self, figure): + self.set_figure(figure) + + def set_figure(self, figure, update_tools=True): + """ + Sets the figure to interact with the tools + + Parameters + ========== + figure: `Figure` + update_tools: bool + Force tools to update figure + """ + if self._key_press_handler_id: + self.canvas.mpl_disconnect(self._key_press_handler_id) + self._figure = figure + if figure: + self._key_press_handler_id = self.canvas.mpl_connect( + 'key_press_event', self._key_press) + if update_tools: + for tool in self._tools.values(): + tool.figure = figure + + def toolmanager_connect(self, s, func): + """ + Connect event with string *s* to *func*. + + Parameters + ---------- + s : String + Name of the event + + The following events are recognized + + - 'tool_message_event' + - 'tool_removed_event' + - 'tool_added_event' + + For every tool added a new event is created + + - 'tool_trigger_TOOLNAME` + Where TOOLNAME is the id of the tool. + + func : function + Function to be called with signature + def func(event) + """ + return self._callbacks.connect(s, func) + + def toolmanager_disconnect(self, cid): + """ + Disconnect callback id *cid* + + Example usage:: + + cid = toolmanager.toolmanager_connect('tool_trigger_zoom', + on_press) + #...later + toolmanager.toolmanager_disconnect(cid) + """ + return self._callbacks.disconnect(cid) + + def message_event(self, message, sender=None): + """ Emit a `ToolManagerMessageEvent`""" + if sender is None: + sender = self + + s = 'tool_message_event' + event = ToolManagerMessageEvent(s, sender, message) + self._callbacks.process(s, event) + + @property + def active_toggle(self): + """Currently toggled tools""" + + return self._toggled + + def get_tool_keymap(self, name): + """ + Get the keymap associated with the specified tool + + Parameters + ---------- + name : string + Name of the Tool + + Returns + ------- + list : list of keys associated with the Tool + """ + + keys = [k for k, i in six.iteritems(self._keys) if i == name] + return keys + + def _remove_keys(self, name): + for k in self.get_tool_keymap(name): + del self._keys[k] + + def update_keymap(self, name, *keys): + """ + Set the keymap to associate with the specified tool + + Parameters + ---------- + name : string + Name of the Tool + keys : keys to associate with the Tool + """ + + if name not in self._tools: + raise KeyError('%s not in Tools' % name) + + self._remove_keys(name) + + for key in keys: + for k in validate_stringlist(key): + if k in self._keys: + warnings.warn('Key %s changed from %s to %s' % + (k, self._keys[k], name)) + self._keys[k] = name + + def remove_tool(self, name): + """ + Remove tool from `ToolManager` + + Parameters + ---------- + name : string + Name of the Tool + """ + + tool = self.get_tool(name) + tool.destroy() + + # If is a toggle tool and toggled, untoggle + if getattr(tool, 'toggled', False): + self.trigger_tool(tool, 'toolmanager') + + self._remove_keys(name) + + s = 'tool_removed_event' + event = ToolEvent(s, self, tool) + self._callbacks.process(s, event) + + del self._tools[name] + + def add_tool(self, name, tool, *args, **kwargs): + """ + Add *tool* to `ToolManager` + + If successful adds a new event `tool_trigger_name` where **name** is + the **name** of the tool, this event is fired everytime + the tool is triggered. + + Parameters + ---------- + name : str + Name of the tool, treated as the ID, has to be unique + tool : class_like, i.e. str or type + Reference to find the class of the Tool to added. + + Notes + ----- + args and kwargs get passed directly to the tools constructor. + + See Also + -------- + matplotlib.backend_tools.ToolBase : The base class for tools. + """ + + tool_cls = self._get_cls_to_instantiate(tool) + if not tool_cls: + raise ValueError('Impossible to find class for %s' % str(tool)) + + if name in self._tools: + warnings.warn('A "Tool class" with the same name already exists, ' + 'not added') + return self._tools[name] + + tool_obj = tool_cls(self, name, *args, **kwargs) + self._tools[name] = tool_obj + + if tool_cls.default_keymap is not None: + self.update_keymap(name, tool_cls.default_keymap) + + # For toggle tools init the radio_group in self._toggled + if isinstance(tool_obj, tools.ToolToggleBase): + # None group is not mutually exclusive, a set is used to keep track + # of all toggled tools in this group + if tool_obj.radio_group is None: + self._toggled.setdefault(None, set()) + else: + self._toggled.setdefault(tool_obj.radio_group, None) + + # If initially toggled + if tool_obj.toggled: + self._handle_toggle(tool_obj, None, None, None) + tool_obj.set_figure(self.figure) + + self._tool_added_event(tool_obj) + return tool_obj + + def _tool_added_event(self, tool): + s = 'tool_added_event' + event = ToolEvent(s, self, tool) + self._callbacks.process(s, event) + + def _handle_toggle(self, tool, sender, canvasevent, data): + """ + Toggle tools, need to untoggle prior to using other Toggle tool + Called from trigger_tool + + Parameters + ---------- + tool: Tool object + sender: object + Object that wishes to trigger the tool + canvasevent : Event + Original Canvas event or None + data : Object + Extra data to pass to the tool when triggering + """ + + radio_group = tool.radio_group + # radio_group None is not mutually exclusive + # just keep track of toggled tools in this group + if radio_group is None: + if tool.name in self._toggled[None]: + self._toggled[None].remove(tool.name) + else: + self._toggled[None].add(tool.name) + return + + # If the tool already has a toggled state, untoggle it + if self._toggled[radio_group] == tool.name: + toggled = None + # If no tool was toggled in the radio_group + # toggle it + elif self._toggled[radio_group] is None: + toggled = tool.name + # Other tool in the radio_group is toggled + else: + # Untoggle previously toggled tool + self.trigger_tool(self._toggled[radio_group], + self, + canvasevent, + data) + toggled = tool.name + + # Keep track of the toggled tool in the radio_group + self._toggled[radio_group] = toggled + + def _get_cls_to_instantiate(self, callback_class): + # Find the class that corresponds to the tool + if isinstance(callback_class, six.string_types): + # FIXME: make more complete searching structure + if callback_class in globals(): + callback_class = globals()[callback_class] + else: + mod = 'backend_tools' + current_module = __import__(mod, + globals(), locals(), [mod], 1) + + callback_class = getattr(current_module, callback_class, False) + if callable(callback_class): + return callback_class + else: + return None + + def trigger_tool(self, name, sender=None, canvasevent=None, + data=None): + """ + Trigger a tool and emit the tool_trigger_[name] event + + Parameters + ---------- + name : string + Name of the tool + sender: object + Object that wishes to trigger the tool + canvasevent : Event + Original Canvas event or None + data : Object + Extra data to pass to the tool when triggering + """ + tool = self.get_tool(name) + if tool is None: + return + + if sender is None: + sender = self + + self._trigger_tool(name, sender, canvasevent, data) + + s = 'tool_trigger_%s' % name + event = ToolTriggerEvent(s, sender, tool, canvasevent, data) + self._callbacks.process(s, event) + + def _trigger_tool(self, name, sender=None, canvasevent=None, data=None): + """ + Trigger on a tool + + Method to actually trigger the tool + """ + tool = self.get_tool(name) + + if isinstance(tool, tools.ToolToggleBase): + self._handle_toggle(tool, sender, canvasevent, data) + + # Important!!! + # This is where the Tool object gets triggered + tool.trigger(sender, canvasevent, data) + + def _key_press(self, event): + if event.key is None or self.keypresslock.locked(): + return + + name = self._keys.get(event.key, None) + if name is None: + return + self.trigger_tool(name, canvasevent=event) + + @property + def tools(self): + """Return the tools controlled by `ToolManager`""" + + return self._tools + + def get_tool(self, name, warn=True): + """ + Return the tool object, also accepts the actual tool for convenience + + Parameters + ---------- + name : str, ToolBase + Name of the tool, or the tool itself + warn : bool, optional + If this method should give warnings. + """ + if isinstance(name, tools.ToolBase) and name.name in self._tools: + return name + if name not in self._tools: + if warn: + warnings.warn("ToolManager does not control tool %s" % name) + return None + return self._tools[name] diff --git a/contrib/python/matplotlib/py2/matplotlib/backend_tools.py b/contrib/python/matplotlib/py2/matplotlib/backend_tools.py new file mode 100644 index 00000000000..6639763e417 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backend_tools.py @@ -0,0 +1,1081 @@ +""" +Abstract base classes define the primitives for Tools. +These tools are used by `matplotlib.backend_managers.ToolManager` + +:class:`ToolBase` + Simple stateless tool + +:class:`ToolToggleBase` + Tool that has two states, only one Toggle tool can be + active at any given time for the same + `matplotlib.backend_managers.ToolManager` +""" + + +from matplotlib import rcParams +from matplotlib._pylab_helpers import Gcf +import matplotlib.cbook as cbook +from weakref import WeakKeyDictionary +import six +import time +import warnings +import numpy as np + + +class Cursors(object): + """Simple namespace for cursor reference""" + HAND, POINTER, SELECT_REGION, MOVE, WAIT = list(range(5)) +cursors = Cursors() + +# Views positions tool +_views_positions = 'viewpos' + + +class ToolBase(object): + """ + Base tool class + + A base tool, only implements `trigger` method or not method at all. + The tool is instantiated by `matplotlib.backend_managers.ToolManager` + + Attributes + ---------- + toolmanager: `matplotlib.backend_managers.ToolManager` + ToolManager that controls this Tool + figure: `FigureCanvas` + Figure instance that is affected by this Tool + name: String + Used as **Id** of the tool, has to be unique among tools of the same + ToolManager + """ + + default_keymap = None + """ + Keymap to associate with this tool + + **String**: List of comma separated keys that will be used to call this + tool when the keypress event of *self.figure.canvas* is emitted + """ + + description = None + """ + Description of the Tool + + **String**: If the Tool is included in the Toolbar this text is used + as a Tooltip + """ + + image = None + """ + Filename of the image + + **String**: Filename of the image to use in the toolbar. If None, the + `name` is used as a label in the toolbar button + """ + + def __init__(self, toolmanager, name): + warnings.warn('Treat the new Tool classes introduced in v1.5 as ' + + 'experimental for now, the API will likely change in ' + + 'version 2.1, and some tools might change name') + self._name = name + self._toolmanager = toolmanager + self._figure = None + + @property + def figure(self): + return self._figure + + @figure.setter + def figure(self, figure): + self.set_figure(figure) + + @property + def canvas(self): + if not self._figure: + return None + return self._figure.canvas + + @property + def toolmanager(self): + return self._toolmanager + + def set_figure(self, figure): + """ + Assign a figure to the tool + + Parameters + ---------- + figure: `Figure` + """ + self._figure = figure + + def trigger(self, sender, event, data=None): + """ + Called when this tool gets used + + This method is called by + `matplotlib.backend_managers.ToolManager.trigger_tool` + + Parameters + ---------- + event: `Event` + The Canvas event that caused this tool to be called + sender: object + Object that requested the tool to be triggered + data: object + Extra data + """ + + pass + + @property + def name(self): + """Tool Id""" + return self._name + + def destroy(self): + """ + Destroy the tool + + This method is called when the tool is removed by + `matplotlib.backend_managers.ToolManager.remove_tool` + """ + pass + + +class ToolToggleBase(ToolBase): + """ + Toggleable tool + + Every time it is triggered, it switches between enable and disable + + Parameters + ---------- + ``*args`` + Variable length argument to be used by the Tool + ``**kwargs`` + `toggled` if present and True, sets the initial state of the Tool + Arbitrary keyword arguments to be consumed by the Tool + """ + + radio_group = None + """Attribute to group 'radio' like tools (mutually exclusive) + + **String** that identifies the group or **None** if not belonging to a + group + """ + + cursor = None + """Cursor to use when the tool is active""" + + default_toggled = False + """Default of toggled state""" + + def __init__(self, *args, **kwargs): + self._toggled = kwargs.pop('toggled', self.default_toggled) + ToolBase.__init__(self, *args, **kwargs) + + def trigger(self, sender, event, data=None): + """Calls `enable` or `disable` based on `toggled` value""" + if self._toggled: + self.disable(event) + else: + self.enable(event) + self._toggled = not self._toggled + + def enable(self, event=None): + """ + Enable the toggle tool + + `trigger` calls this method when `toggled` is False + """ + + pass + + def disable(self, event=None): + """ + Disable the toggle tool + + `trigger` call this method when `toggled` is True. + + This can happen in different circumstances + + * Click on the toolbar tool button + * Call to `matplotlib.backend_managers.ToolManager.trigger_tool` + * Another `ToolToggleBase` derived tool is triggered + (from the same `ToolManager`) + """ + + pass + + @property + def toggled(self): + """State of the toggled tool""" + + return self._toggled + + def set_figure(self, figure): + toggled = self.toggled + if toggled: + if self.figure: + self.trigger(self, None) + else: + # if no figure the internal state is not changed + # we change it here so next call to trigger will change it back + self._toggled = False + ToolBase.set_figure(self, figure) + if toggled: + if figure: + self.trigger(self, None) + else: + # if there is no figure, trigger won't change the internal + # state we change it back + self._toggled = True + + +class SetCursorBase(ToolBase): + """ + Change to the current cursor while inaxes + + This tool, keeps track of all `ToolToggleBase` derived tools, and calls + set_cursor when a tool gets triggered + """ + def __init__(self, *args, **kwargs): + ToolBase.__init__(self, *args, **kwargs) + self._idDrag = None + self._cursor = None + self._default_cursor = cursors.POINTER + self._last_cursor = self._default_cursor + self.toolmanager.toolmanager_connect('tool_added_event', + self._add_tool_cbk) + + # process current tools + for tool in self.toolmanager.tools.values(): + self._add_tool(tool) + + def set_figure(self, figure): + if self._idDrag: + self.canvas.mpl_disconnect(self._idDrag) + ToolBase.set_figure(self, figure) + if figure: + self._idDrag = self.canvas.mpl_connect( + 'motion_notify_event', self._set_cursor_cbk) + + def _tool_trigger_cbk(self, event): + if event.tool.toggled: + self._cursor = event.tool.cursor + else: + self._cursor = None + + self._set_cursor_cbk(event.canvasevent) + + def _add_tool(self, tool): + """set the cursor when the tool is triggered""" + if getattr(tool, 'cursor', None) is not None: + self.toolmanager.toolmanager_connect('tool_trigger_%s' % tool.name, + self._tool_trigger_cbk) + + def _add_tool_cbk(self, event): + """Process every newly added tool""" + if event.tool is self: + return + + self._add_tool(event.tool) + + def _set_cursor_cbk(self, event): + if not event: + return + + if not getattr(event, 'inaxes', False) or not self._cursor: + if self._last_cursor != self._default_cursor: + self.set_cursor(self._default_cursor) + self._last_cursor = self._default_cursor + elif self._cursor: + cursor = self._cursor + if cursor and self._last_cursor != cursor: + self.set_cursor(cursor) + self._last_cursor = cursor + + def set_cursor(self, cursor): + """ + Set the cursor + + This method has to be implemented per backend + """ + raise NotImplementedError + + +class ToolCursorPosition(ToolBase): + """ + Send message with the current pointer position + + This tool runs in the background reporting the position of the cursor + """ + def __init__(self, *args, **kwargs): + self._idDrag = None + ToolBase.__init__(self, *args, **kwargs) + + def set_figure(self, figure): + if self._idDrag: + self.canvas.mpl_disconnect(self._idDrag) + ToolBase.set_figure(self, figure) + if figure: + self._idDrag = self.canvas.mpl_connect( + 'motion_notify_event', self.send_message) + + def send_message(self, event): + """Call `matplotlib.backend_managers.ToolManager.message_event`""" + if self.toolmanager.messagelock.locked(): + return + + message = ' ' + + if event.inaxes and event.inaxes.get_navigate(): + try: + s = event.inaxes.format_coord(event.xdata, event.ydata) + except (ValueError, OverflowError): + pass + else: + artists = [a for a in event.inaxes.mouseover_set + if a.contains(event) and a.get_visible()] + + if artists: + a = cbook._topmost_artist(artists) + if a is not event.inaxes.patch: + data = a.get_cursor_data(event) + if data is not None: + s += ' [%s]' % a.format_cursor_data(data) + + message = s + self.toolmanager.message_event(message, self) + + +class RubberbandBase(ToolBase): + """Draw and remove rubberband""" + def trigger(self, sender, event, data): + """Call `draw_rubberband` or `remove_rubberband` based on data""" + if not self.figure.canvas.widgetlock.available(sender): + return + if data is not None: + self.draw_rubberband(*data) + else: + self.remove_rubberband() + + def draw_rubberband(self, *data): + """ + Draw rubberband + + This method must get implemented per backend + """ + raise NotImplementedError + + def remove_rubberband(self): + """ + Remove rubberband + + This method should get implemented per backend + """ + pass + + +class ToolQuit(ToolBase): + """Tool to call the figure manager destroy method""" + + description = 'Quit the figure' + default_keymap = rcParams['keymap.quit'] + + def trigger(self, sender, event, data=None): + Gcf.destroy_fig(self.figure) + + +class ToolQuitAll(ToolBase): + """Tool to call the figure manager destroy method""" + + description = 'Quit all figures' + default_keymap = rcParams['keymap.quit_all'] + + def trigger(self, sender, event, data=None): + Gcf.destroy_all() + + +class ToolEnableAllNavigation(ToolBase): + """Tool to enable all axes for toolmanager interaction""" + + description = 'Enables all axes toolmanager' + default_keymap = rcParams['keymap.all_axes'] + + def trigger(self, sender, event, data=None): + if event.inaxes is None: + return + + for a in self.figure.get_axes(): + if (event.x is not None and event.y is not None + and a.in_axes(event)): + a.set_navigate(True) + + +class ToolEnableNavigation(ToolBase): + """Tool to enable a specific axes for toolmanager interaction""" + + description = 'Enables one axes toolmanager' + default_keymap = (1, 2, 3, 4, 5, 6, 7, 8, 9) + + def trigger(self, sender, event, data=None): + if event.inaxes is None: + return + + n = int(event.key) - 1 + for i, a in enumerate(self.figure.get_axes()): + if (event.x is not None and event.y is not None + and a.in_axes(event)): + a.set_navigate(i == n) + + +class _ToolGridBase(ToolBase): + """Common functionality between ToolGrid and ToolMinorGrid.""" + + _cycle = [(False, False), (True, False), (True, True), (False, True)] + + def trigger(self, sender, event, data=None): + ax = event.inaxes + if ax is None: + return + try: + x_state, x_which, y_state, y_which = self._get_next_grid_states(ax) + except ValueError: + pass + else: + ax.grid(x_state, which=x_which, axis="x") + ax.grid(y_state, which=y_which, axis="y") + ax.figure.canvas.draw_idle() + + @staticmethod + def _get_uniform_grid_state(ticks): + """ + Check whether all grid lines are in the same visibility state. + + Returns True/False if all grid lines are on or off, None if they are + not all in the same state. + """ + if all(tick.gridOn for tick in ticks): + return True + elif not any(tick.gridOn for tick in ticks): + return False + else: + return None + + +class ToolGrid(_ToolGridBase): + """Tool to toggle the major grids of the figure""" + + description = 'Toogle major grids' + default_keymap = rcParams['keymap.grid'] + + def _get_next_grid_states(self, ax): + if None in map(self._get_uniform_grid_state, + [ax.xaxis.minorTicks, ax.yaxis.minorTicks]): + # Bail out if minor grids are not in a uniform state. + raise ValueError + x_state, y_state = map(self._get_uniform_grid_state, + [ax.xaxis.majorTicks, ax.yaxis.majorTicks]) + cycle = self._cycle + # Bail out (via ValueError) if major grids are not in a uniform state. + x_state, y_state = ( + cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)]) + return (x_state, "major" if x_state else "both", + y_state, "major" if y_state else "both") + + +class ToolMinorGrid(_ToolGridBase): + """Tool to toggle the major and minor grids of the figure""" + + description = 'Toogle major and minor grids' + default_keymap = rcParams['keymap.grid_minor'] + + def _get_next_grid_states(self, ax): + if None in map(self._get_uniform_grid_state, + [ax.xaxis.majorTicks, ax.yaxis.majorTicks]): + # Bail out if major grids are not in a uniform state. + raise ValueError + x_state, y_state = map(self._get_uniform_grid_state, + [ax.xaxis.minorTicks, ax.yaxis.minorTicks]) + cycle = self._cycle + # Bail out (via ValueError) if minor grids are not in a uniform state. + x_state, y_state = ( + cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)]) + return x_state, "both", y_state, "both" + + +class ToolFullScreen(ToolToggleBase): + """Tool to toggle full screen""" + + description = 'Toogle Fullscreen mode' + default_keymap = rcParams['keymap.fullscreen'] + + def enable(self, event): + self.figure.canvas.manager.full_screen_toggle() + + def disable(self, event): + self.figure.canvas.manager.full_screen_toggle() + + +class AxisScaleBase(ToolToggleBase): + """Base Tool to toggle between linear and logarithmic""" + + def trigger(self, sender, event, data=None): + if event.inaxes is None: + return + ToolToggleBase.trigger(self, sender, event, data) + + def enable(self, event): + self.set_scale(event.inaxes, 'log') + self.figure.canvas.draw_idle() + + def disable(self, event): + self.set_scale(event.inaxes, 'linear') + self.figure.canvas.draw_idle() + + +class ToolYScale(AxisScaleBase): + """Tool to toggle between linear and logarithmic scales on the Y axis""" + + description = 'Toogle Scale Y axis' + default_keymap = rcParams['keymap.yscale'] + + def set_scale(self, ax, scale): + ax.set_yscale(scale) + + +class ToolXScale(AxisScaleBase): + """Tool to toggle between linear and logarithmic scales on the X axis""" + + description = 'Toogle Scale X axis' + default_keymap = rcParams['keymap.xscale'] + + def set_scale(self, ax, scale): + ax.set_xscale(scale) + + +class ToolViewsPositions(ToolBase): + """ + Auxiliary Tool to handle changes in views and positions + + Runs in the background and should get used by all the tools that + need to access the figure's history of views and positions, e.g. + + * `ToolZoom` + * `ToolPan` + * `ToolHome` + * `ToolBack` + * `ToolForward` + """ + + def __init__(self, *args, **kwargs): + self.views = WeakKeyDictionary() + self.positions = WeakKeyDictionary() + self.home_views = WeakKeyDictionary() + ToolBase.__init__(self, *args, **kwargs) + + def add_figure(self, figure): + """Add the current figure to the stack of views and positions""" + + if figure not in self.views: + self.views[figure] = cbook.Stack() + self.positions[figure] = cbook.Stack() + self.home_views[figure] = WeakKeyDictionary() + # Define Home + self.push_current(figure) + # Make sure we add a home view for new axes as they're added + figure.add_axobserver(lambda fig: self.update_home_views(fig)) + + def clear(self, figure): + """Reset the axes stack""" + if figure in self.views: + self.views[figure].clear() + self.positions[figure].clear() + self.home_views[figure].clear() + self.update_home_views() + + def update_view(self): + """ + Update the view limits and position for each axes from the current + stack position. If any axes are present in the figure that aren't in + the current stack position, use the home view limits for those axes and + don't update *any* positions. + """ + + views = self.views[self.figure]() + if views is None: + return + pos = self.positions[self.figure]() + if pos is None: + return + home_views = self.home_views[self.figure] + all_axes = self.figure.get_axes() + for a in all_axes: + if a in views: + cur_view = views[a] + else: + cur_view = home_views[a] + a._set_view(cur_view) + + if set(all_axes).issubset(pos): + for a in all_axes: + # Restore both the original and modified positions + a._set_position(pos[a][0], 'original') + a._set_position(pos[a][1], 'active') + + self.figure.canvas.draw_idle() + + def push_current(self, figure=None): + """ + Push the current view limits and position onto their respective stacks + """ + if not figure: + figure = self.figure + views = WeakKeyDictionary() + pos = WeakKeyDictionary() + for a in figure.get_axes(): + views[a] = a._get_view() + pos[a] = self._axes_pos(a) + self.views[figure].push(views) + self.positions[figure].push(pos) + + def _axes_pos(self, ax): + """ + Return the original and modified positions for the specified axes + + Parameters + ---------- + ax : (matplotlib.axes.AxesSubplot) + The axes to get the positions for + + Returns + ------- + limits : (tuple) + A tuple of the original and modified positions + """ + + return (ax.get_position(True).frozen(), + ax.get_position().frozen()) + + def update_home_views(self, figure=None): + """ + Make sure that self.home_views has an entry for all axes present in the + figure + """ + + if not figure: + figure = self.figure + for a in figure.get_axes(): + if a not in self.home_views[figure]: + self.home_views[figure][a] = a._get_view() + + def refresh_locators(self): + """Redraw the canvases, update the locators""" + for a in self.figure.get_axes(): + xaxis = getattr(a, 'xaxis', None) + yaxis = getattr(a, 'yaxis', None) + zaxis = getattr(a, 'zaxis', None) + locators = [] + if xaxis is not None: + locators.append(xaxis.get_major_locator()) + locators.append(xaxis.get_minor_locator()) + if yaxis is not None: + locators.append(yaxis.get_major_locator()) + locators.append(yaxis.get_minor_locator()) + if zaxis is not None: + locators.append(zaxis.get_major_locator()) + locators.append(zaxis.get_minor_locator()) + + for loc in locators: + loc.refresh() + self.figure.canvas.draw_idle() + + def home(self): + """Recall the first view and position from the stack""" + self.views[self.figure].home() + self.positions[self.figure].home() + + def back(self): + """Back one step in the stack of views and positions""" + self.views[self.figure].back() + self.positions[self.figure].back() + + def forward(self): + """Forward one step in the stack of views and positions""" + self.views[self.figure].forward() + self.positions[self.figure].forward() + + +class ViewsPositionsBase(ToolBase): + """Base class for `ToolHome`, `ToolBack` and `ToolForward`""" + + _on_trigger = None + + def trigger(self, sender, event, data=None): + self.toolmanager.get_tool(_views_positions).add_figure(self.figure) + getattr(self.toolmanager.get_tool(_views_positions), + self._on_trigger)() + self.toolmanager.get_tool(_views_positions).update_view() + + +class ToolHome(ViewsPositionsBase): + """Restore the original view lim""" + + description = 'Reset original view' + image = 'home' + default_keymap = rcParams['keymap.home'] + _on_trigger = 'home' + + +class ToolBack(ViewsPositionsBase): + """Move back up the view lim stack""" + + description = 'Back to previous view' + image = 'back' + default_keymap = rcParams['keymap.back'] + _on_trigger = 'back' + + +class ToolForward(ViewsPositionsBase): + """Move forward in the view lim stack""" + + description = 'Forward to next view' + image = 'forward' + default_keymap = rcParams['keymap.forward'] + _on_trigger = 'forward' + + +class ConfigureSubplotsBase(ToolBase): + """Base tool for the configuration of subplots""" + + description = 'Configure subplots' + image = 'subplots' + + +class SaveFigureBase(ToolBase): + """Base tool for figure saving""" + + description = 'Save the figure' + image = 'filesave' + default_keymap = rcParams['keymap.save'] + + +class ZoomPanBase(ToolToggleBase): + """Base class for `ToolZoom` and `ToolPan`""" + def __init__(self, *args): + ToolToggleBase.__init__(self, *args) + self._button_pressed = None + self._xypress = None + self._idPress = None + self._idRelease = None + self._idScroll = None + self.base_scale = 2. + self.scrollthresh = .5 # .5 second scroll threshold + self.lastscroll = time.time()-self.scrollthresh + + def enable(self, event): + """Connect press/release events and lock the canvas""" + self.figure.canvas.widgetlock(self) + self._idPress = self.figure.canvas.mpl_connect( + 'button_press_event', self._press) + self._idRelease = self.figure.canvas.mpl_connect( + 'button_release_event', self._release) + self._idScroll = self.figure.canvas.mpl_connect( + 'scroll_event', self.scroll_zoom) + + def disable(self, event): + """Release the canvas and disconnect press/release events""" + self._cancel_action() + self.figure.canvas.widgetlock.release(self) + self.figure.canvas.mpl_disconnect(self._idPress) + self.figure.canvas.mpl_disconnect(self._idRelease) + self.figure.canvas.mpl_disconnect(self._idScroll) + + def trigger(self, sender, event, data=None): + self.toolmanager.get_tool(_views_positions).add_figure(self.figure) + ToolToggleBase.trigger(self, sender, event, data) + + def scroll_zoom(self, event): + # https://gist.github.com/tacaswell/3144287 + if event.inaxes is None: + return + + if event.button == 'up': + # deal with zoom in + scl = self.base_scale + elif event.button == 'down': + # deal with zoom out + scl = 1/self.base_scale + else: + # deal with something that should never happen + scl = 1 + + ax = event.inaxes + ax._set_view_from_bbox([event.x, event.y, scl]) + + # If last scroll was done within the timing threshold, delete the + # previous view + if (time.time()-self.lastscroll) < self.scrollthresh: + self.toolmanager.get_tool(_views_positions).back() + + self.figure.canvas.draw_idle() # force re-draw + + self.lastscroll = time.time() + self.toolmanager.get_tool(_views_positions).push_current() + + +class ToolZoom(ZoomPanBase): + """Zoom to rectangle""" + + description = 'Zoom to rectangle' + image = 'zoom_to_rect' + default_keymap = rcParams['keymap.zoom'] + cursor = cursors.SELECT_REGION + radio_group = 'default' + + def __init__(self, *args): + ZoomPanBase.__init__(self, *args) + self._ids_zoom = [] + + def _cancel_action(self): + for zoom_id in self._ids_zoom: + self.figure.canvas.mpl_disconnect(zoom_id) + self.toolmanager.trigger_tool('rubberband', self) + self.toolmanager.get_tool(_views_positions).refresh_locators() + self._xypress = None + self._button_pressed = None + self._ids_zoom = [] + return + + def _press(self, event): + """the _press mouse button in zoom to rect mode callback""" + + # If we're already in the middle of a zoom, pressing another + # button works to "cancel" + if self._ids_zoom != []: + self._cancel_action() + + if event.button == 1: + self._button_pressed = 1 + elif event.button == 3: + self._button_pressed = 3 + else: + self._cancel_action() + return + + x, y = event.x, event.y + + self._xypress = [] + for i, a in enumerate(self.figure.get_axes()): + if (x is not None and y is not None and a.in_axes(event) and + a.get_navigate() and a.can_zoom()): + self._xypress.append((x, y, a, i, a._get_view())) + + id1 = self.figure.canvas.mpl_connect( + 'motion_notify_event', self._mouse_move) + id2 = self.figure.canvas.mpl_connect( + 'key_press_event', self._switch_on_zoom_mode) + id3 = self.figure.canvas.mpl_connect( + 'key_release_event', self._switch_off_zoom_mode) + + self._ids_zoom = id1, id2, id3 + self._zoom_mode = event.key + + def _switch_on_zoom_mode(self, event): + self._zoom_mode = event.key + self._mouse_move(event) + + def _switch_off_zoom_mode(self, event): + self._zoom_mode = None + self._mouse_move(event) + + def _mouse_move(self, event): + """the drag callback in zoom mode""" + + if self._xypress: + x, y = event.x, event.y + lastx, lasty, a, ind, view = self._xypress[0] + (x1, y1), (x2, y2) = np.clip( + [[lastx, lasty], [x, y]], a.bbox.min, a.bbox.max) + if self._zoom_mode == "x": + y1, y2 = a.bbox.intervaly + elif self._zoom_mode == "y": + x1, x2 = a.bbox.intervalx + self.toolmanager.trigger_tool( + 'rubberband', self, data=(x1, y1, x2, y2)) + + def _release(self, event): + """the release mouse button callback in zoom to rect mode""" + + for zoom_id in self._ids_zoom: + self.figure.canvas.mpl_disconnect(zoom_id) + self._ids_zoom = [] + + if not self._xypress: + self._cancel_action() + return + + last_a = [] + + for cur_xypress in self._xypress: + x, y = event.x, event.y + lastx, lasty, a, _ind, view = cur_xypress + # ignore singular clicks - 5 pixels is a threshold + if abs(x - lastx) < 5 or abs(y - lasty) < 5: + self._cancel_action() + return + + # detect twinx,y axes and avoid double zooming + twinx, twiny = False, False + if last_a: + for la in last_a: + if a.get_shared_x_axes().joined(a, la): + twinx = True + if a.get_shared_y_axes().joined(a, la): + twiny = True + last_a.append(a) + + if self._button_pressed == 1: + direction = 'in' + elif self._button_pressed == 3: + direction = 'out' + else: + continue + + a._set_view_from_bbox((lastx, lasty, x, y), direction, + self._zoom_mode, twinx, twiny) + + self._zoom_mode = None + self.toolmanager.get_tool(_views_positions).push_current() + self._cancel_action() + + +class ToolPan(ZoomPanBase): + """Pan axes with left mouse, zoom with right""" + + default_keymap = rcParams['keymap.pan'] + description = 'Pan axes with left mouse, zoom with right' + image = 'move' + cursor = cursors.MOVE + radio_group = 'default' + + def __init__(self, *args): + ZoomPanBase.__init__(self, *args) + self._idDrag = None + + def _cancel_action(self): + self._button_pressed = None + self._xypress = [] + self.figure.canvas.mpl_disconnect(self._idDrag) + self.toolmanager.messagelock.release(self) + self.toolmanager.get_tool(_views_positions).refresh_locators() + + def _press(self, event): + if event.button == 1: + self._button_pressed = 1 + elif event.button == 3: + self._button_pressed = 3 + else: + self._cancel_action() + return + + x, y = event.x, event.y + + self._xypress = [] + for i, a in enumerate(self.figure.get_axes()): + if (x is not None and y is not None and a.in_axes(event) and + a.get_navigate() and a.can_pan()): + a.start_pan(x, y, event.button) + self._xypress.append((a, i)) + self.toolmanager.messagelock(self) + self._idDrag = self.figure.canvas.mpl_connect( + 'motion_notify_event', self._mouse_move) + + def _release(self, event): + if self._button_pressed is None: + self._cancel_action() + return + + self.figure.canvas.mpl_disconnect(self._idDrag) + self.toolmanager.messagelock.release(self) + + for a, _ind in self._xypress: + a.end_pan() + if not self._xypress: + self._cancel_action() + return + + self.toolmanager.get_tool(_views_positions).push_current() + self._cancel_action() + + def _mouse_move(self, event): + for a, _ind in self._xypress: + # safer to use the recorded button at the _press than current + # button: # multiple button can get pressed during motion... + a.drag_pan(self._button_pressed, event.key, event.x, event.y) + self.toolmanager.canvas.draw_idle() + + +default_tools = {'home': ToolHome, 'back': ToolBack, 'forward': ToolForward, + 'zoom': ToolZoom, 'pan': ToolPan, + 'subplots': 'ToolConfigureSubplots', + 'save': 'ToolSaveFigure', + 'grid': ToolGrid, + 'grid_minor': ToolMinorGrid, + 'fullscreen': ToolFullScreen, + 'quit': ToolQuit, + 'quit_all': ToolQuitAll, + 'allnav': ToolEnableAllNavigation, + 'nav': ToolEnableNavigation, + 'xscale': ToolXScale, + 'yscale': ToolYScale, + 'position': ToolCursorPosition, + _views_positions: ToolViewsPositions, + 'cursor': 'ToolSetCursor', + 'rubberband': 'ToolRubberband', + } +"""Default tools""" + +default_toolbar_tools = [['navigation', ['home', 'back', 'forward']], + ['zoompan', ['pan', 'zoom', 'subplots']], + ['io', ['save']]] +"""Default tools in the toolbar""" + + +def add_tools_to_manager(toolmanager, tools=default_tools): + """ + Add multiple tools to `ToolManager` + + Parameters + ---------- + toolmanager: ToolManager + `backend_managers.ToolManager` object that will get the tools added + tools : {str: class_like}, optional + The tools to add in a {name: tool} dict, see `add_tool` for more + info. + """ + + for name, tool in six.iteritems(tools): + toolmanager.add_tool(name, tool) + + +def add_tools_to_container(container, tools=default_toolbar_tools): + """ + Add multiple tools to the container. + + Parameters + ---------- + container: Container + `backend_bases.ToolContainerBase` object that will get the tools added + tools : list, optional + List in the form + [[group1, [tool1, tool2 ...]], [group2, [...]]] + Where the tools given by tool1, and tool2 will display in group1. + See `add_tool` for details. + """ + + for group, grouptools in tools: + for position, tool in enumerate(grouptools): + container.add_tool(tool, group, position) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/__init__.py b/contrib/python/matplotlib/py2/matplotlib/backends/__init__.py new file mode 100644 index 00000000000..33c60d85508 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/__init__.py @@ -0,0 +1,97 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import matplotlib +import inspect +import traceback +import warnings +import logging + +_log = logging.getLogger(__name__) + +backend = matplotlib.get_backend() +# the `str` calls here are to make non-ascii paths work on python2 +_backend_loading_tb = str("").join( + line for line in traceback.format_stack() + # Filter out line noise from importlib line. + if not line.startswith(str(' File "', ''): + warnings.warn(""" +Your currently selected backend, '%s' does not support show(). +Please select a GUI backend in your matplotlibrc file ('%s') +or with matplotlib.use()""" % + (name, matplotlib.matplotlib_fname())) + + def do_nothing(*args, **kwargs): + pass + + backend_version = getattr(backend_mod, 'backend_version', 'unknown') + + show = getattr(backend_mod, 'show', do_nothing_show) + + draw_if_interactive = getattr(backend_mod, 'draw_if_interactive', + do_nothing) + + _log.debug('backend %s version %s', name, backend_version) + + # need to keep a global reference to the backend for compatibility + # reasons. See https://github.com/matplotlib/matplotlib/issues/6092 + global backend + backend = name + return backend_mod, new_figure_manager, draw_if_interactive, show diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/_backend_tk.py b/contrib/python/matplotlib/py2/matplotlib/backends/_backend_tk.py new file mode 100644 index 00000000000..da404b6e1bc --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/_backend_tk.py @@ -0,0 +1,1075 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import tkinter as Tk + +import logging +import os.path +import sys + +# Paint image to Tk photo blitter extension +import matplotlib.backends.tkagg as tkagg + +from matplotlib.backends.backend_agg import FigureCanvasAgg +import matplotlib.backends.windowing as windowing + +import matplotlib +from matplotlib import backend_tools, cbook, rcParams +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2, + StatusbarBase, TimerBase, ToolContainerBase, cursors) +from matplotlib.backend_managers import ToolManager +from matplotlib._pylab_helpers import Gcf +from matplotlib.figure import Figure +from matplotlib.widgets import SubplotTool + + +_log = logging.getLogger(__name__) + +backend_version = Tk.TkVersion + +# the true dots per inch on the screen; should be display dependent +# see http://groups.google.com/groups?q=screen+dpi+x11&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=7077.26e81ad5%40swift.cs.tcd.ie&rnum=5 for some info about screen dpi +PIXELS_PER_INCH = 75 + +cursord = { + cursors.MOVE: "fleur", + cursors.HAND: "hand2", + cursors.POINTER: "arrow", + cursors.SELECT_REGION: "tcross", + cursors.WAIT: "watch", + } + + +def raise_msg_to_str(msg): + """msg is a return arg from a raise. Join with new lines""" + if not isinstance(msg, six.string_types): + msg = '\n'.join(map(str, msg)) + return msg + +def error_msg_tkpaint(msg, parent=None): + from six.moves import tkinter_messagebox as tkMessageBox + tkMessageBox.showerror("matplotlib", msg) + + +class TimerTk(TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` that uses Tk's timer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + def __init__(self, parent, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) + self.parent = parent + self._timer = None + + def _timer_start(self): + self._timer_stop() + self._timer = self.parent.after(self._interval, self._on_timer) + + def _timer_stop(self): + if self._timer is not None: + self.parent.after_cancel(self._timer) + self._timer = None + + def _on_timer(self): + TimerBase._on_timer(self) + + # Tk after() is only a single shot, so we need to add code here to + # reset the timer if we're not operating in single shot mode. However, + # if _timer is None, this means that _timer_stop has been called; so + # don't recreate the timer in that case. + if not self._single and self._timer: + self._timer = self.parent.after(self._interval, self._on_timer) + else: + self._timer = None + + +class FigureCanvasTk(FigureCanvasBase): + keyvald = {65507 : 'control', + 65505 : 'shift', + 65513 : 'alt', + 65515 : 'super', + 65508 : 'control', + 65506 : 'shift', + 65514 : 'alt', + 65361 : 'left', + 65362 : 'up', + 65363 : 'right', + 65364 : 'down', + 65307 : 'escape', + 65470 : 'f1', + 65471 : 'f2', + 65472 : 'f3', + 65473 : 'f4', + 65474 : 'f5', + 65475 : 'f6', + 65476 : 'f7', + 65477 : 'f8', + 65478 : 'f9', + 65479 : 'f10', + 65480 : 'f11', + 65481 : 'f12', + 65300 : 'scroll_lock', + 65299 : 'break', + 65288 : 'backspace', + 65293 : 'enter', + 65379 : 'insert', + 65535 : 'delete', + 65360 : 'home', + 65367 : 'end', + 65365 : 'pageup', + 65366 : 'pagedown', + 65438 : '0', + 65436 : '1', + 65433 : '2', + 65435 : '3', + 65430 : '4', + 65437 : '5', + 65432 : '6', + 65429 : '7', + 65431 : '8', + 65434 : '9', + 65451 : '+', + 65453 : '-', + 65450 : '*', + 65455 : '/', + 65439 : 'dec', + 65421 : 'enter', + } + + _keycode_lookup = { + 262145: 'control', + 524320: 'alt', + 524352: 'alt', + 1048584: 'super', + 1048592: 'super', + 131074: 'shift', + 131076: 'shift', + } + """_keycode_lookup is used for badly mapped (i.e. no event.key_sym set) + keys on apple keyboards.""" + + def __init__(self, figure, master=None, resize_callback=None): + super(FigureCanvasTk, self).__init__(figure) + self._idle = True + self._idle_callback = None + t1,t2,w,h = self.figure.bbox.bounds + w, h = int(w), int(h) + self._tkcanvas = Tk.Canvas( + master=master, background="white", + width=w, height=h, borderwidth=0, highlightthickness=0) + self._tkphoto = Tk.PhotoImage( + master=self._tkcanvas, width=w, height=h) + self._tkcanvas.create_image(w//2, h//2, image=self._tkphoto) + self._resize_callback = resize_callback + self._tkcanvas.bind("", self.resize) + self._tkcanvas.bind("", self.key_press) + self._tkcanvas.bind("", self.motion_notify_event) + self._tkcanvas.bind("", self.key_release) + for name in "", "", "": + self._tkcanvas.bind(name, self.button_press_event) + for name in "", "", "": + self._tkcanvas.bind(name, self.button_dblclick_event) + for name in "", "", "": + self._tkcanvas.bind(name, self.button_release_event) + + # Mouse wheel on Linux generates button 4/5 events + for name in "", "": + self._tkcanvas.bind(name, self.scroll_event) + # Mouse wheel for windows goes to the window with the focus. + # Since the canvas won't usually have the focus, bind the + # event to the window containing the canvas instead. + # See http://wiki.tcl.tk/3893 (mousewheel) for details + root = self._tkcanvas.winfo_toplevel() + root.bind("", self.scroll_event_windows, "+") + + # Can't get destroy events by binding to _tkcanvas. Therefore, bind + # to the window and filter. + def filter_destroy(evt): + if evt.widget is self._tkcanvas: + self._master.update_idletasks() + self.close_event() + root.bind("", filter_destroy, "+") + + self._master = master + self._tkcanvas.focus_set() + + def resize(self, event): + width, height = event.width, event.height + if self._resize_callback is not None: + self._resize_callback(event) + + # compute desired figure size in inches + dpival = self.figure.dpi + winch = width/dpival + hinch = height/dpival + self.figure.set_size_inches(winch, hinch, forward=False) + + + self._tkcanvas.delete(self._tkphoto) + self._tkphoto = Tk.PhotoImage( + master=self._tkcanvas, width=int(width), height=int(height)) + self._tkcanvas.create_image(int(width/2),int(height/2),image=self._tkphoto) + self.resize_event() + self.draw() + + # a resizing will in general move the pointer position + # relative to the canvas, so process it as a motion notify + # event. An intended side effect of this call is to allow + # window raises (which trigger a resize) to get the cursor + # position to the mpl event framework so key presses which are + # over the axes will work w/o clicks or explicit motion + self._update_pointer_position(event) + + def _update_pointer_position(self, guiEvent=None): + """ + Figure out if we are inside the canvas or not and update the + canvas enter/leave events + """ + # if the pointer if over the canvas, set the lastx and lasty + # attrs of the canvas so it can process event w/o mouse click + # or move + + # the window's upper, left coords in screen coords + xw = self._tkcanvas.winfo_rootx() + yw = self._tkcanvas.winfo_rooty() + # the pointer's location in screen coords + xp, yp = self._tkcanvas.winfo_pointerxy() + + # not figure out the canvas coordinates of the pointer + xc = xp - xw + yc = yp - yw + + # flip top/bottom + yc = self.figure.bbox.height - yc + + # JDH: this method was written originally to get the pointer + # location to the backend lastx and lasty attrs so that events + # like KeyEvent can be handled without mouse events. e.g., if + # the cursor is already above the axes, then key presses like + # 'g' should toggle the grid. In order for this to work in + # backend_bases, the canvas needs to know _lastx and _lasty. + # There are three ways to get this info the canvas: + # + # 1) set it explicitly + # + # 2) call enter/leave events explicitly. The downside of this + # in the impl below is that enter could be repeatedly + # triggered if the mouse is over the axes and one is + # resizing with the keyboard. This is not entirely bad, + # because the mouse position relative to the canvas is + # changing, but it may be surprising to get repeated entries + # without leaves + # + # 3) process it as a motion notify event. This also has pros + # and cons. The mouse is moving relative to the window, but + # this may surpise an event handler writer who is getting + # motion_notify_events even if the mouse has not moved + + # here are the three scenarios + if 1: + # just manually set it + self._lastx, self._lasty = xc, yc + elif 0: + # alternate implementation: process it as a motion + FigureCanvasBase.motion_notify_event(self, xc, yc, guiEvent) + elif 0: + # alternate implementation -- process enter/leave events + # instead of motion/notify + if self.figure.bbox.contains(xc, yc): + self.enter_notify_event(guiEvent, xy=(xc,yc)) + else: + self.leave_notify_event(guiEvent) + + show = cbook.deprecated("2.2", name="FigureCanvasTk.show", + alternative="FigureCanvasTk.draw")( + lambda self: self.draw()) + + def draw_idle(self): + 'update drawing area only if idle' + if self._idle is False: + return + + self._idle = False + + def idle_draw(*args): + try: + self.draw() + finally: + self._idle = True + + self._idle_callback = self._tkcanvas.after_idle(idle_draw) + + def get_tk_widget(self): + """returns the Tk widget used to implement FigureCanvasTkAgg. + Although the initial implementation uses a Tk canvas, this routine + is intended to hide that fact. + """ + return self._tkcanvas + + def motion_notify_event(self, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.figure.bbox.height - event.y + FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event) + + + def button_press_event(self, event, dblclick=False): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.figure.bbox.height - event.y + num = getattr(event, 'num', None) + + if sys.platform=='darwin': + # 2 and 3 were reversed on the OSX platform I + # tested under tkagg + if num==2: num=3 + elif num==3: num=2 + + FigureCanvasBase.button_press_event(self, x, y, num, dblclick=dblclick, guiEvent=event) + + def button_dblclick_event(self,event): + self.button_press_event(event,dblclick=True) + + def button_release_event(self, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.figure.bbox.height - event.y + + num = getattr(event, 'num', None) + + if sys.platform=='darwin': + # 2 and 3 were reversed on the OSX platform I + # tested under tkagg + if num==2: num=3 + elif num==3: num=2 + + FigureCanvasBase.button_release_event(self, x, y, num, guiEvent=event) + + def scroll_event(self, event): + x = event.x + y = self.figure.bbox.height - event.y + num = getattr(event, 'num', None) + if num==4: step = +1 + elif num==5: step = -1 + else: step = 0 + + FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event) + + def scroll_event_windows(self, event): + """MouseWheel event processor""" + # need to find the window that contains the mouse + w = event.widget.winfo_containing(event.x_root, event.y_root) + if w == self._tkcanvas: + x = event.x_root - w.winfo_rootx() + y = event.y_root - w.winfo_rooty() + y = self.figure.bbox.height - y + step = event.delta/120. + FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event) + + def _get_key(self, event): + val = event.keysym_num + if val in self.keyvald: + key = self.keyvald[val] + elif val == 0 and sys.platform == 'darwin' and \ + event.keycode in self._keycode_lookup: + key = self._keycode_lookup[event.keycode] + elif val < 256: + key = chr(val) + else: + key = None + + # add modifier keys to the key string. Bit details originate from + # http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm + # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004; + # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080; + # BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400; + # In general, the modifier key is excluded from the modifier flag, + # however this is not the case on "darwin", so double check that + # we aren't adding repeat modifier flags to a modifier key. + if sys.platform == 'win32': + modifiers = [(17, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + elif sys.platform == 'darwin': + modifiers = [(3, 'super', 'super'), + (4, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + else: + modifiers = [(6, 'super', 'super'), + (3, 'alt', 'alt'), + (2, 'ctrl', 'control'), + ] + + if key is not None: + # note, shift is not added to the keys as this is already accounted for + for bitmask, prefix, key_name in modifiers: + if event.state & (1 << bitmask) and key_name not in key: + key = '{0}+{1}'.format(prefix, key) + + return key + + def key_press(self, event): + key = self._get_key(event) + FigureCanvasBase.key_press_event(self, key, guiEvent=event) + + def key_release(self, event): + key = self._get_key(event) + FigureCanvasBase.key_release_event(self, key, guiEvent=event) + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + + """ + return TimerTk(self._tkcanvas, *args, **kwargs) + + def flush_events(self): + self._master.update() + + +class FigureManagerTk(FigureManagerBase): + """ + Attributes + ---------- + canvas : `FigureCanvas` + The FigureCanvas instance + num : int or str + The Figure number + toolbar : tk.Toolbar + The tk.Toolbar + window : tk.Window + The tk.Window + + """ + def __init__(self, canvas, num, window): + FigureManagerBase.__init__(self, canvas, num) + self.window = window + self.window.withdraw() + self.set_window_title("Figure %d" % num) + self.canvas = canvas + # If using toolmanager it has to be present when initializing the toolbar + self.toolmanager = self._get_toolmanager() + # packing toolbar first, because if space is getting low, last packed widget is getting shrunk first (-> the canvas) + self.toolbar = self._get_toolbar() + self.canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) + self._num = num + + self.statusbar = None + + if self.toolmanager: + backend_tools.add_tools_to_manager(self.toolmanager) + if self.toolbar: + backend_tools.add_tools_to_container(self.toolbar) + self.statusbar = StatusbarTk(self.window, self.toolmanager) + + self._shown = False + + def notify_axes_change(fig): + 'this will be called whenever the current axes is changed' + if self.toolmanager is not None: + pass + elif self.toolbar is not None: + self.toolbar.update() + self.canvas.figure.add_axobserver(notify_axes_change) + + def _get_toolbar(self): + if matplotlib.rcParams['toolbar'] == 'toolbar2': + toolbar = NavigationToolbar2Tk(self.canvas, self.window) + elif matplotlib.rcParams['toolbar'] == 'toolmanager': + toolbar = ToolbarTk(self.toolmanager, self.window) + else: + toolbar = None + return toolbar + + def _get_toolmanager(self): + if rcParams['toolbar'] == 'toolmanager': + toolmanager = ToolManager(self.canvas.figure) + else: + toolmanager = None + return toolmanager + + def resize(self, width, height=None): + # before 09-12-22, the resize method takes a single *event* + # parameter. On the other hand, the resize method of other + # FigureManager class takes *width* and *height* parameter, + # which is used to change the size of the window. For the + # Figure.set_size_inches with forward=True work with Tk + # backend, I changed the function signature but tried to keep + # it backward compatible. -JJL + + # when a single parameter is given, consider it as a event + if height is None: + cbook.warn_deprecated("2.2", "FigureManagerTkAgg.resize now takes " + "width and height as separate arguments") + width = width.width + else: + self.canvas._tkcanvas.master.geometry("%dx%d" % (width, height)) + + if self.toolbar is not None: + self.toolbar.configure(width=width) + + def show(self): + """ + this function doesn't segfault but causes the + PyEval_RestoreThread: NULL state bug on win32 + """ + _focus = windowing.FocusManager() + if not self._shown: + def destroy(*args): + self.window = None + Gcf.destroy(self._num) + self.canvas._tkcanvas.bind("", destroy) + self.window.deiconify() + else: + self.canvas.draw_idle() + # Raise the new window. + self.canvas.manager.window.attributes('-topmost', 1) + self.canvas.manager.window.attributes('-topmost', 0) + self._shown = True + + def destroy(self, *args): + if self.window is not None: + #self.toolbar.destroy() + if self.canvas._idle_callback: + self.canvas._tkcanvas.after_cancel(self.canvas._idle_callback) + self.window.destroy() + if Gcf.get_num_fig_managers()==0: + if self.window is not None: + self.window.quit() + self.window = None + + def get_window_title(self): + return self.window.wm_title() + + def set_window_title(self, title): + self.window.wm_title(title) + + def full_screen_toggle(self): + is_fullscreen = bool(self.window.attributes('-fullscreen')) + self.window.attributes('-fullscreen', not is_fullscreen) + + +@cbook.deprecated("2.2") +class AxisMenu(object): + def __init__(self, master, naxes): + self._master = master + self._naxes = naxes + self._mbar = Tk.Frame(master=master, relief=Tk.RAISED, borderwidth=2) + self._mbar.pack(side=Tk.LEFT) + self._mbutton = Tk.Menubutton( + master=self._mbar, text="Axes", underline=0) + self._mbutton.pack(side=Tk.LEFT, padx="2m") + self._mbutton.menu = Tk.Menu(self._mbutton) + self._mbutton.menu.add_command( + label="Select All", command=self.select_all) + self._mbutton.menu.add_command( + label="Invert All", command=self.invert_all) + self._axis_var = [] + self._checkbutton = [] + for i in range(naxes): + self._axis_var.append(Tk.IntVar()) + self._axis_var[i].set(1) + self._checkbutton.append(self._mbutton.menu.add_checkbutton( + label = "Axis %d" % (i+1), + variable=self._axis_var[i], + command=self.set_active)) + self._mbutton.menu.invoke(self._mbutton.menu.index("Select All")) + self._mbutton['menu'] = self._mbutton.menu + self._mbar.tk_menuBar(self._mbutton) + self.set_active() + + def adjust(self, naxes): + if self._naxes < naxes: + for i in range(self._naxes, naxes): + self._axis_var.append(Tk.IntVar()) + self._axis_var[i].set(1) + self._checkbutton.append( self._mbutton.menu.add_checkbutton( + label = "Axis %d" % (i+1), + variable=self._axis_var[i], + command=self.set_active)) + elif self._naxes > naxes: + for i in range(self._naxes-1, naxes-1, -1): + del self._axis_var[i] + self._mbutton.menu.forget(self._checkbutton[i]) + del self._checkbutton[i] + self._naxes = naxes + self.set_active() + + def get_indices(self): + a = [i for i in range(len(self._axis_var)) if self._axis_var[i].get()] + return a + + def set_active(self): + self._master.set_active(self.get_indices()) + + def invert_all(self): + for a in self._axis_var: + a.set(not a.get()) + self.set_active() + + def select_all(self): + for a in self._axis_var: + a.set(1) + self.set_active() + + +class NavigationToolbar2Tk(NavigationToolbar2, Tk.Frame): + """ + Attributes + ---------- + canvas : `FigureCanvas` + the figure canvas on which to operate + win : tk.Window + the tk.Window which owns this toolbar + + """ + def __init__(self, canvas, window): + self.canvas = canvas + self.window = window + NavigationToolbar2.__init__(self, canvas) + + def destroy(self, *args): + del self.message + Tk.Frame.destroy(self, *args) + + def set_message(self, s): + self.message.set(s) + + def draw_rubberband(self, event, x0, y0, x1, y1): + height = self.canvas.figure.bbox.height + y0 = height - y0 + y1 = height - y1 + if hasattr(self, "lastrect"): + self.canvas._tkcanvas.delete(self.lastrect) + self.lastrect = self.canvas._tkcanvas.create_rectangle(x0, y0, x1, y1) + + #self.canvas.draw() + + def release(self, event): + try: self.lastrect + except AttributeError: pass + else: + self.canvas._tkcanvas.delete(self.lastrect) + del self.lastrect + + def set_cursor(self, cursor): + self.window.configure(cursor=cursord[cursor]) + self.window.update_idletasks() + + def _Button(self, text, file, command, extension='.gif'): + img_file = os.path.join( + rcParams['datapath'], 'images', file + extension) + im = Tk.PhotoImage(master=self, file=img_file) + b = Tk.Button( + master=self, text=text, padx=2, pady=2, image=im, command=command) + b._ntimage = im + b.pack(side=Tk.LEFT) + return b + + def _Spacer(self): + # Buttons are 30px high, so make this 26px tall with padding to center it + s = Tk.Frame( + master=self, height=26, relief=Tk.RIDGE, pady=2, bg="DarkGray") + s.pack(side=Tk.LEFT, padx=5) + return s + + def _init_toolbar(self): + xmin, xmax = self.canvas.figure.bbox.intervalx + height, width = 50, xmax-xmin + Tk.Frame.__init__(self, master=self.window, + width=int(width), height=int(height), + borderwidth=2) + + self.update() # Make axes menu + + for text, tooltip_text, image_file, callback in self.toolitems: + if text is None: + # Add a spacer; return value is unused. + self._Spacer() + else: + button = self._Button(text=text, file=image_file, + command=getattr(self, callback)) + if tooltip_text is not None: + ToolTip.createToolTip(button, tooltip_text) + + self.message = Tk.StringVar(master=self) + self._message_label = Tk.Label(master=self, textvariable=self.message) + self._message_label.pack(side=Tk.RIGHT) + self.pack(side=Tk.BOTTOM, fill=Tk.X) + + def configure_subplots(self): + toolfig = Figure(figsize=(6,3)) + window = Tk.Toplevel() + canvas = type(self.canvas)(toolfig, master=window) + toolfig.subplots_adjust(top=0.9) + canvas.tool = SubplotTool(self.canvas.figure, toolfig) + canvas.draw() + canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) + window.grab_set() + + def save_figure(self, *args): + from six.moves import tkinter_tkfiledialog, tkinter_messagebox + filetypes = self.canvas.get_supported_filetypes().copy() + default_filetype = self.canvas.get_default_filetype() + + # Tk doesn't provide a way to choose a default filetype, + # so we just have to put it first + default_filetype_name = filetypes.pop(default_filetype) + sorted_filetypes = ([(default_filetype, default_filetype_name)] + + sorted(six.iteritems(filetypes))) + tk_filetypes = [(name, '*.%s' % ext) for ext, name in sorted_filetypes] + + # adding a default extension seems to break the + # asksaveasfilename dialog when you choose various save types + # from the dropdown. Passing in the empty string seems to + # work - JDH! + #defaultextension = self.canvas.get_default_filetype() + defaultextension = '' + initialdir = os.path.expanduser(rcParams['savefig.directory']) + initialfile = self.canvas.get_default_filename() + fname = tkinter_tkfiledialog.asksaveasfilename( + master=self.window, + title='Save the figure', + filetypes=tk_filetypes, + defaultextension=defaultextension, + initialdir=initialdir, + initialfile=initialfile, + ) + + if fname in ["", ()]: + return + # Save dir for next time, unless empty str (i.e., use cwd). + if initialdir != "": + rcParams['savefig.directory'] = ( + os.path.dirname(six.text_type(fname))) + try: + # This method will handle the delegation to the correct type + self.canvas.figure.savefig(fname) + except Exception as e: + tkinter_messagebox.showerror("Error saving file", str(e)) + + def set_active(self, ind): + self._ind = ind + self._active = [self._axes[i] for i in self._ind] + + def update(self): + _focus = windowing.FocusManager() + self._axes = self.canvas.figure.axes + NavigationToolbar2.update(self) + + +class ToolTip(object): + """ + Tooltip recipe from + http://www.voidspace.org.uk/python/weblog/arch_d7_2006_07_01.shtml#e387 + """ + @staticmethod + def createToolTip(widget, text): + toolTip = ToolTip(widget) + def enter(event): + toolTip.showtip(text) + def leave(event): + toolTip.hidetip() + widget.bind('', enter) + widget.bind('', leave) + + def __init__(self, widget): + self.widget = widget + self.tipwindow = None + self.id = None + self.x = self.y = 0 + + def showtip(self, text): + "Display text in tooltip window" + self.text = text + if self.tipwindow or not self.text: + return + x, y, _, _ = self.widget.bbox("insert") + x = x + self.widget.winfo_rootx() + 27 + y = y + self.widget.winfo_rooty() + self.tipwindow = tw = Tk.Toplevel(self.widget) + tw.wm_overrideredirect(1) + tw.wm_geometry("+%d+%d" % (x, y)) + try: + # For Mac OS + tw.tk.call("::tk::unsupported::MacWindowStyle", + "style", tw._w, + "help", "noActivates") + except Tk.TclError: + pass + label = Tk.Label(tw, text=self.text, justify=Tk.LEFT, + background="#ffffe0", relief=Tk.SOLID, borderwidth=1) + label.pack(ipadx=1) + + def hidetip(self): + tw = self.tipwindow + self.tipwindow = None + if tw: + tw.destroy() + + +class RubberbandTk(backend_tools.RubberbandBase): + def __init__(self, *args, **kwargs): + backend_tools.RubberbandBase.__init__(self, *args, **kwargs) + + def draw_rubberband(self, x0, y0, x1, y1): + height = self.figure.canvas.figure.bbox.height + y0 = height - y0 + y1 = height - y1 + if hasattr(self, "lastrect"): + self.figure.canvas._tkcanvas.delete(self.lastrect) + self.lastrect = self.figure.canvas._tkcanvas.create_rectangle( + x0, y0, x1, y1) + + def remove_rubberband(self): + if hasattr(self, "lastrect"): + self.figure.canvas._tkcanvas.delete(self.lastrect) + del self.lastrect + + +class SetCursorTk(backend_tools.SetCursorBase): + def set_cursor(self, cursor): + self.figure.canvas.manager.window.configure(cursor=cursord[cursor]) + + +class ToolbarTk(ToolContainerBase, Tk.Frame): + _icon_extension = '.gif' + def __init__(self, toolmanager, window): + ToolContainerBase.__init__(self, toolmanager) + xmin, xmax = self.toolmanager.canvas.figure.bbox.intervalx + height, width = 50, xmax - xmin + Tk.Frame.__init__(self, master=window, + width=int(width), height=int(height), + borderwidth=2) + self._toolitems = {} + self.pack(side=Tk.TOP, fill=Tk.X) + self._groups = {} + + def add_toolitem( + self, name, group, position, image_file, description, toggle): + frame = self._get_groupframe(group) + button = self._Button(name, image_file, toggle, frame) + if description is not None: + ToolTip.createToolTip(button, description) + self._toolitems.setdefault(name, []) + self._toolitems[name].append(button) + + def _get_groupframe(self, group): + if group not in self._groups: + if self._groups: + self._add_separator() + frame = Tk.Frame(master=self, borderwidth=0) + frame.pack(side=Tk.LEFT, fill=Tk.Y) + self._groups[group] = frame + return self._groups[group] + + def _add_separator(self): + separator = Tk.Frame(master=self, bd=5, width=1, bg='black') + separator.pack(side=Tk.LEFT, fill=Tk.Y, padx=2) + + def _Button(self, text, image_file, toggle, frame): + if image_file is not None: + im = Tk.PhotoImage(master=self, file=image_file) + else: + im = None + + if not toggle: + b = Tk.Button(master=frame, text=text, padx=2, pady=2, image=im, + command=lambda: self._button_click(text)) + else: + # There is a bug in tkinter included in some python 3.6 versions + # that without this variable, produces a "visual" toggling of + # other near checkbuttons + # https://bugs.python.org/issue29402 + # https://bugs.python.org/issue25684 + var = Tk.IntVar() + b = Tk.Checkbutton(master=frame, text=text, padx=2, pady=2, + image=im, indicatoron=False, + command=lambda: self._button_click(text), + variable=var) + b._ntimage = im + b.pack(side=Tk.LEFT) + return b + + def _button_click(self, name): + self.trigger_tool(name) + + def toggle_toolitem(self, name, toggled): + if name not in self._toolitems: + return + for toolitem in self._toolitems[name]: + if toggled: + toolitem.select() + else: + toolitem.deselect() + + def remove_toolitem(self, name): + for toolitem in self._toolitems[name]: + toolitem.pack_forget() + del self._toolitems[name] + + +class StatusbarTk(StatusbarBase, Tk.Frame): + def __init__(self, window, *args, **kwargs): + StatusbarBase.__init__(self, *args, **kwargs) + xmin, xmax = self.toolmanager.canvas.figure.bbox.intervalx + height, width = 50, xmax - xmin + Tk.Frame.__init__(self, master=window, + width=int(width), height=int(height), + borderwidth=2) + self._message = Tk.StringVar(master=self) + self._message_label = Tk.Label(master=self, textvariable=self._message) + self._message_label.pack(side=Tk.RIGHT) + self.pack(side=Tk.TOP, fill=Tk.X) + + def set_message(self, s): + self._message.set(s) + + +class SaveFigureTk(backend_tools.SaveFigureBase): + def trigger(self, *args): + from six.moves import tkinter_tkfiledialog, tkinter_messagebox + filetypes = self.figure.canvas.get_supported_filetypes().copy() + default_filetype = self.figure.canvas.get_default_filetype() + + # Tk doesn't provide a way to choose a default filetype, + # so we just have to put it first + default_filetype_name = filetypes.pop(default_filetype) + sorted_filetypes = ([(default_filetype, default_filetype_name)] + + sorted(six.iteritems(filetypes))) + tk_filetypes = [(name, '*.%s' % ext) for ext, name in sorted_filetypes] + + # adding a default extension seems to break the + # asksaveasfilename dialog when you choose various save types + # from the dropdown. Passing in the empty string seems to + # work - JDH! + # defaultextension = self.figure.canvas.get_default_filetype() + defaultextension = '' + initialdir = os.path.expanduser(rcParams['savefig.directory']) + initialfile = self.figure.canvas.get_default_filename() + fname = tkinter_tkfiledialog.asksaveasfilename( + master=self.figure.canvas.manager.window, + title='Save the figure', + filetypes=tk_filetypes, + defaultextension=defaultextension, + initialdir=initialdir, + initialfile=initialfile, + ) + + if fname == "" or fname == (): + return + else: + if initialdir == '': + # explicitly missing key or empty str signals to use cwd + rcParams['savefig.directory'] = initialdir + else: + # save dir for next time + rcParams['savefig.directory'] = os.path.dirname( + six.text_type(fname)) + try: + # This method will handle the delegation to the correct type + self.figure.savefig(fname) + except Exception as e: + tkinter_messagebox.showerror("Error saving file", str(e)) + + +class ConfigureSubplotsTk(backend_tools.ConfigureSubplotsBase): + def __init__(self, *args, **kwargs): + backend_tools.ConfigureSubplotsBase.__init__(self, *args, **kwargs) + self.window = None + + def trigger(self, *args): + self.init_window() + self.window.lift() + + def init_window(self): + if self.window: + return + + toolfig = Figure(figsize=(6, 3)) + self.window = Tk.Tk() + + canvas = type(self.canvas)(toolfig, master=self.window) + toolfig.subplots_adjust(top=0.9) + _tool = SubplotTool(self.figure, toolfig) + canvas.draw() + canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1) + self.window.protocol("WM_DELETE_WINDOW", self.destroy) + + def destroy(self, *args, **kwargs): + self.window.destroy() + self.window = None + + +backend_tools.ToolSaveFigure = SaveFigureTk +backend_tools.ToolConfigureSubplots = ConfigureSubplotsTk +backend_tools.ToolSetCursor = SetCursorTk +backend_tools.ToolRubberband = RubberbandTk +Toolbar = ToolbarTk + + +@_Backend.export +class _BackendTk(_Backend): + FigureManager = FigureManagerTk + + @classmethod + def new_figure_manager_given_figure(cls, num, figure): + """ + Create a new figure manager instance for the given figure. + """ + _focus = windowing.FocusManager() + window = Tk.Tk(className="matplotlib") + window.withdraw() + + # Put a mpl icon on the window rather than the default tk icon. + # Tkinter doesn't allow colour icons on linux systems, but tk>=8.5 has + # a iconphoto command which we call directly. Source: + # http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html + icon_fname = os.path.join( + rcParams['datapath'], 'images', 'matplotlib.ppm') + icon_img = Tk.PhotoImage(file=icon_fname) + try: + window.tk.call('wm', 'iconphoto', window._w, icon_img) + except Exception as exc: + # log the failure (due e.g. to Tk version), but carry on + _log.info('Could not load matplotlib icon: %s', exc) + + canvas = cls.FigureCanvas(figure, master=window) + manager = cls.FigureManager(canvas, num, window) + if matplotlib.is_interactive(): + manager.show() + canvas.draw_idle() + return manager + + @staticmethod + def trigger_manager_draw(manager): + manager.show() + + @staticmethod + def mainloop(): + Tk.mainloop() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/_gtk3_compat.py b/contrib/python/matplotlib/py2/matplotlib/backends/_gtk3_compat.py new file mode 100644 index 00000000000..825fa2341c8 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/_gtk3_compat.py @@ -0,0 +1,41 @@ +""" +GObject compatibility loader; supports ``gi`` and ``pgi``. + +The binding selection rules are as follows: +- if ``gi`` has already been imported, use it; else +- if ``pgi`` has already been imported, use it; else +- if ``gi`` can be imported, use it; else +- if ``pgi`` can be imported, use it; else +- error out. + +Thus, to force usage of PGI when both bindings are installed, import it first. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import importlib +import sys + + +if "gi" in sys.modules: + import gi +elif "pgi" in sys.modules: + import pgi as gi +else: + try: + import gi + except ImportError: + try: + import pgi as gi + except ImportError: + raise ImportError("The Gtk3 backend requires PyGObject or pgi") + + +gi.require_version("Gtk", "3.0") +globals().update( + {name: + importlib.import_module("{}.repository.{}".format(gi.__name__, name)) + for name in ["GLib", "GObject", "Gtk", "Gdk"]}) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_agg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_agg.py new file mode 100644 index 00000000000..491a9b2c5d6 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_agg.py @@ -0,0 +1,606 @@ +""" +An agg http://antigrain.com/ backend + +Features that are implemented + + * capstyles and join styles + * dashes + * linewidth + * lines, rectangles, ellipses + * clipping to a rectangle + * output to RGBA and PNG, optionally JPEG and TIFF + * alpha blending + * DPI scaling properly - everything scales properly (dashes, linewidths, etc) + * draw polygon + * freetype2 w/ ft2font + +TODO: + + * integrate screen dpi w/ ppi and text + +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +try: + import threading +except ImportError: + import dummy_threading as threading + +import numpy as np +from collections import OrderedDict +from math import radians, cos, sin +from matplotlib import cbook, rcParams, __version__ +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, RendererBase, cursors) +from matplotlib.cbook import maxdict +from matplotlib.figure import Figure +from matplotlib.font_manager import findfont, get_font +from matplotlib.ft2font import (LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING, + LOAD_DEFAULT, LOAD_NO_AUTOHINT) +from matplotlib.mathtext import MathTextParser +from matplotlib.path import Path +from matplotlib.transforms import Bbox, BboxBase +from matplotlib import colors as mcolors + +from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg +from matplotlib import _png + +try: + from PIL import Image + _has_pil = True +except ImportError: + _has_pil = False + +backend_version = 'v2.2' + +def get_hinting_flag(): + mapping = { + True: LOAD_FORCE_AUTOHINT, + False: LOAD_NO_HINTING, + 'either': LOAD_DEFAULT, + 'native': LOAD_NO_AUTOHINT, + 'auto': LOAD_FORCE_AUTOHINT, + 'none': LOAD_NO_HINTING + } + return mapping[rcParams['text.hinting']] + + +class RendererAgg(RendererBase): + """ + The renderer handles all the drawing primitives using a graphics + context instance that controls the colors/styles + """ + + @property + @cbook.deprecated("2.2") + def debug(self): + return 1 + + # we want to cache the fonts at the class level so that when + # multiple figures are created we can reuse them. This helps with + # a bug on windows where the creation of too many figures leads to + # too many open file handles. However, storing them at the class + # level is not thread safe. The solution here is to let the + # FigureCanvas acquire a lock on the fontd at the start of the + # draw, and release it when it is done. This allows multiple + # renderers to share the cached fonts, but only one figure can + # draw at time and so the font cache is used by only one + # renderer at a time. + + lock = threading.RLock() + + def __init__(self, width, height, dpi): + RendererBase.__init__(self) + + self.dpi = dpi + self.width = width + self.height = height + self._renderer = _RendererAgg(int(width), int(height), dpi) + self._filter_renderers = [] + + self._update_methods() + self.mathtext_parser = MathTextParser('Agg') + + self.bbox = Bbox.from_bounds(0, 0, self.width, self.height) + + def __getstate__(self): + # We only want to preserve the init keywords of the Renderer. + # Anything else can be re-created. + return {'width': self.width, 'height': self.height, 'dpi': self.dpi} + + def __setstate__(self, state): + self.__init__(state['width'], state['height'], state['dpi']) + + def _get_hinting_flag(self): + if rcParams['text.hinting']: + return LOAD_FORCE_AUTOHINT + else: + return LOAD_NO_HINTING + + # for filtering to work with rasterization, methods needs to be wrapped. + # maybe there is better way to do it. + def draw_markers(self, *kl, **kw): + return self._renderer.draw_markers(*kl, **kw) + + def draw_path_collection(self, *kl, **kw): + return self._renderer.draw_path_collection(*kl, **kw) + + def _update_methods(self): + self.draw_quad_mesh = self._renderer.draw_quad_mesh + self.draw_gouraud_triangle = self._renderer.draw_gouraud_triangle + self.draw_gouraud_triangles = self._renderer.draw_gouraud_triangles + self.draw_image = self._renderer.draw_image + self.copy_from_bbox = self._renderer.copy_from_bbox + self.get_content_extents = self._renderer.get_content_extents + + def tostring_rgba_minimized(self): + extents = self.get_content_extents() + bbox = [[extents[0], self.height - (extents[1] + extents[3])], + [extents[0] + extents[2], self.height - extents[1]]] + region = self.copy_from_bbox(bbox) + return np.array(region), extents + + def draw_path(self, gc, path, transform, rgbFace=None): + """ + Draw the path + """ + nmax = rcParams['agg.path.chunksize'] # here at least for testing + npts = path.vertices.shape[0] + + if (nmax > 100 and npts > nmax and path.should_simplify and + rgbFace is None and gc.get_hatch() is None): + nch = np.ceil(npts / nmax) + chsize = int(np.ceil(npts / nch)) + i0 = np.arange(0, npts, chsize) + i1 = np.zeros_like(i0) + i1[:-1] = i0[1:] - 1 + i1[-1] = npts + for ii0, ii1 in zip(i0, i1): + v = path.vertices[ii0:ii1, :] + c = path.codes + if c is not None: + c = c[ii0:ii1] + c[0] = Path.MOVETO # move to end of last chunk + p = Path(v, c) + try: + self._renderer.draw_path(gc, p, transform, rgbFace) + except OverflowError: + raise OverflowError("Exceeded cell block limit (set " + "'agg.path.chunksize' rcparam)") + else: + try: + self._renderer.draw_path(gc, path, transform, rgbFace) + except OverflowError: + raise OverflowError("Exceeded cell block limit (set " + "'agg.path.chunksize' rcparam)") + + + def draw_mathtext(self, gc, x, y, s, prop, angle): + """ + Draw the math text using matplotlib.mathtext + """ + ox, oy, width, height, descent, font_image, used_characters = \ + self.mathtext_parser.parse(s, self.dpi, prop) + + xd = descent * sin(radians(angle)) + yd = descent * cos(radians(angle)) + x = np.round(x + ox + xd) + y = np.round(y - oy + yd) + self._renderer.draw_text_image(font_image, x, y + 1, angle, gc) + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + """ + Render the text + """ + if ismath: + return self.draw_mathtext(gc, x, y, s, prop, angle) + + flags = get_hinting_flag() + font = self._get_agg_font(prop) + + if font is None: + return None + if len(s) == 1 and ord(s) > 127: + font.load_char(ord(s), flags=flags) + else: + # We pass '0' for angle here, since it will be rotated (in raster + # space) in the following call to draw_text_image). + font.set_text(s, 0, flags=flags) + font.draw_glyphs_to_bitmap(antialiased=rcParams['text.antialiased']) + d = font.get_descent() / 64.0 + # The descent needs to be adjusted for the angle. + xo, yo = font.get_bitmap_offset() + xo /= 64.0 + yo /= 64.0 + xd = -d * sin(radians(angle)) + yd = d * cos(radians(angle)) + + self._renderer.draw_text_image( + font, np.round(x - xd + xo), np.round(y + yd + yo) + 1, angle, gc) + + def get_text_width_height_descent(self, s, prop, ismath): + """ + Get the width, height, and descent (offset from the bottom + to the baseline), in display coords, of the string *s* with + :class:`~matplotlib.font_manager.FontProperties` *prop* + """ + if ismath in ["TeX", "TeX!"]: + # todo: handle props + size = prop.get_size_in_points() + texmanager = self.get_texmanager() + fontsize = prop.get_size_in_points() + w, h, d = texmanager.get_text_width_height_descent( + s, fontsize, renderer=self) + return w, h, d + + if ismath: + ox, oy, width, height, descent, fonts, used_characters = \ + self.mathtext_parser.parse(s, self.dpi, prop) + return width, height, descent + + flags = get_hinting_flag() + font = self._get_agg_font(prop) + font.set_text(s, 0.0, flags=flags) + w, h = font.get_width_height() # width and height of unrotated string + d = font.get_descent() + w /= 64.0 # convert from subpixels + h /= 64.0 + d /= 64.0 + return w, h, d + + def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None): + # todo, handle props, angle, origins + size = prop.get_size_in_points() + + texmanager = self.get_texmanager() + + Z = texmanager.get_grey(s, size, self.dpi) + Z = np.array(Z * 255.0, np.uint8) + + w, h, d = self.get_text_width_height_descent(s, prop, ismath) + xd = d * sin(radians(angle)) + yd = d * cos(radians(angle)) + x = np.round(x + xd) + y = np.round(y + yd) + + self._renderer.draw_text_image(Z, x, y, angle, gc) + + def get_canvas_width_height(self): + 'return the canvas width and height in display coords' + return self.width, self.height + + def _get_agg_font(self, prop): + """ + Get the font for text instance t, cacheing for efficiency + """ + fname = findfont(prop) + font = get_font(fname) + + font.clear() + size = prop.get_size_in_points() + font.set_size(size, self.dpi) + + return font + + def points_to_pixels(self, points): + """ + convert point measures to pixes using dpi and the pixels per + inch of the display + """ + return points*self.dpi/72.0 + + def tostring_rgb(self): + return self._renderer.tostring_rgb() + + def tostring_argb(self): + return self._renderer.tostring_argb() + + def buffer_rgba(self): + return self._renderer.buffer_rgba() + + def clear(self): + self._renderer.clear() + + def option_image_nocomposite(self): + # It is generally faster to composite each image directly to + # the Figure, and there's no file size benefit to compositing + # with the Agg backend + return True + + def option_scale_image(self): + """ + agg backend doesn't support arbitrary scaling of image. + """ + return False + + def restore_region(self, region, bbox=None, xy=None): + """ + Restore the saved region. If bbox (instance of BboxBase, or + its extents) is given, only the region specified by the bbox + will be restored. *xy* (a tuple of two floasts) optionally + specifies the new position (the LLC of the original region, + not the LLC of the bbox) where the region will be restored. + + >>> region = renderer.copy_from_bbox() + >>> x1, y1, x2, y2 = region.get_extents() + >>> renderer.restore_region(region, bbox=(x1+dx, y1, x2, y2), + ... xy=(x1-dx, y1)) + + """ + if bbox is not None or xy is not None: + if bbox is None: + x1, y1, x2, y2 = region.get_extents() + elif isinstance(bbox, BboxBase): + x1, y1, x2, y2 = bbox.extents + else: + x1, y1, x2, y2 = bbox + + if xy is None: + ox, oy = x1, y1 + else: + ox, oy = xy + + # The incoming data is float, but the _renderer type-checking wants + # to see integers. + self._renderer.restore_region(region, int(x1), int(y1), + int(x2), int(y2), int(ox), int(oy)) + + else: + self._renderer.restore_region(region) + + def start_filter(self): + """ + Start filtering. It simply create a new canvas (the old one is saved). + """ + self._filter_renderers.append(self._renderer) + self._renderer = _RendererAgg(int(self.width), int(self.height), + self.dpi) + self._update_methods() + + def stop_filter(self, post_processing): + """ + Save the plot in the current canvas as a image and apply + the *post_processing* function. + + def post_processing(image, dpi): + # ny, nx, depth = image.shape + # image (numpy array) has RGBA channels and has a depth of 4. + ... + # create a new_image (numpy array of 4 channels, size can be + # different). The resulting image may have offsets from + # lower-left corner of the original image + return new_image, offset_x, offset_y + + The saved renderer is restored and the returned image from + post_processing is plotted (using draw_image) on it. + """ + + # WARNING: For agg_filter to work, the renderer's method need to + # overridden in the class. See draw_markers and draw_path_collections. + + width, height = int(self.width), int(self.height) + + buffer, bounds = self.tostring_rgba_minimized() + + l, b, w, h = bounds + + self._renderer = self._filter_renderers.pop() + self._update_methods() + + if w > 0 and h > 0: + img = np.frombuffer(buffer, np.uint8) + img, ox, oy = post_processing(img.reshape((h, w, 4)) / 255., + self.dpi) + gc = self.new_gc() + if img.dtype.kind == 'f': + img = np.asarray(img * 255., np.uint8) + img = img[::-1] + self._renderer.draw_image( + gc, l + ox, height - b - h + oy, img) + + +class FigureCanvasAgg(FigureCanvasBase): + """ + The canvas the figure renders into. Calls the draw and print fig + methods, creates the renderers, etc... + + Attributes + ---------- + figure : `matplotlib.figure.Figure` + A high-level Figure instance + + """ + + def copy_from_bbox(self, bbox): + renderer = self.get_renderer() + return renderer.copy_from_bbox(bbox) + + def restore_region(self, region, bbox=None, xy=None): + renderer = self.get_renderer() + return renderer.restore_region(region, bbox, xy) + + def draw(self): + """ + Draw the figure using the renderer + """ + self.renderer = self.get_renderer(cleared=True) + # acquire a lock on the shared font cache + RendererAgg.lock.acquire() + + toolbar = self.toolbar + try: + # if toolbar: + # toolbar.set_cursor(cursors.WAIT) + self.figure.draw(self.renderer) + # A GUI class may be need to update a window using this draw, so + # don't forget to call the superclass. + super(FigureCanvasAgg, self).draw() + finally: + # if toolbar: + # toolbar.set_cursor(toolbar._lastCursor) + RendererAgg.lock.release() + + def get_renderer(self, cleared=False): + l, b, w, h = self.figure.bbox.bounds + key = w, h, self.figure.dpi + try: self._lastKey, self.renderer + except AttributeError: need_new_renderer = True + else: need_new_renderer = (self._lastKey != key) + + if need_new_renderer: + self.renderer = RendererAgg(w, h, self.figure.dpi) + self._lastKey = key + elif cleared: + self.renderer.clear() + return self.renderer + + def tostring_rgb(self): + '''Get the image as an RGB byte string + + `draw` must be called at least once before this function will work and + to update the renderer for any subsequent changes to the Figure. + + Returns + ------- + bytes + ''' + return self.renderer.tostring_rgb() + + def tostring_argb(self): + '''Get the image as an ARGB byte string + + `draw` must be called at least once before this function will work and + to update the renderer for any subsequent changes to the Figure. + + Returns + ------- + bytes + + ''' + return self.renderer.tostring_argb() + + def buffer_rgba(self): + '''Get the image as an RGBA byte string + + `draw` must be called at least once before this function will work and + to update the renderer for any subsequent changes to the Figure. + + Returns + ------- + bytes + ''' + return self.renderer.buffer_rgba() + + def print_raw(self, filename_or_obj, *args, **kwargs): + FigureCanvasAgg.draw(self) + renderer = self.get_renderer() + original_dpi = renderer.dpi + renderer.dpi = self.figure.dpi + if isinstance(filename_or_obj, six.string_types): + fileobj = open(filename_or_obj, 'wb') + close = True + else: + fileobj = filename_or_obj + close = False + try: + fileobj.write(renderer._renderer.buffer_rgba()) + finally: + if close: + fileobj.close() + renderer.dpi = original_dpi + print_rgba = print_raw + + def print_png(self, filename_or_obj, *args, **kwargs): + FigureCanvasAgg.draw(self) + renderer = self.get_renderer() + original_dpi = renderer.dpi + renderer.dpi = self.figure.dpi + + version_str = 'matplotlib version ' + __version__ + \ + ', http://matplotlib.org/' + metadata = OrderedDict({'Software': version_str}) + user_metadata = kwargs.pop("metadata", None) + if user_metadata is not None: + metadata.update(user_metadata) + + try: + with cbook.open_file_cm(filename_or_obj, "wb") as fh: + _png.write_png(renderer._renderer, fh, + self.figure.dpi, metadata=metadata) + finally: + renderer.dpi = original_dpi + + def print_to_buffer(self): + FigureCanvasAgg.draw(self) + renderer = self.get_renderer() + original_dpi = renderer.dpi + renderer.dpi = self.figure.dpi + try: + result = (renderer._renderer.buffer_rgba(), + (int(renderer.width), int(renderer.height))) + finally: + renderer.dpi = original_dpi + return result + + if _has_pil: + # add JPEG support + def print_jpg(self, filename_or_obj, *args, **kwargs): + """ + Other Parameters + ---------------- + quality : int + The image quality, on a scale from 1 (worst) to + 95 (best). The default is 95, if not given in the + matplotlibrc file in the savefig.jpeg_quality parameter. + Values above 95 should be avoided; 100 completely + disables the JPEG quantization stage. + + optimize : bool + If present, indicates that the encoder should + make an extra pass over the image in order to select + optimal encoder settings. + + progressive : bool + If present, indicates that this image + should be stored as a progressive JPEG file. + """ + buf, size = self.print_to_buffer() + if kwargs.pop("dryrun", False): + return + # The image is "pasted" onto a white background image to safely + # handle any transparency + image = Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1) + rgba = mcolors.to_rgba(rcParams['savefig.facecolor']) + color = tuple([int(x * 255.0) for x in rgba[:3]]) + background = Image.new('RGB', size, color) + background.paste(image, image) + options = {k: kwargs[k] + for k in ['quality', 'optimize', 'progressive', 'dpi'] + if k in kwargs} + options.setdefault('quality', rcParams['savefig.jpeg_quality']) + if 'dpi' in options: + # Set the same dpi in both x and y directions + options['dpi'] = (options['dpi'], options['dpi']) + + return background.save(filename_or_obj, format='jpeg', **options) + print_jpeg = print_jpg + + # add TIFF support + def print_tif(self, filename_or_obj, *args, **kwargs): + buf, size = self.print_to_buffer() + if kwargs.pop("dryrun", False): + return + image = Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1) + dpi = (self.figure.dpi, self.figure.dpi) + return image.save(filename_or_obj, format='tiff', + dpi=dpi) + print_tiff = print_tif + + +@_Backend.export +class _BackendAgg(_Backend): + FigureCanvas = FigureCanvasAgg + FigureManager = FigureManagerBase diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_cairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_cairo.py new file mode 100644 index 00000000000..c870ba60a55 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_cairo.py @@ -0,0 +1,520 @@ +""" +A Cairo backend for matplotlib +============================== +:Author: Steve Chaplin and others + +This backend depends on `cairo `_, and either on +cairocffi, or (Python 2 only) on pycairo. +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import gzip +import sys +import warnings + +import numpy as np + +# cairocffi is more widely compatible than pycairo (in particular pgi only +# works with cairocffi) so try it first. +try: + import cairocffi as cairo +except ImportError: + try: + import cairo + except ImportError: + raise ImportError("cairo backend requires that cairocffi or pycairo " + "is installed") + else: + HAS_CAIRO_CFFI = False +else: + HAS_CAIRO_CFFI = True + +if cairo.version_info < (1, 4, 0): + raise ImportError("cairo {} is installed; " + "cairo>=1.4.0 is required".format(cairo.version)) +backend_version = cairo.version + +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + RendererBase) +from matplotlib.mathtext import MathTextParser +from matplotlib.path import Path +from matplotlib.transforms import Affine2D +from matplotlib.font_manager import ttfFontProperty + + +class ArrayWrapper: + """Thin wrapper around numpy ndarray to expose the interface + expected by cairocffi. Basically replicates the + array.array interface. + """ + def __init__(self, myarray): + self.__array = myarray + self.__data = myarray.ctypes.data + self.__size = len(myarray.flatten()) + self.itemsize = myarray.itemsize + + def buffer_info(self): + return (self.__data, self.__size) + + +class RendererCairo(RendererBase): + fontweights = { + 100 : cairo.FONT_WEIGHT_NORMAL, + 200 : cairo.FONT_WEIGHT_NORMAL, + 300 : cairo.FONT_WEIGHT_NORMAL, + 400 : cairo.FONT_WEIGHT_NORMAL, + 500 : cairo.FONT_WEIGHT_NORMAL, + 600 : cairo.FONT_WEIGHT_BOLD, + 700 : cairo.FONT_WEIGHT_BOLD, + 800 : cairo.FONT_WEIGHT_BOLD, + 900 : cairo.FONT_WEIGHT_BOLD, + 'ultralight' : cairo.FONT_WEIGHT_NORMAL, + 'light' : cairo.FONT_WEIGHT_NORMAL, + 'normal' : cairo.FONT_WEIGHT_NORMAL, + 'medium' : cairo.FONT_WEIGHT_NORMAL, + 'regular' : cairo.FONT_WEIGHT_NORMAL, + 'semibold' : cairo.FONT_WEIGHT_BOLD, + 'bold' : cairo.FONT_WEIGHT_BOLD, + 'heavy' : cairo.FONT_WEIGHT_BOLD, + 'ultrabold' : cairo.FONT_WEIGHT_BOLD, + 'black' : cairo.FONT_WEIGHT_BOLD, + } + fontangles = { + 'italic' : cairo.FONT_SLANT_ITALIC, + 'normal' : cairo.FONT_SLANT_NORMAL, + 'oblique' : cairo.FONT_SLANT_OBLIQUE, + } + + + def __init__(self, dpi): + self.dpi = dpi + self.gc = GraphicsContextCairo(renderer=self) + self.text_ctx = cairo.Context( + cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1)) + self.mathtext_parser = MathTextParser('Cairo') + RendererBase.__init__(self) + + def set_ctx_from_surface(self, surface): + self.gc.ctx = cairo.Context(surface) + # Although it may appear natural to automatically call + # `self.set_width_height(surface.get_width(), surface.get_height())` + # here (instead of having the caller do so separately), this would fail + # for PDF/PS/SVG surfaces, which have no way to report their extents. + + def set_width_height(self, width, height): + self.width = width + self.height = height + + def _fill_and_stroke(self, ctx, fill_c, alpha, alpha_overrides): + if fill_c is not None: + ctx.save() + if len(fill_c) == 3 or alpha_overrides: + ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], alpha) + else: + ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], fill_c[3]) + ctx.fill_preserve() + ctx.restore() + ctx.stroke() + + @staticmethod + def convert_path(ctx, path, transform, clip=None): + for points, code in path.iter_segments(transform, clip=clip): + if code == Path.MOVETO: + ctx.move_to(*points) + elif code == Path.CLOSEPOLY: + ctx.close_path() + elif code == Path.LINETO: + ctx.line_to(*points) + elif code == Path.CURVE3: + ctx.curve_to(points[0], points[1], + points[0], points[1], + points[2], points[3]) + elif code == Path.CURVE4: + ctx.curve_to(*points) + + def draw_path(self, gc, path, transform, rgbFace=None): + ctx = gc.ctx + + # We'll clip the path to the actual rendering extents + # if the path isn't filled. + if rgbFace is None and gc.get_hatch() is None: + clip = ctx.clip_extents() + else: + clip = None + + transform = (transform + + Affine2D().scale(1.0, -1.0).translate(0, self.height)) + + ctx.new_path() + self.convert_path(ctx, path, transform, clip) + + self._fill_and_stroke( + ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) + + def draw_markers(self, gc, marker_path, marker_trans, path, transform, + rgbFace=None): + ctx = gc.ctx + + ctx.new_path() + # Create the path for the marker; it needs to be flipped here already! + self.convert_path( + ctx, marker_path, marker_trans + Affine2D().scale(1.0, -1.0)) + marker_path = ctx.copy_path_flat() + + # Figure out whether the path has a fill + x1, y1, x2, y2 = ctx.fill_extents() + if x1 == 0 and y1 == 0 and x2 == 0 and y2 == 0: + filled = False + # No fill, just unset this (so we don't try to fill it later on) + rgbFace = None + else: + filled = True + + transform = (transform + + Affine2D().scale(1.0, -1.0).translate(0, self.height)) + + ctx.new_path() + for i, (vertices, codes) in enumerate( + path.iter_segments(transform, simplify=False)): + if len(vertices): + x, y = vertices[-2:] + ctx.save() + + # Translate and apply path + ctx.translate(x, y) + ctx.append_path(marker_path) + + ctx.restore() + + # Slower code path if there is a fill; we need to draw + # the fill and stroke for each marker at the same time. + # Also flush out the drawing every once in a while to + # prevent the paths from getting way too long. + if filled or i % 1000 == 0: + self._fill_and_stroke( + ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) + + # Fast path, if there is no fill, draw everything in one step + if not filled: + self._fill_and_stroke( + ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha()) + + def draw_image(self, gc, x, y, im): + # bbox - not currently used + if sys.byteorder == 'little': + im = im[:, :, (2, 1, 0, 3)] + else: + im = im[:, :, (3, 0, 1, 2)] + if HAS_CAIRO_CFFI: + # cairocffi tries to use the buffer_info from array.array + # that we replicate in ArrayWrapper and alternatively falls back + # on ctypes to get a pointer to the numpy array. This works + # correctly on a numpy array in python3 but not 2.7. We replicate + # the array.array functionality here to get cross version support. + imbuffer = ArrayWrapper(im.flatten()) + else: + # pycairo uses PyObject_AsWriteBuffer to get a pointer to the + # numpy array; this works correctly on a regular numpy array but + # not on a py2 memoryview. + imbuffer = im.flatten() + surface = cairo.ImageSurface.create_for_data( + imbuffer, cairo.FORMAT_ARGB32, + im.shape[1], im.shape[0], im.shape[1]*4) + ctx = gc.ctx + y = self.height - y - im.shape[0] + + ctx.save() + ctx.set_source_surface(surface, float(x), float(y)) + if gc.get_alpha() != 1.0: + ctx.paint_with_alpha(gc.get_alpha()) + else: + ctx.paint() + ctx.restore() + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + # Note: x,y are device/display coords, not user-coords, unlike other + # draw_* methods + if ismath: + self._draw_mathtext(gc, x, y, s, prop, angle) + + else: + ctx = gc.ctx + ctx.new_path() + ctx.move_to(x, y) + ctx.select_font_face(prop.get_name(), + self.fontangles[prop.get_style()], + self.fontweights[prop.get_weight()]) + + size = prop.get_size_in_points() * self.dpi / 72.0 + + ctx.save() + if angle: + ctx.rotate(np.deg2rad(-angle)) + ctx.set_font_size(size) + + if HAS_CAIRO_CFFI: + if not isinstance(s, six.text_type): + s = six.text_type(s) + else: + if six.PY2 and isinstance(s, six.text_type): + s = s.encode("utf-8") + + ctx.show_text(s) + ctx.restore() + + def _draw_mathtext(self, gc, x, y, s, prop, angle): + ctx = gc.ctx + width, height, descent, glyphs, rects = self.mathtext_parser.parse( + s, self.dpi, prop) + + ctx.save() + ctx.translate(x, y) + if angle: + ctx.rotate(np.deg2rad(-angle)) + + for font, fontsize, s, ox, oy in glyphs: + ctx.new_path() + ctx.move_to(ox, oy) + + fontProp = ttfFontProperty(font) + ctx.save() + ctx.select_font_face(fontProp.name, + self.fontangles[fontProp.style], + self.fontweights[fontProp.weight]) + + size = fontsize * self.dpi / 72.0 + ctx.set_font_size(size) + if not six.PY3 and isinstance(s, six.text_type): + s = s.encode("utf-8") + ctx.show_text(s) + ctx.restore() + + for ox, oy, w, h in rects: + ctx.new_path() + ctx.rectangle(ox, oy, w, h) + ctx.set_source_rgb(0, 0, 0) + ctx.fill_preserve() + + ctx.restore() + + def get_canvas_width_height(self): + return self.width, self.height + + def get_text_width_height_descent(self, s, prop, ismath): + if ismath: + width, height, descent, fonts, used_characters = \ + self.mathtext_parser.parse(s, self.dpi, prop) + return width, height, descent + + ctx = self.text_ctx + ctx.save() + ctx.select_font_face(prop.get_name(), + self.fontangles[prop.get_style()], + self.fontweights[prop.get_weight()]) + + # Cairo (says it) uses 1/96 inch user space units, ref: cairo_gstate.c + # but if /96.0 is used the font is too small + size = prop.get_size_in_points() * self.dpi / 72 + + # problem - scale remembers last setting and font can become + # enormous causing program to crash + # save/restore prevents the problem + ctx.set_font_size(size) + + y_bearing, w, h = ctx.text_extents(s)[1:4] + ctx.restore() + + return w, h, h + y_bearing + + def new_gc(self): + self.gc.ctx.save() + self.gc._alpha = 1 + self.gc._forced_alpha = False # if True, _alpha overrides A from RGBA + return self.gc + + def points_to_pixels(self, points): + return points / 72 * self.dpi + + +class GraphicsContextCairo(GraphicsContextBase): + _joind = { + 'bevel' : cairo.LINE_JOIN_BEVEL, + 'miter' : cairo.LINE_JOIN_MITER, + 'round' : cairo.LINE_JOIN_ROUND, + } + + _capd = { + 'butt' : cairo.LINE_CAP_BUTT, + 'projecting' : cairo.LINE_CAP_SQUARE, + 'round' : cairo.LINE_CAP_ROUND, + } + + def __init__(self, renderer): + GraphicsContextBase.__init__(self) + self.renderer = renderer + + def restore(self): + self.ctx.restore() + + def set_alpha(self, alpha): + GraphicsContextBase.set_alpha(self, alpha) + _alpha = self.get_alpha() + rgb = self._rgb + if self.get_forced_alpha(): + self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], _alpha) + else: + self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], rgb[3]) + + # def set_antialiased(self, b): + # cairo has many antialiasing modes, we need to pick one for True and + # one for False. + + def set_capstyle(self, cs): + if cs in ('butt', 'round', 'projecting'): + self._capstyle = cs + self.ctx.set_line_cap(self._capd[cs]) + else: + raise ValueError('Unrecognized cap style. Found %s' % cs) + + def set_clip_rectangle(self, rectangle): + if not rectangle: + return + x, y, w, h = np.round(rectangle.bounds) + ctx = self.ctx + ctx.new_path() + ctx.rectangle(x, self.renderer.height - h - y, w, h) + ctx.clip() + + def set_clip_path(self, path): + if not path: + return + tpath, affine = path.get_transformed_path_and_affine() + ctx = self.ctx + ctx.new_path() + affine = (affine + + Affine2D().scale(1, -1).translate(0, self.renderer.height)) + RendererCairo.convert_path(ctx, tpath, affine) + ctx.clip() + + def set_dashes(self, offset, dashes): + self._dashes = offset, dashes + if dashes == None: + self.ctx.set_dash([], 0) # switch dashes off + else: + self.ctx.set_dash( + list(self.renderer.points_to_pixels(np.asarray(dashes))), + offset) + + def set_foreground(self, fg, isRGBA=None): + GraphicsContextBase.set_foreground(self, fg, isRGBA) + if len(self._rgb) == 3: + self.ctx.set_source_rgb(*self._rgb) + else: + self.ctx.set_source_rgba(*self._rgb) + + def get_rgb(self): + return self.ctx.get_source().get_rgba()[:3] + + def set_joinstyle(self, js): + if js in ('miter', 'round', 'bevel'): + self._joinstyle = js + self.ctx.set_line_join(self._joind[js]) + else: + raise ValueError('Unrecognized join style. Found %s' % js) + + def set_linewidth(self, w): + self._linewidth = float(w) + self.ctx.set_line_width(self.renderer.points_to_pixels(w)) + + +class FigureCanvasCairo(FigureCanvasBase): + supports_blit = False + + def print_png(self, fobj, *args, **kwargs): + width, height = self.get_width_height() + + renderer = RendererCairo(self.figure.dpi) + renderer.set_width_height(width, height) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + renderer.set_ctx_from_surface(surface) + + self.figure.draw(renderer) + surface.write_to_png(fobj) + + def print_pdf(self, fobj, *args, **kwargs): + return self._save(fobj, 'pdf', *args, **kwargs) + + def print_ps(self, fobj, *args, **kwargs): + return self._save(fobj, 'ps', *args, **kwargs) + + def print_svg(self, fobj, *args, **kwargs): + return self._save(fobj, 'svg', *args, **kwargs) + + def print_svgz(self, fobj, *args, **kwargs): + return self._save(fobj, 'svgz', *args, **kwargs) + + def _save(self, fo, fmt, **kwargs): + # save PDF/PS/SVG + orientation = kwargs.get('orientation', 'portrait') + + dpi = 72 + self.figure.dpi = dpi + w_in, h_in = self.figure.get_size_inches() + width_in_points, height_in_points = w_in * dpi, h_in * dpi + + if orientation == 'landscape': + width_in_points, height_in_points = ( + height_in_points, width_in_points) + + if fmt == 'ps': + if not hasattr(cairo, 'PSSurface'): + raise RuntimeError('cairo has not been compiled with PS ' + 'support enabled') + surface = cairo.PSSurface(fo, width_in_points, height_in_points) + elif fmt == 'pdf': + if not hasattr(cairo, 'PDFSurface'): + raise RuntimeError('cairo has not been compiled with PDF ' + 'support enabled') + surface = cairo.PDFSurface(fo, width_in_points, height_in_points) + elif fmt in ('svg', 'svgz'): + if not hasattr(cairo, 'SVGSurface'): + raise RuntimeError('cairo has not been compiled with SVG ' + 'support enabled') + if fmt == 'svgz': + if isinstance(fo, six.string_types): + fo = gzip.GzipFile(fo, 'wb') + else: + fo = gzip.GzipFile(None, 'wb', fileobj=fo) + surface = cairo.SVGSurface(fo, width_in_points, height_in_points) + else: + warnings.warn("unknown format: %s" % fmt) + return + + # surface.set_dpi() can be used + renderer = RendererCairo(self.figure.dpi) + renderer.set_width_height(width_in_points, height_in_points) + renderer.set_ctx_from_surface(surface) + ctx = renderer.gc.ctx + + if orientation == 'landscape': + ctx.rotate(np.pi / 2) + ctx.translate(0, -height_in_points) + # Perhaps add an '%%Orientation: Landscape' comment? + + self.figure.draw(renderer) + + ctx.show_page() + surface.finish() + if fmt == 'svgz': + fo.close() + + +@_Backend.export +class _BackendCairo(_Backend): + FigureCanvas = FigureCanvasCairo + FigureManager = FigureManagerBase diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gdk.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gdk.py new file mode 100644 index 00000000000..7d18922fc37 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gdk.py @@ -0,0 +1,438 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import warnings + +import gobject +import gtk; gdk = gtk.gdk +import pango +pygtk_version_required = (2,2,0) +if gtk.pygtk_version < pygtk_version_required: + raise ImportError ("PyGTK %d.%d.%d is installed\n" + "PyGTK %d.%d.%d or later is required" + % (gtk.pygtk_version + pygtk_version_required)) +del pygtk_version_required + +import numpy as np + +import matplotlib +from matplotlib import rcParams +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + RendererBase) +from matplotlib.cbook import warn_deprecated +from matplotlib.mathtext import MathTextParser +from matplotlib.transforms import Affine2D +from matplotlib.backends._backend_gdk import pixbuf_get_pixels_array + +backend_version = "%d.%d.%d" % gtk.pygtk_version + +# Image formats that this backend supports - for FileChooser and print_figure() +IMAGE_FORMAT = sorted(['bmp', 'eps', 'jpg', 'png', 'ps', 'svg']) # 'raw', 'rgb' +IMAGE_FORMAT_DEFAULT = 'png' + + +class RendererGDK(RendererBase): + fontweights = { + 100 : pango.WEIGHT_ULTRALIGHT, + 200 : pango.WEIGHT_LIGHT, + 300 : pango.WEIGHT_LIGHT, + 400 : pango.WEIGHT_NORMAL, + 500 : pango.WEIGHT_NORMAL, + 600 : pango.WEIGHT_BOLD, + 700 : pango.WEIGHT_BOLD, + 800 : pango.WEIGHT_HEAVY, + 900 : pango.WEIGHT_ULTRABOLD, + 'ultralight' : pango.WEIGHT_ULTRALIGHT, + 'light' : pango.WEIGHT_LIGHT, + 'normal' : pango.WEIGHT_NORMAL, + 'medium' : pango.WEIGHT_NORMAL, + 'semibold' : pango.WEIGHT_BOLD, + 'bold' : pango.WEIGHT_BOLD, + 'heavy' : pango.WEIGHT_HEAVY, + 'ultrabold' : pango.WEIGHT_ULTRABOLD, + 'black' : pango.WEIGHT_ULTRABOLD, + } + + # cache for efficiency, these must be at class, not instance level + layoutd = {} # a map from text prop tups to pango layouts + rotated = {} # a map from text prop tups to rotated text pixbufs + + def __init__(self, gtkDA, dpi): + # widget gtkDA is used for: + # '.create_pango_layout(s)' + # cmap line below) + self.gtkDA = gtkDA + self.dpi = dpi + self._cmap = gtkDA.get_colormap() + self.mathtext_parser = MathTextParser("Agg") + + def set_pixmap (self, pixmap): + self.gdkDrawable = pixmap + + def set_width_height (self, width, height): + """w,h is the figure w,h not the pixmap w,h + """ + self.width, self.height = width, height + + def draw_path(self, gc, path, transform, rgbFace=None): + transform = transform + Affine2D(). \ + scale(1.0, -1.0).translate(0, self.height) + polygons = path.to_polygons(transform, self.width, self.height) + for polygon in polygons: + # draw_polygon won't take an arbitrary sequence -- it must be a list + # of tuples + polygon = [(int(np.round(x)), int(np.round(y))) for x, y in polygon] + if rgbFace is not None: + saveColor = gc.gdkGC.foreground + gc.gdkGC.foreground = gc.rgb_to_gdk_color(rgbFace) + self.gdkDrawable.draw_polygon(gc.gdkGC, True, polygon) + gc.gdkGC.foreground = saveColor + if gc.gdkGC.line_width > 0: + self.gdkDrawable.draw_lines(gc.gdkGC, polygon) + + def draw_image(self, gc, x, y, im): + bbox = gc.get_clip_rectangle() + + if bbox != None: + l,b,w,h = bbox.bounds + #rectangle = (int(l), self.height-int(b+h), + # int(w), int(h)) + # set clip rect? + + rows, cols = im.shape[:2] + + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, + has_alpha=True, bits_per_sample=8, + width=cols, height=rows) + + array = pixbuf_get_pixels_array(pixbuf) + array[:, :, :] = im[::-1] + + gc = self.new_gc() + + + y = self.height-y-rows + + try: # new in 2.2 + # can use None instead of gc.gdkGC, if don't need clipping + self.gdkDrawable.draw_pixbuf (gc.gdkGC, pixbuf, 0, 0, + int(x), int(y), cols, rows, + gdk.RGB_DITHER_NONE, 0, 0) + except AttributeError: + # deprecated in 2.2 + pixbuf.render_to_drawable(self.gdkDrawable, gc.gdkGC, 0, 0, + int(x), int(y), cols, rows, + gdk.RGB_DITHER_NONE, 0, 0) + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + x, y = int(x), int(y) + + if x < 0 or y < 0: # window has shrunk and text is off the edge + return + + if angle not in (0,90): + warnings.warn('backend_gdk: unable to draw text at angles ' + + 'other than 0 or 90') + elif ismath: + self._draw_mathtext(gc, x, y, s, prop, angle) + + elif angle==90: + self._draw_rotated_text(gc, x, y, s, prop, angle) + + else: + layout, inkRect, logicalRect = self._get_pango_layout(s, prop) + l, b, w, h = inkRect + if (x + w > self.width or y + h > self.height): + return + + self.gdkDrawable.draw_layout(gc.gdkGC, x, y-h-b, layout) + + def _draw_mathtext(self, gc, x, y, s, prop, angle): + ox, oy, width, height, descent, font_image, used_characters = \ + self.mathtext_parser.parse(s, self.dpi, prop) + + if angle == 90: + width, height = height, width + x -= width + y -= height + + imw = font_image.get_width() + imh = font_image.get_height() + + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=True, + bits_per_sample=8, width=imw, height=imh) + + array = pixbuf_get_pixels_array(pixbuf) + + rgb = gc.get_rgb() + array[:,:,0] = int(rgb[0]*255) + array[:,:,1] = int(rgb[1]*255) + array[:,:,2] = int(rgb[2]*255) + array[:,:,3] = ( + np.fromstring(font_image.as_str(), np.uint8).reshape((imh, imw))) + + # can use None instead of gc.gdkGC, if don't need clipping + self.gdkDrawable.draw_pixbuf(gc.gdkGC, pixbuf, 0, 0, + int(x), int(y), imw, imh, + gdk.RGB_DITHER_NONE, 0, 0) + + def _draw_rotated_text(self, gc, x, y, s, prop, angle): + """ + Draw the text rotated 90 degrees, other angles are not supported + """ + # this function (and its called functions) is a bottleneck + # Pango 1.6 supports rotated text, but pygtk 2.4.0 does not yet have + # wrapper functions + # GTK+ 2.6 pixbufs support rotation + + gdrawable = self.gdkDrawable + ggc = gc.gdkGC + + layout, inkRect, logicalRect = self._get_pango_layout(s, prop) + l, b, w, h = inkRect + x = int(x-h) + y = int(y-w) + + if (x < 0 or y < 0 or # window has shrunk and text is off the edge + x + w > self.width or y + h > self.height): + return + + key = (x,y,s,angle,hash(prop)) + imageVert = self.rotated.get(key) + if imageVert != None: + gdrawable.draw_image(ggc, imageVert, 0, 0, x, y, h, w) + return + + imageBack = gdrawable.get_image(x, y, w, h) + imageVert = gdrawable.get_image(x, y, h, w) + imageFlip = gtk.gdk.Image(type=gdk.IMAGE_FASTEST, + visual=gdrawable.get_visual(), + width=w, height=h) + if imageFlip == None or imageBack == None or imageVert == None: + warnings.warn("Could not renderer vertical text") + return + imageFlip.set_colormap(self._cmap) + for i in range(w): + for j in range(h): + imageFlip.put_pixel(i, j, imageVert.get_pixel(j,w-i-1) ) + + gdrawable.draw_image(ggc, imageFlip, 0, 0, x, y, w, h) + gdrawable.draw_layout(ggc, x, y-b, layout) + + imageIn = gdrawable.get_image(x, y, w, h) + for i in range(w): + for j in range(h): + imageVert.put_pixel(j, i, imageIn.get_pixel(w-i-1,j) ) + + gdrawable.draw_image(ggc, imageBack, 0, 0, x, y, w, h) + gdrawable.draw_image(ggc, imageVert, 0, 0, x, y, h, w) + self.rotated[key] = imageVert + + def _get_pango_layout(self, s, prop): + """ + Create a pango layout instance for Text 's' with properties 'prop'. + Return - pango layout (from cache if already exists) + + Note that pango assumes a logical DPI of 96 + Ref: pango/fonts.c/pango_font_description_set_size() manual page + """ + # problem? - cache gets bigger and bigger, is never cleared out + # two (not one) layouts are created for every text item s (then they + # are cached) - why? + + key = self.dpi, s, hash(prop) + value = self.layoutd.get(key) + if value != None: + return value + + size = prop.get_size_in_points() * self.dpi / 96.0 + size = np.round(size) + + font_str = '%s, %s %i' % (prop.get_name(), prop.get_style(), size,) + font = pango.FontDescription(font_str) + + # later - add fontweight to font_str + font.set_weight(self.fontweights[prop.get_weight()]) + + layout = self.gtkDA.create_pango_layout(s) + layout.set_font_description(font) + inkRect, logicalRect = layout.get_pixel_extents() + + self.layoutd[key] = layout, inkRect, logicalRect + return layout, inkRect, logicalRect + + def flipy(self): + return True + + def get_canvas_width_height(self): + return self.width, self.height + + def get_text_width_height_descent(self, s, prop, ismath): + if ismath: + ox, oy, width, height, descent, font_image, used_characters = \ + self.mathtext_parser.parse(s, self.dpi, prop) + return width, height, descent + + layout, inkRect, logicalRect = self._get_pango_layout(s, prop) + l, b, w, h = inkRect + ll, lb, lw, lh = logicalRect + + return w, h + 1, h - lh + + def new_gc(self): + return GraphicsContextGDK(renderer=self) + + def points_to_pixels(self, points): + return points/72.0 * self.dpi + + +class GraphicsContextGDK(GraphicsContextBase): + # a cache shared by all class instances + _cached = {} # map: rgb color -> gdk.Color + + _joind = { + 'bevel' : gdk.JOIN_BEVEL, + 'miter' : gdk.JOIN_MITER, + 'round' : gdk.JOIN_ROUND, + } + + _capd = { + 'butt' : gdk.CAP_BUTT, + 'projecting' : gdk.CAP_PROJECTING, + 'round' : gdk.CAP_ROUND, + } + + + def __init__(self, renderer): + GraphicsContextBase.__init__(self) + self.renderer = renderer + self.gdkGC = gtk.gdk.GC(renderer.gdkDrawable) + self._cmap = renderer._cmap + + + def rgb_to_gdk_color(self, rgb): + """ + rgb - an RGB tuple (three 0.0-1.0 values) + return an allocated gtk.gdk.Color + """ + try: + return self._cached[tuple(rgb)] + except KeyError: + color = self._cached[tuple(rgb)] = \ + self._cmap.alloc_color( + int(rgb[0]*65535),int(rgb[1]*65535),int(rgb[2]*65535)) + return color + + + #def set_antialiased(self, b): + # anti-aliasing is not supported by GDK + + def set_capstyle(self, cs): + GraphicsContextBase.set_capstyle(self, cs) + self.gdkGC.cap_style = self._capd[self._capstyle] + + + def set_clip_rectangle(self, rectangle): + GraphicsContextBase.set_clip_rectangle(self, rectangle) + if rectangle is None: + return + l,b,w,h = rectangle.bounds + rectangle = (int(l), self.renderer.height-int(b+h)+1, + int(w), int(h)) + #rectangle = (int(l), self.renderer.height-int(b+h), + # int(w+1), int(h+2)) + self.gdkGC.set_clip_rectangle(rectangle) + + def set_dashes(self, dash_offset, dash_list): + GraphicsContextBase.set_dashes(self, dash_offset, dash_list) + + if dash_list == None: + self.gdkGC.line_style = gdk.LINE_SOLID + else: + pixels = self.renderer.points_to_pixels(np.asarray(dash_list)) + dl = [max(1, int(np.round(val))) for val in pixels] + self.gdkGC.set_dashes(dash_offset, dl) + self.gdkGC.line_style = gdk.LINE_ON_OFF_DASH + + + def set_foreground(self, fg, isRGBA=False): + GraphicsContextBase.set_foreground(self, fg, isRGBA) + self.gdkGC.foreground = self.rgb_to_gdk_color(self.get_rgb()) + + + def set_joinstyle(self, js): + GraphicsContextBase.set_joinstyle(self, js) + self.gdkGC.join_style = self._joind[self._joinstyle] + + + def set_linewidth(self, w): + GraphicsContextBase.set_linewidth(self, w) + if w == 0: + self.gdkGC.line_width = 0 + else: + pixels = self.renderer.points_to_pixels(w) + self.gdkGC.line_width = max(1, int(np.round(pixels))) + + +class FigureCanvasGDK (FigureCanvasBase): + def __init__(self, figure): + FigureCanvasBase.__init__(self, figure) + if self.__class__ == matplotlib.backends.backend_gdk.FigureCanvasGDK: + warn_deprecated('2.0', message="The GDK backend is " + "deprecated. It is untested, known to be " + "broken and will be removed in Matplotlib 3.0. " + "Use the Agg backend instead. " + "See Matplotlib usage FAQ for" + " more info on backends.", + alternative="Agg") + self._renderer_init() + + def _renderer_init(self): + self._renderer = RendererGDK (gtk.DrawingArea(), self.figure.dpi) + + def _render_figure(self, pixmap, width, height): + self._renderer.set_pixmap (pixmap) + self._renderer.set_width_height (width, height) + self.figure.draw (self._renderer) + + filetypes = FigureCanvasBase.filetypes.copy() + filetypes['jpg'] = 'JPEG' + filetypes['jpeg'] = 'JPEG' + + def print_jpeg(self, filename, *args, **kwargs): + return self._print_image(filename, 'jpeg') + print_jpg = print_jpeg + + def print_png(self, filename, *args, **kwargs): + return self._print_image(filename, 'png') + + def _print_image(self, filename, format, *args, **kwargs): + width, height = self.get_width_height() + pixmap = gtk.gdk.Pixmap (None, width, height, depth=24) + self._render_figure(pixmap, width, height) + + # jpg colors don't match the display very well, png colors match + # better + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, + width, height) + pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), + 0, 0, 0, 0, width, height) + + # set the default quality, if we are writing a JPEG. + # http://www.pygtk.org/docs/pygtk/class-gdkpixbuf.html#method-gdkpixbuf--save + options = {k: kwargs[k] for k in ['quality'] if k in kwargs} + if format in ['jpg', 'jpeg']: + options.setdefault('quality', rcParams['savefig.jpeg_quality']) + options['quality'] = str(options['quality']) + + pixbuf.save(filename, format, options=options) + + +@_Backend.export +class _BackendGDK(_Backend): + FigureCanvas = FigureCanvasGDK + FigureManager = FigureManagerBase diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk.py new file mode 100644 index 00000000000..a4ae7cc28b7 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk.py @@ -0,0 +1,1037 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import logging +import os +import sys +import warnings + +if six.PY3: + warnings.warn( + "The gtk* backends have not been tested with Python 3.x", + ImportWarning) + +try: + import gobject + import gtk; gdk = gtk.gdk + import pango +except ImportError: + raise ImportError("Gtk* backend requires pygtk to be installed.") + +pygtk_version_required = (2,4,0) +if gtk.pygtk_version < pygtk_version_required: + raise ImportError ("PyGTK %d.%d.%d is installed\n" + "PyGTK %d.%d.%d or later is required" + % (gtk.pygtk_version + pygtk_version_required)) +del pygtk_version_required + +_new_tooltip_api = (gtk.pygtk_version[1] >= 12) + +import matplotlib +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2, + TimerBase, cursors) + +from matplotlib.backends.backend_gdk import RendererGDK, FigureCanvasGDK +from matplotlib.cbook import is_writable_file_like, warn_deprecated +from matplotlib.figure import Figure +from matplotlib.widgets import SubplotTool + +from matplotlib import ( + cbook, colors as mcolors, lines, markers, rcParams) + +_log = logging.getLogger(__name__) + +backend_version = "%d.%d.%d" % gtk.pygtk_version + +# the true dots per inch on the screen; should be display dependent +# see http://groups.google.com/groups?q=screen+dpi+x11&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=7077.26e81ad5%40swift.cs.tcd.ie&rnum=5 for some info about screen dpi +PIXELS_PER_INCH = 96 + +# Hide the benign warning that it can't stat a file that doesn't +warnings.filterwarnings('ignore', '.*Unable to retrieve the file info for.*', gtk.Warning) + +cursord = { + cursors.MOVE : gdk.Cursor(gdk.FLEUR), + cursors.HAND : gdk.Cursor(gdk.HAND2), + cursors.POINTER : gdk.Cursor(gdk.LEFT_PTR), + cursors.SELECT_REGION : gdk.Cursor(gdk.TCROSS), + cursors.WAIT : gdk.Cursor(gdk.WATCH), + } + +# ref gtk+/gtk/gtkwidget.h +def GTK_WIDGET_DRAWABLE(w): + flags = w.flags(); + return flags & gtk.VISIBLE != 0 and flags & gtk.MAPPED != 0 + + +class TimerGTK(TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` using GTK for timer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + def _timer_start(self): + # Need to stop it, otherwise we potentially leak a timer id that will + # never be stopped. + self._timer_stop() + self._timer = gobject.timeout_add(self._interval, self._on_timer) + + def _timer_stop(self): + if self._timer is not None: + gobject.source_remove(self._timer) + self._timer = None + + def _timer_set_interval(self): + # Only stop and restart it if the timer has already been started + if self._timer is not None: + self._timer_stop() + self._timer_start() + + def _on_timer(self): + TimerBase._on_timer(self) + + # Gtk timeout_add() requires that the callback returns True if it + # is to be called again. + if len(self.callbacks) > 0 and not self._single: + return True + else: + self._timer = None + return False + + +class FigureCanvasGTK (gtk.DrawingArea, FigureCanvasBase): + keyvald = {65507 : 'control', + 65505 : 'shift', + 65513 : 'alt', + 65508 : 'control', + 65506 : 'shift', + 65514 : 'alt', + 65361 : 'left', + 65362 : 'up', + 65363 : 'right', + 65364 : 'down', + 65307 : 'escape', + 65470 : 'f1', + 65471 : 'f2', + 65472 : 'f3', + 65473 : 'f4', + 65474 : 'f5', + 65475 : 'f6', + 65476 : 'f7', + 65477 : 'f8', + 65478 : 'f9', + 65479 : 'f10', + 65480 : 'f11', + 65481 : 'f12', + 65300 : 'scroll_lock', + 65299 : 'break', + 65288 : 'backspace', + 65293 : 'enter', + 65379 : 'insert', + 65535 : 'delete', + 65360 : 'home', + 65367 : 'end', + 65365 : 'pageup', + 65366 : 'pagedown', + 65438 : '0', + 65436 : '1', + 65433 : '2', + 65435 : '3', + 65430 : '4', + 65437 : '5', + 65432 : '6', + 65429 : '7', + 65431 : '8', + 65434 : '9', + 65451 : '+', + 65453 : '-', + 65450 : '*', + 65455 : '/', + 65439 : 'dec', + 65421 : 'enter', + 65511 : 'super', + 65512 : 'super', + 65406 : 'alt', + 65289 : 'tab', + } + + # Setting this as a static constant prevents + # this resulting expression from leaking + event_mask = (gdk.BUTTON_PRESS_MASK | + gdk.BUTTON_RELEASE_MASK | + gdk.EXPOSURE_MASK | + gdk.KEY_PRESS_MASK | + gdk.KEY_RELEASE_MASK | + gdk.ENTER_NOTIFY_MASK | + gdk.LEAVE_NOTIFY_MASK | + gdk.POINTER_MOTION_MASK | + gdk.POINTER_MOTION_HINT_MASK) + + def __init__(self, figure): + if self.__class__ == matplotlib.backends.backend_gtk.FigureCanvasGTK: + warn_deprecated('2.0', message="The GTK backend is " + "deprecated. It is untested, known to be " + "broken and will be removed in Matplotlib 3.0. " + "Use the GTKAgg backend instead. " + "See Matplotlib usage FAQ for" + " more info on backends.", + alternative="GTKAgg") + FigureCanvasBase.__init__(self, figure) + gtk.DrawingArea.__init__(self) + + self._idle_draw_id = 0 + self._need_redraw = True + self._pixmap_width = -1 + self._pixmap_height = -1 + self._lastCursor = None + + self.connect('scroll_event', self.scroll_event) + self.connect('button_press_event', self.button_press_event) + self.connect('button_release_event', self.button_release_event) + self.connect('configure_event', self.configure_event) + self.connect('expose_event', self.expose_event) + self.connect('key_press_event', self.key_press_event) + self.connect('key_release_event', self.key_release_event) + self.connect('motion_notify_event', self.motion_notify_event) + self.connect('leave_notify_event', self.leave_notify_event) + self.connect('enter_notify_event', self.enter_notify_event) + + self.set_events(self.__class__.event_mask) + + self.set_double_buffered(False) + self.set_flags(gtk.CAN_FOCUS) + self._renderer_init() + + self.last_downclick = {} + + def destroy(self): + #gtk.DrawingArea.destroy(self) + self.close_event() + if self._idle_draw_id != 0: + gobject.source_remove(self._idle_draw_id) + + def scroll_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.allocation.height - event.y + if event.direction==gdk.SCROLL_UP: + step = 1 + else: + step = -1 + FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event) + return False # finish event propagation? + + def button_press_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.allocation.height - event.y + dblclick = (event.type == gdk._2BUTTON_PRESS) + if not dblclick: + # GTK is the only backend that generates a DOWN-UP-DOWN-DBLCLICK-UP event + # sequence for a double click. All other backends have a DOWN-UP-DBLCLICK-UP + # sequence. In order to provide consistency to matplotlib users, we will + # eat the extra DOWN event in the case that we detect it is part of a double + # click. + # first, get the double click time in milliseconds. + current_time = event.get_time() + last_time = self.last_downclick.get(event.button,0) + dblclick_time = gtk.settings_get_for_screen(gdk.screen_get_default()).get_property('gtk-double-click-time') + delta_time = current_time-last_time + if delta_time < dblclick_time: + del self.last_downclick[event.button] # we do not want to eat more than one event. + return False # eat. + self.last_downclick[event.button] = current_time + FigureCanvasBase.button_press_event(self, x, y, event.button, dblclick=dblclick, guiEvent=event) + return False # finish event propagation? + + def button_release_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.allocation.height - event.y + FigureCanvasBase.button_release_event(self, x, y, event.button, guiEvent=event) + return False # finish event propagation? + + def key_press_event(self, widget, event): + key = self._get_key(event) + FigureCanvasBase.key_press_event(self, key, guiEvent=event) + return True # stop event propagation + + def key_release_event(self, widget, event): + key = self._get_key(event) + FigureCanvasBase.key_release_event(self, key, guiEvent=event) + return True # stop event propagation + + def motion_notify_event(self, widget, event): + if event.is_hint: + x, y, state = event.window.get_pointer() + else: + x, y, state = event.x, event.y, event.state + + # flipy so y=0 is bottom of canvas + y = self.allocation.height - y + FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event) + return False # finish event propagation? + + def leave_notify_event(self, widget, event): + FigureCanvasBase.leave_notify_event(self, event) + + def enter_notify_event(self, widget, event): + x, y, state = event.window.get_pointer() + FigureCanvasBase.enter_notify_event(self, event, xy=(x, y)) + + def _get_key(self, event): + if event.keyval in self.keyvald: + key = self.keyvald[event.keyval] + elif event.keyval < 256: + key = chr(event.keyval) + else: + key = None + + for key_mask, prefix in ( + [gdk.MOD4_MASK, 'super'], + [gdk.MOD1_MASK, 'alt'], + [gdk.CONTROL_MASK, 'ctrl'], ): + if event.state & key_mask: + key = '{0}+{1}'.format(prefix, key) + + return key + + def configure_event(self, widget, event): + if widget.window is None: + return + w, h = event.width, event.height + if w < 3 or h < 3: + return # empty fig + + # resize the figure (in inches) + dpi = self.figure.dpi + self.figure.set_size_inches(w/dpi, h/dpi, forward=False) + self._need_redraw = True + + return False # finish event propagation? + + def draw(self): + # Note: FigureCanvasBase.draw() is inconveniently named as it clashes + # with the deprecated gtk.Widget.draw() + + self._need_redraw = True + if GTK_WIDGET_DRAWABLE(self): + self.queue_draw() + # do a synchronous draw (its less efficient than an async draw, + # but is required if/when animation is used) + self.window.process_updates (False) + + def draw_idle(self): + if self._idle_draw_id != 0: + return + def idle_draw(*args): + try: + self.draw() + finally: + self._idle_draw_id = 0 + return False + self._idle_draw_id = gobject.idle_add(idle_draw) + + + def _renderer_init(self): + """Override by GTK backends to select a different renderer + Renderer should provide the methods: + set_pixmap () + set_width_height () + that are used by + _render_figure() / _pixmap_prepare() + """ + self._renderer = RendererGDK (self, self.figure.dpi) + + + def _pixmap_prepare(self, width, height): + """ + Make sure _._pixmap is at least width, height, + create new pixmap if necessary + """ + create_pixmap = False + if width > self._pixmap_width: + # increase the pixmap in 10%+ (rather than 1 pixel) steps + self._pixmap_width = max (int (self._pixmap_width * 1.1), + width) + create_pixmap = True + + if height > self._pixmap_height: + self._pixmap_height = max (int (self._pixmap_height * 1.1), + height) + create_pixmap = True + + if create_pixmap: + self._pixmap = gdk.Pixmap (self.window, self._pixmap_width, + self._pixmap_height) + self._renderer.set_pixmap (self._pixmap) + + + def _render_figure(self, pixmap, width, height): + """used by GTK and GTKcairo. GTKAgg overrides + """ + self._renderer.set_width_height (width, height) + self.figure.draw (self._renderer) + + + def expose_event(self, widget, event): + """Expose_event for all GTK backends. Should not be overridden. + """ + toolbar = self.toolbar + # if toolbar: + # toolbar.set_cursor(cursors.WAIT) + if GTK_WIDGET_DRAWABLE(self): + if self._need_redraw: + x, y, w, h = self.allocation + self._pixmap_prepare (w, h) + self._render_figure(self._pixmap, w, h) + self._need_redraw = False + x, y, w, h = event.area + self.window.draw_drawable (self.style.fg_gc[self.state], + self._pixmap, x, y, x, y, w, h) + # if toolbar: + # toolbar.set_cursor(toolbar._lastCursor) + return False # finish event propagation? + + filetypes = FigureCanvasBase.filetypes.copy() + filetypes['jpg'] = 'JPEG' + filetypes['jpeg'] = 'JPEG' + filetypes['png'] = 'Portable Network Graphics' + + def print_jpeg(self, filename, *args, **kwargs): + return self._print_image(filename, 'jpeg') + print_jpg = print_jpeg + + def print_png(self, filename, *args, **kwargs): + return self._print_image(filename, 'png') + + def _print_image(self, filename, format, *args, **kwargs): + if self.flags() & gtk.REALIZED == 0: + # for self.window(for pixmap) and has a side effect of altering + # figure width,height (via configure-event?) + gtk.DrawingArea.realize(self) + + width, height = self.get_width_height() + pixmap = gdk.Pixmap (self.window, width, height) + self._renderer.set_pixmap (pixmap) + self._render_figure(pixmap, width, height) + + # jpg colors don't match the display very well, png colors match + # better + pixbuf = gdk.Pixbuf(gdk.COLORSPACE_RGB, 0, 8, width, height) + pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), + 0, 0, 0, 0, width, height) + + # set the default quality, if we are writing a JPEG. + # http://www.pygtk.org/docs/pygtk/class-gdkpixbuf.html#method-gdkpixbuf--save + options = {k: kwargs[k] for k in ['quality'] if k in kwargs} + if format in ['jpg', 'jpeg']: + options.setdefault('quality', rcParams['savefig.jpeg_quality']) + options['quality'] = str(options['quality']) + + if isinstance(filename, six.string_types): + try: + pixbuf.save(filename, format, options=options) + except gobject.GError as exc: + error_msg_gtk('Save figure failure:\n%s' % (exc,), parent=self) + elif is_writable_file_like(filename): + if hasattr(pixbuf, 'save_to_callback'): + def save_callback(buf, data=None): + data.write(buf) + try: + pixbuf.save_to_callback(save_callback, format, user_data=filename, options=options) + except gobject.GError as exc: + error_msg_gtk('Save figure failure:\n%s' % (exc,), parent=self) + else: + raise ValueError("Saving to a Python file-like object is only supported by PyGTK >= 2.8") + else: + raise ValueError("filename must be a path or a file-like object") + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + """ + return TimerGTK(*args, **kwargs) + + def flush_events(self): + gtk.gdk.threads_enter() + while gtk.events_pending(): + gtk.main_iteration(True) + gtk.gdk.flush() + gtk.gdk.threads_leave() + + +class FigureManagerGTK(FigureManagerBase): + """ + Attributes + ---------- + canvas : `FigureCanvas` + The FigureCanvas instance + num : int or str + The Figure number + toolbar : gtk.Toolbar + The gtk.Toolbar (gtk only) + vbox : gtk.VBox + The gtk.VBox containing the canvas and toolbar (gtk only) + window : gtk.Window + The gtk.Window (gtk only) + + """ + def __init__(self, canvas, num): + FigureManagerBase.__init__(self, canvas, num) + + self.window = gtk.Window() + self.window.set_wmclass("matplotlib", "Matplotlib") + self.set_window_title("Figure %d" % num) + if window_icon: + try: + self.window.set_icon_from_file(window_icon) + except: + # some versions of gtk throw a glib.GError but not + # all, so I am not sure how to catch it. I am unhappy + # diong a blanket catch here, but an not sure what a + # better way is - JDH + _log.info('Could not load matplotlib ' + 'icon: %s', sys.exc_info()[1]) + + self.vbox = gtk.VBox() + self.window.add(self.vbox) + self.vbox.show() + + self.canvas.show() + + self.vbox.pack_start(self.canvas, True, True) + + self.toolbar = self._get_toolbar(canvas) + + # calculate size for window + w = int (self.canvas.figure.bbox.width) + h = int (self.canvas.figure.bbox.height) + + if self.toolbar is not None: + self.toolbar.show() + self.vbox.pack_end(self.toolbar, False, False) + + tb_w, tb_h = self.toolbar.size_request() + h += tb_h + self.window.set_default_size (w, h) + + def destroy(*args): + Gcf.destroy(num) + self.window.connect("destroy", destroy) + self.window.connect("delete_event", destroy) + if matplotlib.is_interactive(): + self.window.show() + self.canvas.draw_idle() + + def notify_axes_change(fig): + 'this will be called whenever the current axes is changed' + if self.toolbar is not None: self.toolbar.update() + self.canvas.figure.add_axobserver(notify_axes_change) + + self.canvas.grab_focus() + + def destroy(self, *args): + if hasattr(self, 'toolbar') and self.toolbar is not None: + self.toolbar.destroy() + if hasattr(self, 'vbox'): + self.vbox.destroy() + if hasattr(self, 'window'): + self.window.destroy() + if hasattr(self, 'canvas'): + self.canvas.destroy() + self.__dict__.clear() #Is this needed? Other backends don't have it. + + if Gcf.get_num_fig_managers()==0 and \ + not matplotlib.is_interactive() and \ + gtk.main_level() >= 1: + gtk.main_quit() + + def show(self): + # show the figure window + self.window.show() + # raise the window above others and release the "above lock" + self.window.set_keep_above(True) + self.window.set_keep_above(False) + + def full_screen_toggle(self): + self._full_screen_flag = not self._full_screen_flag + if self._full_screen_flag: + self.window.fullscreen() + else: + self.window.unfullscreen() + _full_screen_flag = False + + + def _get_toolbar(self, canvas): + # must be inited after the window, drawingArea and figure + # attrs are set + if rcParams['toolbar'] == 'toolbar2': + toolbar = NavigationToolbar2GTK (canvas, self.window) + else: + toolbar = None + return toolbar + + def get_window_title(self): + return self.window.get_title() + + def set_window_title(self, title): + self.window.set_title(title) + + def resize(self, width, height): + 'set the canvas size in pixels' + #_, _, cw, ch = self.canvas.allocation + #_, _, ww, wh = self.window.allocation + #self.window.resize (width-cw+ww, height-ch+wh) + self.window.resize(width, height) + + +class NavigationToolbar2GTK(NavigationToolbar2, gtk.Toolbar): + def __init__(self, canvas, window): + self.win = window + gtk.Toolbar.__init__(self) + NavigationToolbar2.__init__(self, canvas) + + def set_message(self, s): + self.message.set_label(s) + + def set_cursor(self, cursor): + self.canvas.window.set_cursor(cursord[cursor]) + gtk.main_iteration() + + def release(self, event): + try: del self._pixmapBack + except AttributeError: pass + + def draw_rubberband(self, event, x0, y0, x1, y1): + 'adapted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/189744' + drawable = self.canvas.window + if drawable is None: + return + + gc = drawable.new_gc() + + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + + w = abs(x1 - x0) + h = abs(y1 - y0) + + rect = [int(val)for val in (min(x0,x1), min(y0, y1), w, h)] + try: + lastrect, pixmapBack = self._pixmapBack + except AttributeError: + #snap image back + if event.inaxes is None: + return + + ax = event.inaxes + l,b,w,h = [int(val) for val in ax.bbox.bounds] + b = int(height)-(b+h) + axrect = l,b,w,h + self._pixmapBack = axrect, gtk.gdk.Pixmap(drawable, w, h) + self._pixmapBack[1].draw_drawable(gc, drawable, l, b, 0, 0, w, h) + else: + drawable.draw_drawable(gc, pixmapBack, 0, 0, *lastrect) + drawable.draw_rectangle(gc, False, *rect) + + + def _init_toolbar(self): + self.set_style(gtk.TOOLBAR_ICONS) + self._init_toolbar2_4() + + + def _init_toolbar2_4(self): + basedir = os.path.join(rcParams['datapath'],'images') + if not _new_tooltip_api: + self.tooltips = gtk.Tooltips() + + for text, tooltip_text, image_file, callback in self.toolitems: + if text is None: + self.insert( gtk.SeparatorToolItem(), -1 ) + continue + fname = os.path.join(basedir, image_file + '.png') + image = gtk.Image() + image.set_from_file(fname) + tbutton = gtk.ToolButton(image, text) + self.insert(tbutton, -1) + tbutton.connect('clicked', getattr(self, callback)) + if _new_tooltip_api: + tbutton.set_tooltip_text(tooltip_text) + else: + tbutton.set_tooltip(self.tooltips, tooltip_text, 'Private') + + toolitem = gtk.SeparatorToolItem() + self.insert(toolitem, -1) + # set_draw() not making separator invisible, + # bug #143692 fixed Jun 06 2004, will be in GTK+ 2.6 + toolitem.set_draw(False) + toolitem.set_expand(True) + + toolitem = gtk.ToolItem() + self.insert(toolitem, -1) + self.message = gtk.Label() + toolitem.add(self.message) + + self.show_all() + + def get_filechooser(self): + fc = FileChooserDialog( + title='Save the figure', + parent=self.win, + path=os.path.expanduser(rcParams['savefig.directory']), + filetypes=self.canvas.get_supported_filetypes(), + default_filetype=self.canvas.get_default_filetype()) + fc.set_current_name(self.canvas.get_default_filename()) + return fc + + def save_figure(self, *args): + chooser = self.get_filechooser() + fname, format = chooser.get_filename_from_user() + chooser.destroy() + if fname: + startpath = os.path.expanduser(rcParams['savefig.directory']) + # Save dir for next time, unless empty str (i.e., use cwd). + if startpath != "": + rcParams['savefig.directory'] = ( + os.path.dirname(six.text_type(fname))) + try: + self.canvas.figure.savefig(fname, format=format) + except Exception as e: + error_msg_gtk(str(e), parent=self) + + def configure_subplots(self, button): + toolfig = Figure(figsize=(6,3)) + canvas = self._get_canvas(toolfig) + toolfig.subplots_adjust(top=0.9) + tool = SubplotTool(self.canvas.figure, toolfig) + + w = int(toolfig.bbox.width) + h = int(toolfig.bbox.height) + + window = gtk.Window() + if window_icon: + try: + window.set_icon_from_file(window_icon) + except: + # we presumably already logged a message on the + # failure of the main plot, don't keep reporting + pass + window.set_title("Subplot Configuration Tool") + window.set_default_size(w, h) + vbox = gtk.VBox() + window.add(vbox) + vbox.show() + + canvas.show() + vbox.pack_start(canvas, True, True) + window.show() + + def _get_canvas(self, fig): + return FigureCanvasGTK(fig) + + +class FileChooserDialog(gtk.FileChooserDialog): + """GTK+ 2.4 file selector which presents the user with a menu + of supported image formats + """ + def __init__ (self, + title = 'Save file', + parent = None, + action = gtk.FILE_CHOOSER_ACTION_SAVE, + buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, gtk.RESPONSE_OK), + path = None, + filetypes = [], + default_filetype = None + ): + super(FileChooserDialog, self).__init__(title, parent, action, buttons) + super(FileChooserDialog, self).set_do_overwrite_confirmation(True) + self.set_default_response(gtk.RESPONSE_OK) + + if not path: + path = os.getcwd() + os.sep + + # create an extra widget to list supported image formats + self.set_current_folder (path) + self.set_current_name ('image.' + default_filetype) + + hbox = gtk.HBox(spacing=10) + hbox.pack_start(gtk.Label ("File Format:"), expand=False) + + liststore = gtk.ListStore(gobject.TYPE_STRING) + cbox = gtk.ComboBox(liststore) + cell = gtk.CellRendererText() + cbox.pack_start(cell, True) + cbox.add_attribute(cell, 'text', 0) + hbox.pack_start(cbox) + + self.filetypes = filetypes + self.sorted_filetypes = sorted(six.iteritems(filetypes)) + default = 0 + for i, (ext, name) in enumerate(self.sorted_filetypes): + cbox.append_text("%s (*.%s)" % (name, ext)) + if ext == default_filetype: + default = i + cbox.set_active(default) + self.ext = default_filetype + + def cb_cbox_changed (cbox, data=None): + """File extension changed""" + head, filename = os.path.split(self.get_filename()) + root, ext = os.path.splitext(filename) + ext = ext[1:] + new_ext = self.sorted_filetypes[cbox.get_active()][0] + self.ext = new_ext + + if ext in self.filetypes: + filename = root + '.' + new_ext + elif ext == '': + filename = filename.rstrip('.') + '.' + new_ext + + self.set_current_name(filename) + cbox.connect("changed", cb_cbox_changed) + + hbox.show_all() + self.set_extra_widget(hbox) + + def get_filename_from_user (self): + while True: + filename = None + if self.run() != int(gtk.RESPONSE_OK): + break + filename = self.get_filename() + break + + return filename, self.ext + + +class DialogLineprops(object): + """ + A GUI dialog for controlling lineprops + """ + signals = ( + 'on_combobox_lineprops_changed', + 'on_combobox_linestyle_changed', + 'on_combobox_marker_changed', + 'on_colorbutton_linestyle_color_set', + 'on_colorbutton_markerface_color_set', + 'on_dialog_lineprops_okbutton_clicked', + 'on_dialog_lineprops_cancelbutton_clicked', + ) + + linestyles = [ls for ls in lines.Line2D.lineStyles if ls.strip()] + linestyled = {s: i for i, s in enumerate(linestyles)} + + markers = [m for m in markers.MarkerStyle.markers + if isinstance(m, six.string_types)] + markerd = {s: i for i, s in enumerate(markers)} + + def __init__(self, lines): + import gtk.glade + + datadir = matplotlib.get_data_path() + gladefile = os.path.join(datadir, 'lineprops.glade') + if not os.path.exists(gladefile): + raise IOError( + 'Could not find gladefile lineprops.glade in %s' % datadir) + + self._inited = False + self._updateson = True # suppress updates when setting widgets manually + self.wtree = gtk.glade.XML(gladefile, 'dialog_lineprops') + self.wtree.signal_autoconnect( + {s: getattr(self, s) for s in self.signals}) + + self.dlg = self.wtree.get_widget('dialog_lineprops') + + self.lines = lines + + cbox = self.wtree.get_widget('combobox_lineprops') + cbox.set_active(0) + self.cbox_lineprops = cbox + + cbox = self.wtree.get_widget('combobox_linestyles') + for ls in self.linestyles: + cbox.append_text(ls) + cbox.set_active(0) + self.cbox_linestyles = cbox + + cbox = self.wtree.get_widget('combobox_markers') + for m in self.markers: + cbox.append_text(m) + cbox.set_active(0) + self.cbox_markers = cbox + self._lastcnt = 0 + self._inited = True + + def show(self): + 'populate the combo box' + self._updateson = False + # flush the old + cbox = self.cbox_lineprops + for i in range(self._lastcnt-1,-1,-1): + cbox.remove_text(i) + + # add the new + for line in self.lines: + cbox.append_text(line.get_label()) + cbox.set_active(0) + + self._updateson = True + self._lastcnt = len(self.lines) + self.dlg.show() + + def get_active_line(self): + 'get the active line' + ind = self.cbox_lineprops.get_active() + line = self.lines[ind] + return line + + def get_active_linestyle(self): + 'get the active lineinestyle' + ind = self.cbox_linestyles.get_active() + ls = self.linestyles[ind] + return ls + + def get_active_marker(self): + 'get the active lineinestyle' + ind = self.cbox_markers.get_active() + m = self.markers[ind] + return m + + def _update(self): + 'update the active line props from the widgets' + if not self._inited or not self._updateson: return + line = self.get_active_line() + ls = self.get_active_linestyle() + marker = self.get_active_marker() + line.set_linestyle(ls) + line.set_marker(marker) + + button = self.wtree.get_widget('colorbutton_linestyle') + color = button.get_color() + r, g, b = [val/65535. for val in (color.red, color.green, color.blue)] + line.set_color((r,g,b)) + + button = self.wtree.get_widget('colorbutton_markerface') + color = button.get_color() + r, g, b = [val/65535. for val in (color.red, color.green, color.blue)] + line.set_markerfacecolor((r,g,b)) + + line.figure.canvas.draw() + + def on_combobox_lineprops_changed(self, item): + 'update the widgets from the active line' + if not self._inited: return + self._updateson = False + line = self.get_active_line() + + ls = line.get_linestyle() + if ls is None: ls = 'None' + self.cbox_linestyles.set_active(self.linestyled[ls]) + + marker = line.get_marker() + if marker is None: marker = 'None' + self.cbox_markers.set_active(self.markerd[marker]) + + rgba = mcolors.to_rgba(line.get_color()) + color = gtk.gdk.Color(*[int(val*65535) for val in rgba[:3]]) + button = self.wtree.get_widget('colorbutton_linestyle') + button.set_color(color) + + rgba = mcolors.to_rgba(line.get_markerfacecolor()) + color = gtk.gdk.Color(*[int(val*65535) for val in rgba[:3]]) + button = self.wtree.get_widget('colorbutton_markerface') + button.set_color(color) + self._updateson = True + + def on_combobox_linestyle_changed(self, item): + self._update() + + def on_combobox_marker_changed(self, item): + self._update() + + def on_colorbutton_linestyle_color_set(self, button): + self._update() + + def on_colorbutton_markerface_color_set(self, button): + 'called colorbutton marker clicked' + self._update() + + def on_dialog_lineprops_okbutton_clicked(self, button): + self._update() + self.dlg.hide() + + def on_dialog_lineprops_cancelbutton_clicked(self, button): + self.dlg.hide() + +# set icon used when windows are minimized +# Unfortunately, the SVG renderer (rsvg) leaks memory under earlier +# versions of pygtk, so we have to use a PNG file instead. +try: + if gtk.pygtk_version < (2, 8, 0) or sys.platform == 'win32': + icon_filename = 'matplotlib.png' + else: + icon_filename = 'matplotlib.svg' + window_icon = os.path.join(rcParams['datapath'], 'images', icon_filename) +except: + window_icon = None + _log.info('Could not load matplotlib icon: %s', sys.exc_info()[1]) + +def error_msg_gtk(msg, parent=None): + if parent is not None: # find the toplevel gtk.Window + parent = parent.get_toplevel() + if parent.flags() & gtk.TOPLEVEL == 0: + parent = None + + if not isinstance(msg, six.string_types): + msg = ','.join(map(str, msg)) + + dialog = gtk.MessageDialog( + parent = parent, + type = gtk.MESSAGE_ERROR, + buttons = gtk.BUTTONS_OK, + message_format = msg) + dialog.run() + dialog.destroy() + + +@_Backend.export +class _BackendGTK(_Backend): + FigureCanvas = FigureCanvasGTK + FigureManager = FigureManagerGTK + + @staticmethod + def trigger_manager_draw(manager): + manager.canvas.draw_idle() + + @staticmethod + def mainloop(): + if gtk.main_level() == 0: + gtk.main() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3.py new file mode 100644 index 00000000000..359b8fd8848 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3.py @@ -0,0 +1,920 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import logging +import os +import sys + +import matplotlib +from matplotlib import backend_tools, rcParams +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2, + StatusbarBase, TimerBase, ToolContainerBase, cursors) +from matplotlib.backend_managers import ToolManager +from matplotlib.figure import Figure +from matplotlib.widgets import SubplotTool +from ._gtk3_compat import GLib, GObject, Gtk, Gdk + + +_log = logging.getLogger(__name__) + +backend_version = "%s.%s.%s" % ( + Gtk.get_major_version(), Gtk.get_micro_version(), Gtk.get_minor_version()) + +# the true dots per inch on the screen; should be display dependent +# see http://groups.google.com/groups?q=screen+dpi+x11&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=7077.26e81ad5%40swift.cs.tcd.ie&rnum=5 for some info about screen dpi +PIXELS_PER_INCH = 96 + +cursord = { + cursors.MOVE : Gdk.Cursor.new(Gdk.CursorType.FLEUR), + cursors.HAND : Gdk.Cursor.new(Gdk.CursorType.HAND2), + cursors.POINTER : Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR), + cursors.SELECT_REGION : Gdk.Cursor.new(Gdk.CursorType.TCROSS), + cursors.WAIT : Gdk.Cursor.new(Gdk.CursorType.WATCH), + } + + +class TimerGTK3(TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` using GTK3 for timer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + def _timer_start(self): + # Need to stop it, otherwise we potentially leak a timer id that will + # never be stopped. + self._timer_stop() + self._timer = GLib.timeout_add(self._interval, self._on_timer) + + def _timer_stop(self): + if self._timer is not None: + GLib.source_remove(self._timer) + self._timer = None + + def _timer_set_interval(self): + # Only stop and restart it if the timer has already been started + if self._timer is not None: + self._timer_stop() + self._timer_start() + + def _on_timer(self): + TimerBase._on_timer(self) + + # Gtk timeout_add() requires that the callback returns True if it + # is to be called again. + if len(self.callbacks) > 0 and not self._single: + return True + else: + self._timer = None + return False + + +class FigureCanvasGTK3(Gtk.DrawingArea, FigureCanvasBase): + keyvald = {65507 : 'control', + 65505 : 'shift', + 65513 : 'alt', + 65508 : 'control', + 65506 : 'shift', + 65514 : 'alt', + 65361 : 'left', + 65362 : 'up', + 65363 : 'right', + 65364 : 'down', + 65307 : 'escape', + 65470 : 'f1', + 65471 : 'f2', + 65472 : 'f3', + 65473 : 'f4', + 65474 : 'f5', + 65475 : 'f6', + 65476 : 'f7', + 65477 : 'f8', + 65478 : 'f9', + 65479 : 'f10', + 65480 : 'f11', + 65481 : 'f12', + 65300 : 'scroll_lock', + 65299 : 'break', + 65288 : 'backspace', + 65293 : 'enter', + 65379 : 'insert', + 65535 : 'delete', + 65360 : 'home', + 65367 : 'end', + 65365 : 'pageup', + 65366 : 'pagedown', + 65438 : '0', + 65436 : '1', + 65433 : '2', + 65435 : '3', + 65430 : '4', + 65437 : '5', + 65432 : '6', + 65429 : '7', + 65431 : '8', + 65434 : '9', + 65451 : '+', + 65453 : '-', + 65450 : '*', + 65455 : '/', + 65439 : 'dec', + 65421 : 'enter', + } + + # Setting this as a static constant prevents + # this resulting expression from leaking + event_mask = (Gdk.EventMask.BUTTON_PRESS_MASK | + Gdk.EventMask.BUTTON_RELEASE_MASK | + Gdk.EventMask.EXPOSURE_MASK | + Gdk.EventMask.KEY_PRESS_MASK | + Gdk.EventMask.KEY_RELEASE_MASK | + Gdk.EventMask.ENTER_NOTIFY_MASK | + Gdk.EventMask.LEAVE_NOTIFY_MASK | + Gdk.EventMask.POINTER_MOTION_MASK | + Gdk.EventMask.POINTER_MOTION_HINT_MASK| + Gdk.EventMask.SCROLL_MASK) + + def __init__(self, figure): + FigureCanvasBase.__init__(self, figure) + GObject.GObject.__init__(self) + + self._idle_draw_id = 0 + self._lastCursor = None + + self.connect('scroll_event', self.scroll_event) + self.connect('button_press_event', self.button_press_event) + self.connect('button_release_event', self.button_release_event) + self.connect('configure_event', self.configure_event) + self.connect('draw', self.on_draw_event) + self.connect('key_press_event', self.key_press_event) + self.connect('key_release_event', self.key_release_event) + self.connect('motion_notify_event', self.motion_notify_event) + self.connect('leave_notify_event', self.leave_notify_event) + self.connect('enter_notify_event', self.enter_notify_event) + self.connect('size_allocate', self.size_allocate) + + self.set_events(self.__class__.event_mask) + + self.set_double_buffered(True) + self.set_can_focus(True) + self._renderer_init() + default_context = GLib.main_context_get_thread_default() or GLib.main_context_default() + + def destroy(self): + #Gtk.DrawingArea.destroy(self) + self.close_event() + if self._idle_draw_id != 0: + GLib.source_remove(self._idle_draw_id) + + def scroll_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.get_allocation().height - event.y + if event.direction==Gdk.ScrollDirection.UP: + step = 1 + else: + step = -1 + FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event) + return False # finish event propagation? + + def button_press_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.get_allocation().height - event.y + FigureCanvasBase.button_press_event(self, x, y, event.button, guiEvent=event) + return False # finish event propagation? + + def button_release_event(self, widget, event): + x = event.x + # flipy so y=0 is bottom of canvas + y = self.get_allocation().height - event.y + FigureCanvasBase.button_release_event(self, x, y, event.button, guiEvent=event) + return False # finish event propagation? + + def key_press_event(self, widget, event): + key = self._get_key(event) + FigureCanvasBase.key_press_event(self, key, guiEvent=event) + return True # stop event propagation + + def key_release_event(self, widget, event): + key = self._get_key(event) + FigureCanvasBase.key_release_event(self, key, guiEvent=event) + return True # stop event propagation + + def motion_notify_event(self, widget, event): + if event.is_hint: + t, x, y, state = event.window.get_pointer() + else: + x, y, state = event.x, event.y, event.get_state() + + # flipy so y=0 is bottom of canvas + y = self.get_allocation().height - y + FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event) + return False # finish event propagation? + + def leave_notify_event(self, widget, event): + FigureCanvasBase.leave_notify_event(self, event) + + def enter_notify_event(self, widget, event): + FigureCanvasBase.enter_notify_event(self, event) + + def size_allocate(self, widget, allocation): + dpival = self.figure.dpi + winch = allocation.width / dpival + hinch = allocation.height / dpival + self.figure.set_size_inches(winch, hinch, forward=False) + FigureCanvasBase.resize_event(self) + self.draw_idle() + + def _get_key(self, event): + if event.keyval in self.keyvald: + key = self.keyvald[event.keyval] + elif event.keyval < 256: + key = chr(event.keyval) + else: + key = None + + modifiers = [ + (Gdk.ModifierType.MOD4_MASK, 'super'), + (Gdk.ModifierType.MOD1_MASK, 'alt'), + (Gdk.ModifierType.CONTROL_MASK, 'ctrl'), + ] + for key_mask, prefix in modifiers: + if event.state & key_mask: + key = '{0}+{1}'.format(prefix, key) + + return key + + def configure_event(self, widget, event): + if widget.get_property("window") is None: + return + w, h = event.width, event.height + if w < 3 or h < 3: + return # empty fig + # resize the figure (in inches) + dpi = self.figure.dpi + self.figure.set_size_inches(w/dpi, h/dpi, forward=False) + return False # finish event propagation? + + def on_draw_event(self, widget, ctx): + # to be overwritten by GTK3Agg or GTK3Cairo + pass + + def draw(self): + if self.get_visible() and self.get_mapped(): + self.queue_draw() + # do a synchronous draw (its less efficient than an async draw, + # but is required if/when animation is used) + self.get_property("window").process_updates (False) + + def draw_idle(self): + if self._idle_draw_id != 0: + return + def idle_draw(*args): + try: + self.draw() + finally: + self._idle_draw_id = 0 + return False + self._idle_draw_id = GLib.idle_add(idle_draw) + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of :class:`backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + """ + return TimerGTK3(*args, **kwargs) + + def flush_events(self): + Gdk.threads_enter() + while Gtk.events_pending(): + Gtk.main_iteration() + Gdk.flush() + Gdk.threads_leave() + + +class FigureManagerGTK3(FigureManagerBase): + """ + Attributes + ---------- + canvas : `FigureCanvas` + The FigureCanvas instance + num : int or str + The Figure number + toolbar : Gtk.Toolbar + The Gtk.Toolbar (gtk only) + vbox : Gtk.VBox + The Gtk.VBox containing the canvas and toolbar (gtk only) + window : Gtk.Window + The Gtk.Window (gtk only) + + """ + def __init__(self, canvas, num): + FigureManagerBase.__init__(self, canvas, num) + + self.window = Gtk.Window() + self.window.set_wmclass("matplotlib", "Matplotlib") + self.set_window_title("Figure %d" % num) + try: + self.window.set_icon_from_file(window_icon) + except (SystemExit, KeyboardInterrupt): + # re-raise exit type Exceptions + raise + except: + # some versions of gtk throw a glib.GError but not + # all, so I am not sure how to catch it. I am unhappy + # doing a blanket catch here, but am not sure what a + # better way is - JDH + _log.info('Could not load matplotlib icon: %s', sys.exc_info()[1]) + + self.vbox = Gtk.Box() + self.vbox.set_property("orientation", Gtk.Orientation.VERTICAL) + self.window.add(self.vbox) + self.vbox.show() + + self.canvas.show() + + self.vbox.pack_start(self.canvas, True, True, 0) + # calculate size for window + w = int (self.canvas.figure.bbox.width) + h = int (self.canvas.figure.bbox.height) + + self.toolmanager = self._get_toolmanager() + self.toolbar = self._get_toolbar() + self.statusbar = None + + def add_widget(child, expand, fill, padding): + child.show() + self.vbox.pack_end(child, False, False, 0) + size_request = child.size_request() + return size_request.height + + if self.toolmanager: + backend_tools.add_tools_to_manager(self.toolmanager) + if self.toolbar: + backend_tools.add_tools_to_container(self.toolbar) + self.statusbar = StatusbarGTK3(self.toolmanager) + h += add_widget(self.statusbar, False, False, 0) + h += add_widget(Gtk.HSeparator(), False, False, 0) + + if self.toolbar is not None: + self.toolbar.show() + h += add_widget(self.toolbar, False, False, 0) + + self.window.set_default_size (w, h) + + def destroy(*args): + Gcf.destroy(num) + self.window.connect("destroy", destroy) + self.window.connect("delete_event", destroy) + if matplotlib.is_interactive(): + self.window.show() + self.canvas.draw_idle() + + def notify_axes_change(fig): + 'this will be called whenever the current axes is changed' + if self.toolmanager is not None: + pass + elif self.toolbar is not None: + self.toolbar.update() + self.canvas.figure.add_axobserver(notify_axes_change) + + self.canvas.grab_focus() + + def destroy(self, *args): + self.vbox.destroy() + self.window.destroy() + self.canvas.destroy() + if self.toolbar: + self.toolbar.destroy() + + if (Gcf.get_num_fig_managers() == 0 and + not matplotlib.is_interactive() and + Gtk.main_level() >= 1): + Gtk.main_quit() + + def show(self): + # show the figure window + self.window.show() + self.window.present() + + def full_screen_toggle (self): + self._full_screen_flag = not self._full_screen_flag + if self._full_screen_flag: + self.window.fullscreen() + else: + self.window.unfullscreen() + _full_screen_flag = False + + def _get_toolbar(self): + # must be inited after the window, drawingArea and figure + # attrs are set + if rcParams['toolbar'] == 'toolbar2': + toolbar = NavigationToolbar2GTK3(self.canvas, self.window) + elif rcParams['toolbar'] == 'toolmanager': + toolbar = ToolbarGTK3(self.toolmanager) + else: + toolbar = None + return toolbar + + def _get_toolmanager(self): + # must be initialised after toolbar has been set + if rcParams['toolbar'] == 'toolmanager': + toolmanager = ToolManager(self.canvas.figure) + else: + toolmanager = None + return toolmanager + + def get_window_title(self): + return self.window.get_title() + + def set_window_title(self, title): + self.window.set_title(title) + + def resize(self, width, height): + 'set the canvas size in pixels' + #_, _, cw, ch = self.canvas.allocation + #_, _, ww, wh = self.window.allocation + #self.window.resize (width-cw+ww, height-ch+wh) + self.window.resize(width, height) + + +class NavigationToolbar2GTK3(NavigationToolbar2, Gtk.Toolbar): + def __init__(self, canvas, window): + self.win = window + GObject.GObject.__init__(self) + NavigationToolbar2.__init__(self, canvas) + self.ctx = None + + def set_message(self, s): + self.message.set_label(s) + + def set_cursor(self, cursor): + self.canvas.get_property("window").set_cursor(cursord[cursor]) + Gtk.main_iteration() + + def release(self, event): + try: del self._pixmapBack + except AttributeError: pass + + def draw_rubberband(self, event, x0, y0, x1, y1): + 'adapted from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/189744' + self.ctx = self.canvas.get_property("window").cairo_create() + + # todo: instead of redrawing the entire figure, copy the part of + # the figure that was covered by the previous rubberband rectangle + self.canvas.draw() + + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + w = abs(x1 - x0) + h = abs(y1 - y0) + rect = [int(val) for val in (min(x0,x1), min(y0, y1), w, h)] + + self.ctx.new_path() + self.ctx.set_line_width(0.5) + self.ctx.rectangle(rect[0], rect[1], rect[2], rect[3]) + self.ctx.set_source_rgb(0, 0, 0) + self.ctx.stroke() + + def _init_toolbar(self): + self.set_style(Gtk.ToolbarStyle.ICONS) + basedir = os.path.join(rcParams['datapath'],'images') + + for text, tooltip_text, image_file, callback in self.toolitems: + if text is None: + self.insert( Gtk.SeparatorToolItem(), -1 ) + continue + fname = os.path.join(basedir, image_file + '.png') + image = Gtk.Image() + image.set_from_file(fname) + tbutton = Gtk.ToolButton() + tbutton.set_label(text) + tbutton.set_icon_widget(image) + self.insert(tbutton, -1) + tbutton.connect('clicked', getattr(self, callback)) + tbutton.set_tooltip_text(tooltip_text) + + toolitem = Gtk.SeparatorToolItem() + self.insert(toolitem, -1) + toolitem.set_draw(False) + toolitem.set_expand(True) + + toolitem = Gtk.ToolItem() + self.insert(toolitem, -1) + self.message = Gtk.Label() + toolitem.add(self.message) + + self.show_all() + + def get_filechooser(self): + fc = FileChooserDialog( + title='Save the figure', + parent=self.win, + path=os.path.expanduser(rcParams['savefig.directory']), + filetypes=self.canvas.get_supported_filetypes(), + default_filetype=self.canvas.get_default_filetype()) + fc.set_current_name(self.canvas.get_default_filename()) + return fc + + def save_figure(self, *args): + chooser = self.get_filechooser() + fname, format = chooser.get_filename_from_user() + chooser.destroy() + if fname: + startpath = os.path.expanduser(rcParams['savefig.directory']) + # Save dir for next time, unless empty str (i.e., use cwd). + if startpath != "": + rcParams['savefig.directory'] = ( + os.path.dirname(six.text_type(fname))) + try: + self.canvas.figure.savefig(fname, format=format) + except Exception as e: + error_msg_gtk(str(e), parent=self) + + def configure_subplots(self, button): + toolfig = Figure(figsize=(6,3)) + canvas = self._get_canvas(toolfig) + toolfig.subplots_adjust(top=0.9) + tool = SubplotTool(self.canvas.figure, toolfig) + + w = int(toolfig.bbox.width) + h = int(toolfig.bbox.height) + + window = Gtk.Window() + try: + window.set_icon_from_file(window_icon) + except (SystemExit, KeyboardInterrupt): + # re-raise exit type Exceptions + raise + except: + # we presumably already logged a message on the + # failure of the main plot, don't keep reporting + pass + window.set_title("Subplot Configuration Tool") + window.set_default_size(w, h) + vbox = Gtk.Box() + vbox.set_property("orientation", Gtk.Orientation.VERTICAL) + window.add(vbox) + vbox.show() + + canvas.show() + vbox.pack_start(canvas, True, True, 0) + window.show() + + def _get_canvas(self, fig): + return self.canvas.__class__(fig) + + +class FileChooserDialog(Gtk.FileChooserDialog): + """GTK+ file selector which remembers the last file/directory + selected and presents the user with a menu of supported image formats + """ + def __init__ (self, + title = 'Save file', + parent = None, + action = Gtk.FileChooserAction.SAVE, + buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_SAVE, Gtk.ResponseType.OK), + path = None, + filetypes = [], + default_filetype = None + ): + super (FileChooserDialog, self).__init__ (title, parent, action, + buttons) + self.set_default_response (Gtk.ResponseType.OK) + + if not path: path = os.getcwd() + os.sep + + # create an extra widget to list supported image formats + self.set_current_folder (path) + self.set_current_name ('image.' + default_filetype) + + hbox = Gtk.Box(spacing=10) + hbox.pack_start(Gtk.Label(label="File Format:"), False, False, 0) + + liststore = Gtk.ListStore(GObject.TYPE_STRING) + cbox = Gtk.ComboBox() #liststore) + cbox.set_model(liststore) + cell = Gtk.CellRendererText() + cbox.pack_start(cell, True) + cbox.add_attribute(cell, 'text', 0) + hbox.pack_start(cbox, False, False, 0) + + self.filetypes = filetypes + self.sorted_filetypes = sorted(six.iteritems(filetypes)) + default = 0 + for i, (ext, name) in enumerate(self.sorted_filetypes): + liststore.append(["%s (*.%s)" % (name, ext)]) + if ext == default_filetype: + default = i + cbox.set_active(default) + self.ext = default_filetype + + def cb_cbox_changed (cbox, data=None): + """File extension changed""" + head, filename = os.path.split(self.get_filename()) + root, ext = os.path.splitext(filename) + ext = ext[1:] + new_ext = self.sorted_filetypes[cbox.get_active()][0] + self.ext = new_ext + + if ext in self.filetypes: + filename = root + '.' + new_ext + elif ext == '': + filename = filename.rstrip('.') + '.' + new_ext + + self.set_current_name (filename) + cbox.connect ("changed", cb_cbox_changed) + + hbox.show_all() + self.set_extra_widget(hbox) + + def get_filename_from_user (self): + while True: + filename = None + if self.run() != int(Gtk.ResponseType.OK): + break + filename = self.get_filename() + break + + return filename, self.ext + + +class RubberbandGTK3(backend_tools.RubberbandBase): + def __init__(self, *args, **kwargs): + backend_tools.RubberbandBase.__init__(self, *args, **kwargs) + self.ctx = None + + def draw_rubberband(self, x0, y0, x1, y1): + # 'adapted from http://aspn.activestate.com/ASPN/Cookbook/Python/ + # Recipe/189744' + self.ctx = self.figure.canvas.get_property("window").cairo_create() + + # todo: instead of redrawing the entire figure, copy the part of + # the figure that was covered by the previous rubberband rectangle + self.figure.canvas.draw() + + height = self.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + w = abs(x1 - x0) + h = abs(y1 - y0) + rect = [int(val) for val in (min(x0, x1), min(y0, y1), w, h)] + + self.ctx.new_path() + self.ctx.set_line_width(0.5) + self.ctx.rectangle(rect[0], rect[1], rect[2], rect[3]) + self.ctx.set_source_rgb(0, 0, 0) + self.ctx.stroke() + + +class ToolbarGTK3(ToolContainerBase, Gtk.Box): + _icon_extension = '.png' + def __init__(self, toolmanager): + ToolContainerBase.__init__(self, toolmanager) + Gtk.Box.__init__(self) + self.set_property("orientation", Gtk.Orientation.VERTICAL) + + self._toolarea = Gtk.Box() + self._toolarea.set_property('orientation', Gtk.Orientation.HORIZONTAL) + self.pack_start(self._toolarea, False, False, 0) + self._toolarea.show_all() + self._groups = {} + self._toolitems = {} + + def add_toolitem(self, name, group, position, image_file, description, + toggle): + if toggle: + tbutton = Gtk.ToggleToolButton() + else: + tbutton = Gtk.ToolButton() + tbutton.set_label(name) + + if image_file is not None: + image = Gtk.Image() + image.set_from_file(image_file) + tbutton.set_icon_widget(image) + + if position is None: + position = -1 + + self._add_button(tbutton, group, position) + signal = tbutton.connect('clicked', self._call_tool, name) + tbutton.set_tooltip_text(description) + tbutton.show_all() + self._toolitems.setdefault(name, []) + self._toolitems[name].append((tbutton, signal)) + + def _add_button(self, button, group, position): + if group not in self._groups: + if self._groups: + self._add_separator() + toolbar = Gtk.Toolbar() + toolbar.set_style(Gtk.ToolbarStyle.ICONS) + self._toolarea.pack_start(toolbar, False, False, 0) + toolbar.show_all() + self._groups[group] = toolbar + self._groups[group].insert(button, position) + + def _call_tool(self, btn, name): + self.trigger_tool(name) + + def toggle_toolitem(self, name, toggled): + if name not in self._toolitems: + return + for toolitem, signal in self._toolitems[name]: + toolitem.handler_block(signal) + toolitem.set_active(toggled) + toolitem.handler_unblock(signal) + + def remove_toolitem(self, name): + if name not in self._toolitems: + self.toolmanager.message_event('%s Not in toolbar' % name, self) + return + + for group in self._groups: + for toolitem, _signal in self._toolitems[name]: + if toolitem in self._groups[group]: + self._groups[group].remove(toolitem) + del self._toolitems[name] + + def _add_separator(self): + sep = Gtk.Separator() + sep.set_property("orientation", Gtk.Orientation.VERTICAL) + self._toolarea.pack_start(sep, False, True, 0) + sep.show_all() + + +class StatusbarGTK3(StatusbarBase, Gtk.Statusbar): + def __init__(self, *args, **kwargs): + StatusbarBase.__init__(self, *args, **kwargs) + Gtk.Statusbar.__init__(self) + self._context = self.get_context_id('message') + + def set_message(self, s): + self.pop(self._context) + self.push(self._context, s) + + +class SaveFigureGTK3(backend_tools.SaveFigureBase): + + def get_filechooser(self): + fc = FileChooserDialog( + title='Save the figure', + parent=self.figure.canvas.manager.window, + path=os.path.expanduser(rcParams['savefig.directory']), + filetypes=self.figure.canvas.get_supported_filetypes(), + default_filetype=self.figure.canvas.get_default_filetype()) + fc.set_current_name(self.figure.canvas.get_default_filename()) + return fc + + def trigger(self, *args, **kwargs): + chooser = self.get_filechooser() + fname, format_ = chooser.get_filename_from_user() + chooser.destroy() + if fname: + startpath = os.path.expanduser(rcParams['savefig.directory']) + if startpath == '': + # explicitly missing key or empty str signals to use cwd + rcParams['savefig.directory'] = startpath + else: + # save dir for next time + rcParams['savefig.directory'] = os.path.dirname( + six.text_type(fname)) + try: + self.figure.canvas.print_figure(fname, format=format_) + except Exception as e: + error_msg_gtk(str(e), parent=self) + + +class SetCursorGTK3(backend_tools.SetCursorBase): + def set_cursor(self, cursor): + self.figure.canvas.get_property("window").set_cursor(cursord[cursor]) + + +class ConfigureSubplotsGTK3(backend_tools.ConfigureSubplotsBase, Gtk.Window): + def __init__(self, *args, **kwargs): + backend_tools.ConfigureSubplotsBase.__init__(self, *args, **kwargs) + self.window = None + + def init_window(self): + if self.window: + return + self.window = Gtk.Window(title="Subplot Configuration Tool") + + try: + self.window.window.set_icon_from_file(window_icon) + except (SystemExit, KeyboardInterrupt): + # re-raise exit type Exceptions + raise + except: + # we presumably already logged a message on the + # failure of the main plot, don't keep reporting + pass + + self.vbox = Gtk.Box() + self.vbox.set_property("orientation", Gtk.Orientation.VERTICAL) + self.window.add(self.vbox) + self.vbox.show() + self.window.connect('destroy', self.destroy) + + toolfig = Figure(figsize=(6, 3)) + canvas = self.figure.canvas.__class__(toolfig) + + toolfig.subplots_adjust(top=0.9) + SubplotTool(self.figure, toolfig) + + w = int(toolfig.bbox.width) + h = int(toolfig.bbox.height) + + self.window.set_default_size(w, h) + + canvas.show() + self.vbox.pack_start(canvas, True, True, 0) + self.window.show() + + def destroy(self, *args): + self.window.destroy() + self.window = None + + def _get_canvas(self, fig): + return self.canvas.__class__(fig) + + def trigger(self, sender, event, data=None): + self.init_window() + self.window.present() + + +# Define the file to use as the GTk icon +if sys.platform == 'win32': + icon_filename = 'matplotlib.png' +else: + icon_filename = 'matplotlib.svg' +window_icon = os.path.join( + matplotlib.rcParams['datapath'], 'images', icon_filename) + + +def error_msg_gtk(msg, parent=None): + if parent is not None: # find the toplevel Gtk.Window + parent = parent.get_toplevel() + if not parent.is_toplevel(): + parent = None + + if not isinstance(msg, six.string_types): + msg = ','.join(map(str, msg)) + + dialog = Gtk.MessageDialog( + parent = parent, + type = Gtk.MessageType.ERROR, + buttons = Gtk.ButtonsType.OK, + message_format = msg) + dialog.run() + dialog.destroy() + + +backend_tools.ToolSaveFigure = SaveFigureGTK3 +backend_tools.ToolConfigureSubplots = ConfigureSubplotsGTK3 +backend_tools.ToolSetCursor = SetCursorGTK3 +backend_tools.ToolRubberband = RubberbandGTK3 + +Toolbar = ToolbarGTK3 + + +@_Backend.export +class _BackendGTK3(_Backend): + FigureCanvas = FigureCanvasGTK3 + FigureManager = FigureManagerGTK3 + + @staticmethod + def trigger_manager_draw(manager): + manager.canvas.draw_idle() + + @staticmethod + def mainloop(): + if Gtk.main_level() == 0: + Gtk.main() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3agg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3agg.py new file mode 100644 index 00000000000..53c625b8a50 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3agg.py @@ -0,0 +1,102 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import numpy as np +import warnings + +from . import backend_agg, backend_gtk3 +from .backend_cairo import cairo, HAS_CAIRO_CFFI +from .backend_gtk3 import _BackendGTK3 +from matplotlib import transforms + +if six.PY3 and not HAS_CAIRO_CFFI: + warnings.warn( + "The Gtk3Agg backend is known to not work on Python 3.x with pycairo. " + "Try installing cairocffi.") + + +class FigureCanvasGTK3Agg(backend_gtk3.FigureCanvasGTK3, + backend_agg.FigureCanvasAgg): + def __init__(self, figure): + backend_gtk3.FigureCanvasGTK3.__init__(self, figure) + self._bbox_queue = [] + + def _renderer_init(self): + pass + + def _render_figure(self, width, height): + backend_agg.FigureCanvasAgg.draw(self) + + def on_draw_event(self, widget, ctx): + """ GtkDrawable draw event, like expose_event in GTK 2.X + """ + allocation = self.get_allocation() + w, h = allocation.width, allocation.height + + if not len(self._bbox_queue): + self._render_figure(w, h) + bbox_queue = [transforms.Bbox([[0, 0], [w, h]])] + else: + bbox_queue = self._bbox_queue + + if HAS_CAIRO_CFFI and not isinstance(ctx, cairo.Context): + ctx = cairo.Context._from_pointer( + cairo.ffi.cast('cairo_t **', + id(ctx) + object.__basicsize__)[0], + incref=True) + + for bbox in bbox_queue: + area = self.copy_from_bbox(bbox) + buf = np.fromstring(area.to_string_argb(), dtype='uint8') + + x = int(bbox.x0) + y = h - int(bbox.y1) + width = int(bbox.x1) - int(bbox.x0) + height = int(bbox.y1) - int(bbox.y0) + + if HAS_CAIRO_CFFI: + image = cairo.ImageSurface.create_for_data( + buf.data, cairo.FORMAT_ARGB32, width, height) + else: + image = cairo.ImageSurface.create_for_data( + buf, cairo.FORMAT_ARGB32, width, height) + ctx.set_source_surface(image, x, y) + ctx.paint() + + if len(self._bbox_queue): + self._bbox_queue = [] + + return False + + def blit(self, bbox=None): + # If bbox is None, blit the entire canvas to gtk. Otherwise + # blit only the area defined by the bbox. + if bbox is None: + bbox = self.figure.bbox + + allocation = self.get_allocation() + w, h = allocation.width, allocation.height + x = int(bbox.x0) + y = h - int(bbox.y1) + width = int(bbox.x1) - int(bbox.x0) + height = int(bbox.y1) - int(bbox.y0) + + self._bbox_queue.append(bbox) + self.queue_draw_area(x, y, width, height) + + def print_png(self, filename, *args, **kwargs): + # Do this so we can save the resolution of figure in the PNG file + agg = self.switch_backends(backend_agg.FigureCanvasAgg) + return agg.print_png(filename, *args, **kwargs) + + +class FigureManagerGTK3Agg(backend_gtk3.FigureManagerGTK3): + pass + + +@_BackendGTK3.export +class _BackendGTK3Cairo(_BackendGTK3): + FigureCanvas = FigureCanvasGTK3Agg + FigureManager = FigureManagerGTK3Agg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3cairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3cairo.py new file mode 100644 index 00000000000..2591b112d2c --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtk3cairo.py @@ -0,0 +1,55 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from . import backend_cairo, backend_gtk3 +from .backend_cairo import cairo, HAS_CAIRO_CFFI +from .backend_gtk3 import _BackendGTK3 +from matplotlib.backend_bases import cursors + + +class RendererGTK3Cairo(backend_cairo.RendererCairo): + def set_context(self, ctx): + if HAS_CAIRO_CFFI and not isinstance(ctx, cairo.Context): + ctx = cairo.Context._from_pointer( + cairo.ffi.cast( + 'cairo_t **', + id(ctx) + object.__basicsize__)[0], + incref=True) + + self.gc.ctx = ctx + + +class FigureCanvasGTK3Cairo(backend_gtk3.FigureCanvasGTK3, + backend_cairo.FigureCanvasCairo): + + def _renderer_init(self): + """Use cairo renderer.""" + self._renderer = RendererGTK3Cairo(self.figure.dpi) + + def _render_figure(self, width, height): + self._renderer.set_width_height(width, height) + self.figure.draw(self._renderer) + + def on_draw_event(self, widget, ctx): + """GtkDrawable draw event.""" + toolbar = self.toolbar + # if toolbar: + # toolbar.set_cursor(cursors.WAIT) + self._renderer.set_context(ctx) + allocation = self.get_allocation() + self._render_figure(allocation.width, allocation.height) + # if toolbar: + # toolbar.set_cursor(toolbar._lastCursor) + return False # finish event propagation? + + +class FigureManagerGTK3Cairo(backend_gtk3.FigureManagerGTK3): + pass + + +@_BackendGTK3.export +class _BackendGTK3Cairo(_BackendGTK3): + FigureCanvas = FigureCanvasGTK3Cairo + FigureManager = FigureManagerGTK3Cairo diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkagg.py new file mode 100644 index 00000000000..14240647ccb --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkagg.py @@ -0,0 +1,96 @@ +""" +Render to gtk from agg +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import matplotlib +from matplotlib.cbook import warn_deprecated +from matplotlib.backends.backend_agg import FigureCanvasAgg +from matplotlib.backends.backend_gtk import ( + gtk, _BackendGTK, FigureCanvasGTK, FigureManagerGTK, NavigationToolbar2GTK, + backend_version, error_msg_gtk, PIXELS_PER_INCH) +from matplotlib.backends._gtkagg import agg_to_gtk_drawable + + +class NavigationToolbar2GTKAgg(NavigationToolbar2GTK): + def _get_canvas(self, fig): + return FigureCanvasGTKAgg(fig) + + +class FigureManagerGTKAgg(FigureManagerGTK): + def _get_toolbar(self, canvas): + # must be inited after the window, drawingArea and figure + # attrs are set + if matplotlib.rcParams['toolbar']=='toolbar2': + toolbar = NavigationToolbar2GTKAgg (canvas, self.window) + else: + toolbar = None + return toolbar + + +class FigureCanvasGTKAgg(FigureCanvasGTK, FigureCanvasAgg): + filetypes = FigureCanvasGTK.filetypes.copy() + filetypes.update(FigureCanvasAgg.filetypes) + + def __init__(self, *args, **kwargs): + warn_deprecated('2.2', + message=('The GTKAgg backend is deprecated. It is ' + 'untested and will be removed in Matplotlib ' + '3.0. Use the GTK3Agg backend instead. See ' + 'Matplotlib usage FAQ for more info on ' + 'backends.'), + alternative='GTK3Agg') + super(FigureCanvasGTKAgg, self).__init__(*args, **kwargs) + + def configure_event(self, widget, event=None): + + if widget.window is None: + return + try: + del self.renderer + except AttributeError: + pass + w,h = widget.window.get_size() + if w==1 or h==1: return # empty fig + + # compute desired figure size in inches + dpival = self.figure.dpi + winch = w/dpival + hinch = h/dpival + self.figure.set_size_inches(winch, hinch, forward=False) + self._need_redraw = True + self.resize_event() + return True + + def _render_figure(self, pixmap, width, height): + FigureCanvasAgg.draw(self) + + buf = self.buffer_rgba() + ren = self.get_renderer() + w = int(ren.width) + h = int(ren.height) + + pixbuf = gtk.gdk.pixbuf_new_from_data( + buf, gtk.gdk.COLORSPACE_RGB, True, 8, w, h, w*4) + pixmap.draw_pixbuf(pixmap.new_gc(), pixbuf, 0, 0, 0, 0, w, h, + gtk.gdk.RGB_DITHER_NONE, 0, 0) + + def blit(self, bbox=None): + agg_to_gtk_drawable(self._pixmap, self.renderer._renderer, bbox) + x, y, w, h = self.allocation + self.window.draw_drawable(self.style.fg_gc[self.state], self._pixmap, + 0, 0, 0, 0, w, h) + + def print_png(self, filename, *args, **kwargs): + # Do this so we can save the resolution of figure in the PNG file + agg = self.switch_backends(FigureCanvasAgg) + return agg.print_png(filename, *args, **kwargs) + + +@_BackendGTK.export +class _BackendGTKAgg(_BackendGTK): + FigureCanvas = FigureCanvasGTKAgg + FigureManager = FigureManagerGTKAgg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkcairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkcairo.py new file mode 100644 index 00000000000..87e6debae79 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_gtkcairo.py @@ -0,0 +1,74 @@ +""" +GTK+ Matplotlib interface using cairo (not GDK) drawing operations. +Author: Steve Chaplin +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import gtk +if gtk.pygtk_version < (2, 7, 0): + import cairo.gtk + +from matplotlib import cbook +from matplotlib.backends import backend_cairo +from matplotlib.backends.backend_gtk import * +from matplotlib.backends.backend_gtk import _BackendGTK + +backend_version = ('PyGTK(%d.%d.%d) ' % gtk.pygtk_version + + 'Pycairo(%s)' % backend_cairo.backend_version) + + +class RendererGTKCairo (backend_cairo.RendererCairo): + if gtk.pygtk_version >= (2,7,0): + def set_pixmap (self, pixmap): + self.gc.ctx = pixmap.cairo_create() + else: + def set_pixmap (self, pixmap): + self.gc.ctx = cairo.gtk.gdk_cairo_create (pixmap) + + +class FigureCanvasGTKCairo(backend_cairo.FigureCanvasCairo, FigureCanvasGTK): + filetypes = FigureCanvasGTK.filetypes.copy() + filetypes.update(backend_cairo.FigureCanvasCairo.filetypes) + + def __init__(self, *args, **kwargs): + warn_deprecated('2.2', + message=('The GTKCairo backend is deprecated. It is ' + 'untested and will be removed in Matplotlib ' + '3.0. Use the GTK3Cairo backend instead. See ' + 'Matplotlib usage FAQ for more info on ' + 'backends.'), + alternative='GTK3Cairo') + super(FigureCanvasGTKCairo, self).__init__(*args, **kwargs) + + def _renderer_init(self): + """Override to use cairo (rather than GDK) renderer""" + self._renderer = RendererGTKCairo(self.figure.dpi) + + +# This class has been unused for a while at least. +@cbook.deprecated("2.1") +class FigureManagerGTKCairo(FigureManagerGTK): + def _get_toolbar(self, canvas): + # must be inited after the window, drawingArea and figure + # attrs are set + if matplotlib.rcParams['toolbar']=='toolbar2': + toolbar = NavigationToolbar2GTKCairo (canvas, self.window) + else: + toolbar = None + return toolbar + + +# This class has been unused for a while at least. +@cbook.deprecated("2.1") +class NavigationToolbar2Cairo(NavigationToolbar2GTK): + def _get_canvas(self, fig): + return FigureCanvasGTKCairo(fig) + + +@_BackendGTK.export +class _BackendGTKCairo(_BackendGTK): + FigureCanvas = FigureCanvasGTKCairo + FigureManager = FigureManagerGTK diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_macosx.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_macosx.py new file mode 100644 index 00000000000..4ab5d0c9077 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_macosx.py @@ -0,0 +1,210 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import os + +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2, + TimerBase) + +from matplotlib.figure import Figure +from matplotlib import rcParams + +from matplotlib.widgets import SubplotTool + +import matplotlib +from matplotlib.backends import _macosx + +from .backend_agg import FigureCanvasAgg + + +######################################################################## +# +# The following functions and classes are for pylab and implement +# window/figure managers, etc... +# +######################################################################## + + +class TimerMac(_macosx.Timer, TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` that uses CoreFoundation + run loops for timer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + # completely implemented at the C-level (in _macosx.Timer) + + +class FigureCanvasMac(_macosx.FigureCanvas, FigureCanvasAgg): + """ + The canvas the figure renders into. Calls the draw and print fig + methods, creates the renderers, etc... + + Events such as button presses, mouse movements, and key presses + are handled in the C code and the base class methods + button_press_event, button_release_event, motion_notify_event, + key_press_event, and key_release_event are called from there. + + Attributes + ---------- + figure : `matplotlib.figure.Figure` + A high-level Figure instance + + """ + + def __init__(self, figure): + FigureCanvasBase.__init__(self, figure) + width, height = self.get_width_height() + _macosx.FigureCanvas.__init__(self, width, height) + self._device_scale = 1.0 + + def _set_device_scale(self, value): + if self._device_scale != value: + self.figure.dpi = self.figure.dpi / self._device_scale * value + self._device_scale = value + + def _draw(self): + renderer = self.get_renderer(cleared=self.figure.stale) + + if self.figure.stale: + self.figure.draw(renderer) + + return renderer + + def draw(self): + self.invalidate() + self.flush_events() + + def draw_idle(self, *args, **kwargs): + self.invalidate() + + def blit(self, bbox): + self.invalidate() + + def resize(self, width, height): + dpi = self.figure.dpi + width /= dpi + height /= dpi + self.figure.set_size_inches(width * self._device_scale, + height * self._device_scale, + forward=False) + FigureCanvasBase.resize_event(self) + self.draw_idle() + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of `backend_bases.Timer`. + This is useful for getting periodic events through the backend's native + event loop. Implemented only for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + """ + return TimerMac(*args, **kwargs) + + +class FigureManagerMac(_macosx.FigureManager, FigureManagerBase): + """ + Wrap everything up into a window for the pylab interface + """ + def __init__(self, canvas, num): + FigureManagerBase.__init__(self, canvas, num) + title = "Figure %d" % num + _macosx.FigureManager.__init__(self, canvas, title) + if rcParams['toolbar']=='toolbar2': + self.toolbar = NavigationToolbar2Mac(canvas) + else: + self.toolbar = None + if self.toolbar is not None: + self.toolbar.update() + + def notify_axes_change(fig): + 'this will be called whenever the current axes is changed' + if self.toolbar != None: self.toolbar.update() + self.canvas.figure.add_axobserver(notify_axes_change) + + if matplotlib.is_interactive(): + self.show() + self.canvas.draw_idle() + + def close(self): + Gcf.destroy(self.num) + + +class NavigationToolbar2Mac(_macosx.NavigationToolbar2, NavigationToolbar2): + + def __init__(self, canvas): + NavigationToolbar2.__init__(self, canvas) + + def _init_toolbar(self): + basedir = os.path.join(rcParams['datapath'], "images") + _macosx.NavigationToolbar2.__init__(self, basedir) + + def draw_rubberband(self, event, x0, y0, x1, y1): + self.canvas.set_rubberband(int(x0), int(y0), int(x1), int(y1)) + + def release(self, event): + self.canvas.remove_rubberband() + + def set_cursor(self, cursor): + _macosx.set_cursor(cursor) + + def save_figure(self, *args): + filename = _macosx.choose_save_file('Save the figure', + self.canvas.get_default_filename()) + if filename is None: # Cancel + return + self.canvas.figure.savefig(filename) + + def prepare_configure_subplots(self): + toolfig = Figure(figsize=(6,3)) + canvas = FigureCanvasMac(toolfig) + toolfig.subplots_adjust(top=0.9) + tool = SubplotTool(self.canvas.figure, toolfig) + return canvas + + def set_message(self, message): + _macosx.NavigationToolbar2.set_message(self, message.encode('utf-8')) + + +######################################################################## +# +# Now just provide the standard names that backend.__init__ is expecting +# +######################################################################## + +@_Backend.export +class _BackendMac(_Backend): + FigureCanvas = FigureCanvasMac + FigureManager = FigureManagerMac + + @staticmethod + def trigger_manager_draw(manager): + # For performance reasons, we don't want to redraw the figure after + # each draw command. Instead, we mark the figure as invalid, so that it + # will be redrawn as soon as the event loop resumes via PyOS_InputHook. + # This function should be called after each draw event, even if + # matplotlib is not running interactively. + manager.canvas.invalidate() + + @staticmethod + def mainloop(): + _macosx.show() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_mixed.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_mixed.py new file mode 100644 index 00000000000..8e475bd13c9 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_mixed.py @@ -0,0 +1,155 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import numpy as np + +import six + +from matplotlib.backends.backend_agg import RendererAgg +from matplotlib.tight_bbox import process_figure_for_rasterizing + + +class MixedModeRenderer(object): + """ + A helper class to implement a renderer that switches between + vector and raster drawing. An example may be a PDF writer, where + most things are drawn with PDF vector commands, but some very + complex objects, such as quad meshes, are rasterised and then + output as images. + """ + def __init__(self, figure, width, height, dpi, vector_renderer, + raster_renderer_class=None, + bbox_inches_restore=None): + """ + Parameters + ---------- + figure : `matplotlib.figure.Figure` + The figure instance. + + width : scalar + The width of the canvas in logical units + + height : scalar + The height of the canvas in logical units + + dpi : scalar + The dpi of the canvas + + vector_renderer : `matplotlib.backend_bases.RendererBase` + An instance of a subclass of + `~matplotlib.backend_bases.RendererBase` that will be used for the + vector drawing. + + raster_renderer_class : `matplotlib.backend_bases.RendererBase` + The renderer class to use for the raster drawing. If not provided, + this will use the Agg backend (which is currently the only viable + option anyway.) + + """ + if raster_renderer_class is None: + raster_renderer_class = RendererAgg + + self._raster_renderer_class = raster_renderer_class + self._width = width + self._height = height + self.dpi = dpi + + self._vector_renderer = vector_renderer + + self._raster_renderer = None + self._rasterizing = 0 + + # A reference to the figure is needed as we need to change + # the figure dpi before and after the rasterization. Although + # this looks ugly, I couldn't find a better solution. -JJL + self.figure = figure + self._figdpi = figure.get_dpi() + + self._bbox_inches_restore = bbox_inches_restore + + self._set_current_renderer(vector_renderer) + + _methods = """ + close_group draw_image draw_markers draw_path + draw_path_collection draw_quad_mesh draw_tex draw_text + finalize flipy get_canvas_width_height get_image_magnification + get_texmanager get_text_width_height_descent new_gc open_group + option_image_nocomposite points_to_pixels strip_math + start_filter stop_filter draw_gouraud_triangle + draw_gouraud_triangles option_scale_image + _text2path _get_text_path_transform height width + """.split() + + def _set_current_renderer(self, renderer): + self._renderer = renderer + + for method in self._methods: + if hasattr(renderer, method): + setattr(self, method, getattr(renderer, method)) + renderer.start_rasterizing = self.start_rasterizing + renderer.stop_rasterizing = self.stop_rasterizing + + def start_rasterizing(self): + """ + Enter "raster" mode. All subsequent drawing commands (until + stop_rasterizing is called) will be drawn with the raster + backend. + + If start_rasterizing is called multiple times before + stop_rasterizing is called, this method has no effect. + """ + + # change the dpi of the figure temporarily. + self.figure.set_dpi(self.dpi) + + if self._bbox_inches_restore: # when tight bbox is used + r = process_figure_for_rasterizing(self.figure, + self._bbox_inches_restore) + self._bbox_inches_restore = r + + if self._rasterizing == 0: + self._raster_renderer = self._raster_renderer_class( + self._width*self.dpi, self._height*self.dpi, self.dpi) + self._set_current_renderer(self._raster_renderer) + self._rasterizing += 1 + + def stop_rasterizing(self): + """ + Exit "raster" mode. All of the drawing that was done since + the last start_rasterizing command will be copied to the + vector backend by calling draw_image. + + If stop_rasterizing is called multiple times before + start_rasterizing is called, this method has no effect. + """ + self._rasterizing -= 1 + if self._rasterizing == 0: + self._set_current_renderer(self._vector_renderer) + + height = self._height * self.dpi + buffer, bounds = self._raster_renderer.tostring_rgba_minimized() + l, b, w, h = bounds + if w > 0 and h > 0: + image = np.frombuffer(buffer, dtype=np.uint8) + image = image.reshape((h, w, 4)) + image = image[::-1] + gc = self._renderer.new_gc() + # TODO: If the mixedmode resolution differs from the figure's + # dpi, the image must be scaled (dpi->_figdpi). Not all + # backends support this. + self._renderer.draw_image( + gc, + l * self._figdpi / self.dpi, + (height-b-h) * self._figdpi / self.dpi, + image) + self._raster_renderer = None + self._rasterizing = False + + # restore the figure dpi. + self.figure.set_dpi(self._figdpi) + + if self._bbox_inches_restore: # when tight bbox is used + r = process_figure_for_rasterizing(self.figure, + self._bbox_inches_restore, + self._figdpi) + self._bbox_inches_restore = r diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_nbagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_nbagg.py new file mode 100644 index 00000000000..429fb1e7cce --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_nbagg.py @@ -0,0 +1,270 @@ +"""Interactive figures in the IPython notebook""" +# Note: There is a notebook in +# lib/matplotlib/backends/web_backend/nbagg_uat.ipynb to help verify +# that changes made maintain expected behaviour. + +import six + +from base64 import b64encode +import io +import json +import os +import uuid + +from IPython.display import display, Javascript, HTML +try: + # Jupyter/IPython 4.x or later + from ipykernel.comm import Comm +except ImportError: + # Jupyter/IPython 3.x or earlier + from IPython.kernel.comm import Comm + +from matplotlib import rcParams, is_interactive +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, NavigationToolbar2) +from matplotlib.backends.backend_webagg_core import ( + FigureCanvasWebAggCore, FigureManagerWebAgg, NavigationToolbar2WebAgg, + TimerTornado) + + +def connection_info(): + """ + Return a string showing the figure and connection status for + the backend. This is intended as a diagnostic tool, and not for general + use. + + """ + result = [] + for manager in Gcf.get_all_fig_managers(): + fig = manager.canvas.figure + result.append('{0} - {0}'.format((fig.get_label() or + "Figure {0}".format(manager.num)), + manager.web_sockets)) + if not is_interactive(): + result.append('Figures pending show: {0}'.format(len(Gcf._activeQue))) + return '\n'.join(result) + + +# Note: Version 3.2 and 4.x icons +# http://fontawesome.io/3.2.1/icons/ +# http://fontawesome.io/ +# the `fa fa-xxx` part targets font-awesome 4, (IPython 3.x) +# the icon-xxx targets font awesome 3.21 (IPython 2.x) +_FONT_AWESOME_CLASSES = { + 'home': 'fa fa-home icon-home', + 'back': 'fa fa-arrow-left icon-arrow-left', + 'forward': 'fa fa-arrow-right icon-arrow-right', + 'zoom_to_rect': 'fa fa-square-o icon-check-empty', + 'move': 'fa fa-arrows icon-move', + 'download': 'fa fa-floppy-o icon-save', + None: None +} + + +class NavigationIPy(NavigationToolbar2WebAgg): + + # Use the standard toolbar items + download button + toolitems = [(text, tooltip_text, + _FONT_AWESOME_CLASSES[image_file], name_of_method) + for text, tooltip_text, image_file, name_of_method + in (NavigationToolbar2.toolitems + + (('Download', 'Download plot', 'download', 'download'),)) + if image_file in _FONT_AWESOME_CLASSES] + + +class FigureManagerNbAgg(FigureManagerWebAgg): + ToolbarCls = NavigationIPy + + def __init__(self, canvas, num): + self._shown = False + FigureManagerWebAgg.__init__(self, canvas, num) + + def display_js(self): + # XXX How to do this just once? It has to deal with multiple + # browser instances using the same kernel (require.js - but the + # file isn't static?). + display(Javascript(FigureManagerNbAgg.get_javascript())) + + def show(self): + if not self._shown: + self.display_js() + self._create_comm() + else: + self.canvas.draw_idle() + self._shown = True + + def reshow(self): + """ + A special method to re-show the figure in the notebook. + + """ + self._shown = False + self.show() + + @property + def connected(self): + return bool(self.web_sockets) + + @classmethod + def get_javascript(cls, stream=None): + if stream is None: + output = io.StringIO() + else: + output = stream + super(FigureManagerNbAgg, cls).get_javascript(stream=output) + with io.open(os.path.join( + os.path.dirname(__file__), + "web_backend", 'js', + "nbagg_mpl.js"), encoding='utf8') as fd: + output.write(fd.read()) + if stream is None: + return output.getvalue() + + def _create_comm(self): + comm = CommSocket(self) + self.add_web_socket(comm) + return comm + + def destroy(self): + self._send_event('close') + # need to copy comms as callbacks will modify this list + for comm in list(self.web_sockets): + comm.on_close() + self.clearup_closed() + + def clearup_closed(self): + """Clear up any closed Comms.""" + self.web_sockets = set([socket for socket in self.web_sockets + if socket.is_open()]) + + if len(self.web_sockets) == 0: + self.canvas.close_event() + + def remove_comm(self, comm_id): + self.web_sockets = set([socket for socket in self.web_sockets + if not socket.comm.comm_id == comm_id]) + + +class FigureCanvasNbAgg(FigureCanvasWebAggCore): + def new_timer(self, *args, **kwargs): + return TimerTornado(*args, **kwargs) + + +class CommSocket(object): + """ + Manages the Comm connection between IPython and the browser (client). + + Comms are 2 way, with the CommSocket being able to publish a message + via the send_json method, and handle a message with on_message. On the + JS side figure.send_message and figure.ws.onmessage do the sending and + receiving respectively. + + """ + def __init__(self, manager): + self.supports_binary = None + self.manager = manager + self.uuid = str(uuid.uuid4()) + # Publish an output area with a unique ID. The javascript can then + # hook into this area. + display(HTML("
" % self.uuid)) + try: + self.comm = Comm('matplotlib', data={'id': self.uuid}) + except AttributeError: + raise RuntimeError('Unable to create an IPython notebook Comm ' + 'instance. Are you in the IPython notebook?') + self.comm.on_msg(self.on_message) + + manager = self.manager + self._ext_close = False + + def _on_close(close_message): + self._ext_close = True + manager.remove_comm(close_message['content']['comm_id']) + manager.clearup_closed() + + self.comm.on_close(_on_close) + + def is_open(self): + return not (self._ext_close or self.comm._closed) + + def on_close(self): + # When the socket is closed, deregister the websocket with + # the FigureManager. + if self.is_open(): + try: + self.comm.close() + except KeyError: + # apparently already cleaned it up? + pass + + def send_json(self, content): + self.comm.send({'data': json.dumps(content)}) + + def send_binary(self, blob): + # The comm is ascii, so we always send the image in base64 + # encoded data URL form. + data = b64encode(blob) + if six.PY3: + data = data.decode('ascii') + data_uri = "data:image/png;base64,{0}".format(data) + self.comm.send({'data': data_uri}) + + def on_message(self, message): + # The 'supports_binary' message is relevant to the + # websocket itself. The other messages get passed along + # to matplotlib as-is. + + # Every message has a "type" and a "figure_id". + message = json.loads(message['content']['data']) + if message['type'] == 'closing': + self.on_close() + self.manager.clearup_closed() + elif message['type'] == 'supports_binary': + self.supports_binary = message['value'] + else: + self.manager.handle_json(message) + + +@_Backend.export +class _BackendNbAgg(_Backend): + FigureCanvas = FigureCanvasNbAgg + FigureManager = FigureManagerNbAgg + + @staticmethod + def new_figure_manager_given_figure(num, figure): + canvas = FigureCanvasNbAgg(figure) + manager = FigureManagerNbAgg(canvas, num) + if is_interactive(): + manager.show() + figure.canvas.draw_idle() + canvas.mpl_connect('close_event', lambda event: Gcf.destroy(num)) + return manager + + @staticmethod + def trigger_manager_draw(manager): + manager.show() + + @staticmethod + def show(*args, **kwargs): + ## TODO: something to do when keyword block==False ? + from matplotlib._pylab_helpers import Gcf + + managers = Gcf.get_all_fig_managers() + if not managers: + return + + interactive = is_interactive() + + for manager in managers: + manager.show() + + # plt.figure adds an event which puts the figure in focus + # in the activeQue. Disable this behaviour, as it results in + # figures being put as the active figure after they have been + # shown, even in non-interactive mode. + if hasattr(manager, '_cidgcf'): + manager.canvas.mpl_disconnect(manager._cidgcf) + + if not interactive and manager in Gcf._activeQue: + Gcf._activeQue.remove(manager) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_pdf.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_pdf.py new file mode 100644 index 00000000000..4f248fde9a7 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_pdf.py @@ -0,0 +1,2604 @@ +# -*- coding: utf-8 -*- + +""" +A PDF matplotlib backend +Author: Jouni K Seppänen +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six import unichr + +import codecs +import collections +from datetime import datetime +from functools import total_ordering +from io import BytesIO +import logging +from math import ceil, cos, floor, pi, sin +import os +import re +import struct +import sys +import time +import warnings +import zlib + +import numpy as np + +from matplotlib import cbook, __version__, rcParams +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + RendererBase) +from matplotlib.backends.backend_mixed import MixedModeRenderer +from matplotlib.cbook import (Bunch, get_realpath_and_stat, + is_writable_file_like, maxdict) +from matplotlib.figure import Figure +from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font +from matplotlib.afm import AFM +import matplotlib.type1font as type1font +import matplotlib.dviread as dviread +from matplotlib.ft2font import (FIXED_WIDTH, ITALIC, LOAD_NO_SCALE, + LOAD_NO_HINTING, KERNING_UNFITTED) +from matplotlib.mathtext import MathTextParser +from matplotlib.transforms import Affine2D, BboxBase +from matplotlib.path import Path +from matplotlib.dates import UTC +from matplotlib import _path +from matplotlib import _png +from matplotlib import ttconv + +_log = logging.getLogger(__name__) + +# Overview +# +# The low-level knowledge about pdf syntax lies mainly in the pdfRepr +# function and the classes Reference, Name, Operator, and Stream. The +# PdfFile class knows about the overall structure of pdf documents. +# It provides a "write" method for writing arbitrary strings in the +# file, and an "output" method that passes objects through the pdfRepr +# function before writing them in the file. The output method is +# called by the RendererPdf class, which contains the various draw_foo +# methods. RendererPdf contains a GraphicsContextPdf instance, and +# each draw_foo calls self.check_gc before outputting commands. This +# method checks whether the pdf graphics state needs to be modified +# and outputs the necessary commands. GraphicsContextPdf represents +# the graphics state, and its "delta" method returns the commands that +# modify the state. + +# Add "pdf.use14corefonts: True" in your configuration file to use only +# the 14 PDF core fonts. These fonts do not need to be embedded; every +# PDF viewing application is required to have them. This results in very +# light PDF files you can use directly in LaTeX or ConTeXt documents +# generated with pdfTeX, without any conversion. + +# These fonts are: Helvetica, Helvetica-Bold, Helvetica-Oblique, +# Helvetica-BoldOblique, Courier, Courier-Bold, Courier-Oblique, +# Courier-BoldOblique, Times-Roman, Times-Bold, Times-Italic, +# Times-BoldItalic, Symbol, ZapfDingbats. +# +# Some tricky points: +# +# 1. The clip path can only be widened by popping from the state +# stack. Thus the state must be pushed onto the stack before narrowing +# the clip path. This is taken care of by GraphicsContextPdf. +# +# 2. Sometimes it is necessary to refer to something (e.g., font, +# image, or extended graphics state, which contains the alpha value) +# in the page stream by a name that needs to be defined outside the +# stream. PdfFile provides the methods fontName, imageObject, and +# alphaState for this purpose. The implementations of these methods +# should perhaps be generalized. + +# TODOs: +# +# * encoding of fonts, including mathtext fonts and unicode support +# * TTF support has lots of small TODOs, e.g., how do you know if a font +# is serif/sans-serif, or symbolic/non-symbolic? +# * draw_markers, draw_line_collection, etc. + + +def fill(strings, linelen=75): + """Make one string from sequence of strings, with whitespace + in between. The whitespace is chosen to form lines of at most + linelen characters, if possible.""" + currpos = 0 + lasti = 0 + result = [] + for i, s in enumerate(strings): + length = len(s) + if currpos + length < linelen: + currpos += length + 1 + else: + result.append(b' '.join(strings[lasti:i])) + lasti = i + currpos = length + result.append(b' '.join(strings[lasti:])) + return b'\n'.join(result) + +# PDF strings are supposed to be able to include any eight-bit data, +# except that unbalanced parens and backslashes must be escaped by a +# backslash. However, sf bug #2708559 shows that the carriage return +# character may get read as a newline; these characters correspond to +# \gamma and \Omega in TeX's math font encoding. Escaping them fixes +# the bug. +_string_escape_regex = re.compile(br'([\\()\r\n])') + + +def _string_escape(match): + m = match.group(0) + if m in br'\()': + return b'\\' + m + elif m == b'\n': + return br'\n' + elif m == b'\r': + return br'\r' + assert False + + +def pdfRepr(obj): + """Map Python objects to PDF syntax.""" + + # Some objects defined later have their own pdfRepr method. + if hasattr(obj, 'pdfRepr'): + return obj.pdfRepr() + + # Floats. PDF does not have exponential notation (1.0e-10) so we + # need to use %f with some precision. Perhaps the precision + # should adapt to the magnitude of the number? + elif isinstance(obj, (float, np.floating)): + if not np.isfinite(obj): + raise ValueError("Can only output finite numbers in PDF") + r = ("%.10f" % obj).encode('ascii') + return r.rstrip(b'0').rstrip(b'.') + + # Booleans. Needs to be tested before integers since + # isinstance(True, int) is true. + elif isinstance(obj, bool): + return [b'false', b'true'][obj] + + # Integers are written as such. + elif isinstance(obj, (six.integer_types, np.integer)): + return ("%d" % obj).encode('ascii') + + # Unicode strings are encoded in UTF-16BE with byte-order mark. + elif isinstance(obj, six.text_type): + try: + # But maybe it's really ASCII? + s = obj.encode('ASCII') + return pdfRepr(s) + except UnicodeEncodeError: + s = codecs.BOM_UTF16_BE + obj.encode('UTF-16BE') + return pdfRepr(s) + + # Strings are written in parentheses, with backslashes and parens + # escaped. Actually balanced parens are allowed, but it is + # simpler to escape them all. TODO: cut long strings into lines; + # I believe there is some maximum line length in PDF. + elif isinstance(obj, bytes): + return b'(' + _string_escape_regex.sub(_string_escape, obj) + b')' + + # Dictionaries. The keys must be PDF names, so if we find strings + # there, we make Name objects from them. The values may be + # anything, so the caller must ensure that PDF names are + # represented as Name objects. + elif isinstance(obj, dict): + r = [b"<<"] + r.extend([Name(key).pdfRepr() + b" " + pdfRepr(obj[key]) + for key in sorted(obj)]) + r.append(b">>") + return fill(r) + + # Lists. + elif isinstance(obj, (list, tuple)): + r = [b"["] + r.extend([pdfRepr(val) for val in obj]) + r.append(b"]") + return fill(r) + + # The null keyword. + elif obj is None: + return b'null' + + # A date. + elif isinstance(obj, datetime): + r = obj.strftime('D:%Y%m%d%H%M%S') + z = obj.utcoffset() + if z is not None: + z = z.seconds + else: + if time.daylight: + z = time.altzone + else: + z = time.timezone + if z == 0: + r += 'Z' + elif z < 0: + r += "+%02d'%02d'" % ((-z) // 3600, (-z) % 3600) + else: + r += "-%02d'%02d'" % (z // 3600, z % 3600) + return pdfRepr(r) + + # A bounding box + elif isinstance(obj, BboxBase): + return fill([pdfRepr(val) for val in obj.bounds]) + + else: + raise TypeError("Don't know a PDF representation for {} objects" + .format(type(obj))) + + +class Reference(object): + """PDF reference object. + Use PdfFile.reserveObject() to create References. + """ + + def __init__(self, id): + self.id = id + + def __repr__(self): + return "" % self.id + + def pdfRepr(self): + return ("%d 0 R" % self.id).encode('ascii') + + def write(self, contents, file): + write = file.write + write(("%d 0 obj\n" % self.id).encode('ascii')) + write(pdfRepr(contents)) + write(b"\nendobj\n") + + +@total_ordering +class Name(object): + """PDF name object.""" + __slots__ = ('name',) + _regex = re.compile(r'[^!-~]') + + def __init__(self, name): + if isinstance(name, Name): + self.name = name.name + else: + if isinstance(name, bytes): + name = name.decode('ascii') + self.name = self._regex.sub(Name.hexify, name).encode('ascii') + + def __repr__(self): + return "" % self.name + + def __str__(self): + return '/' + six.text_type(self.name) + + def __eq__(self, other): + return isinstance(other, Name) and self.name == other.name + + def __lt__(self, other): + return isinstance(other, Name) and self.name < other.name + + def __hash__(self): + return hash(self.name) + + @staticmethod + def hexify(match): + return '#%02x' % ord(match.group()) + + def pdfRepr(self): + return b'/' + self.name + + +class Operator(object): + """PDF operator object.""" + __slots__ = ('op',) + + def __init__(self, op): + self.op = op + + def __repr__(self): + return '' % self.op + + def pdfRepr(self): + return self.op + + +class Verbatim(object): + """Store verbatim PDF command content for later inclusion in the + stream.""" + def __init__(self, x): + self._x = x + + def pdfRepr(self): + return self._x + + +# PDF operators (not an exhaustive list) +_pdfops = dict( + close_fill_stroke=b'b', fill_stroke=b'B', fill=b'f', closepath=b'h', + close_stroke=b's', stroke=b'S', endpath=b'n', begin_text=b'BT', + end_text=b'ET', curveto=b'c', rectangle=b're', lineto=b'l', moveto=b'm', + concat_matrix=b'cm', use_xobject=b'Do', setgray_stroke=b'G', + setgray_nonstroke=b'g', setrgb_stroke=b'RG', setrgb_nonstroke=b'rg', + setcolorspace_stroke=b'CS', setcolorspace_nonstroke=b'cs', + setcolor_stroke=b'SCN', setcolor_nonstroke=b'scn', setdash=b'd', + setlinejoin=b'j', setlinecap=b'J', setgstate=b'gs', gsave=b'q', + grestore=b'Q', textpos=b'Td', selectfont=b'Tf', textmatrix=b'Tm', + show=b'Tj', showkern=b'TJ', setlinewidth=b'w', clip=b'W', shading=b'sh') + +Op = Bunch(**{name: Operator(value) for name, value in six.iteritems(_pdfops)}) + + +def _paint_path(fill, stroke): + """Return the PDF operator to paint a path in the following way: + fill: fill the path with the fill color + stroke: stroke the outline of the path with the line color""" + if stroke: + if fill: + return Op.fill_stroke + else: + return Op.stroke + else: + if fill: + return Op.fill + else: + return Op.endpath +Op.paint_path = _paint_path + + +class Stream(object): + """PDF stream object. + + This has no pdfRepr method. Instead, call begin(), then output the + contents of the stream by calling write(), and finally call end(). + """ + __slots__ = ('id', 'len', 'pdfFile', 'file', 'compressobj', 'extra', 'pos') + + def __init__(self, id, len, file, extra=None, png=None): + """id: object id of stream; len: an unused Reference object for the + length of the stream, or None (to use a memory buffer); file: + a PdfFile; extra: a dictionary of extra key-value pairs to + include in the stream header; png: if the data is already + png compressed, the decode parameters""" + self.id = id # object id + self.len = len # id of length object + self.pdfFile = file + self.file = file.fh # file to which the stream is written + self.compressobj = None # compression object + if extra is None: + self.extra = dict() + else: + self.extra = extra.copy() + if png is not None: + self.extra.update({'Filter': Name('FlateDecode'), + 'DecodeParms': png}) + + self.pdfFile.recordXref(self.id) + if rcParams['pdf.compression'] and not png: + self.compressobj = zlib.compressobj(rcParams['pdf.compression']) + if self.len is None: + self.file = BytesIO() + else: + self._writeHeader() + self.pos = self.file.tell() + + def _writeHeader(self): + write = self.file.write + write(("%d 0 obj\n" % self.id).encode('ascii')) + dict = self.extra + dict['Length'] = self.len + if rcParams['pdf.compression']: + dict['Filter'] = Name('FlateDecode') + + write(pdfRepr(dict)) + write(b"\nstream\n") + + def end(self): + """Finalize stream.""" + + self._flush() + if self.len is None: + contents = self.file.getvalue() + self.len = len(contents) + self.file = self.pdfFile.fh + self._writeHeader() + self.file.write(contents) + self.file.write(b"\nendstream\nendobj\n") + else: + length = self.file.tell() - self.pos + self.file.write(b"\nendstream\nendobj\n") + self.pdfFile.writeObject(self.len, length) + + def write(self, data): + """Write some data on the stream.""" + + if self.compressobj is None: + self.file.write(data) + else: + compressed = self.compressobj.compress(data) + self.file.write(compressed) + + def _flush(self): + """Flush the compression object.""" + + if self.compressobj is not None: + compressed = self.compressobj.flush() + self.file.write(compressed) + self.compressobj = None + + +class PdfFile(object): + """PDF file object.""" + + def __init__(self, filename, metadata=None): + self.nextObject = 1 # next free object id + self.xrefTable = [[0, 65535, 'the zero object']] + self.passed_in_file_object = False + self.original_file_like = None + self.tell_base = 0 + fh, opened = cbook.to_filehandle(filename, "wb", return_opened=True) + if not opened: + try: + self.tell_base = filename.tell() + except IOError: + fh = BytesIO() + self.original_file_like = filename + else: + fh = filename + self.passed_in_file_object = True + + self._core14fontdir = os.path.join( + rcParams['datapath'], 'fonts', 'pdfcorefonts') + self.fh = fh + self.currentstream = None # stream object to write to, if any + fh.write(b"%PDF-1.4\n") # 1.4 is the first version to have alpha + # Output some eight-bit chars as a comment so various utilities + # recognize the file as binary by looking at the first few + # lines (see note in section 3.4.1 of the PDF reference). + fh.write(b"%\254\334 \253\272\n") + + self.rootObject = self.reserveObject('root') + self.pagesObject = self.reserveObject('pages') + self.pageList = [] + self.fontObject = self.reserveObject('fonts') + self.alphaStateObject = self.reserveObject('extended graphics states') + self.hatchObject = self.reserveObject('tiling patterns') + self.gouraudObject = self.reserveObject('Gouraud triangles') + self.XObjectObject = self.reserveObject('external objects') + self.resourceObject = self.reserveObject('resources') + + root = {'Type': Name('Catalog'), + 'Pages': self.pagesObject} + self.writeObject(self.rootObject, root) + + # get source date from SOURCE_DATE_EPOCH, if set + # See https://reproducible-builds.org/specs/source-date-epoch/ + source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") + if source_date_epoch: + source_date = datetime.utcfromtimestamp(int(source_date_epoch)) + source_date = source_date.replace(tzinfo=UTC) + else: + source_date = datetime.today() + + self.infoDict = { + 'Creator': 'matplotlib %s, http://matplotlib.org' % __version__, + 'Producer': 'matplotlib pdf backend %s' % __version__, + 'CreationDate': source_date + } + if metadata is not None: + self.infoDict.update(metadata) + self.infoDict = {k: v for (k, v) in self.infoDict.items() + if v is not None} + + self.fontNames = {} # maps filenames to internal font names + self.nextFont = 1 # next free internal font name + self.dviFontInfo = {} # maps dvi font names to embedding information + self._texFontMap = None # maps TeX font names to PostScript fonts + # differently encoded Type-1 fonts may share the same descriptor + self.type1Descriptors = {} + self.used_characters = {} + + self.alphaStates = {} # maps alpha values to graphics state objects + self.nextAlphaState = 1 + # reproducible writeHatches needs an ordered dict: + self.hatchPatterns = collections.OrderedDict() + self.nextHatch = 1 + self.gouraudTriangles = [] + + self._images = collections.OrderedDict() # reproducible writeImages + self.nextImage = 1 + + self.markers = collections.OrderedDict() # reproducible writeMarkers + self.multi_byte_charprocs = {} + + self.paths = [] + + self.pageAnnotations = [] # A list of annotations for the + # current page + + # The PDF spec recommends to include every procset + procsets = [Name(x) + for x in "PDF Text ImageB ImageC ImageI".split()] + + # Write resource dictionary. + # Possibly TODO: more general ExtGState (graphics state dictionaries) + # ColorSpace Pattern Shading Properties + resources = {'Font': self.fontObject, + 'XObject': self.XObjectObject, + 'ExtGState': self.alphaStateObject, + 'Pattern': self.hatchObject, + 'Shading': self.gouraudObject, + 'ProcSet': procsets} + self.writeObject(self.resourceObject, resources) + + def newPage(self, width, height): + self.endStream() + + self.width, self.height = width, height + contentObject = self.reserveObject('page contents') + thePage = {'Type': Name('Page'), + 'Parent': self.pagesObject, + 'Resources': self.resourceObject, + 'MediaBox': [0, 0, 72 * width, 72 * height], + 'Contents': contentObject, + 'Group': {'Type': Name('Group'), + 'S': Name('Transparency'), + 'CS': Name('DeviceRGB')}, + 'Annots': self.pageAnnotations, + } + pageObject = self.reserveObject('page') + self.writeObject(pageObject, thePage) + self.pageList.append(pageObject) + + self.beginStream(contentObject.id, + self.reserveObject('length of content stream')) + # Initialize the pdf graphics state to match the default mpl + # graphics context: currently only the join style needs to be set + self.output(GraphicsContextPdf.joinstyles['round'], Op.setlinejoin) + + # Clear the list of annotations for the next page + self.pageAnnotations = [] + + def newTextnote(self, text, positionRect=[-100, -100, 0, 0]): + # Create a new annotation of type text + theNote = {'Type': Name('Annot'), + 'Subtype': Name('Text'), + 'Contents': text, + 'Rect': positionRect, + } + annotObject = self.reserveObject('annotation') + self.writeObject(annotObject, theNote) + self.pageAnnotations.append(annotObject) + + def finalize(self): + "Write out the various deferred objects and the pdf end matter." + + self.endStream() + self.writeFonts() + self.writeObject( + self.alphaStateObject, + {val[0]: val[1] for val in six.itervalues(self.alphaStates)}) + self.writeHatches() + self.writeGouraudTriangles() + xobjects = { + name: ob for image, name, ob in six.itervalues(self._images)} + for tup in six.itervalues(self.markers): + xobjects[tup[0]] = tup[1] + for name, value in six.iteritems(self.multi_byte_charprocs): + xobjects[name] = value + for name, path, trans, ob, join, cap, padding, filled, stroked \ + in self.paths: + xobjects[name] = ob + self.writeObject(self.XObjectObject, xobjects) + self.writeImages() + self.writeMarkers() + self.writePathCollectionTemplates() + self.writeObject(self.pagesObject, + {'Type': Name('Pages'), + 'Kids': self.pageList, + 'Count': len(self.pageList)}) + self.writeInfoDict() + + # Finalize the file + self.writeXref() + self.writeTrailer() + + def close(self): + "Flush all buffers and free all resources." + + self.endStream() + if self.passed_in_file_object: + self.fh.flush() + else: + if self.original_file_like is not None: + self.original_file_like.write(self.fh.getvalue()) + self.fh.close() + + def write(self, data): + if self.currentstream is None: + self.fh.write(data) + else: + self.currentstream.write(data) + + def output(self, *data): + self.write(fill([pdfRepr(x) for x in data])) + self.write(b'\n') + + def beginStream(self, id, len, extra=None, png=None): + assert self.currentstream is None + self.currentstream = Stream(id, len, self, extra, png) + + def endStream(self): + if self.currentstream is not None: + self.currentstream.end() + self.currentstream = None + + def fontName(self, fontprop): + """ + Select a font based on fontprop and return a name suitable for + Op.selectfont. If fontprop is a string, it will be interpreted + as the filename of the font. + """ + + if isinstance(fontprop, six.string_types): + filename = fontprop + elif rcParams['pdf.use14corefonts']: + filename = findfont( + fontprop, fontext='afm', directory=self._core14fontdir) + if filename is None: + filename = findfont( + "Helvetica", fontext='afm', directory=self._core14fontdir) + else: + filename = findfont(fontprop) + + Fx = self.fontNames.get(filename) + if Fx is None: + Fx = Name('F%d' % self.nextFont) + self.fontNames[filename] = Fx + self.nextFont += 1 + _log.debug('Assigning font %s = %r', Fx, filename) + + return Fx + + @property + def texFontMap(self): + # lazy-load texFontMap, it takes a while to parse + # and usetex is a relatively rare use case + if self._texFontMap is None: + self._texFontMap = dviread.PsfontsMap( + dviread.find_tex_file('pdftex.map')) + + return self._texFontMap + + def dviFontName(self, dvifont): + """ + Given a dvi font object, return a name suitable for Op.selectfont. + This registers the font information in self.dviFontInfo if not yet + registered. + """ + + dvi_info = self.dviFontInfo.get(dvifont.texname) + if dvi_info is not None: + return dvi_info.pdfname + + psfont = self.texFontMap[dvifont.texname] + if psfont.filename is None: + raise ValueError( + "No usable font file found for {} (TeX: {}); " + "the font may lack a Type-1 version" + .format(psfont.psname, dvifont.texname)) + + pdfname = Name('F%d' % self.nextFont) + self.nextFont += 1 + _log.debug('Assigning font %s = %s (dvi)', pdfname, dvifont.texname) + self.dviFontInfo[dvifont.texname] = Bunch( + dvifont=dvifont, + pdfname=pdfname, + fontfile=psfont.filename, + basefont=psfont.psname, + encodingfile=psfont.encoding, + effects=psfont.effects) + return pdfname + + def writeFonts(self): + fonts = {} + for dviname, info in sorted(self.dviFontInfo.items()): + Fx = info.pdfname + _log.debug('Embedding Type-1 font %s from dvi.', dviname) + fonts[Fx] = self._embedTeXFont(info) + for filename in sorted(self.fontNames): + Fx = self.fontNames[filename] + _log.debug('Embedding font %s.', filename) + if filename.endswith('.afm'): + # from pdf.use14corefonts + _log.debug('Writing AFM font.') + fonts[Fx] = self._write_afm_font(filename) + else: + # a normal TrueType font + _log.debug('Writing TrueType font.') + realpath, stat_key = get_realpath_and_stat(filename) + chars = self.used_characters.get(stat_key) + if chars is not None and len(chars[1]): + fonts[Fx] = self.embedTTF(realpath, chars[1]) + self.writeObject(self.fontObject, fonts) + + def _write_afm_font(self, filename): + with open(filename, 'rb') as fh: + font = AFM(fh) + fontname = font.get_fontname() + fontdict = {'Type': Name('Font'), + 'Subtype': Name('Type1'), + 'BaseFont': Name(fontname), + 'Encoding': Name('WinAnsiEncoding')} + fontdictObject = self.reserveObject('font dictionary') + self.writeObject(fontdictObject, fontdict) + return fontdictObject + + def _embedTeXFont(self, fontinfo): + _log.debug('Embedding TeX font %s - fontinfo=%s', + fontinfo.dvifont.texname, fontinfo.__dict__) + + # Widths + widthsObject = self.reserveObject('font widths') + self.writeObject(widthsObject, fontinfo.dvifont.widths) + + # Font dictionary + fontdictObject = self.reserveObject('font dictionary') + fontdict = { + 'Type': Name('Font'), + 'Subtype': Name('Type1'), + 'FirstChar': 0, + 'LastChar': len(fontinfo.dvifont.widths) - 1, + 'Widths': widthsObject, + } + + # Encoding (if needed) + if fontinfo.encodingfile is not None: + enc = dviread.Encoding(fontinfo.encodingfile) + differencesArray = [Name(ch) for ch in enc] + differencesArray = [0] + differencesArray + fontdict['Encoding'] = \ + {'Type': Name('Encoding'), + 'Differences': differencesArray} + + # If no file is specified, stop short + if fontinfo.fontfile is None: + _log.warning( + "Because of TeX configuration (pdftex.map, see updmap option " + "pdftexDownloadBase14) the font %s is not embedded. This is " + "deprecated as of PDF 1.5 and it may cause the consumer " + "application to show something that was not intended.", + fontinfo.basefont) + fontdict['BaseFont'] = Name(fontinfo.basefont) + self.writeObject(fontdictObject, fontdict) + return fontdictObject + + # We have a font file to embed - read it in and apply any effects + t1font = type1font.Type1Font(fontinfo.fontfile) + if fontinfo.effects: + t1font = t1font.transform(fontinfo.effects) + fontdict['BaseFont'] = Name(t1font.prop['FontName']) + + # Font descriptors may be shared between differently encoded + # Type-1 fonts, so only create a new descriptor if there is no + # existing descriptor for this font. + effects = (fontinfo.effects.get('slant', 0.0), + fontinfo.effects.get('extend', 1.0)) + fontdesc = self.type1Descriptors.get((fontinfo.fontfile, effects)) + if fontdesc is None: + fontdesc = self.createType1Descriptor(t1font, fontinfo.fontfile) + self.type1Descriptors[(fontinfo.fontfile, effects)] = fontdesc + fontdict['FontDescriptor'] = fontdesc + + self.writeObject(fontdictObject, fontdict) + return fontdictObject + + def createType1Descriptor(self, t1font, fontfile): + # Create and write the font descriptor and the font file + # of a Type-1 font + fontdescObject = self.reserveObject('font descriptor') + fontfileObject = self.reserveObject('font file') + + italic_angle = t1font.prop['ItalicAngle'] + fixed_pitch = t1font.prop['isFixedPitch'] + + flags = 0 + # fixed width + if fixed_pitch: + flags |= 1 << 0 + # TODO: serif + if 0: + flags |= 1 << 1 + # TODO: symbolic (most TeX fonts are) + if 1: + flags |= 1 << 2 + # non-symbolic + else: + flags |= 1 << 5 + # italic + if italic_angle: + flags |= 1 << 6 + # TODO: all caps + if 0: + flags |= 1 << 16 + # TODO: small caps + if 0: + flags |= 1 << 17 + # TODO: force bold + if 0: + flags |= 1 << 18 + + ft2font = get_font(fontfile) + + descriptor = { + 'Type': Name('FontDescriptor'), + 'FontName': Name(t1font.prop['FontName']), + 'Flags': flags, + 'FontBBox': ft2font.bbox, + 'ItalicAngle': italic_angle, + 'Ascent': ft2font.ascender, + 'Descent': ft2font.descender, + 'CapHeight': 1000, # TODO: find this out + 'XHeight': 500, # TODO: this one too + 'FontFile': fontfileObject, + 'FontFamily': t1font.prop['FamilyName'], + 'StemV': 50, # TODO + # (see also revision 3874; but not all TeX distros have AFM files!) + # 'FontWeight': a number where 400 = Regular, 700 = Bold + } + + self.writeObject(fontdescObject, descriptor) + + self.beginStream(fontfileObject.id, None, + {'Length1': len(t1font.parts[0]), + 'Length2': len(t1font.parts[1]), + 'Length3': 0}) + self.currentstream.write(t1font.parts[0]) + self.currentstream.write(t1font.parts[1]) + self.endStream() + + return fontdescObject + + def _get_xobject_symbol_name(self, filename, symbol_name): + return "%s-%s" % ( + os.path.splitext(os.path.basename(filename))[0], + symbol_name) + + _identityToUnicodeCMap = """/CIDInit /ProcSet findresource begin +12 dict begin +begincmap +/CIDSystemInfo +<< /Registry (Adobe) + /Ordering (UCS) + /Supplement 0 +>> def +/CMapName /Adobe-Identity-UCS def +/CMapType 2 def +1 begincodespacerange +<0000> +endcodespacerange +%d beginbfrange +%s +endbfrange +endcmap +CMapName currentdict /CMap defineresource pop +end +end""" + + def embedTTF(self, filename, characters): + """Embed the TTF font from the named file into the document.""" + + font = get_font(filename) + fonttype = rcParams['pdf.fonttype'] + + def cvt(length, upe=font.units_per_EM, nearest=True): + "Convert font coordinates to PDF glyph coordinates" + value = length / upe * 1000 + if nearest: + return np.round(value) + # Perhaps best to round away from zero for bounding + # boxes and the like + if value < 0: + return floor(value) + else: + return ceil(value) + + def embedTTFType3(font, characters, descriptor): + """The Type 3-specific part of embedding a Truetype font""" + widthsObject = self.reserveObject('font widths') + fontdescObject = self.reserveObject('font descriptor') + fontdictObject = self.reserveObject('font dictionary') + charprocsObject = self.reserveObject('character procs') + differencesArray = [] + firstchar, lastchar = 0, 255 + bbox = [cvt(x, nearest=False) for x in font.bbox] + + fontdict = { + 'Type': Name('Font'), + 'BaseFont': ps_name, + 'FirstChar': firstchar, + 'LastChar': lastchar, + 'FontDescriptor': fontdescObject, + 'Subtype': Name('Type3'), + 'Name': descriptor['FontName'], + 'FontBBox': bbox, + 'FontMatrix': [.001, 0, 0, .001, 0, 0], + 'CharProcs': charprocsObject, + 'Encoding': { + 'Type': Name('Encoding'), + 'Differences': differencesArray}, + 'Widths': widthsObject + } + + # Make the "Widths" array + from encodings import cp1252 + # The "decoding_map" was changed + # to a "decoding_table" as of Python 2.5. + if hasattr(cp1252, 'decoding_map'): + def decode_char(charcode): + return cp1252.decoding_map[charcode] or 0 + else: + def decode_char(charcode): + return ord(cp1252.decoding_table[charcode]) + + def get_char_width(charcode): + s = decode_char(charcode) + width = font.load_char( + s, flags=LOAD_NO_SCALE | LOAD_NO_HINTING).horiAdvance + return cvt(width) + + widths = [get_char_width(charcode) + for charcode in range(firstchar, lastchar+1)] + descriptor['MaxWidth'] = max(widths) + + # Make the "Differences" array, sort the ccodes < 255 from + # the multi-byte ccodes, and build the whole set of glyph ids + # that we need from this font. + glyph_ids = [] + differences = [] + multi_byte_chars = set() + for c in characters: + ccode = c + gind = font.get_char_index(ccode) + glyph_ids.append(gind) + glyph_name = font.get_glyph_name(gind) + if ccode <= 255: + differences.append((ccode, glyph_name)) + else: + multi_byte_chars.add(glyph_name) + differences.sort() + + last_c = -2 + for c, name in differences: + if c != last_c + 1: + differencesArray.append(c) + differencesArray.append(Name(name)) + last_c = c + + # Make the charprocs array (using ttconv to generate the + # actual outlines) + rawcharprocs = ttconv.get_pdf_charprocs( + filename.encode(sys.getfilesystemencoding()), glyph_ids) + charprocs = {} + for charname in sorted(rawcharprocs): + stream = rawcharprocs[charname] + charprocDict = {'Length': len(stream)} + # The 2-byte characters are used as XObjects, so they + # need extra info in their dictionary + if charname in multi_byte_chars: + charprocDict['Type'] = Name('XObject') + charprocDict['Subtype'] = Name('Form') + charprocDict['BBox'] = bbox + # Each glyph includes bounding box information, + # but xpdf and ghostscript can't handle it in a + # Form XObject (they segfault!!!), so we remove it + # from the stream here. It's not needed anyway, + # since the Form XObject includes it in its BBox + # value. + stream = stream[stream.find(b"d1") + 2:] + charprocObject = self.reserveObject('charProc') + self.beginStream(charprocObject.id, None, charprocDict) + self.currentstream.write(stream) + self.endStream() + + # Send the glyphs with ccode > 255 to the XObject dictionary, + # and the others to the font itself + if charname in multi_byte_chars: + name = self._get_xobject_symbol_name(filename, charname) + self.multi_byte_charprocs[name] = charprocObject + else: + charprocs[charname] = charprocObject + + # Write everything out + self.writeObject(fontdictObject, fontdict) + self.writeObject(fontdescObject, descriptor) + self.writeObject(widthsObject, widths) + self.writeObject(charprocsObject, charprocs) + + return fontdictObject + + def embedTTFType42(font, characters, descriptor): + """The Type 42-specific part of embedding a Truetype font""" + fontdescObject = self.reserveObject('font descriptor') + cidFontDictObject = self.reserveObject('CID font dictionary') + type0FontDictObject = self.reserveObject('Type 0 font dictionary') + cidToGidMapObject = self.reserveObject('CIDToGIDMap stream') + fontfileObject = self.reserveObject('font file stream') + wObject = self.reserveObject('Type 0 widths') + toUnicodeMapObject = self.reserveObject('ToUnicode map') + + cidFontDict = { + 'Type': Name('Font'), + 'Subtype': Name('CIDFontType2'), + 'BaseFont': ps_name, + 'CIDSystemInfo': { + 'Registry': 'Adobe', + 'Ordering': 'Identity', + 'Supplement': 0}, + 'FontDescriptor': fontdescObject, + 'W': wObject, + 'CIDToGIDMap': cidToGidMapObject + } + + type0FontDict = { + 'Type': Name('Font'), + 'Subtype': Name('Type0'), + 'BaseFont': ps_name, + 'Encoding': Name('Identity-H'), + 'DescendantFonts': [cidFontDictObject], + 'ToUnicode': toUnicodeMapObject + } + + # Make fontfile stream + descriptor['FontFile2'] = fontfileObject + length1Object = self.reserveObject('decoded length of a font') + self.beginStream( + fontfileObject.id, + self.reserveObject('length of font stream'), + {'Length1': length1Object}) + with open(filename, 'rb') as fontfile: + length1 = 0 + while True: + data = fontfile.read(4096) + if not data: + break + length1 += len(data) + self.currentstream.write(data) + self.endStream() + self.writeObject(length1Object, length1) + + # Make the 'W' (Widths) array, CidToGidMap and ToUnicode CMap + # at the same time + cid_to_gid_map = ['\0'] * 65536 + widths = [] + max_ccode = 0 + for c in characters: + ccode = c + gind = font.get_char_index(ccode) + glyph = font.load_char(ccode, + flags=LOAD_NO_SCALE | LOAD_NO_HINTING) + widths.append((ccode, cvt(glyph.horiAdvance))) + if ccode < 65536: + cid_to_gid_map[ccode] = unichr(gind) + max_ccode = max(ccode, max_ccode) + widths.sort() + cid_to_gid_map = cid_to_gid_map[:max_ccode + 1] + + last_ccode = -2 + w = [] + max_width = 0 + unicode_groups = [] + for ccode, width in widths: + if ccode != last_ccode + 1: + w.append(ccode) + w.append([width]) + unicode_groups.append([ccode, ccode]) + else: + w[-1].append(width) + unicode_groups[-1][1] = ccode + max_width = max(max_width, width) + last_ccode = ccode + + unicode_bfrange = [] + for start, end in unicode_groups: + unicode_bfrange.append( + "<%04x> <%04x> [%s]" % + (start, end, + " ".join(["<%04x>" % x for x in range(start, end+1)]))) + unicode_cmap = (self._identityToUnicodeCMap % + (len(unicode_groups), + "\n".join(unicode_bfrange))).encode('ascii') + + # CIDToGIDMap stream + cid_to_gid_map = "".join(cid_to_gid_map).encode("utf-16be") + self.beginStream(cidToGidMapObject.id, + None, + {'Length': len(cid_to_gid_map)}) + self.currentstream.write(cid_to_gid_map) + self.endStream() + + # ToUnicode CMap + self.beginStream(toUnicodeMapObject.id, + None, + {'Length': unicode_cmap}) + self.currentstream.write(unicode_cmap) + self.endStream() + + descriptor['MaxWidth'] = max_width + + # Write everything out + self.writeObject(cidFontDictObject, cidFontDict) + self.writeObject(type0FontDictObject, type0FontDict) + self.writeObject(fontdescObject, descriptor) + self.writeObject(wObject, w) + + return type0FontDictObject + + # Beginning of main embedTTF function... + + # You are lost in a maze of TrueType tables, all different... + sfnt = font.get_sfnt() + try: + ps_name = sfnt[1, 0, 0, 6].decode('mac_roman') # Macintosh scheme + except KeyError: + # Microsoft scheme: + ps_name = sfnt[3, 1, 0x0409, 6].decode('utf-16be') + # (see freetype/ttnameid.h) + ps_name = ps_name.encode('ascii', 'replace') + ps_name = Name(ps_name) + pclt = font.get_sfnt_table('pclt') or {'capHeight': 0, 'xHeight': 0} + post = font.get_sfnt_table('post') or {'italicAngle': (0, 0)} + ff = font.face_flags + sf = font.style_flags + + flags = 0 + symbolic = False # ps_name.name in ('Cmsy10', 'Cmmi10', 'Cmex10') + if ff & FIXED_WIDTH: + flags |= 1 << 0 + if 0: # TODO: serif + flags |= 1 << 1 + if symbolic: + flags |= 1 << 2 + else: + flags |= 1 << 5 + if sf & ITALIC: + flags |= 1 << 6 + if 0: # TODO: all caps + flags |= 1 << 16 + if 0: # TODO: small caps + flags |= 1 << 17 + if 0: # TODO: force bold + flags |= 1 << 18 + + descriptor = { + 'Type': Name('FontDescriptor'), + 'FontName': ps_name, + 'Flags': flags, + 'FontBBox': [cvt(x, nearest=False) for x in font.bbox], + 'Ascent': cvt(font.ascender, nearest=False), + 'Descent': cvt(font.descender, nearest=False), + 'CapHeight': cvt(pclt['capHeight'], nearest=False), + 'XHeight': cvt(pclt['xHeight']), + 'ItalicAngle': post['italicAngle'][1], # ??? + 'StemV': 0 # ??? + } + + # The font subsetting to a Type 3 font does not work for + # OpenType (.otf) that embed a Postscript CFF font, so avoid that -- + # save as a (non-subsetted) Type 42 font instead. + if is_opentype_cff_font(filename): + fonttype = 42 + _log.warning("%r can not be subsetted into a Type 3 font. The " + "entire font will be embedded in the output.", + os.path.basename(filename)) + + if fonttype == 3: + return embedTTFType3(font, characters, descriptor) + elif fonttype == 42: + return embedTTFType42(font, characters, descriptor) + + def alphaState(self, alpha): + """Return name of an ExtGState that sets alpha to the given value.""" + + state = self.alphaStates.get(alpha, None) + if state is not None: + return state[0] + + name = Name('A%d' % self.nextAlphaState) + self.nextAlphaState += 1 + self.alphaStates[alpha] = \ + (name, {'Type': Name('ExtGState'), + 'CA': alpha[0], 'ca': alpha[1]}) + return name + + def hatchPattern(self, hatch_style): + # The colors may come in as numpy arrays, which aren't hashable + if hatch_style is not None: + edge, face, hatch = hatch_style + if edge is not None: + edge = tuple(edge) + if face is not None: + face = tuple(face) + hatch_style = (edge, face, hatch) + + pattern = self.hatchPatterns.get(hatch_style, None) + if pattern is not None: + return pattern + + name = Name('H%d' % self.nextHatch) + self.nextHatch += 1 + self.hatchPatterns[hatch_style] = name + return name + + def writeHatches(self): + hatchDict = dict() + sidelen = 72.0 + for hatch_style, name in six.iteritems(self.hatchPatterns): + ob = self.reserveObject('hatch pattern') + hatchDict[name] = ob + res = {'Procsets': + [Name(x) for x in "PDF Text ImageB ImageC ImageI".split()]} + self.beginStream( + ob.id, None, + {'Type': Name('Pattern'), + 'PatternType': 1, 'PaintType': 1, 'TilingType': 1, + 'BBox': [0, 0, sidelen, sidelen], + 'XStep': sidelen, 'YStep': sidelen, + 'Resources': res, + # Change origin to match Agg at top-left. + 'Matrix': [1, 0, 0, 1, 0, self.height * 72]}) + + stroke_rgb, fill_rgb, path = hatch_style + self.output(stroke_rgb[0], stroke_rgb[1], stroke_rgb[2], + Op.setrgb_stroke) + if fill_rgb is not None: + self.output(fill_rgb[0], fill_rgb[1], fill_rgb[2], + Op.setrgb_nonstroke, + 0, 0, sidelen, sidelen, Op.rectangle, + Op.fill) + + self.output(rcParams['hatch.linewidth'], Op.setlinewidth) + + self.output(*self.pathOperations( + Path.hatch(path), + Affine2D().scale(sidelen), + simplify=False)) + self.output(Op.fill_stroke) + + self.endStream() + self.writeObject(self.hatchObject, hatchDict) + + def addGouraudTriangles(self, points, colors): + name = Name('GT%d' % len(self.gouraudTriangles)) + self.gouraudTriangles.append((name, points, colors)) + return name + + def writeGouraudTriangles(self): + gouraudDict = dict() + for name, points, colors in self.gouraudTriangles: + ob = self.reserveObject('Gouraud triangle') + gouraudDict[name] = ob + shape = points.shape + flat_points = points.reshape((shape[0] * shape[1], 2)) + flat_colors = colors.reshape((shape[0] * shape[1], 4)) + points_min = np.min(flat_points, axis=0) - (1 << 8) + points_max = np.max(flat_points, axis=0) + (1 << 8) + factor = 0xffffffff / (points_max - points_min) + + self.beginStream( + ob.id, None, + {'ShadingType': 4, + 'BitsPerCoordinate': 32, + 'BitsPerComponent': 8, + 'BitsPerFlag': 8, + 'ColorSpace': Name('DeviceRGB'), + 'AntiAlias': True, + 'Decode': [points_min[0], points_max[0], + points_min[1], points_max[1], + 0, 1, 0, 1, 0, 1] + }) + + streamarr = np.empty( + (shape[0] * shape[1],), + dtype=[(str('flags'), str('u1')), + (str('points'), str('>u4'), (2,)), + (str('colors'), str('u1'), (3,))]) + streamarr['flags'] = 0 + streamarr['points'] = (flat_points - points_min) * factor + streamarr['colors'] = flat_colors[:, :3] * 255.0 + + self.write(streamarr.tostring()) + self.endStream() + self.writeObject(self.gouraudObject, gouraudDict) + + def imageObject(self, image): + """Return name of an image XObject representing the given image.""" + + entry = self._images.get(id(image), None) + if entry is not None: + return entry[1] + + name = Name('I%d' % self.nextImage) + ob = self.reserveObject('image %d' % self.nextImage) + self.nextImage += 1 + self._images[id(image)] = (image, name, ob) + return name + + def _unpack(self, im): + """ + Unpack the image object im into height, width, data, alpha, + where data and alpha are HxWx3 (RGB) or HxWx1 (grayscale or alpha) + arrays, except alpha is None if the image is fully opaque. + """ + h, w = im.shape[:2] + im = im[::-1] + if im.ndim == 2: + return h, w, im, None + else: + rgb = im[:, :, :3] + rgb = np.array(rgb, order='C') + # PDF needs a separate alpha image + if im.shape[2] == 4: + alpha = im[:, :, 3][..., None] + if np.all(alpha == 255): + alpha = None + else: + alpha = np.array(alpha, order='C') + else: + alpha = None + return h, w, rgb, alpha + + def _writePng(self, data): + """ + Write the image *data* into the pdf file using png + predictors with Flate compression. + """ + + buffer = BytesIO() + _png.write_png(data, buffer) + buffer.seek(8) + written = 0 + header = bytearray(8) + while True: + n = buffer.readinto(header) + assert n == 8 + length, type = struct.unpack(b'!L4s', bytes(header)) + if type == b'IDAT': + data = bytearray(length) + n = buffer.readinto(data) + assert n == length + self.currentstream.write(bytes(data)) + written += n + elif type == b'IEND': + break + else: + buffer.seek(length, 1) + buffer.seek(4, 1) # skip CRC + + def _writeImg(self, data, height, width, grayscale, id, smask=None): + """ + Write the image *data* of size *height* x *width*, as grayscale + if *grayscale* is true and RGB otherwise, as pdf object *id* + and with the soft mask (alpha channel) *smask*, which should be + either None or a *height* x *width* x 1 array. + """ + + obj = {'Type': Name('XObject'), + 'Subtype': Name('Image'), + 'Width': width, + 'Height': height, + 'ColorSpace': Name('DeviceGray' if grayscale + else 'DeviceRGB'), + 'BitsPerComponent': 8} + if smask: + obj['SMask'] = smask + if rcParams['pdf.compression']: + png = {'Predictor': 10, + 'Colors': 1 if grayscale else 3, + 'Columns': width} + else: + png = None + self.beginStream( + id, + self.reserveObject('length of image stream'), + obj, + png=png + ) + if png: + self._writePng(data) + else: + self.currentstream.write(data.tostring()) + self.endStream() + + def writeImages(self): + for img, name, ob in six.itervalues(self._images): + height, width, data, adata = self._unpack(img) + if adata is not None: + smaskObject = self.reserveObject("smask") + self._writeImg(adata, height, width, True, smaskObject.id) + else: + smaskObject = None + self._writeImg(data, height, width, False, + ob.id, smaskObject) + + def markerObject(self, path, trans, fill, stroke, lw, joinstyle, + capstyle): + """Return name of a marker XObject representing the given path.""" + # self.markers used by markerObject, writeMarkers, close: + # mapping from (path operations, fill?, stroke?) to + # [name, object reference, bounding box, linewidth] + # This enables different draw_markers calls to share the XObject + # if the gc is sufficiently similar: colors etc can vary, but + # the choices of whether to fill and whether to stroke cannot. + # We need a bounding box enclosing all of the XObject path, + # but since line width may vary, we store the maximum of all + # occurring line widths in self.markers. + # close() is somewhat tightly coupled in that it expects the + # first two components of each value in self.markers to be the + # name and object reference. + pathops = self.pathOperations(path, trans, simplify=False) + key = (tuple(pathops), bool(fill), bool(stroke), joinstyle, capstyle) + result = self.markers.get(key) + if result is None: + name = Name('M%d' % len(self.markers)) + ob = self.reserveObject('marker %d' % len(self.markers)) + bbox = path.get_extents(trans) + self.markers[key] = [name, ob, bbox, lw] + else: + if result[-1] < lw: + result[-1] = lw + name = result[0] + return name + + def writeMarkers(self): + for ((pathops, fill, stroke, joinstyle, capstyle), + (name, ob, bbox, lw)) in six.iteritems(self.markers): + bbox = bbox.padded(lw * 0.5) + self.beginStream( + ob.id, None, + {'Type': Name('XObject'), 'Subtype': Name('Form'), + 'BBox': list(bbox.extents)}) + self.output(GraphicsContextPdf.joinstyles[joinstyle], + Op.setlinejoin) + self.output(GraphicsContextPdf.capstyles[capstyle], Op.setlinecap) + self.output(*pathops) + self.output(Op.paint_path(fill, stroke)) + self.endStream() + + def pathCollectionObject(self, gc, path, trans, padding, filled, stroked): + name = Name('P%d' % len(self.paths)) + ob = self.reserveObject('path %d' % len(self.paths)) + self.paths.append( + (name, path, trans, ob, gc.get_joinstyle(), gc.get_capstyle(), + padding, filled, stroked)) + return name + + def writePathCollectionTemplates(self): + for (name, path, trans, ob, joinstyle, capstyle, padding, filled, + stroked) in self.paths: + pathops = self.pathOperations(path, trans, simplify=False) + bbox = path.get_extents(trans) + if not np.all(np.isfinite(bbox.extents)): + extents = [0, 0, 0, 0] + else: + bbox = bbox.padded(padding) + extents = list(bbox.extents) + self.beginStream( + ob.id, None, + {'Type': Name('XObject'), 'Subtype': Name('Form'), + 'BBox': extents}) + self.output(GraphicsContextPdf.joinstyles[joinstyle], + Op.setlinejoin) + self.output(GraphicsContextPdf.capstyles[capstyle], Op.setlinecap) + self.output(*pathops) + self.output(Op.paint_path(filled, stroked)) + self.endStream() + + @staticmethod + def pathOperations(path, transform, clip=None, simplify=None, sketch=None): + return [Verbatim(_path.convert_to_string( + path, transform, clip, simplify, sketch, + 6, + [Op.moveto.op, Op.lineto.op, b'', Op.curveto.op, Op.closepath.op], + True))] + + def writePath(self, path, transform, clip=False, sketch=None): + if clip: + clip = (0.0, 0.0, self.width * 72, self.height * 72) + simplify = path.should_simplify + else: + clip = None + simplify = False + cmds = self.pathOperations(path, transform, clip, simplify=simplify, + sketch=sketch) + self.output(*cmds) + + def reserveObject(self, name=''): + """Reserve an ID for an indirect object. + The name is used for debugging in case we forget to print out + the object with writeObject. + """ + + id = self.nextObject + self.nextObject += 1 + self.xrefTable.append([None, 0, name]) + return Reference(id) + + def recordXref(self, id): + self.xrefTable[id][0] = self.fh.tell() - self.tell_base + + def writeObject(self, object, contents): + self.recordXref(object.id) + object.write(contents, self) + + def writeXref(self): + """Write out the xref table.""" + + self.startxref = self.fh.tell() - self.tell_base + self.write(("xref\n0 %d\n" % self.nextObject).encode('ascii')) + i = 0 + borken = False + for offset, generation, name in self.xrefTable: + if offset is None: + print('No offset for object %d (%s)' % (i, name), + file=sys.stderr) + borken = True + else: + if name == 'the zero object': + key = "f" + else: + key = "n" + text = "%010d %05d %s \n" % (offset, generation, key) + self.write(text.encode('ascii')) + i += 1 + if borken: + raise AssertionError('Indirect object does not exist') + + def writeInfoDict(self): + """Write out the info dictionary, checking it for good form""" + + def is_string_like(x): + return isinstance(x, six.string_types) + + def is_date(x): + return isinstance(x, datetime) + + check_trapped = (lambda x: isinstance(x, Name) and + x.name in ('True', 'False', 'Unknown')) + + keywords = {'Title': is_string_like, + 'Author': is_string_like, + 'Subject': is_string_like, + 'Keywords': is_string_like, + 'Creator': is_string_like, + 'Producer': is_string_like, + 'CreationDate': is_date, + 'ModDate': is_date, + 'Trapped': check_trapped} + for k in self.infoDict: + if k not in keywords: + warnings.warn('Unknown infodict keyword: %s' % k) + else: + if not keywords[k](self.infoDict[k]): + warnings.warn('Bad value for infodict keyword %s' % k) + + self.infoObject = self.reserveObject('info') + self.writeObject(self.infoObject, self.infoDict) + + def writeTrailer(self): + """Write out the PDF trailer.""" + + self.write(b"trailer\n") + self.write(pdfRepr( + {'Size': self.nextObject, + 'Root': self.rootObject, + 'Info': self.infoObject})) + # Could add 'ID' + self.write(("\nstartxref\n%d\n%%%%EOF\n" % + self.startxref).encode('ascii')) + + +class RendererPdf(RendererBase): + afm_font_cache = maxdict(50) + + def __init__(self, file, image_dpi, height, width): + RendererBase.__init__(self) + self.height = height + self.width = width + self.file = file + self.gc = self.new_gc() + self.mathtext_parser = MathTextParser("Pdf") + self.image_dpi = image_dpi + + def finalize(self): + self.file.output(*self.gc.finalize()) + + def check_gc(self, gc, fillcolor=None): + orig_fill = getattr(gc, '_fillcolor', (0., 0., 0.)) + gc._fillcolor = fillcolor + + orig_alphas = getattr(gc, '_effective_alphas', (1.0, 1.0)) + + if gc.get_rgb() is None: + # it should not matter what color here + # since linewidth should be 0 + # unless affected by global settings in rcParams + # hence setting zero alpha just incase + gc.set_foreground((0, 0, 0, 0), isRGBA=True) + + if gc._forced_alpha: + gc._effective_alphas = (gc._alpha, gc._alpha) + elif fillcolor is None or len(fillcolor) < 4: + gc._effective_alphas = (gc._rgb[3], 1.0) + else: + gc._effective_alphas = (gc._rgb[3], fillcolor[3]) + + delta = self.gc.delta(gc) + if delta: + self.file.output(*delta) + + # Restore gc to avoid unwanted side effects + gc._fillcolor = orig_fill + gc._effective_alphas = orig_alphas + + def track_characters(self, font, s): + """Keeps track of which characters are required from + each font.""" + if isinstance(font, six.string_types): + fname = font + else: + fname = font.fname + realpath, stat_key = get_realpath_and_stat(fname) + used_characters = self.file.used_characters.setdefault( + stat_key, (realpath, set())) + used_characters[1].update([ord(x) for x in s]) + + def merge_used_characters(self, other): + for stat_key, (realpath, charset) in six.iteritems(other): + used_characters = self.file.used_characters.setdefault( + stat_key, (realpath, set())) + used_characters[1].update(charset) + + def get_image_magnification(self): + return self.image_dpi/72.0 + + def option_scale_image(self): + """ + pdf backend support arbitrary scaling of image. + """ + return True + + def option_image_nocomposite(self): + """ + return whether to generate a composite image from multiple images on + a set of axes + """ + return not rcParams['image.composite_image'] + + def draw_image(self, gc, x, y, im, transform=None): + h, w = im.shape[:2] + if w == 0 or h == 0: + return + + if transform is None: + # If there's no transform, alpha has already been applied + gc.set_alpha(1.0) + + self.check_gc(gc) + + w = 72.0 * w / self.image_dpi + h = 72.0 * h / self.image_dpi + + imob = self.file.imageObject(im) + + if transform is None: + self.file.output(Op.gsave, + w, 0, 0, h, x, y, Op.concat_matrix, + imob, Op.use_xobject, Op.grestore) + else: + tr1, tr2, tr3, tr4, tr5, tr6 = transform.frozen().to_values() + + self.file.output(Op.gsave, + 1, 0, 0, 1, x, y, Op.concat_matrix, + tr1, tr2, tr3, tr4, tr5, tr6, Op.concat_matrix, + imob, Op.use_xobject, Op.grestore) + + def draw_path(self, gc, path, transform, rgbFace=None): + self.check_gc(gc, rgbFace) + self.file.writePath( + path, transform, + rgbFace is None and gc.get_hatch_path() is None, + gc.get_sketch_params()) + self.file.output(self.gc.paint()) + + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position): + # We can only reuse the objects if the presence of fill and + # stroke (and the amount of alpha for each) is the same for + # all of them + can_do_optimization = True + facecolors = np.asarray(facecolors) + edgecolors = np.asarray(edgecolors) + + if not len(facecolors): + filled = False + can_do_optimization = not gc.get_hatch() + else: + if np.all(facecolors[:, 3] == facecolors[0, 3]): + filled = facecolors[0, 3] != 0.0 + else: + can_do_optimization = False + + if not len(edgecolors): + stroked = False + else: + if np.all(np.asarray(linewidths) == 0.0): + stroked = False + elif np.all(edgecolors[:, 3] == edgecolors[0, 3]): + stroked = edgecolors[0, 3] != 0.0 + else: + can_do_optimization = False + + # Is the optimization worth it? Rough calculation: + # cost of emitting a path in-line is len_path * uses_per_path + # cost of XObject is len_path + 5 for the definition, + # uses_per_path for the uses + len_path = len(paths[0].vertices) if len(paths) > 0 else 0 + uses_per_path = self._iter_collection_uses_per_path( + paths, all_transforms, offsets, facecolors, edgecolors) + should_do_optimization = \ + len_path + uses_per_path + 5 < len_path * uses_per_path + + if (not can_do_optimization) or (not should_do_optimization): + return RendererBase.draw_path_collection( + self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position) + + padding = np.max(linewidths) + path_codes = [] + for i, (path, transform) in enumerate(self._iter_collection_raw_paths( + master_transform, paths, all_transforms)): + name = self.file.pathCollectionObject( + gc, path, transform, padding, filled, stroked) + path_codes.append(name) + + output = self.file.output + output(*self.gc.push()) + lastx, lasty = 0, 0 + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, master_transform, all_transforms, path_codes, offsets, + offsetTrans, facecolors, edgecolors, linewidths, linestyles, + antialiaseds, urls, offset_position): + + self.check_gc(gc0, rgbFace) + dx, dy = xo - lastx, yo - lasty + output(1, 0, 0, 1, dx, dy, Op.concat_matrix, path_id, + Op.use_xobject) + lastx, lasty = xo, yo + output(*self.gc.pop()) + + def draw_markers(self, gc, marker_path, marker_trans, path, trans, + rgbFace=None): + # Same logic as in draw_path_collection + len_marker_path = len(marker_path) + uses = len(path) + if len_marker_path * uses < len_marker_path + uses + 5: + RendererBase.draw_markers(self, gc, marker_path, marker_trans, + path, trans, rgbFace) + return + + self.check_gc(gc, rgbFace) + fill = gc.fill(rgbFace) + stroke = gc.stroke() + + output = self.file.output + marker = self.file.markerObject( + marker_path, marker_trans, fill, stroke, self.gc._linewidth, + gc.get_joinstyle(), gc.get_capstyle()) + + output(Op.gsave) + lastx, lasty = 0, 0 + for vertices, code in path.iter_segments( + trans, + clip=(0, 0, self.file.width*72, self.file.height*72), + simplify=False): + if len(vertices): + x, y = vertices[-2:] + if (x < 0 or y < 0 or + x > self.file.width * 72 or y > self.file.height * 72): + continue + dx, dy = x - lastx, y - lasty + output(1, 0, 0, 1, dx, dy, Op.concat_matrix, + marker, Op.use_xobject) + lastx, lasty = x, y + output(Op.grestore) + + def draw_gouraud_triangle(self, gc, points, colors, trans): + self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), + colors.reshape((1, 3, 4)), trans) + + def draw_gouraud_triangles(self, gc, points, colors, trans): + assert len(points) == len(colors) + assert points.ndim == 3 + assert points.shape[1] == 3 + assert points.shape[2] == 2 + assert colors.ndim == 3 + assert colors.shape[1] == 3 + assert colors.shape[2] == 4 + + shape = points.shape + points = points.reshape((shape[0] * shape[1], 2)) + tpoints = trans.transform(points) + tpoints = tpoints.reshape(shape) + name = self.file.addGouraudTriangles(tpoints, colors) + self.check_gc(gc) + self.file.output(name, Op.shading) + + def _setup_textpos(self, x, y, angle, oldx=0, oldy=0, oldangle=0): + if angle == oldangle == 0: + self.file.output(x - oldx, y - oldy, Op.textpos) + else: + angle = angle / 180.0 * pi + self.file.output(cos(angle), sin(angle), + -sin(angle), cos(angle), + x, y, Op.textmatrix) + self.file.output(0, 0, Op.textpos) + + def draw_mathtext(self, gc, x, y, s, prop, angle): + # TODO: fix positioning and encoding + width, height, descent, glyphs, rects, used_characters = \ + self.mathtext_parser.parse(s, 72, prop) + self.merge_used_characters(used_characters) + + # When using Type 3 fonts, we can't use character codes higher + # than 255, so we use the "Do" command to render those + # instead. + global_fonttype = rcParams['pdf.fonttype'] + + # Set up a global transformation matrix for the whole math expression + a = angle / 180.0 * pi + self.file.output(Op.gsave) + self.file.output(cos(a), sin(a), -sin(a), cos(a), x, y, + Op.concat_matrix) + + self.check_gc(gc, gc._rgb) + self.file.output(Op.begin_text) + prev_font = None, None + oldx, oldy = 0, 0 + for ox, oy, fontname, fontsize, num, symbol_name in glyphs: + if is_opentype_cff_font(fontname): + fonttype = 42 + else: + fonttype = global_fonttype + + if fonttype == 42 or num <= 255: + self._setup_textpos(ox, oy, 0, oldx, oldy) + oldx, oldy = ox, oy + if (fontname, fontsize) != prev_font: + self.file.output(self.file.fontName(fontname), fontsize, + Op.selectfont) + prev_font = fontname, fontsize + self.file.output(self.encode_string(unichr(num), fonttype), + Op.show) + self.file.output(Op.end_text) + + # If using Type 3 fonts, render all of the multi-byte characters + # as XObjects using the 'Do' command. + if global_fonttype == 3: + for ox, oy, fontname, fontsize, num, symbol_name in glyphs: + if is_opentype_cff_font(fontname): + fonttype = 42 + else: + fonttype = global_fonttype + + if fonttype == 3 and num > 255: + self.file.fontName(fontname) + self.file.output(Op.gsave, + 0.001 * fontsize, 0, + 0, 0.001 * fontsize, + ox, oy, Op.concat_matrix) + name = self.file._get_xobject_symbol_name( + fontname, symbol_name) + self.file.output(Name(name), Op.use_xobject) + self.file.output(Op.grestore) + + # Draw any horizontal lines in the math layout + for ox, oy, width, height in rects: + self.file.output(Op.gsave, ox, oy, width, height, + Op.rectangle, Op.fill, Op.grestore) + + # Pop off the global transformation + self.file.output(Op.grestore) + + def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None): + texmanager = self.get_texmanager() + fontsize = prop.get_size_in_points() + dvifile = texmanager.make_dvi(s, fontsize) + with dviread.Dvi(dvifile, 72) as dvi: + page = next(iter(dvi)) + + # Gather font information and do some setup for combining + # characters into strings. The variable seq will contain a + # sequence of font and text entries. A font entry is a list + # ['font', name, size] where name is a Name object for the + # font. A text entry is ['text', x, y, glyphs, x+w] where x + # and y are the starting coordinates, w is the width, and + # glyphs is a list; in this phase it will always contain just + # one one-character string, but later it may have longer + # strings interspersed with kern amounts. + oldfont, seq = None, [] + for x1, y1, dvifont, glyph, width in page.text: + if dvifont != oldfont: + pdfname = self.file.dviFontName(dvifont) + seq += [['font', pdfname, dvifont.size]] + oldfont = dvifont + # We need to convert the glyph numbers to bytes, and the easiest + # way to do this on both Python 2 and 3 is .encode('latin-1') + seq += [['text', x1, y1, + [six.unichr(glyph).encode('latin-1')], x1+width]] + + # Find consecutive text strings with constant y coordinate and + # combine into a sequence of strings and kerns, or just one + # string (if any kerns would be less than 0.1 points). + i, curx, fontsize = 0, 0, None + while i < len(seq)-1: + elt, nxt = seq[i:i+2] + if elt[0] == 'font': + fontsize = elt[2] + elif elt[0] == nxt[0] == 'text' and elt[2] == nxt[2]: + offset = elt[4] - nxt[1] + if abs(offset) < 0.1: + elt[3][-1] += nxt[3][0] + elt[4] += nxt[4]-nxt[1] + else: + elt[3] += [offset*1000.0/fontsize, nxt[3][0]] + elt[4] = nxt[4] + del seq[i+1] + continue + i += 1 + + # Create a transform to map the dvi contents to the canvas. + mytrans = Affine2D().rotate_deg(angle).translate(x, y) + + # Output the text. + self.check_gc(gc, gc._rgb) + self.file.output(Op.begin_text) + curx, cury, oldx, oldy = 0, 0, 0, 0 + for elt in seq: + if elt[0] == 'font': + self.file.output(elt[1], elt[2], Op.selectfont) + elif elt[0] == 'text': + curx, cury = mytrans.transform_point((elt[1], elt[2])) + self._setup_textpos(curx, cury, angle, oldx, oldy) + oldx, oldy = curx, cury + if len(elt[3]) == 1: + self.file.output(elt[3][0], Op.show) + else: + self.file.output(elt[3], Op.showkern) + else: + assert False + self.file.output(Op.end_text) + + # Then output the boxes (e.g., variable-length lines of square + # roots). + boxgc = self.new_gc() + boxgc.copy_properties(gc) + boxgc.set_linewidth(0) + pathops = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.LINETO, + Path.CLOSEPOLY] + for x1, y1, h, w in page.boxes: + path = Path([[x1, y1], [x1+w, y1], [x1+w, y1+h], [x1, y1+h], + [0, 0]], pathops) + self.draw_path(boxgc, path, mytrans, gc._rgb) + + def encode_string(self, s, fonttype): + if fonttype in (1, 3): + return s.encode('cp1252', 'replace') + return s.encode('utf-16be', 'replace') + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + # TODO: combine consecutive texts into one BT/ET delimited section + + # This function is rather complex, since there is no way to + # access characters of a Type 3 font with codes > 255. (Type + # 3 fonts can not have a CIDMap). Therefore, we break the + # string into chunks, where each chunk contains exclusively + # 1-byte or exclusively 2-byte characters, and output each + # chunk a separate command. 1-byte characters use the regular + # text show command (Tj), whereas 2-byte characters use the + # use XObject command (Do). If using Type 42 fonts, all of + # this complication is avoided, but of course, those fonts can + # not be subsetted. + + self.check_gc(gc, gc._rgb) + if ismath: + return self.draw_mathtext(gc, x, y, s, prop, angle) + + fontsize = prop.get_size_in_points() + + if rcParams['pdf.use14corefonts']: + font = self._get_font_afm(prop) + l, b, w, h = font.get_str_bbox(s) + fonttype = 1 + else: + font = self._get_font_ttf(prop) + self.track_characters(font, s) + font.set_text(s, 0.0, flags=LOAD_NO_HINTING) + + fonttype = rcParams['pdf.fonttype'] + + # We can't subset all OpenType fonts, so switch to Type 42 + # in that case. + if is_opentype_cff_font(font.fname): + fonttype = 42 + + def check_simple_method(s): + """Determine if we should use the simple or woven method + to output this text, and chunks the string into 1-byte and + 2-byte sections if necessary.""" + use_simple_method = True + chunks = [] + + if not rcParams['pdf.use14corefonts']: + if fonttype == 3 and not isinstance(s, bytes) and len(s) != 0: + # Break the string into chunks where each chunk is either + # a string of chars <= 255, or a single character > 255. + s = six.text_type(s) + for c in s: + if ord(c) <= 255: + char_type = 1 + else: + char_type = 2 + if len(chunks) and chunks[-1][0] == char_type: + chunks[-1][1].append(c) + else: + chunks.append((char_type, [c])) + use_simple_method = (len(chunks) == 1 and + chunks[-1][0] == 1) + return use_simple_method, chunks + + def draw_text_simple(): + """Outputs text using the simple method.""" + self.file.output(Op.begin_text, + self.file.fontName(prop), + fontsize, + Op.selectfont) + self._setup_textpos(x, y, angle) + self.file.output(self.encode_string(s, fonttype), Op.show, + Op.end_text) + + def draw_text_woven(chunks): + """Outputs text using the woven method, alternating + between chunks of 1-byte characters and 2-byte characters. + Only used for Type 3 fonts.""" + chunks = [(a, ''.join(b)) for a, b in chunks] + + # Do the rotation and global translation as a single matrix + # concatenation up front + self.file.output(Op.gsave) + a = angle / 180.0 * pi + self.file.output(cos(a), sin(a), -sin(a), cos(a), x, y, + Op.concat_matrix) + + # Output all the 1-byte characters in a BT/ET group, then + # output all the 2-byte characters. + for mode in (1, 2): + newx = oldx = 0 + # Output a 1-byte character chunk + if mode == 1: + self.file.output(Op.begin_text, + self.file.fontName(prop), + fontsize, + Op.selectfont) + + for chunk_type, chunk in chunks: + if mode == 1 and chunk_type == 1: + self._setup_textpos(newx, 0, 0, oldx, 0, 0) + self.file.output(self.encode_string(chunk, fonttype), + Op.show) + oldx = newx + + lastgind = None + for c in chunk: + ccode = ord(c) + gind = font.get_char_index(ccode) + if gind is not None: + if mode == 2 and chunk_type == 2: + glyph_name = font.get_glyph_name(gind) + self.file.output(Op.gsave) + self.file.output(0.001 * fontsize, 0, + 0, 0.001 * fontsize, + newx, 0, Op.concat_matrix) + name = self.file._get_xobject_symbol_name( + font.fname, glyph_name) + self.file.output(Name(name), Op.use_xobject) + self.file.output(Op.grestore) + + # Move the pointer based on the character width + # and kerning + glyph = font.load_char(ccode, + flags=LOAD_NO_HINTING) + if lastgind is not None: + kern = font.get_kerning( + lastgind, gind, KERNING_UNFITTED) + else: + kern = 0 + lastgind = gind + newx += kern/64.0 + glyph.linearHoriAdvance/65536.0 + + if mode == 1: + self.file.output(Op.end_text) + + self.file.output(Op.grestore) + + use_simple_method, chunks = check_simple_method(s) + if use_simple_method: + return draw_text_simple() + else: + return draw_text_woven(chunks) + + def get_text_width_height_descent(self, s, prop, ismath): + if rcParams['text.usetex']: + texmanager = self.get_texmanager() + fontsize = prop.get_size_in_points() + w, h, d = texmanager.get_text_width_height_descent(s, fontsize, + renderer=self) + return w, h, d + + if ismath: + w, h, d, glyphs, rects, used_characters = \ + self.mathtext_parser.parse(s, 72, prop) + + elif rcParams['pdf.use14corefonts']: + font = self._get_font_afm(prop) + l, b, w, h, d = font.get_str_bbox_and_descent(s) + scale = prop.get_size_in_points() + w *= scale / 1000 + h *= scale / 1000 + d *= scale / 1000 + else: + font = self._get_font_ttf(prop) + font.set_text(s, 0.0, flags=LOAD_NO_HINTING) + w, h = font.get_width_height() + scale = (1.0 / 64.0) + w *= scale + h *= scale + d = font.get_descent() + d *= scale + return w, h, d + + def _get_font_afm(self, prop): + key = hash(prop) + font = self.afm_font_cache.get(key) + if font is None: + filename = findfont( + prop, fontext='afm', directory=self.file._core14fontdir) + if filename is None: + filename = findfont( + "Helvetica", fontext='afm', + directory=self.file._core14fontdir) + font = self.afm_font_cache.get(filename) + if font is None: + with open(filename, 'rb') as fh: + font = AFM(fh) + self.afm_font_cache[filename] = font + self.afm_font_cache[key] = font + return font + + def _get_font_ttf(self, prop): + filename = findfont(prop) + font = get_font(filename) + font.clear() + font.set_size(prop.get_size_in_points(), 72) + return font + + def flipy(self): + return False + + def get_canvas_width_height(self): + return self.file.width * 72.0, self.file.height * 72.0 + + def new_gc(self): + return GraphicsContextPdf(self.file) + + +class GraphicsContextPdf(GraphicsContextBase): + + def __init__(self, file): + GraphicsContextBase.__init__(self) + self._fillcolor = (0.0, 0.0, 0.0) + self._effective_alphas = (1.0, 1.0) + self.file = file + self.parent = None + + def __repr__(self): + d = dict(self.__dict__) + del d['file'] + del d['parent'] + return repr(d) + + def stroke(self): + """ + Predicate: does the path need to be stroked (its outline drawn)? + This tests for the various conditions that disable stroking + the path, in which case it would presumably be filled. + """ + # _linewidth > 0: in pdf a line of width 0 is drawn at minimum + # possible device width, but e.g., agg doesn't draw at all + return (self._linewidth > 0 and self._alpha > 0 and + (len(self._rgb) <= 3 or self._rgb[3] != 0.0)) + + def fill(self, *args): + """ + Predicate: does the path need to be filled? + + An optional argument can be used to specify an alternative + _fillcolor, as needed by RendererPdf.draw_markers. + """ + if len(args): + _fillcolor = args[0] + else: + _fillcolor = self._fillcolor + return (self._hatch or + (_fillcolor is not None and + (len(_fillcolor) <= 3 or _fillcolor[3] != 0.0))) + + def paint(self): + """ + Return the appropriate pdf operator to cause the path to be + stroked, filled, or both. + """ + return Op.paint_path(self.fill(), self.stroke()) + + capstyles = {'butt': 0, 'round': 1, 'projecting': 2} + joinstyles = {'miter': 0, 'round': 1, 'bevel': 2} + + def capstyle_cmd(self, style): + return [self.capstyles[style], Op.setlinecap] + + def joinstyle_cmd(self, style): + return [self.joinstyles[style], Op.setlinejoin] + + def linewidth_cmd(self, width): + return [width, Op.setlinewidth] + + def dash_cmd(self, dashes): + offset, dash = dashes + if dash is None: + dash = [] + offset = 0 + return [list(dash), offset, Op.setdash] + + def alpha_cmd(self, alpha, forced, effective_alphas): + name = self.file.alphaState(effective_alphas) + return [name, Op.setgstate] + + def hatch_cmd(self, hatch, hatch_color): + if not hatch: + if self._fillcolor is not None: + return self.fillcolor_cmd(self._fillcolor) + else: + return [Name('DeviceRGB'), Op.setcolorspace_nonstroke] + else: + hatch_style = (hatch_color, self._fillcolor, hatch) + name = self.file.hatchPattern(hatch_style) + return [Name('Pattern'), Op.setcolorspace_nonstroke, + name, Op.setcolor_nonstroke] + + def rgb_cmd(self, rgb): + if rcParams['pdf.inheritcolor']: + return [] + if rgb[0] == rgb[1] == rgb[2]: + return [rgb[0], Op.setgray_stroke] + else: + return list(rgb[:3]) + [Op.setrgb_stroke] + + def fillcolor_cmd(self, rgb): + if rgb is None or rcParams['pdf.inheritcolor']: + return [] + elif rgb[0] == rgb[1] == rgb[2]: + return [rgb[0], Op.setgray_nonstroke] + else: + return list(rgb[:3]) + [Op.setrgb_nonstroke] + + def push(self): + parent = GraphicsContextPdf(self.file) + parent.copy_properties(self) + parent.parent = self.parent + self.parent = parent + return [Op.gsave] + + def pop(self): + assert self.parent is not None + self.copy_properties(self.parent) + self.parent = self.parent.parent + return [Op.grestore] + + def clip_cmd(self, cliprect, clippath): + """Set clip rectangle. Calls self.pop() and self.push().""" + cmds = [] + # Pop graphics state until we hit the right one or the stack is empty + while ((self._cliprect, self._clippath) != (cliprect, clippath) + and self.parent is not None): + cmds.extend(self.pop()) + # Unless we hit the right one, set the clip polygon + if ((self._cliprect, self._clippath) != (cliprect, clippath) or + self.parent is None): + cmds.extend(self.push()) + if self._cliprect != cliprect: + cmds.extend([cliprect, Op.rectangle, Op.clip, Op.endpath]) + if self._clippath != clippath: + path, affine = clippath.get_transformed_path_and_affine() + cmds.extend( + PdfFile.pathOperations(path, affine, simplify=False) + + [Op.clip, Op.endpath]) + return cmds + + commands = ( + # must come first since may pop + (('_cliprect', '_clippath'), clip_cmd), + (('_alpha', '_forced_alpha', '_effective_alphas'), alpha_cmd), + (('_capstyle',), capstyle_cmd), + (('_fillcolor',), fillcolor_cmd), + (('_joinstyle',), joinstyle_cmd), + (('_linewidth',), linewidth_cmd), + (('_dashes',), dash_cmd), + (('_rgb',), rgb_cmd), + # must come after fillcolor and rgb + (('_hatch', '_hatch_color'), hatch_cmd), + ) + + def delta(self, other): + """ + Copy properties of other into self and return PDF commands + needed to transform self into other. + """ + cmds = [] + fill_performed = False + for params, cmd in self.commands: + different = False + for p in params: + ours = getattr(self, p) + theirs = getattr(other, p) + try: + if ours is None or theirs is None: + different = ours is not theirs + else: + different = bool(ours != theirs) + except ValueError: + ours = np.asarray(ours) + theirs = np.asarray(theirs) + different = (ours.shape != theirs.shape or + np.any(ours != theirs)) + if different: + break + + # Need to update hatching if we also updated fillcolor + if params == ('_hatch', '_hatch_color') and fill_performed: + different = True + + if different: + if params == ('_fillcolor',): + fill_performed = True + theirs = [getattr(other, p) for p in params] + cmds.extend(cmd(self, *theirs)) + for p in params: + setattr(self, p, getattr(other, p)) + return cmds + + def copy_properties(self, other): + """ + Copy properties of other into self. + """ + GraphicsContextBase.copy_properties(self, other) + fillcolor = getattr(other, '_fillcolor', self._fillcolor) + effective_alphas = getattr(other, '_effective_alphas', + self._effective_alphas) + self._fillcolor = fillcolor + self._effective_alphas = effective_alphas + + def finalize(self): + """ + Make sure every pushed graphics state is popped. + """ + cmds = [] + while self.parent is not None: + cmds.extend(self.pop()) + return cmds + +######################################################################## +# +# The following functions and classes are for pylab and implement +# window/figure managers, etc... +# +######################################################################## + + +class PdfPages(object): + """ + A multi-page PDF file. + + Examples + -------- + + >>> import matplotlib.pyplot as plt + >>> # Initialize: + >>> with PdfPages('foo.pdf') as pdf: + ... # As many times as you like, create a figure fig and save it: + ... fig = plt.figure() + ... pdf.savefig(fig) + ... # When no figure is specified the current figure is saved + ... pdf.savefig() + + Notes + ----- + + In reality :class:`PdfPages` is a thin wrapper around :class:`PdfFile`, in + order to avoid confusion when using :func:`~matplotlib.pyplot.savefig` and + forgetting the format argument. + """ + __slots__ = ('_file', 'keep_empty') + + def __init__(self, filename, keep_empty=True, metadata=None): + """ + Create a new PdfPages object. + + Parameters + ---------- + + filename : str + Plots using :meth:`PdfPages.savefig` will be written to a file at + this location. The file is opened at once and any older file with + the same name is overwritten. + keep_empty : bool, optional + If set to False, then empty pdf files will be deleted automatically + when closed. + metadata : dictionary, optional + Information dictionary object (see PDF reference section 10.2.1 + 'Document Information Dictionary'), e.g.: + `{'Creator': 'My software', 'Author': 'Me', + 'Title': 'Awesome fig'}` + + The standard keys are `'Title'`, `'Author'`, `'Subject'`, + `'Keywords'`, `'Creator'`, `'Producer'`, `'CreationDate'`, + `'ModDate'`, and `'Trapped'`. Values have been predefined + for `'Creator'`, `'Producer'` and `'CreationDate'`. They + can be removed by setting them to `None`. + + """ + self._file = PdfFile(filename, metadata=metadata) + self.keep_empty = keep_empty + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def close(self): + """ + Finalize this object, making the underlying file a complete + PDF file. + """ + self._file.finalize() + self._file.close() + if (self.get_pagecount() == 0 and not self.keep_empty and + not self._file.passed_in_file_object): + os.remove(self._file.fh.name) + self._file = None + + def infodict(self): + """ + Return a modifiable information dictionary object + (see PDF reference section 10.2.1 'Document Information + Dictionary'). + """ + return self._file.infoDict + + def savefig(self, figure=None, **kwargs): + """ + Saves a :class:`~matplotlib.figure.Figure` to this file as a new page. + + Any other keyword arguments are passed to + :meth:`~matplotlib.figure.Figure.savefig`. + + Parameters + ---------- + + figure : :class:`~matplotlib.figure.Figure` or int, optional + Specifies what figure is saved to file. If not specified, the + active figure is saved. If a :class:`~matplotlib.figure.Figure` + instance is provided, this figure is saved. If an int is specified, + the figure instance to save is looked up by number. + """ + if not isinstance(figure, Figure): + if figure is None: + manager = Gcf.get_active() + else: + manager = Gcf.get_fig_manager(figure) + if manager is None: + raise ValueError("No figure {}".format(figure)) + figure = manager.canvas.figure + # Force use of pdf backend, as PdfPages is tightly coupled with it. + try: + orig_canvas = figure.canvas + figure.canvas = FigureCanvasPdf(figure) + figure.savefig(self, format="pdf", **kwargs) + finally: + figure.canvas = orig_canvas + + def get_pagecount(self): + """ + Returns the current number of pages in the multipage pdf file. + """ + return len(self._file.pageList) + + def attach_note(self, text, positionRect=[-100, -100, 0, 0]): + """ + Add a new text note to the page to be saved next. The optional + positionRect specifies the position of the new note on the + page. It is outside the page per default to make sure it is + invisible on printouts. + """ + self._file.newTextnote(text, positionRect) + + +class FigureCanvasPdf(FigureCanvasBase): + """ + The canvas the figure renders into. Calls the draw and print fig + methods, creates the renderers, etc... + + Attributes + ---------- + figure : `matplotlib.figure.Figure` + A high-level Figure instance + + """ + + fixed_dpi = 72 + + def draw(self): + pass + + filetypes = {'pdf': 'Portable Document Format'} + + def get_default_filetype(self): + return 'pdf' + + def print_pdf(self, filename, **kwargs): + image_dpi = kwargs.get('dpi', 72) # dpi to use for images + self.figure.set_dpi(72) # there are 72 pdf points to an inch + width, height = self.figure.get_size_inches() + if isinstance(filename, PdfPages): + file = filename._file + else: + file = PdfFile(filename, metadata=kwargs.pop("metadata", None)) + try: + file.newPage(width, height) + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer( + self.figure, width, height, image_dpi, + RendererPdf(file, image_dpi, height, width), + bbox_inches_restore=_bbox_inches_restore) + self.figure.draw(renderer) + renderer.finalize() + if not isinstance(filename, PdfPages): + file.finalize() + finally: + if isinstance(filename, PdfPages): # finish off this page + file.endStream() + else: # we opened the file above; now finish it off + file.close() + + +class FigureManagerPdf(FigureManagerBase): + pass + + +@_Backend.export +class _BackendPdf(_Backend): + FigureCanvas = FigureCanvasPdf + FigureManager = FigureManagerPdf diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_pgf.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_pgf.py new file mode 100644 index 00000000000..cec6358452d --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_pgf.py @@ -0,0 +1,990 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import atexit +import codecs +import errno +import math +import os +import re +import shutil +import sys +import tempfile +import warnings +import weakref + +import matplotlib as mpl +from matplotlib import _png, rcParams +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + RendererBase) +from matplotlib.backends.backend_mixed import MixedModeRenderer +from matplotlib.cbook import is_writable_file_like +from matplotlib.compat import subprocess +from matplotlib.compat.subprocess import check_output +from matplotlib.path import Path + + +############################################################################### + +# create a list of system fonts, all of these should work with xe/lua-latex +system_fonts = [] +if sys.platform.startswith('win'): + from matplotlib import font_manager + for f in font_manager.win32InstalledFonts(): + try: + system_fonts.append(font_manager.get_font(str(f)).family_name) + except: + pass # unknown error, skip this font +else: + # assuming fontconfig is installed and the command 'fc-list' exists + try: + # list scalable (non-bitmap) fonts + fc_list = check_output([str('fc-list'), ':outline,scalable', 'family']) + fc_list = fc_list.decode('utf8') + system_fonts = [f.split(',')[0] for f in fc_list.splitlines()] + system_fonts = list(set(system_fonts)) + except: + warnings.warn('error getting fonts from fc-list', UserWarning) + +def get_texcommand(): + """Get chosen TeX system from rc.""" + texsystem_options = ["xelatex", "lualatex", "pdflatex"] + texsystem = rcParams["pgf.texsystem"] + return texsystem if texsystem in texsystem_options else "xelatex" + + +def get_fontspec(): + """Build fontspec preamble from rc.""" + latex_fontspec = [] + texcommand = get_texcommand() + + if texcommand != "pdflatex": + latex_fontspec.append("\\usepackage{fontspec}") + + if texcommand != "pdflatex" and rcParams["pgf.rcfonts"]: + # try to find fonts from rc parameters + families = ["serif", "sans-serif", "monospace"] + fontspecs = [r"\setmainfont{%s}", r"\setsansfont{%s}", + r"\setmonofont{%s}"] + for family, fontspec in zip(families, fontspecs): + matches = [f for f in rcParams["font." + family] + if f in system_fonts] + if matches: + latex_fontspec.append(fontspec % matches[0]) + else: + pass # no fonts found, fallback to LaTeX defaule + + return "\n".join(latex_fontspec) + + +def get_preamble(): + """Get LaTeX preamble from rc.""" + return "\n".join(rcParams["pgf.preamble"]) + +############################################################################### + +# This almost made me cry!!! +# In the end, it's better to use only one unit for all coordinates, since the +# arithmetic in latex seems to produce inaccurate conversions. +latex_pt_to_in = 1. / 72.27 +latex_in_to_pt = 1. / latex_pt_to_in +mpl_pt_to_in = 1. / 72. +mpl_in_to_pt = 1. / mpl_pt_to_in + +############################################################################### +# helper functions + +NO_ESCAPE = r"(? 3 else 1.0 + + if has_fill: + writeln(self.fh, + r"\definecolor{currentfill}{rgb}{%f,%f,%f}" + % tuple(rgbFace[:3])) + writeln(self.fh, r"\pgfsetfillcolor{currentfill}") + if has_fill and fillopacity != 1.0: + writeln(self.fh, r"\pgfsetfillopacity{%f}" % fillopacity) + + # linewidth and color + lw = gc.get_linewidth() * mpl_pt_to_in * latex_in_to_pt + stroke_rgba = gc.get_rgb() + writeln(self.fh, r"\pgfsetlinewidth{%fpt}" % lw) + writeln(self.fh, + r"\definecolor{currentstroke}{rgb}{%f,%f,%f}" + % stroke_rgba[:3]) + writeln(self.fh, r"\pgfsetstrokecolor{currentstroke}") + if strokeopacity != 1.0: + writeln(self.fh, r"\pgfsetstrokeopacity{%f}" % strokeopacity) + + # line style + dash_offset, dash_list = gc.get_dashes() + if dash_list is None: + writeln(self.fh, r"\pgfsetdash{}{0pt}") + else: + writeln(self.fh, + r"\pgfsetdash{%s}{%fpt}" + % ("".join(r"{%fpt}" % dash for dash in dash_list), + dash_offset)) + + def _print_pgf_path(self, gc, path, transform, rgbFace=None): + f = 1. / self.dpi + # check for clip box / ignore clip for filled paths + bbox = gc.get_clip_rectangle() if gc else None + if bbox and (rgbFace is None): + p1, p2 = bbox.get_points() + clip = (p1[0], p1[1], p2[0], p2[1]) + else: + clip = None + # build path + for points, code in path.iter_segments(transform, clip=clip): + if code == Path.MOVETO: + x, y = tuple(points) + writeln(self.fh, + r"\pgfpathmoveto{\pgfqpoint{%fin}{%fin}}" % + (f * x, f * y)) + elif code == Path.CLOSEPOLY: + writeln(self.fh, r"\pgfpathclose") + elif code == Path.LINETO: + x, y = tuple(points) + writeln(self.fh, + r"\pgfpathlineto{\pgfqpoint{%fin}{%fin}}" % + (f * x, f * y)) + elif code == Path.CURVE3: + cx, cy, px, py = tuple(points) + coords = cx * f, cy * f, px * f, py * f + writeln(self.fh, + r"\pgfpathquadraticcurveto" + r"{\pgfqpoint{%fin}{%fin}}{\pgfqpoint{%fin}{%fin}}" + % coords) + elif code == Path.CURVE4: + c1x, c1y, c2x, c2y, px, py = tuple(points) + coords = c1x * f, c1y * f, c2x * f, c2y * f, px * f, py * f + writeln(self.fh, + r"\pgfpathcurveto" + r"{\pgfqpoint{%fin}{%fin}}" + r"{\pgfqpoint{%fin}{%fin}}" + r"{\pgfqpoint{%fin}{%fin}}" + % coords) + + def _pgf_path_draw(self, stroke=True, fill=False): + actions = [] + if stroke: + actions.append("stroke") + if fill: + actions.append("fill") + writeln(self.fh, r"\pgfusepath{%s}" % ",".join(actions)) + + def option_scale_image(self): + """ + pgf backend supports affine transform of image. + """ + return True + + def option_image_nocomposite(self): + """ + return whether to generate a composite image from multiple images on + a set of axes + """ + return not rcParams['image.composite_image'] + + def draw_image(self, gc, x, y, im, transform=None): + h, w = im.shape[:2] + if w == 0 or h == 0: + return + + # save the images to png files + path = os.path.dirname(self.fh.name) + fname = os.path.splitext(os.path.basename(self.fh.name))[0] + fname_img = "%s-img%d.png" % (fname, self.image_counter) + self.image_counter += 1 + _png.write_png(im[::-1], os.path.join(path, fname_img)) + + # reference the image in the pgf picture + writeln(self.fh, r"\begin{pgfscope}") + self._print_pgf_clip(gc) + f = 1. / self.dpi # from display coords to inch + if transform is None: + writeln(self.fh, + r"\pgfsys@transformshift{%fin}{%fin}" % (x * f, y * f)) + w, h = w * f, h * f + else: + tr1, tr2, tr3, tr4, tr5, tr6 = transform.frozen().to_values() + writeln(self.fh, + r"\pgfsys@transformcm{%f}{%f}{%f}{%f}{%fin}{%fin}" % + (tr1 * f, tr2 * f, tr3 * f, tr4 * f, + (tr5 + x) * f, (tr6 + y) * f)) + w = h = 1 # scale is already included in the transform + interp = str(transform is None).lower() # interpolation in PDF reader + writeln(self.fh, + r"\pgftext[left,bottom]" + r"{\pgfimage[interpolate=%s,width=%fin,height=%fin]{%s}}" % + (interp, w, h, fname_img)) + writeln(self.fh, r"\end{pgfscope}") + + def draw_tex(self, gc, x, y, s, prop, angle, ismath="TeX!", mtext=None): + self.draw_text(gc, x, y, s, prop, angle, ismath, mtext) + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + # prepare string for tex + s = common_texification(s) + prop_cmds = _font_properties_str(prop) + s = r"%s %s" % (prop_cmds, s) + + + writeln(self.fh, r"\begin{pgfscope}") + + alpha = gc.get_alpha() + if alpha != 1.0: + writeln(self.fh, r"\pgfsetfillopacity{%f}" % alpha) + writeln(self.fh, r"\pgfsetstrokeopacity{%f}" % alpha) + rgb = tuple(gc.get_rgb())[:3] + if rgb != (0, 0, 0): + writeln(self.fh, r"\definecolor{textcolor}{rgb}{%f,%f,%f}" % rgb) + writeln(self.fh, r"\pgfsetstrokecolor{textcolor}") + writeln(self.fh, r"\pgfsetfillcolor{textcolor}") + s = r"\color{textcolor}" + s + + f = 1.0 / self.figure.dpi + text_args = [] + if mtext and ( + (angle == 0 or + mtext.get_rotation_mode() == "anchor") and + mtext.get_va() != "center_baseline"): + # if text anchoring can be supported, get the original coordinates + # and add alignment information + x, y = mtext.get_transform().transform_point(mtext.get_position()) + text_args.append("x=%fin" % (x * f)) + text_args.append("y=%fin" % (y * f)) + + halign = {"left": "left", "right": "right", "center": ""} + valign = {"top": "top", "bottom": "bottom", + "baseline": "base", "center": ""} + text_args.append(halign[mtext.get_ha()]) + text_args.append(valign[mtext.get_va()]) + else: + # if not, use the text layout provided by matplotlib + text_args.append("x=%fin" % (x * f)) + text_args.append("y=%fin" % (y * f)) + text_args.append("left") + text_args.append("base") + + if angle != 0: + text_args.append("rotate=%f" % angle) + + writeln(self.fh, r"\pgftext[%s]{%s}" % (",".join(text_args), s)) + writeln(self.fh, r"\end{pgfscope}") + + def get_text_width_height_descent(self, s, prop, ismath): + # check if the math is supposed to be displaystyled + s = common_texification(s) + + # get text metrics in units of latex pt, convert to display units + w, h, d = self.latexManager.get_width_height_descent(s, prop) + # TODO: this should be latex_pt_to_in instead of mpl_pt_to_in + # but having a little bit more space around the text looks better, + # plus the bounding box reported by LaTeX is VERY narrow + f = mpl_pt_to_in * self.dpi + return w * f, h * f, d * f + + def flipy(self): + return False + + def get_canvas_width_height(self): + return self.figure.get_figwidth(), self.figure.get_figheight() + + def points_to_pixels(self, points): + return points * mpl_pt_to_in * self.dpi + + def new_gc(self): + return GraphicsContextPgf() + + +class GraphicsContextPgf(GraphicsContextBase): + pass + +######################################################################## + + +class TmpDirCleaner(object): + remaining_tmpdirs = set() + + @staticmethod + def add(tmpdir): + TmpDirCleaner.remaining_tmpdirs.add(tmpdir) + + @staticmethod + def cleanup_remaining_tmpdirs(): + for tmpdir in TmpDirCleaner.remaining_tmpdirs: + try: + shutil.rmtree(tmpdir) + except: + sys.stderr.write("error deleting tmp directory %s\n" % tmpdir) + + +class FigureCanvasPgf(FigureCanvasBase): + filetypes = {"pgf": "LaTeX PGF picture", + "pdf": "LaTeX compiled PGF picture", + "png": "Portable Network Graphics", } + + def get_default_filetype(self): + return 'pdf' + + def _print_pgf_to_fh(self, fh, *args, **kwargs): + if kwargs.get("dryrun", False): + renderer = RendererPgf(self.figure, None, dummy=True) + self.figure.draw(renderer) + return + + header_text = """%% Creator: Matplotlib, PGF backend +%% +%% To include the figure in your LaTeX document, write +%% \\input{.pgf} +%% +%% Make sure the required packages are loaded in your preamble +%% \\usepackage{pgf} +%% +%% Figures using additional raster images can only be included by \\input if +%% they are in the same directory as the main LaTeX file. For loading figures +%% from other directories you can use the `import` package +%% \\usepackage{import} +%% and then include the figures with +%% \\import{}{.pgf} +%% +""" + + # append the preamble used by the backend as a comment for debugging + header_info_preamble = ["%% Matplotlib used the following preamble"] + for line in get_preamble().splitlines(): + header_info_preamble.append("%% " + line) + for line in get_fontspec().splitlines(): + header_info_preamble.append("%% " + line) + header_info_preamble.append("%%") + header_info_preamble = "\n".join(header_info_preamble) + + # get figure size in inch + w, h = self.figure.get_figwidth(), self.figure.get_figheight() + dpi = self.figure.get_dpi() + + # create pgfpicture environment and write the pgf code + fh.write(header_text) + fh.write(header_info_preamble) + fh.write("\n") + writeln(fh, r"\begingroup") + writeln(fh, r"\makeatletter") + writeln(fh, r"\begin{pgfpicture}") + writeln(fh, + r"\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{%fin}{%fin}}" + % (w, h)) + writeln(fh, r"\pgfusepath{use as bounding box, clip}") + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer(self.figure, w, h, dpi, + RendererPgf(self.figure, fh), + bbox_inches_restore=_bbox_inches_restore) + self.figure.draw(renderer) + + # end the pgfpicture environment + writeln(fh, r"\end{pgfpicture}") + writeln(fh, r"\makeatother") + writeln(fh, r"\endgroup") + + def print_pgf(self, fname_or_fh, *args, **kwargs): + """ + Output pgf commands for drawing the figure so it can be included and + rendered in latex documents. + """ + if kwargs.get("dryrun", False): + self._print_pgf_to_fh(None, *args, **kwargs) + return + + # figure out where the pgf is to be written to + if isinstance(fname_or_fh, six.string_types): + with codecs.open(fname_or_fh, "w", encoding="utf-8") as fh: + self._print_pgf_to_fh(fh, *args, **kwargs) + elif is_writable_file_like(fname_or_fh): + fh = codecs.getwriter("utf-8")(fname_or_fh) + self._print_pgf_to_fh(fh, *args, **kwargs) + else: + raise ValueError("filename must be a path") + + def _print_pdf_to_fh(self, fh, *args, **kwargs): + w, h = self.figure.get_figwidth(), self.figure.get_figheight() + + try: + # create temporary directory for compiling the figure + tmpdir = tempfile.mkdtemp(prefix="mpl_pgf_") + fname_pgf = os.path.join(tmpdir, "figure.pgf") + fname_tex = os.path.join(tmpdir, "figure.tex") + fname_pdf = os.path.join(tmpdir, "figure.pdf") + + # print figure to pgf and compile it with latex + self.print_pgf(fname_pgf, *args, **kwargs) + + latex_preamble = get_preamble() + latex_fontspec = get_fontspec() + latexcode = """ +\\documentclass[12pt]{minimal} +\\usepackage[paperwidth=%fin, paperheight=%fin, margin=0in]{geometry} +%s +%s +\\usepackage{pgf} + +\\begin{document} +\\centering +\\input{figure.pgf} +\\end{document}""" % (w, h, latex_preamble, latex_fontspec) + with codecs.open(fname_tex, "w", "utf-8") as fh_tex: + fh_tex.write(latexcode) + + texcommand = get_texcommand() + cmdargs = [str(texcommand), "-interaction=nonstopmode", + "-halt-on-error", "figure.tex"] + try: + check_output(cmdargs, stderr=subprocess.STDOUT, cwd=tmpdir) + except subprocess.CalledProcessError as e: + raise RuntimeError( + "%s was not able to process your file.\n\nFull log:\n%s" + % (texcommand, e.output)) + + # copy file contents to target + with open(fname_pdf, "rb") as fh_src: + shutil.copyfileobj(fh_src, fh) + finally: + try: + shutil.rmtree(tmpdir) + except: + TmpDirCleaner.add(tmpdir) + + def print_pdf(self, fname_or_fh, *args, **kwargs): + """ + Use LaTeX to compile a Pgf generated figure to PDF. + """ + if kwargs.get("dryrun", False): + self._print_pgf_to_fh(None, *args, **kwargs) + return + + # figure out where the pdf is to be written to + if isinstance(fname_or_fh, six.string_types): + with open(fname_or_fh, "wb") as fh: + self._print_pdf_to_fh(fh, *args, **kwargs) + elif is_writable_file_like(fname_or_fh): + self._print_pdf_to_fh(fname_or_fh, *args, **kwargs) + else: + raise ValueError("filename must be a path or a file-like object") + + def _print_png_to_fh(self, fh, *args, **kwargs): + converter = make_pdf_to_png_converter() + + try: + # create temporary directory for pdf creation and png conversion + tmpdir = tempfile.mkdtemp(prefix="mpl_pgf_") + fname_pdf = os.path.join(tmpdir, "figure.pdf") + fname_png = os.path.join(tmpdir, "figure.png") + # create pdf and try to convert it to png + self.print_pdf(fname_pdf, *args, **kwargs) + converter(fname_pdf, fname_png, dpi=self.figure.dpi) + # copy file contents to target + with open(fname_png, "rb") as fh_src: + shutil.copyfileobj(fh_src, fh) + finally: + try: + shutil.rmtree(tmpdir) + except: + TmpDirCleaner.add(tmpdir) + + def print_png(self, fname_or_fh, *args, **kwargs): + """ + Use LaTeX to compile a pgf figure to pdf and convert it to png. + """ + if kwargs.get("dryrun", False): + self._print_pgf_to_fh(None, *args, **kwargs) + return + + if isinstance(fname_or_fh, six.string_types): + with open(fname_or_fh, "wb") as fh: + self._print_png_to_fh(fh, *args, **kwargs) + elif is_writable_file_like(fname_or_fh): + self._print_png_to_fh(fname_or_fh, *args, **kwargs) + else: + raise ValueError("filename must be a path or a file-like object") + + def get_renderer(self): + return RendererPgf(self.figure, None, dummy=True) + + +class FigureManagerPgf(FigureManagerBase): + def __init__(self, *args): + FigureManagerBase.__init__(self, *args) + + +@_Backend.export +class _BackendPgf(_Backend): + FigureCanvas = FigureCanvasPgf + FigureManager = FigureManagerPgf + + +def _cleanup_all(): + LatexManager._cleanup_remaining_instances() + TmpDirCleaner.cleanup_remaining_tmpdirs() + +atexit.register(_cleanup_all) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_ps.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_ps.py new file mode 100644 index 00000000000..5e475101d3b --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_ps.py @@ -0,0 +1,1762 @@ +""" +A PostScript backend, which can produce both PostScript .ps and .eps +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import StringIO + +import glob, os, shutil, sys, time, datetime +import io +import logging + +from tempfile import mkstemp +from matplotlib import cbook, __version__, rcParams, checkdep_ghostscript +from matplotlib.afm import AFM +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + RendererBase) + +from matplotlib.cbook import (get_realpath_and_stat, is_writable_file_like, + maxdict, file_requires_unicode) +from matplotlib.compat.subprocess import subprocess + +from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font +from matplotlib.ft2font import KERNING_DEFAULT, LOAD_NO_HINTING +from matplotlib.ttconv import convert_ttf_to_ps +from matplotlib.mathtext import MathTextParser +from matplotlib._mathtext_data import uni2type1 +from matplotlib.path import Path +from matplotlib import _path +from matplotlib.transforms import Affine2D + +from matplotlib.backends.backend_mixed import MixedModeRenderer + + +import numpy as np +import binascii +import re + +_log = logging.getLogger(__name__) + +backend_version = 'Level II' + +debugPS = 0 + + +class PsBackendHelper(object): + + def __init__(self): + self._cached = {} + + @property + def gs_exe(self): + """ + executable name of ghostscript. + """ + try: + return self._cached["gs_exe"] + except KeyError: + pass + + gs_exe, gs_version = checkdep_ghostscript() + if gs_exe is None: + gs_exe = 'gs' + + self._cached["gs_exe"] = str(gs_exe) + return str(gs_exe) + + @property + def gs_version(self): + """ + version of ghostscript. + """ + try: + return self._cached["gs_version"] + except KeyError: + pass + + from matplotlib.compat.subprocess import Popen, PIPE + s = Popen([self.gs_exe, "--version"], stdout=PIPE) + pipe, stderr = s.communicate() + if six.PY3: + ver = pipe.decode('ascii') + else: + ver = pipe + try: + gs_version = tuple(map(int, ver.strip().split("."))) + except ValueError: + # if something went wrong parsing return null version number + gs_version = (0, 0) + self._cached["gs_version"] = gs_version + return gs_version + + @property + def supports_ps2write(self): + """ + True if the installed ghostscript supports ps2write device. + """ + return self.gs_version[0] >= 9 + +ps_backend_helper = PsBackendHelper() + +papersize = {'letter': (8.5,11), + 'legal': (8.5,14), + 'ledger': (11,17), + 'a0': (33.11,46.81), + 'a1': (23.39,33.11), + 'a2': (16.54,23.39), + 'a3': (11.69,16.54), + 'a4': (8.27,11.69), + 'a5': (5.83,8.27), + 'a6': (4.13,5.83), + 'a7': (2.91,4.13), + 'a8': (2.07,2.91), + 'a9': (1.457,2.05), + 'a10': (1.02,1.457), + 'b0': (40.55,57.32), + 'b1': (28.66,40.55), + 'b2': (20.27,28.66), + 'b3': (14.33,20.27), + 'b4': (10.11,14.33), + 'b5': (7.16,10.11), + 'b6': (5.04,7.16), + 'b7': (3.58,5.04), + 'b8': (2.51,3.58), + 'b9': (1.76,2.51), + 'b10': (1.26,1.76)} + +def _get_papertype(w, h): + keys = list(six.iterkeys(papersize)) + keys.sort() + keys.reverse() + for key in keys: + if key.startswith('l'): continue + pw, ph = papersize[key] + if (w < pw) and (h < ph): return key + return 'a0' + +def _num_to_str(val): + if isinstance(val, six.string_types): return val + + ival = int(val) + if val == ival: return str(ival) + + s = "%1.3f"%val + s = s.rstrip("0") + s = s.rstrip(".") + return s + +def _nums_to_str(*args): + return ' '.join(map(_num_to_str,args)) + + +def quote_ps_string(s): + "Quote dangerous characters of S for use in a PostScript string constant." + s = s.replace(b"\\", b"\\\\") + s = s.replace(b"(", b"\\(") + s = s.replace(b")", b"\\)") + s = s.replace(b"'", b"\\251") + s = s.replace(b"`", b"\\301") + s = re.sub(br"[^ -~\n]", lambda x: br"\%03o" % ord(x.group()), s) + return s.decode('ascii') + + +def _move_path_to_path_or_stream(src, dst): + """Move the contents of file at *src* to path-or-filelike *dst*. + + If *dst* is a path, the metadata of *src* are *not* copied. + """ + if is_writable_file_like(dst): + fh = (io.open(src, 'r', encoding='latin-1') + if file_requires_unicode(dst) + else io.open(src, 'rb')) + with fh: + shutil.copyfileobj(fh, dst) + else: + # Py3: shutil.move(src, dst, copy_function=shutil.copyfile) + open(dst, 'w').close() + mode = os.stat(dst).st_mode + shutil.move(src, dst) + os.chmod(dst, mode) + + +class RendererPS(RendererBase): + """ + The renderer handles all the drawing primitives using a graphics + context instance that controls the colors/styles. + """ + + afmfontd = maxdict(50) + + def __init__(self, width, height, pswriter, imagedpi=72): + """ + Although postscript itself is dpi independent, we need to + imform the image code about a requested dpi to generate high + res images and them scale them before embeddin them + """ + RendererBase.__init__(self) + self.width = width + self.height = height + self._pswriter = pswriter + if rcParams['text.usetex']: + self.textcnt = 0 + self.psfrag = [] + self.imagedpi = imagedpi + + # current renderer state (None=uninitialised) + self.color = None + self.linewidth = None + self.linejoin = None + self.linecap = None + self.linedash = None + self.fontname = None + self.fontsize = None + self._hatches = {} + self.image_magnification = imagedpi/72.0 + self._clip_paths = {} + self._path_collection_id = 0 + + self.used_characters = {} + self.mathtext_parser = MathTextParser("PS") + + self._afm_font_dir = os.path.join( + rcParams['datapath'], 'fonts', 'afm') + + def track_characters(self, font, s): + """Keeps track of which characters are required from + each font.""" + realpath, stat_key = get_realpath_and_stat(font.fname) + used_characters = self.used_characters.setdefault( + stat_key, (realpath, set())) + used_characters[1].update([ord(x) for x in s]) + + def merge_used_characters(self, other): + for stat_key, (realpath, charset) in six.iteritems(other): + used_characters = self.used_characters.setdefault( + stat_key, (realpath, set())) + used_characters[1].update(charset) + + def set_color(self, r, g, b, store=1): + if (r,g,b) != self.color: + if r==g and r==b: + self._pswriter.write("%1.3f setgray\n"%r) + else: + self._pswriter.write("%1.3f %1.3f %1.3f setrgbcolor\n"%(r,g,b)) + if store: self.color = (r,g,b) + + def set_linewidth(self, linewidth, store=1): + linewidth = float(linewidth) + if linewidth != self.linewidth: + self._pswriter.write("%1.3f setlinewidth\n"%linewidth) + if store: self.linewidth = linewidth + + def set_linejoin(self, linejoin, store=1): + if linejoin != self.linejoin: + self._pswriter.write("%d setlinejoin\n"%linejoin) + if store: self.linejoin = linejoin + + def set_linecap(self, linecap, store=1): + if linecap != self.linecap: + self._pswriter.write("%d setlinecap\n"%linecap) + if store: self.linecap = linecap + + def set_linedash(self, offset, seq, store=1): + if self.linedash is not None: + oldo, oldseq = self.linedash + if np.array_equal(seq, oldseq) and oldo == offset: + return + + if seq is not None and len(seq): + s="[%s] %d setdash\n"%(_nums_to_str(*seq), offset) + self._pswriter.write(s) + else: + self._pswriter.write("[] 0 setdash\n") + if store: + self.linedash = (offset, seq) + + def set_font(self, fontname, fontsize, store=1): + if rcParams['ps.useafm']: return + if (fontname,fontsize) != (self.fontname,self.fontsize): + out = ("/%s findfont\n" + "%1.3f scalefont\n" + "setfont\n" % (fontname, fontsize)) + + self._pswriter.write(out) + if store: self.fontname = fontname + if store: self.fontsize = fontsize + + def create_hatch(self, hatch): + sidelen = 72 + if hatch in self._hatches: + return self._hatches[hatch] + name = 'H%d' % len(self._hatches) + linewidth = rcParams['hatch.linewidth'] + pageheight = self.height * 72 + self._pswriter.write("""\ + << /PatternType 1 + /PaintType 2 + /TilingType 2 + /BBox[0 0 %(sidelen)d %(sidelen)d] + /XStep %(sidelen)d + /YStep %(sidelen)d + + /PaintProc { + pop + %(linewidth)f setlinewidth +""" % locals()) + self._pswriter.write( + self._convert_path(Path.hatch(hatch), Affine2D().scale(sidelen), + simplify=False)) + self._pswriter.write("""\ + fill + stroke + } bind + >> + matrix + 0.0 %(pageheight)f translate + makepattern + /%(name)s exch def +""" % locals()) + self._hatches[hatch] = name + return name + + def get_canvas_width_height(self): + 'return the canvas width and height in display coords' + return self.width * 72.0, self.height * 72.0 + + def get_text_width_height_descent(self, s, prop, ismath): + """ + get the width and height in display coords of the string s + with FontPropertry prop + + """ + if rcParams['text.usetex']: + texmanager = self.get_texmanager() + fontsize = prop.get_size_in_points() + w, h, d = texmanager.get_text_width_height_descent(s, fontsize, + renderer=self) + return w, h, d + + if ismath: + width, height, descent, pswriter, used_characters = \ + self.mathtext_parser.parse(s, 72, prop) + return width, height, descent + + if rcParams['ps.useafm']: + if ismath: s = s[1:-1] + font = self._get_font_afm(prop) + l,b,w,h,d = font.get_str_bbox_and_descent(s) + + fontsize = prop.get_size_in_points() + scale = 0.001*fontsize + w *= scale + h *= scale + d *= scale + return w, h, d + + font = self._get_font_ttf(prop) + font.set_text(s, 0.0, flags=LOAD_NO_HINTING) + w, h = font.get_width_height() + w /= 64.0 # convert from subpixels + h /= 64.0 + d = font.get_descent() + d /= 64.0 + return w, h, d + + def flipy(self): + 'return true if small y numbers are top for renderer' + return False + + def _get_font_afm(self, prop): + key = hash(prop) + font = self.afmfontd.get(key) + if font is None: + fname = findfont(prop, fontext='afm', directory=self._afm_font_dir) + if fname is None: + fname = findfont( + "Helvetica", fontext='afm', directory=self._afm_font_dir) + font = self.afmfontd.get(fname) + if font is None: + with io.open(fname, 'rb') as fh: + font = AFM(fh) + self.afmfontd[fname] = font + self.afmfontd[key] = font + return font + + def _get_font_ttf(self, prop): + fname = findfont(prop) + font = get_font(fname) + font.clear() + size = prop.get_size_in_points() + font.set_size(size, 72.0) + return font + + def _rgb(self, rgba): + h, w = rgba.shape[:2] + rgb = rgba[::-1, :, :3] + return h, w, rgb.tostring() + + def _hex_lines(self, s, chars_per_line=128): + s = binascii.b2a_hex(s) + nhex = len(s) + lines = [] + for i in range(0,nhex,chars_per_line): + limit = min(i+chars_per_line, nhex) + lines.append(s[i:limit]) + return lines + + def get_image_magnification(self): + """ + Get the factor by which to magnify images passed to draw_image. + Allows a backend to have images at a different resolution to other + artists. + """ + return self.image_magnification + + def option_scale_image(self): + """ + ps backend support arbitrary scaling of image. + """ + return True + + def option_image_nocomposite(self): + """ + return whether to generate a composite image from multiple images on + a set of axes + """ + return not rcParams['image.composite_image'] + + def _get_image_h_w_bits_command(self, im): + h, w, bits = self._rgb(im) + imagecmd = "false 3 colorimage" + + return h, w, bits, imagecmd + + def draw_image(self, gc, x, y, im, transform=None): + """ + Draw the Image instance into the current axes; x is the + distance in pixels from the left hand side of the canvas and y + is the distance from bottom + """ + + h, w, bits, imagecmd = self._get_image_h_w_bits_command(im) + hexlines = b'\n'.join(self._hex_lines(bits)).decode('ascii') + + if transform is None: + matrix = "1 0 0 1 0 0" + xscale = w / self.image_magnification + yscale = h / self.image_magnification + else: + matrix = " ".join(map(str, transform.frozen().to_values())) + xscale = 1.0 + yscale = 1.0 + + figh = self.height * 72 + + bbox = gc.get_clip_rectangle() + clippath, clippath_trans = gc.get_clip_path() + + clip = [] + if bbox is not None: + clipx,clipy,clipw,cliph = bbox.bounds + clip.append('%s clipbox' % _nums_to_str(clipw, cliph, clipx, clipy)) + if clippath is not None: + id = self._get_clip_path(clippath, clippath_trans) + clip.append('%s' % id) + clip = '\n'.join(clip) + + ps = """gsave +%(clip)s +%(x)s %(y)s translate +[%(matrix)s] concat +%(xscale)s %(yscale)s scale +/DataString %(w)s string def +%(w)s %(h)s 8 [ %(w)s 0 0 -%(h)s 0 %(h)s ] +{ +currentfile DataString readhexstring pop +} bind %(imagecmd)s +%(hexlines)s +grestore +""" % locals() + self._pswriter.write(ps) + + def _convert_path(self, path, transform, clip=False, simplify=None): + if clip: + clip = (0.0, 0.0, self.width * 72.0, + self.height * 72.0) + else: + clip = None + return _path.convert_to_string( + path, transform, clip, simplify, None, + 6, [b'm', b'l', b'', b'c', b'cl'], True).decode('ascii') + + def _get_clip_path(self, clippath, clippath_transform): + key = (clippath, id(clippath_transform)) + pid = self._clip_paths.get(key) + if pid is None: + pid = 'c%x' % len(self._clip_paths) + ps_cmd = ['/%s {' % pid] + ps_cmd.append(self._convert_path(clippath, clippath_transform, + simplify=False)) + ps_cmd.extend(['clip', 'newpath', '} bind def\n']) + self._pswriter.write('\n'.join(ps_cmd)) + self._clip_paths[key] = pid + return pid + + def draw_path(self, gc, path, transform, rgbFace=None): + """ + Draws a Path instance using the given affine transform. + """ + clip = rgbFace is None and gc.get_hatch_path() is None + simplify = path.should_simplify and clip + ps = self._convert_path(path, transform, clip=clip, simplify=simplify) + self._draw_ps(ps, gc, rgbFace) + + def draw_markers( + self, gc, marker_path, marker_trans, path, trans, rgbFace=None): + """ + Draw the markers defined by path at each of the positions in x + and y. path coordinates are points, x and y coords will be + transformed by the transform + """ + if debugPS: self._pswriter.write('% draw_markers \n') + + if rgbFace: + if len(rgbFace) == 4 and rgbFace[3] == 0: + ps_color = None + else: + if rgbFace[0] == rgbFace[1] == rgbFace[2]: + ps_color = '%1.3f setgray' % rgbFace[0] + else: + ps_color = '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace[:3] + + # construct the generic marker command: + ps_cmd = ['/o {', 'gsave', 'newpath', 'translate'] # don't want the translate to be global + + lw = gc.get_linewidth() + alpha = (gc.get_alpha() + if gc.get_forced_alpha() or len(gc.get_rgb()) == 3 + else gc.get_rgb()[3]) + stroke = lw > 0 and alpha > 0 + if stroke: + ps_cmd.append('%.1f setlinewidth' % lw) + jint = gc.get_joinstyle() + ps_cmd.append('%d setlinejoin' % jint) + cint = gc.get_capstyle() + ps_cmd.append('%d setlinecap' % cint) + + ps_cmd.append(self._convert_path(marker_path, marker_trans, + simplify=False)) + + if rgbFace: + if stroke: + ps_cmd.append('gsave') + if ps_color: + ps_cmd.extend([ps_color, 'fill']) + if stroke: + ps_cmd.append('grestore') + + if stroke: + ps_cmd.append('stroke') + ps_cmd.extend(['grestore', '} bind def']) + + for vertices, code in path.iter_segments( + trans, + clip=(0, 0, self.width*72, self.height*72), + simplify=False): + if len(vertices): + x, y = vertices[-2:] + ps_cmd.append("%g %g o" % (x, y)) + + ps = '\n'.join(ps_cmd) + self._draw_ps(ps, gc, rgbFace, fill=False, stroke=False) + + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position): + # Is the optimization worth it? Rough calculation: + # cost of emitting a path in-line is + # (len_path + 2) * uses_per_path + # cost of definition+use is + # (len_path + 3) + 3 * uses_per_path + len_path = len(paths[0].vertices) if len(paths) > 0 else 0 + uses_per_path = self._iter_collection_uses_per_path( + paths, all_transforms, offsets, facecolors, edgecolors) + should_do_optimization = \ + len_path + 3 * uses_per_path + 3 < (len_path + 2) * uses_per_path + if not should_do_optimization: + return RendererBase.draw_path_collection( + self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position) + + write = self._pswriter.write + + path_codes = [] + for i, (path, transform) in enumerate(self._iter_collection_raw_paths( + master_transform, paths, all_transforms)): + name = 'p%x_%x' % (self._path_collection_id, i) + ps_cmd = ['/%s {' % name, + 'newpath', 'translate'] + ps_cmd.append(self._convert_path(path, transform, simplify=False)) + ps_cmd.extend(['} bind def\n']) + write('\n'.join(ps_cmd)) + path_codes.append(name) + + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, master_transform, all_transforms, path_codes, offsets, + offsetTrans, facecolors, edgecolors, linewidths, linestyles, + antialiaseds, urls, offset_position): + ps = "%g %g %s" % (xo, yo, path_id) + self._draw_ps(ps, gc0, rgbFace) + + self._path_collection_id += 1 + + def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None): + """ + draw a Text instance + """ + w, h, bl = self.get_text_width_height_descent(s, prop, ismath) + fontsize = prop.get_size_in_points() + thetext = 'psmarker%d' % self.textcnt + color = '%1.3f,%1.3f,%1.3f'% gc.get_rgb()[:3] + fontcmd = {'sans-serif' : r'{\sffamily %s}', + 'monospace' : r'{\ttfamily %s}'}.get( + rcParams['font.family'][0], r'{\rmfamily %s}') + s = fontcmd % s + tex = r'\color[rgb]{%s} %s' % (color, s) + + corr = 0#w/2*(fontsize-10)/10 + if rcParams['text.latex.preview']: + # use baseline alignment! + pos = _nums_to_str(x-corr, y) + self.psfrag.append(r'\psfrag{%s}[Bl][Bl][1][%f]{\fontsize{%f}{%f}%s}'%(thetext, angle, fontsize, fontsize*1.25, tex)) + else: + # stick to the bottom alignment, but this may give incorrect baseline some times. + pos = _nums_to_str(x-corr, y-bl) + self.psfrag.append(r'\psfrag{%s}[bl][bl][1][%f]{\fontsize{%f}{%f}%s}'%(thetext, angle, fontsize, fontsize*1.25, tex)) + + ps = """\ +gsave +%(pos)s moveto +(%(thetext)s) +show +grestore + """ % locals() + + self._pswriter.write(ps) + self.textcnt += 1 + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + """ + Draw a Text instance. + """ + # local to avoid repeated attribute lookups + write = self._pswriter.write + if debugPS: + write("% text\n") + + if len(gc.get_rgb()) == 4 and gc.get_rgb()[3] == 0: + return # Special handling for fully transparent. + + if ismath=='TeX': + return self.draw_tex(gc, x, y, s, prop, angle) + + elif ismath: + return self.draw_mathtext(gc, x, y, s, prop, angle) + + elif rcParams['ps.useafm']: + self.set_color(*gc.get_rgb()) + + font = self._get_font_afm(prop) + fontname = font.get_fontname() + fontsize = prop.get_size_in_points() + scale = 0.001*fontsize + + thisx = 0 + thisy = font.get_str_bbox_and_descent(s)[4] * scale + last_name = None + lines = [] + for c in s: + name = uni2type1.get(ord(c), 'question') + try: + width = font.get_width_from_char_name(name) + except KeyError: + name = 'question' + width = font.get_width_char('?') + if last_name is not None: + kern = font.get_kern_dist_from_name(last_name, name) + else: + kern = 0 + last_name = name + thisx += kern * scale + + lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name)) + + thisx += width * scale + + thetext = "\n".join(lines) + ps = """\ +gsave +/%(fontname)s findfont +%(fontsize)s scalefont +setfont +%(x)f %(y)f translate +%(angle)f rotate +%(thetext)s +grestore + """ % locals() + self._pswriter.write(ps) + + else: + font = self._get_font_ttf(prop) + font.set_text(s, 0, flags=LOAD_NO_HINTING) + self.track_characters(font, s) + + self.set_color(*gc.get_rgb()) + sfnt = font.get_sfnt() + try: + ps_name = sfnt[1, 0, 0, 6].decode('mac_roman') + except KeyError: + ps_name = sfnt[3, 1, 0x0409, 6].decode('utf-16be') + ps_name = ps_name.encode('ascii', 'replace').decode('ascii') + self.set_font(ps_name, prop.get_size_in_points()) + + lastgind = None + lines = [] + thisx = 0 + thisy = 0 + for c in s: + ccode = ord(c) + gind = font.get_char_index(ccode) + if gind is None: + ccode = ord('?') + name = '.notdef' + gind = 0 + else: + name = font.get_glyph_name(gind) + glyph = font.load_char(ccode, flags=LOAD_NO_HINTING) + + if lastgind is not None: + kern = font.get_kerning(lastgind, gind, KERNING_DEFAULT) + else: + kern = 0 + lastgind = gind + thisx += kern/64.0 + + lines.append('%f %f m /%s glyphshow'%(thisx, thisy, name)) + thisx += glyph.linearHoriAdvance/65536.0 + + + thetext = '\n'.join(lines) + ps = """gsave +%(x)f %(y)f translate +%(angle)f rotate +%(thetext)s +grestore +""" % locals() + self._pswriter.write(ps) + + def new_gc(self): + return GraphicsContextPS() + + def draw_mathtext(self, gc, + x, y, s, prop, angle): + """ + Draw the math text using matplotlib.mathtext + """ + if debugPS: + self._pswriter.write("% mathtext\n") + + width, height, descent, pswriter, used_characters = \ + self.mathtext_parser.parse(s, 72, prop) + self.merge_used_characters(used_characters) + self.set_color(*gc.get_rgb()) + thetext = pswriter.getvalue() + ps = """gsave +%(x)f %(y)f translate +%(angle)f rotate +%(thetext)s +grestore +""" % locals() + self._pswriter.write(ps) + + def draw_gouraud_triangle(self, gc, points, colors, trans): + self.draw_gouraud_triangles(gc, points.reshape((1, 3, 2)), + colors.reshape((1, 3, 4)), trans) + + def draw_gouraud_triangles(self, gc, points, colors, trans): + assert len(points) == len(colors) + assert points.ndim == 3 + assert points.shape[1] == 3 + assert points.shape[2] == 2 + assert colors.ndim == 3 + assert colors.shape[1] == 3 + assert colors.shape[2] == 4 + + shape = points.shape + flat_points = points.reshape((shape[0] * shape[1], 2)) + flat_points = trans.transform(flat_points) + flat_colors = colors.reshape((shape[0] * shape[1], 4)) + points_min = np.min(flat_points, axis=0) - (1 << 12) + points_max = np.max(flat_points, axis=0) + (1 << 12) + factor = np.ceil((2 ** 32 - 1) / (points_max - points_min)) + + xmin, ymin = points_min + xmax, ymax = points_max + + streamarr = np.empty( + (shape[0] * shape[1],), + dtype=[('flags', 'u1'), + ('points', '>u4', (2,)), + ('colors', 'u1', (3,))]) + streamarr['flags'] = 0 + streamarr['points'] = (flat_points - points_min) * factor + streamarr['colors'] = flat_colors[:, :3] * 255.0 + + stream = quote_ps_string(streamarr.tostring()) + + self._pswriter.write(""" +gsave +<< /ShadingType 4 + /ColorSpace [/DeviceRGB] + /BitsPerCoordinate 32 + /BitsPerComponent 8 + /BitsPerFlag 8 + /AntiAlias true + /Decode [ %(xmin)f %(xmax)f %(ymin)f %(ymax)f 0 1 0 1 0 1 ] + /DataSource (%(stream)s) +>> +shfill +grestore +""" % locals()) + + def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None): + """ + Emit the PostScript sniplet 'ps' with all the attributes from 'gc' + applied. 'ps' must consist of PostScript commands to construct a path. + + The fill and/or stroke kwargs can be set to False if the + 'ps' string already includes filling and/or stroking, in + which case _draw_ps is just supplying properties and + clipping. + """ + # local variable eliminates all repeated attribute lookups + write = self._pswriter.write + if debugPS and command: + write("% "+command+"\n") + mightstroke = gc.shouldstroke() + stroke = stroke and mightstroke + fill = (fill and rgbFace is not None and + (len(rgbFace) <= 3 or rgbFace[3] != 0.0)) + hatch = gc.get_hatch() + + if mightstroke: + self.set_linewidth(gc.get_linewidth()) + jint = gc.get_joinstyle() + self.set_linejoin(jint) + cint = gc.get_capstyle() + self.set_linecap(cint) + self.set_linedash(*gc.get_dashes()) + self.set_color(*gc.get_rgb()[:3]) + write('gsave\n') + + cliprect = gc.get_clip_rectangle() + if cliprect: + x,y,w,h=cliprect.bounds + write('%1.4g %1.4g %1.4g %1.4g clipbox\n' % (w,h,x,y)) + clippath, clippath_trans = gc.get_clip_path() + if clippath: + id = self._get_clip_path(clippath, clippath_trans) + write('%s\n' % id) + + # Jochen, is the strip necessary? - this could be a honking big string + write(ps.strip()) + write("\n") + + if fill: + if stroke or hatch: + write("gsave\n") + self.set_color(store=0, *rgbFace[:3]) + write("fill\n") + if stroke or hatch: + write("grestore\n") + + if hatch: + hatch_name = self.create_hatch(hatch) + write("gsave\n") + write("%f %f %f " % gc.get_hatch_color()[:3]) + write("%s setpattern fill grestore\n" % hatch_name) + + if stroke: + write("stroke\n") + + write("grestore\n") + + +class GraphicsContextPS(GraphicsContextBase): + def get_capstyle(self): + return {'butt':0, + 'round':1, + 'projecting':2}[GraphicsContextBase.get_capstyle(self)] + + def get_joinstyle(self): + return {'miter':0, + 'round':1, + 'bevel':2}[GraphicsContextBase.get_joinstyle(self)] + + def shouldstroke(self): + return (self.get_linewidth() > 0.0 and + (len(self.get_rgb()) <= 3 or self.get_rgb()[3] != 0.0)) + + +class FigureCanvasPS(FigureCanvasBase): + _renderer_class = RendererPS + + fixed_dpi = 72 + + def draw(self): + pass + + filetypes = {'ps' : 'Postscript', + 'eps' : 'Encapsulated Postscript'} + + def get_default_filetype(self): + return 'ps' + + def print_ps(self, outfile, *args, **kwargs): + return self._print_ps(outfile, 'ps', *args, **kwargs) + + def print_eps(self, outfile, *args, **kwargs): + return self._print_ps(outfile, 'eps', *args, **kwargs) + + def _print_ps(self, outfile, format, *args, **kwargs): + papertype = kwargs.pop("papertype", rcParams['ps.papersize']) + papertype = papertype.lower() + if papertype == 'auto': + pass + elif papertype not in papersize: + raise RuntimeError('%s is not a valid papertype. Use one of %s' % + (papertype, ', '.join(papersize))) + + orientation = kwargs.pop("orientation", "portrait").lower() + if orientation == 'landscape': isLandscape = True + elif orientation == 'portrait': isLandscape = False + else: raise RuntimeError('Orientation must be "portrait" or "landscape"') + + self.figure.set_dpi(72) # Override the dpi kwarg + imagedpi = kwargs.pop("dpi", 72) + facecolor = kwargs.pop("facecolor", "w") + edgecolor = kwargs.pop("edgecolor", "w") + + if rcParams['text.usetex']: + self._print_figure_tex(outfile, format, imagedpi, facecolor, edgecolor, + orientation, isLandscape, papertype, + **kwargs) + else: + self._print_figure(outfile, format, imagedpi, facecolor, edgecolor, + orientation, isLandscape, papertype, + **kwargs) + + def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w', + orientation='portrait', isLandscape=False, papertype=None, + metadata=None, **kwargs): + """ + Render the figure to hardcopy. Set the figure patch face and + edge colors. This is useful because some of the GUIs have a + gray figure face color background and you'll probably want to + override this on hardcopy + + If outfile is a string, it is interpreted as a file name. + If the extension matches .ep* write encapsulated postscript, + otherwise write a stand-alone PostScript file. + + If outfile is a file object, a stand-alone PostScript file is + written into this file object. + + metadata must be a dictionary. Currently, only the value for + the key 'Creator' is used. + """ + isEPSF = format == 'eps' + if isinstance(outfile, + (six.string_types, getattr(os, "PathLike", ()),)): + outfile = title = getattr(os, "fspath", lambda obj: obj)(outfile) + passed_in_file_object = False + elif is_writable_file_like(outfile): + title = None + passed_in_file_object = True + else: + raise ValueError("outfile must be a path or a file-like object") + + # find the appropriate papertype + width, height = self.figure.get_size_inches() + if papertype == 'auto': + if isLandscape: papertype = _get_papertype(height, width) + else: papertype = _get_papertype(width, height) + + if isLandscape: paperHeight, paperWidth = papersize[papertype] + else: paperWidth, paperHeight = papersize[papertype] + + if rcParams['ps.usedistiller'] and not papertype == 'auto': + # distillers will improperly clip eps files if the pagesize is + # too small + if width>paperWidth or height>paperHeight: + if isLandscape: + papertype = _get_papertype(height, width) + paperHeight, paperWidth = papersize[papertype] + else: + papertype = _get_papertype(width, height) + paperWidth, paperHeight = papersize[papertype] + + # center the figure on the paper + xo = 72*0.5*(paperWidth - width) + yo = 72*0.5*(paperHeight - height) + + l, b, w, h = self.figure.bbox.bounds + llx = xo + lly = yo + urx = llx + w + ury = lly + h + rotation = 0 + if isLandscape: + llx, lly, urx, ury = lly, llx, ury, urx + xo, yo = 72*paperHeight - yo, xo + rotation = 90 + bbox = (llx, lly, urx, ury) + + # generate PostScript code for the figure and store it in a string + origfacecolor = self.figure.get_facecolor() + origedgecolor = self.figure.get_edgecolor() + self.figure.set_facecolor(facecolor) + self.figure.set_edgecolor(edgecolor) + + + dryrun = kwargs.get("dryrun", False) + if dryrun: + class NullWriter(object): + def write(self, *kl, **kwargs): + pass + + self._pswriter = NullWriter() + else: + self._pswriter = io.StringIO() + + + # mixed mode rendering + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + ps_renderer = self._renderer_class(width, height, self._pswriter, + imagedpi=dpi) + renderer = MixedModeRenderer(self.figure, + width, height, dpi, ps_renderer, + bbox_inches_restore=_bbox_inches_restore) + + self.figure.draw(renderer) + + if dryrun: # return immediately if dryrun (tightbbox=True) + return + + self.figure.set_facecolor(origfacecolor) + self.figure.set_edgecolor(origedgecolor) + + # check for custom metadata + if metadata is not None and 'Creator' in metadata: + creator_str = metadata['Creator'] + else: + creator_str = "matplotlib version " + __version__ + \ + ", http://matplotlib.org/" + + def print_figure_impl(fh): + # write the PostScript headers + if isEPSF: + print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) + else: + print("%!PS-Adobe-3.0", file=fh) + if title: + print("%%Title: "+title, file=fh) + print("%%Creator: " + creator_str, file=fh) + # get source date from SOURCE_DATE_EPOCH, if set + # See https://reproducible-builds.org/specs/source-date-epoch/ + source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") + if source_date_epoch: + source_date = datetime.datetime.utcfromtimestamp( + int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y") + else: + source_date = time.ctime() + print("%%CreationDate: "+source_date, file=fh) + print("%%Orientation: " + orientation, file=fh) + if not isEPSF: + print("%%DocumentPaperSizes: "+papertype, file=fh) + print("%%%%BoundingBox: %d %d %d %d" % bbox, file=fh) + if not isEPSF: + print("%%Pages: 1", file=fh) + print("%%EndComments", file=fh) + + Ndict = len(psDefs) + print("%%BeginProlog", file=fh) + if not rcParams['ps.useafm']: + Ndict += len(ps_renderer.used_characters) + print("/mpldict %d dict def" % Ndict, file=fh) + print("mpldict begin", file=fh) + for d in psDefs: + d = d.strip() + for l in d.split('\n'): + print(l.strip(), file=fh) + if not rcParams['ps.useafm']: + for font_filename, chars in six.itervalues( + ps_renderer.used_characters): + if len(chars): + font = get_font(font_filename) + glyph_ids = [] + for c in chars: + gind = font.get_char_index(c) + glyph_ids.append(gind) + + fonttype = rcParams['ps.fonttype'] + + # Can not use more than 255 characters from a + # single font for Type 3 + if len(glyph_ids) > 255: + fonttype = 42 + + # The ttf to ps (subsetting) support doesn't work for + # OpenType fonts that are Postscript inside (like the + # STIX fonts). This will simply turn that off to avoid + # errors. + if is_opentype_cff_font(font_filename): + raise RuntimeError( + "OpenType CFF fonts can not be saved using " + "the internal Postscript backend at this " + "time; consider using the Cairo backend") + else: + fh.flush() + convert_ttf_to_ps( + font_filename.encode( + sys.getfilesystemencoding()), + fh, fonttype, glyph_ids) + print("end", file=fh) + print("%%EndProlog", file=fh) + + if not isEPSF: + print("%%Page: 1 1", file=fh) + print("mpldict begin", file=fh) + + print("%s translate" % _nums_to_str(xo, yo), file=fh) + if rotation: + print("%d rotate" % rotation, file=fh) + print("%s clipbox" % _nums_to_str(width*72, height*72, 0, 0), + file=fh) + + # write the figure + content = self._pswriter.getvalue() + if not isinstance(content, six.text_type): + content = content.decode('ascii') + print(content, file=fh) + + # write the trailer + print("end", file=fh) + print("showpage", file=fh) + if not isEPSF: + print("%%EOF", file=fh) + fh.flush() + + if rcParams['ps.usedistiller']: + # We are going to use an external program to process the output. + # Write to a temporary file. + fd, tmpfile = mkstemp() + try: + with io.open(fd, 'w', encoding='latin-1') as fh: + print_figure_impl(fh) + if rcParams['ps.usedistiller'] == 'ghostscript': + gs_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) + elif rcParams['ps.usedistiller'] == 'xpdf': + xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox) + + _move_path_to_path_or_stream(tmpfile, outfile) + finally: + if os.path.isfile(tmpfile): + os.unlink(tmpfile) + + else: + # Write directly to outfile. + if passed_in_file_object: + requires_unicode = file_requires_unicode(outfile) + + if (not requires_unicode and + (six.PY3 or not isinstance(outfile, StringIO))): + fh = io.TextIOWrapper(outfile, encoding="latin-1") + + # Prevent the io.TextIOWrapper from closing the + # underlying file + def do_nothing(): + pass + fh.close = do_nothing + else: + fh = outfile + + print_figure_impl(fh) + else: + with io.open(outfile, 'w', encoding='latin-1') as fh: + print_figure_impl(fh) + + def _print_figure_tex(self, outfile, format, dpi, facecolor, edgecolor, + orientation, isLandscape, papertype, metadata=None, + **kwargs): + """ + If text.usetex is True in rc, a temporary pair of tex/eps files + are created to allow tex to manage the text layout via the PSFrags + package. These files are processed to yield the final ps or eps file. + + metadata must be a dictionary. Currently, only the value for + the key 'Creator' is used. + """ + isEPSF = format == 'eps' + if isinstance(outfile, six.string_types): + title = outfile + elif is_writable_file_like(outfile): + title = None + else: + raise ValueError("outfile must be a path or a file-like object") + + self.figure.dpi = 72 # ignore the dpi kwarg + width, height = self.figure.get_size_inches() + xo = 0 + yo = 0 + + l, b, w, h = self.figure.bbox.bounds + llx = xo + lly = yo + urx = llx + w + ury = lly + h + bbox = (llx, lly, urx, ury) + + # generate PostScript code for the figure and store it in a string + origfacecolor = self.figure.get_facecolor() + origedgecolor = self.figure.get_edgecolor() + self.figure.set_facecolor(facecolor) + self.figure.set_edgecolor(edgecolor) + + dryrun = kwargs.get("dryrun", False) + if dryrun: + class NullWriter(object): + def write(self, *kl, **kwargs): + pass + + self._pswriter = NullWriter() + else: + self._pswriter = io.StringIO() + + # mixed mode rendering + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + ps_renderer = self._renderer_class(width, height, + self._pswriter, imagedpi=dpi) + renderer = MixedModeRenderer(self.figure, + width, height, dpi, ps_renderer, + bbox_inches_restore=_bbox_inches_restore) + + self.figure.draw(renderer) + + if dryrun: # return immediately if dryrun (tightbbox=True) + return + + self.figure.set_facecolor(origfacecolor) + self.figure.set_edgecolor(origedgecolor) + + # check for custom metadata + if metadata is not None and 'Creator' in metadata: + creator_str = metadata['Creator'] + else: + creator_str = "matplotlib version " + __version__ + \ + ", http://matplotlib.org/" + + # write to a temp file, we'll move it to outfile when done + + fd, tmpfile = mkstemp() + try: + with io.open(fd, 'w', encoding='latin-1') as fh: + # write the Encapsulated PostScript headers + print("%!PS-Adobe-3.0 EPSF-3.0", file=fh) + if title: + print("%%Title: "+title, file=fh) + print("%%Creator: " + creator_str, file=fh) + # get source date from SOURCE_DATE_EPOCH, if set + # See https://reproducible-builds.org/specs/source-date-epoch/ + source_date_epoch = os.getenv("SOURCE_DATE_EPOCH") + if source_date_epoch: + source_date = datetime.datetime.utcfromtimestamp( + int(source_date_epoch)).strftime( + "%a %b %d %H:%M:%S %Y") + else: + source_date = time.ctime() + print("%%CreationDate: "+source_date, file=fh) + print("%%%%BoundingBox: %d %d %d %d" % bbox, file=fh) + print("%%EndComments", file=fh) + + Ndict = len(psDefs) + print("%%BeginProlog", file=fh) + print("/mpldict %d dict def" % Ndict, file=fh) + print("mpldict begin", file=fh) + for d in psDefs: + d = d.strip() + for l in d.split('\n'): + print(l.strip(), file=fh) + print("end", file=fh) + print("%%EndProlog", file=fh) + + print("mpldict begin", file=fh) + print("%s translate" % _nums_to_str(xo, yo), file=fh) + print("%s clipbox" % _nums_to_str(width*72, height*72, 0, 0), + file=fh) + + # write the figure + print(self._pswriter.getvalue(), file=fh) + + # write the trailer + print("end", file=fh) + print("showpage", file=fh) + fh.flush() + + if isLandscape: # now we are ready to rotate + isLandscape = True + width, height = height, width + bbox = (lly, llx, ury, urx) + + # set the paper size to the figure size if isEPSF. The + # resulting ps file has the given size with correct bounding + # box so that there is no need to call 'pstoeps' + if isEPSF: + paperWidth, paperHeight = self.figure.get_size_inches() + if isLandscape: + paperWidth, paperHeight = paperHeight, paperWidth + else: + temp_papertype = _get_papertype(width, height) + if papertype == 'auto': + papertype = temp_papertype + paperWidth, paperHeight = papersize[temp_papertype] + else: + paperWidth, paperHeight = papersize[papertype] + if (width > paperWidth or height > paperHeight) and isEPSF: + paperWidth, paperHeight = papersize[temp_papertype] + _log.info('Your figure is too big to fit on %s paper. ' + '%s paper will be used to prevent clipping.', + papertype, temp_papertype) + + texmanager = ps_renderer.get_texmanager() + font_preamble = texmanager.get_font_preamble() + custom_preamble = texmanager.get_custom_preamble() + + psfrag_rotated = convert_psfrags(tmpfile, ps_renderer.psfrag, + font_preamble, + custom_preamble, paperWidth, + paperHeight, + orientation) + + if (rcParams['ps.usedistiller'] == 'ghostscript' + or rcParams['text.usetex']): + gs_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox, + rotated=psfrag_rotated) + elif rcParams['ps.usedistiller'] == 'xpdf': + xpdf_distill(tmpfile, isEPSF, ptype=papertype, bbox=bbox, + rotated=psfrag_rotated) + + _move_path_to_path_or_stream(tmpfile, outfile) + finally: + if os.path.isfile(tmpfile): + os.unlink(tmpfile) + + +def convert_psfrags(tmpfile, psfrags, font_preamble, custom_preamble, + paperWidth, paperHeight, orientation): + """ + When we want to use the LaTeX backend with postscript, we write PSFrag tags + to a temporary postscript file, each one marking a position for LaTeX to + render some text. convert_psfrags generates a LaTeX document containing the + commands to convert those tags to text. LaTeX/dvips produces the postscript + file that includes the actual text. + """ + tmpdir = os.path.split(tmpfile)[0] + epsfile = tmpfile+'.eps' + shutil.move(tmpfile, epsfile) + latexfile = tmpfile+'.tex' + dvifile = tmpfile+'.dvi' + psfile = tmpfile+'.ps' + + if orientation == 'landscape': + angle = 90 + else: + angle = 0 + + if rcParams['text.latex.unicode']: + unicode_preamble = """\\usepackage{ucs} +\\usepackage[utf8x]{inputenc}""" + else: + unicode_preamble = '' + + s = """\\documentclass{article} +%s +%s +%s +\\usepackage[dvips, papersize={%sin,%sin}, body={%sin,%sin}, margin={0in,0in}]{geometry} +\\usepackage{psfrag} +\\usepackage[dvips]{graphicx} +\\usepackage{color} +\\pagestyle{empty} +\\begin{document} +\\begin{figure} +\\centering +\\leavevmode +%s +\\includegraphics*[angle=%s]{%s} +\\end{figure} +\\end{document} +"""% (font_preamble, unicode_preamble, custom_preamble, paperWidth, paperHeight, + paperWidth, paperHeight, + '\n'.join(psfrags), angle, os.path.split(epsfile)[-1]) + + with io.open(latexfile, 'wb') as latexh: + if rcParams['text.latex.unicode']: + latexh.write(s.encode('utf8')) + else: + try: + latexh.write(s.encode('ascii')) + except UnicodeEncodeError: + _log.info("You are using unicode and latex, but have " + "not enabled the matplotlib 'text.latex.unicode' " + "rcParam.") + raise + + # Replace \\ for / so latex does not think there is a function call + latexfile = latexfile.replace("\\", "/") + # Replace ~ so Latex does not think it is line break + latexfile = latexfile.replace("~", "\\string~") + command = [str("latex"), "-interaction=nonstopmode", + '"%s"' % latexfile] + _log.debug('%s', command) + try: + report = subprocess.check_output(command, cwd=tmpdir, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as exc: + raise RuntimeError( + ('LaTeX was not able to process the following ' + 'file:\n%s\n\n' + 'Here is the full report generated by LaTeX:\n%s ' + '\n\n' % (latexfile, + exc.output.decode("utf-8")))) + _log.debug(report) + + command = [str('dvips'), '-q', '-R0', '-o', os.path.basename(psfile), + os.path.basename(dvifile)] + _log.debug(command) + try: + report = subprocess.check_output(command, cwd=tmpdir, + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as exc: + raise RuntimeError( + ('dvips was not able to process the following ' + 'file:\n%s\n\n' + 'Here is the full report generated by dvips:\n%s ' + '\n\n' % (dvifile, + exc.output.decode("utf-8")))) + _log.debug(report) + os.remove(epsfile) + shutil.move(psfile, tmpfile) + + # check if the dvips created a ps in landscape paper. Somehow, + # above latex+dvips results in a ps file in a landscape mode for a + # certain figure sizes (e.g., 8.3in,5.8in which is a5). And the + # bounding box of the final output got messed up. We check see if + # the generated ps file is in landscape and return this + # information. The return value is used in pstoeps step to recover + # the correct bounding box. 2010-06-05 JJL + with io.open(tmpfile) as fh: + if "Landscape" in fh.read(1000): + psfrag_rotated = True + else: + psfrag_rotated = False + + if not debugPS: + for fname in glob.glob(tmpfile+'.*'): + os.remove(fname) + + return psfrag_rotated + + +def gs_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False): + """ + Use ghostscript's pswrite or epswrite device to distill a file. + This yields smaller files without illegal encapsulated postscript + operators. The output is low-level, converting text to outlines. + """ + + if eps: + paper_option = "-dEPSCrop" + else: + paper_option = "-sPAPERSIZE=%s" % ptype + + psfile = tmpfile + '.ps' + dpi = rcParams['ps.distiller.res'] + + gs_exe = ps_backend_helper.gs_exe + if ps_backend_helper.supports_ps2write: # gs version >= 9 + device_name = "ps2write" + else: + device_name = "pswrite" + + command = [str(gs_exe), "-dBATCH", "-dNOPAUSE", "-r%d" % dpi, + "-sDEVICE=%s" % device_name, paper_option, + "-sOutputFile=%s" % psfile, tmpfile] + _log.debug(command) + try: + report = subprocess.check_output(command, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as exc: + raise RuntimeError( + ('ghostscript was not able to process your image.\n' + 'Here is the full report generated by ghostscript:\n%s ' + '\n\n' % exc.output.decode("utf-8"))) + _log.debug(report) + os.remove(tmpfile) + shutil.move(psfile, tmpfile) + + + # While it is best if above steps preserve the original bounding + # box, there seem to be cases when it is not. For those cases, + # the original bbox can be restored during the pstoeps step. + + if eps: + # For some versions of gs, above steps result in an ps file + # where the original bbox is no more correct. Do not adjust + # bbox for now. + if ps_backend_helper.supports_ps2write: + # fo gs version >= 9 w/ ps2write device + pstoeps(tmpfile, bbox, rotated=rotated) + else: + pstoeps(tmpfile) + + +def xpdf_distill(tmpfile, eps=False, ptype='letter', bbox=None, rotated=False): + """ + Use ghostscript's ps2pdf and xpdf's/poppler's pdftops to distill a file. + This yields smaller files without illegal encapsulated postscript + operators. This distiller is preferred, generating high-level postscript + output that treats text as text. + """ + pdffile = tmpfile + '.pdf' + psfile = tmpfile + '.ps' + + # Pass options as `-foo#bar` instead of `-foo=bar` to keep Windows happy + # (https://www.ghostscript.com/doc/9.22/Use.htm#MS_Windows). + command = [str("ps2pdf"), + "-dAutoFilterColorImages#false", + "-dAutoFilterGrayImages#false", + "-dAutoRotatePages#false", + "-sGrayImageFilter#FlateEncode", + "-sColorImageFilter#FlateEncode", + "-dEPSCrop" if eps else "-sPAPERSIZE#%s" % ptype, + tmpfile, pdffile] + _log.debug(command) + + try: + report = subprocess.check_output(command, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as exc: + raise RuntimeError( + ('ps2pdf was not able to process your image.\n' + 'Here is the full report generated by ps2pdf:\n%s ' + '\n\n' % exc.output.decode("utf-8"))) + _log.debug(report) + + command = [str("pdftops"), "-paper", "match", "-level2", pdffile, psfile] + _log.debug(command) + try: + report = subprocess.check_output(command, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as exc: + raise RuntimeError( + ('pdftops was not able to process your image.\n' + 'Here is the full report generated by pdftops:\n%s ' + '\n\n' % exc.output.decode("utf-8"))) + _log.debug(report) + os.remove(tmpfile) + shutil.move(psfile, tmpfile) + + if eps: + pstoeps(tmpfile) + + for fname in glob.glob(tmpfile+'.*'): + os.remove(fname) + + +def get_bbox_header(lbrt, rotated=False): + """ + return a postscript header stringfor the given bbox lbrt=(l, b, r, t). + Optionally, return rotate command. + """ + + l, b, r, t = lbrt + if rotated: + rotate = "%.2f %.2f translate\n90 rotate" % (l+r, 0) + else: + rotate = "" + bbox_info = '%%%%BoundingBox: %d %d %d %d' % (l, b, np.ceil(r), np.ceil(t)) + hires_bbox_info = '%%%%HiResBoundingBox: %.6f %.6f %.6f %.6f' % (l, b, r, t) + + return '\n'.join([bbox_info, hires_bbox_info]), rotate + + +# get_bbox is deprecated. I don't see any reason to use ghostscript to +# find the bounding box, as the required bounding box is alread known. +def get_bbox(tmpfile, bbox): + """ + Use ghostscript's bbox device to find the center of the bounding box. + Return an appropriately sized bbox centered around that point. A bit of a + hack. + """ + + gs_exe = ps_backend_helper.gs_exe + command = [gs_exe, "-dBATCH", "-dNOPAUSE", "-sDEVICE=bbox", "%s" % tmpfile] + _log.debug(command) + p = subprocess.Popen(command, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + close_fds=True) + (stdout, stderr) = (p.stdout, p.stderr) + _log.debug(stdout.read()) + bbox_info = stderr.read() + _log.info(bbox_info) + bbox_found = re.search('%%HiResBoundingBox: .*', bbox_info) + if bbox_found: + bbox_info = bbox_found.group() + else: + raise RuntimeError('Ghostscript was not able to extract a bounding box.\ +Here is the Ghostscript output:\n\n%s' % bbox_info) + l, b, r, t = [float(i) for i in bbox_info.split()[-4:]] + + # this is a hack to deal with the fact that ghostscript does not return the + # intended bbox, but a tight bbox. For now, we just center the ink in the + # intended bbox. This is not ideal, users may intend the ink to not be + # centered. + if bbox is None: + l, b, r, t = (l-1, b-1, r+1, t+1) + else: + x = (l+r)/2 + y = (b+t)/2 + dx = (bbox[2]-bbox[0])/2 + dy = (bbox[3]-bbox[1])/2 + l,b,r,t = (x-dx, y-dy, x+dx, y+dy) + + bbox_info = '%%%%BoundingBox: %d %d %d %d' % (l, b, np.ceil(r), np.ceil(t)) + hires_bbox_info = '%%%%HiResBoundingBox: %.6f %.6f %.6f %.6f' % (l, b, r, t) + + return '\n'.join([bbox_info, hires_bbox_info]) + + +def pstoeps(tmpfile, bbox=None, rotated=False): + """ + Convert the postscript to encapsulated postscript. The bbox of + the eps file will be replaced with the given *bbox* argument. If + None, original bbox will be used. + """ + + # if rotated==True, the output eps file need to be rotated + if bbox: + bbox_info, rotate = get_bbox_header(bbox, rotated=rotated) + else: + bbox_info, rotate = None, None + + epsfile = tmpfile + '.eps' + with io.open(epsfile, 'wb') as epsh, io.open(tmpfile, 'rb') as tmph: + write = epsh.write + # Modify the header: + for line in tmph: + if line.startswith(b'%!PS'): + write(b"%!PS-Adobe-3.0 EPSF-3.0\n") + if bbox: + write(bbox_info.encode('ascii') + b'\n') + elif line.startswith(b'%%EndComments'): + write(line) + write(b'%%BeginProlog\n' + b'save\n' + b'countdictstack\n' + b'mark\n' + b'newpath\n' + b'/showpage {} def\n' + b'/setpagedevice {pop} def\n' + b'%%EndProlog\n' + b'%%Page 1 1\n') + if rotate: + write(rotate.encode('ascii') + b'\n') + break + elif bbox and line.startswith((b'%%Bound', b'%%HiResBound', + b'%%DocumentMedia', b'%%Pages')): + pass + else: + write(line) + # Now rewrite the rest of the file, and modify the trailer. + # This is done in a second loop such that the header of the embedded + # eps file is not modified. + for line in tmph: + if line.startswith(b'%%EOF'): + write(b'cleartomark\n' + b'countdictstack\n' + b'exch sub { end } repeat\n' + b'restore\n' + b'showpage\n' + b'%%EOF\n') + elif line.startswith(b'%%PageBoundingBox'): + pass + else: + write(line) + + os.remove(tmpfile) + shutil.move(epsfile, tmpfile) + + +class FigureManagerPS(FigureManagerBase): + pass + + +# The following Python dictionary psDefs contains the entries for the +# PostScript dictionary mpldict. This dictionary implements most of +# the matplotlib primitives and some abbreviations. +# +# References: +# http://www.adobe.com/products/postscript/pdfs/PLRM.pdf +# http://www.mactech.com/articles/mactech/Vol.09/09.04/PostscriptTutorial/ +# http://www.math.ubc.ca/people/faculty/cass/graphics/text/www/ +# + +# The usage comments use the notation of the operator summary +# in the PostScript Language reference manual. +psDefs = [ + # x y *m* - + "/m { moveto } bind def", + # x y *l* - + "/l { lineto } bind def", + # x y *r* - + "/r { rlineto } bind def", + # x1 y1 x2 y2 x y *c* - + "/c { curveto } bind def", + # *closepath* - + "/cl { closepath } bind def", + # w h x y *box* - + """/box { + m + 1 index 0 r + 0 exch r + neg 0 r + cl + } bind def""", + # w h x y *clipbox* - + """/clipbox { + box + clip + newpath + } bind def""", +] + + +@_Backend.export +class _BackendPS(_Backend): + FigureCanvas = FigureCanvasPS + FigureManager = FigureManagerPS diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4.py new file mode 100644 index 00000000000..92463a6573a --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4.py @@ -0,0 +1,15 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from .backend_qt5 import ( + backend_version, SPECIAL_KEYS, SUPER, ALT, CTRL, SHIFT, MODIFIER_KEYS, + cursord, _create_qApp, _BackendQT5, TimerQT, MainWindow, FigureManagerQT, + NavigationToolbar2QT, SubplotToolQt, error_msg_qt, exception_handler) +from .backend_qt5 import FigureCanvasQT as FigureCanvasQT5 + + +@_BackendQT5.export +class _BackendQT4(_BackendQT5): + pass diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4agg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4agg.py new file mode 100644 index 00000000000..7e90a09bf35 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4agg.py @@ -0,0 +1,15 @@ +""" +Render to qt from agg +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from .backend_qt5agg import ( + _BackendQT5Agg, FigureCanvasQTAgg, FigureManagerQT, NavigationToolbar2QT) + + +@_BackendQT5Agg.export +class _BackendQT4Agg(_BackendQT5Agg): + pass diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4cairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4cairo.py new file mode 100644 index 00000000000..f94851da382 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt4cairo.py @@ -0,0 +1,6 @@ +from .backend_qt5cairo import _BackendQT5Cairo + + +@_BackendQT5Cairo.export +class _BackendQT4Cairo(_BackendQT5Cairo): + pass diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5.py new file mode 100644 index 00000000000..20b0b5bc1bd --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5.py @@ -0,0 +1,1119 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) +import six + +import functools +import os +import re +import signal +import sys +from six import unichr +import traceback + +import matplotlib + +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2, + TimerBase, cursors, ToolContainerBase, StatusbarBase) +import matplotlib.backends.qt_editor.figureoptions as figureoptions +from matplotlib.backends.qt_editor.formsubplottool import UiSubplotTool +from matplotlib.figure import Figure +from matplotlib.backend_managers import ToolManager +from matplotlib import backend_tools + +from .qt_compat import ( + QtCore, QtGui, QtWidgets, _getSaveFileName, is_pyqt5, __version__, QT_API) + +backend_version = __version__ + +# SPECIAL_KEYS are keys that do *not* return their unicode name +# instead they have manually specified names +SPECIAL_KEYS = {QtCore.Qt.Key_Control: 'control', + QtCore.Qt.Key_Shift: 'shift', + QtCore.Qt.Key_Alt: 'alt', + QtCore.Qt.Key_Meta: 'super', + QtCore.Qt.Key_Return: 'enter', + QtCore.Qt.Key_Left: 'left', + QtCore.Qt.Key_Up: 'up', + QtCore.Qt.Key_Right: 'right', + QtCore.Qt.Key_Down: 'down', + QtCore.Qt.Key_Escape: 'escape', + QtCore.Qt.Key_F1: 'f1', + QtCore.Qt.Key_F2: 'f2', + QtCore.Qt.Key_F3: 'f3', + QtCore.Qt.Key_F4: 'f4', + QtCore.Qt.Key_F5: 'f5', + QtCore.Qt.Key_F6: 'f6', + QtCore.Qt.Key_F7: 'f7', + QtCore.Qt.Key_F8: 'f8', + QtCore.Qt.Key_F9: 'f9', + QtCore.Qt.Key_F10: 'f10', + QtCore.Qt.Key_F11: 'f11', + QtCore.Qt.Key_F12: 'f12', + QtCore.Qt.Key_Home: 'home', + QtCore.Qt.Key_End: 'end', + QtCore.Qt.Key_PageUp: 'pageup', + QtCore.Qt.Key_PageDown: 'pagedown', + QtCore.Qt.Key_Tab: 'tab', + QtCore.Qt.Key_Backspace: 'backspace', + QtCore.Qt.Key_Enter: 'enter', + QtCore.Qt.Key_Insert: 'insert', + QtCore.Qt.Key_Delete: 'delete', + QtCore.Qt.Key_Pause: 'pause', + QtCore.Qt.Key_SysReq: 'sysreq', + QtCore.Qt.Key_Clear: 'clear', } + +# define which modifier keys are collected on keyboard events. +# elements are (mpl names, Modifier Flag, Qt Key) tuples +SUPER = 0 +ALT = 1 +CTRL = 2 +SHIFT = 3 +MODIFIER_KEYS = [('super', QtCore.Qt.MetaModifier, QtCore.Qt.Key_Meta), + ('alt', QtCore.Qt.AltModifier, QtCore.Qt.Key_Alt), + ('ctrl', QtCore.Qt.ControlModifier, QtCore.Qt.Key_Control), + ('shift', QtCore.Qt.ShiftModifier, QtCore.Qt.Key_Shift), + ] + +if sys.platform == 'darwin': + # in OSX, the control and super (aka cmd/apple) keys are switched, so + # switch them back. + SPECIAL_KEYS.update({QtCore.Qt.Key_Control: 'cmd', # cmd/apple key + QtCore.Qt.Key_Meta: 'control', + }) + MODIFIER_KEYS[0] = ('cmd', QtCore.Qt.ControlModifier, + QtCore.Qt.Key_Control) + MODIFIER_KEYS[2] = ('ctrl', QtCore.Qt.MetaModifier, + QtCore.Qt.Key_Meta) + + +cursord = { + cursors.MOVE: QtCore.Qt.SizeAllCursor, + cursors.HAND: QtCore.Qt.PointingHandCursor, + cursors.POINTER: QtCore.Qt.ArrowCursor, + cursors.SELECT_REGION: QtCore.Qt.CrossCursor, + cursors.WAIT: QtCore.Qt.WaitCursor, + } + + +# make place holder +qApp = None + + +def _create_qApp(): + """ + Only one qApp can exist at a time, so check before creating one. + """ + global qApp + + if qApp is None: + app = QtWidgets.QApplication.instance() + if app is None: + # check for DISPLAY env variable on X11 build of Qt + if is_pyqt5(): + try: + from PyQt5 import QtX11Extras + is_x11_build = True + except ImportError: + is_x11_build = False + else: + is_x11_build = hasattr(QtGui, "QX11Info") + if is_x11_build: + display = os.environ.get('DISPLAY') + if display is None or not re.search(r':\d', display): + raise RuntimeError('Invalid DISPLAY variable') + + qApp = QtWidgets.QApplication([b"matplotlib"]) + qApp.lastWindowClosed.connect(qApp.quit) + else: + qApp = app + + if is_pyqt5(): + try: + qApp.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps) + qApp.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling) + except AttributeError: + pass + + +def _allow_super_init(__init__): + """ + Decorator for ``__init__`` to allow ``super().__init__`` on PyQt4/PySide2. + """ + + if QT_API == "PyQt5": + + return __init__ + + else: + # To work around lack of cooperative inheritance in PyQt4, PySide, + # and PySide2, when calling FigureCanvasQT.__init__, we temporarily + # patch QWidget.__init__ by a cooperative version, that first calls + # QWidget.__init__ with no additional arguments, and then finds the + # next class in the MRO with an __init__ that does support cooperative + # inheritance (i.e., not defined by the PyQt4, PySide, PySide2, sip + # or Shiboken packages), and manually call its `__init__`, once again + # passing the additional arguments. + + qwidget_init = QtWidgets.QWidget.__init__ + + def cooperative_qwidget_init(self, *args, **kwargs): + qwidget_init(self) + mro = type(self).__mro__ + next_coop_init = next( + cls for cls in mro[mro.index(QtWidgets.QWidget) + 1:] + if cls.__module__.split(".")[0] not in [ + "PyQt4", "sip", "PySide", "PySide2", "Shiboken"]) + next_coop_init.__init__(self, *args, **kwargs) + + @functools.wraps(__init__) + def wrapper(self, **kwargs): + try: + QtWidgets.QWidget.__init__ = cooperative_qwidget_init + __init__(self, **kwargs) + finally: + # Restore __init__ + QtWidgets.QWidget.__init__ = qwidget_init + + return wrapper + + +class TimerQT(TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` that uses Qt timer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should + operate as single shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + + def __init__(self, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) + + # Create a new timer and connect the timeout() signal to the + # _on_timer method. + self._timer = QtCore.QTimer() + self._timer.timeout.connect(self._on_timer) + self._timer_set_interval() + + def _timer_set_single_shot(self): + self._timer.setSingleShot(self._single) + + def _timer_set_interval(self): + self._timer.setInterval(self._interval) + + def _timer_start(self): + self._timer.start() + + def _timer_stop(self): + self._timer.stop() + + +class FigureCanvasQT(QtWidgets.QWidget, FigureCanvasBase): + + # map Qt button codes to MouseEvent's ones: + buttond = {QtCore.Qt.LeftButton: 1, + QtCore.Qt.MidButton: 2, + QtCore.Qt.RightButton: 3, + # QtCore.Qt.XButton1: None, + # QtCore.Qt.XButton2: None, + } + + @_allow_super_init + def __init__(self, figure): + _create_qApp() + super(FigureCanvasQT, self).__init__(figure=figure) + + self.figure = figure + # We don't want to scale up the figure DPI more than once. + # Note, we don't handle a signal for changing DPI yet. + figure._original_dpi = figure.dpi + self._update_figure_dpi() + # In cases with mixed resolution displays, we need to be careful if the + # dpi_ratio changes - in this case we need to resize the canvas + # accordingly. We could watch for screenChanged events from Qt, but + # the issue is that we can't guarantee this will be emitted *before* + # the first paintEvent for the canvas, so instead we keep track of the + # dpi_ratio value here and in paintEvent we resize the canvas if + # needed. + self._dpi_ratio_prev = None + + self._draw_pending = False + self._is_drawing = False + self._draw_rect_callback = lambda painter: None + + self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent) + self.setMouseTracking(True) + self.resize(*self.get_width_height()) + # Key auto-repeat enabled by default + self._keyautorepeat = True + + palette = QtGui.QPalette(QtCore.Qt.white) + self.setPalette(palette) + + def _update_figure_dpi(self): + dpi = self._dpi_ratio * self.figure._original_dpi + self.figure._set_dpi(dpi, forward=False) + + @property + def _dpi_ratio(self): + # Not available on Qt4 or some older Qt5. + try: + # self.devicePixelRatio() returns 0 in rare cases + return self.devicePixelRatio() or 1 + except AttributeError: + return 1 + + def _update_dpi(self): + # As described in __init__ above, we need to be careful in cases with + # mixed resolution displays if dpi_ratio is changing between painting + # events. + # Return whether we triggered a resizeEvent (and thus a paintEvent) + # from within this function. + if self._dpi_ratio != self._dpi_ratio_prev: + # We need to update the figure DPI. + self._update_figure_dpi() + self._dpi_ratio_prev = self._dpi_ratio + # The easiest way to resize the canvas is to emit a resizeEvent + # since we implement all the logic for resizing the canvas for + # that event. + event = QtGui.QResizeEvent(self.size(), self.size()) + self.resizeEvent(event) + # resizeEvent triggers a paintEvent itself, so we exit this one + # (after making sure that the event is immediately handled). + return True + return False + + def get_width_height(self): + w, h = FigureCanvasBase.get_width_height(self) + return int(w / self._dpi_ratio), int(h / self._dpi_ratio) + + def enterEvent(self, event): + FigureCanvasBase.enter_notify_event(self, guiEvent=event) + + def leaveEvent(self, event): + QtWidgets.QApplication.restoreOverrideCursor() + FigureCanvasBase.leave_notify_event(self, guiEvent=event) + + def mouseEventCoords(self, pos): + """Calculate mouse coordinates in physical pixels + + Qt5 use logical pixels, but the figure is scaled to physical + pixels for rendering. Transform to physical pixels so that + all of the down-stream transforms work as expected. + + Also, the origin is different and needs to be corrected. + + """ + dpi_ratio = self._dpi_ratio + x = pos.x() + # flip y so y=0 is bottom of canvas + y = self.figure.bbox.height / dpi_ratio - pos.y() + return x * dpi_ratio, y * dpi_ratio + + def mousePressEvent(self, event): + x, y = self.mouseEventCoords(event.pos()) + button = self.buttond.get(event.button()) + if button is not None: + FigureCanvasBase.button_press_event(self, x, y, button, + guiEvent=event) + + def mouseDoubleClickEvent(self, event): + x, y = self.mouseEventCoords(event.pos()) + button = self.buttond.get(event.button()) + if button is not None: + FigureCanvasBase.button_press_event(self, x, y, + button, dblclick=True, + guiEvent=event) + + def mouseMoveEvent(self, event): + x, y = self.mouseEventCoords(event) + FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event) + + def mouseReleaseEvent(self, event): + x, y = self.mouseEventCoords(event) + button = self.buttond.get(event.button()) + if button is not None: + FigureCanvasBase.button_release_event(self, x, y, button, + guiEvent=event) + + if is_pyqt5(): + def wheelEvent(self, event): + x, y = self.mouseEventCoords(event) + # from QWheelEvent::delta doc + if event.pixelDelta().x() == 0 and event.pixelDelta().y() == 0: + steps = event.angleDelta().y() / 120 + else: + steps = event.pixelDelta().y() + if steps: + FigureCanvasBase.scroll_event( + self, x, y, steps, guiEvent=event) + else: + def wheelEvent(self, event): + x = event.x() + # flipy so y=0 is bottom of canvas + y = self.figure.bbox.height - event.y() + # from QWheelEvent::delta doc + steps = event.delta() / 120 + if event.orientation() == QtCore.Qt.Vertical: + FigureCanvasBase.scroll_event( + self, x, y, steps, guiEvent=event) + + def keyPressEvent(self, event): + key = self._get_key(event) + if key is not None: + FigureCanvasBase.key_press_event(self, key, guiEvent=event) + + def keyReleaseEvent(self, event): + key = self._get_key(event) + if key is not None: + FigureCanvasBase.key_release_event(self, key, guiEvent=event) + + @property + def keyAutoRepeat(self): + """ + If True, enable auto-repeat for key events. + """ + return self._keyautorepeat + + @keyAutoRepeat.setter + def keyAutoRepeat(self, val): + self._keyautorepeat = bool(val) + + def resizeEvent(self, event): + # _dpi_ratio_prev will be set the first time the canvas is painted, and + # the rendered buffer is useless before anyways. + if self._dpi_ratio_prev is None: + return + w = event.size().width() * self._dpi_ratio + h = event.size().height() * self._dpi_ratio + dpival = self.figure.dpi + winch = w / dpival + hinch = h / dpival + self.figure.set_size_inches(winch, hinch, forward=False) + # pass back into Qt to let it finish + QtWidgets.QWidget.resizeEvent(self, event) + # emit our resize events + FigureCanvasBase.resize_event(self) + + def sizeHint(self): + w, h = self.get_width_height() + return QtCore.QSize(w, h) + + def minumumSizeHint(self): + return QtCore.QSize(10, 10) + + def _get_key(self, event): + if not self._keyautorepeat and event.isAutoRepeat(): + return None + + event_key = event.key() + event_mods = int(event.modifiers()) # actually a bitmask + + # get names of the pressed modifier keys + # bit twiddling to pick out modifier keys from event_mods bitmask, + # if event_key is a MODIFIER, it should not be duplicated in mods + mods = [name for name, mod_key, qt_key in MODIFIER_KEYS + if event_key != qt_key and (event_mods & mod_key) == mod_key] + try: + # for certain keys (enter, left, backspace, etc) use a word for the + # key, rather than unicode + key = SPECIAL_KEYS[event_key] + except KeyError: + # unicode defines code points up to 0x0010ffff + # QT will use Key_Codes larger than that for keyboard keys that are + # are not unicode characters (like multimedia keys) + # skip these + # if you really want them, you should add them to SPECIAL_KEYS + MAX_UNICODE = 0x10ffff + if event_key > MAX_UNICODE: + return None + + key = unichr(event_key) + # qt delivers capitalized letters. fix capitalization + # note that capslock is ignored + if 'shift' in mods: + mods.remove('shift') + else: + key = key.lower() + + mods.reverse() + return '+'.join(mods + [key]) + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of + :class:`backend_bases.Timer`. This is useful for getting + periodic events through the backend's native event + loop. Implemented only for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + + """ + return TimerQT(*args, **kwargs) + + def flush_events(self): + qApp.processEvents() + + def start_event_loop(self, timeout=0): + if hasattr(self, "_event_loop") and self._event_loop.isRunning(): + raise RuntimeError("Event loop already running") + self._event_loop = event_loop = QtCore.QEventLoop() + if timeout: + timer = QtCore.QTimer.singleShot(timeout * 1000, event_loop.quit) + event_loop.exec_() + + def stop_event_loop(self, event=None): + if hasattr(self, "_event_loop"): + self._event_loop.quit() + + def draw(self): + """Render the figure, and queue a request for a Qt draw. + """ + # The renderer draw is done here; delaying causes problems with code + # that uses the result of the draw() to update plot elements. + if self._is_drawing: + return + self._is_drawing = True + try: + super(FigureCanvasQT, self).draw() + finally: + self._is_drawing = False + self.update() + + def draw_idle(self): + """Queue redraw of the Agg buffer and request Qt paintEvent. + """ + # The Agg draw needs to be handled by the same thread matplotlib + # modifies the scene graph from. Post Agg draw request to the + # current event loop in order to ensure thread affinity and to + # accumulate multiple draw requests from event handling. + # TODO: queued signal connection might be safer than singleShot + if not (getattr(self, '_draw_pending', False) or + getattr(self, '_is_drawing', False)): + self._draw_pending = True + QtCore.QTimer.singleShot(0, self._draw_idle) + + def _draw_idle(self): + if self.height() < 0 or self.width() < 0: + self._draw_pending = False + if not self._draw_pending: + return + try: + self.draw() + except Exception: + # Uncaught exceptions are fatal for PyQt5, so catch them instead. + traceback.print_exc() + finally: + self._draw_pending = False + + def drawRectangle(self, rect): + # Draw the zoom rectangle to the QPainter. _draw_rect_callback needs + # to be called at the end of paintEvent. + if rect is not None: + def _draw_rect_callback(painter): + pen = QtGui.QPen(QtCore.Qt.black, 1 / self._dpi_ratio, + QtCore.Qt.DotLine) + painter.setPen(pen) + painter.drawRect(*(pt / self._dpi_ratio for pt in rect)) + else: + def _draw_rect_callback(painter): + return + self._draw_rect_callback = _draw_rect_callback + self.update() + + +class MainWindow(QtWidgets.QMainWindow): + closing = QtCore.Signal() + + def closeEvent(self, event): + self.closing.emit() + QtWidgets.QMainWindow.closeEvent(self, event) + + +class FigureManagerQT(FigureManagerBase): + """ + Attributes + ---------- + canvas : `FigureCanvas` + The FigureCanvas instance + num : int or str + The Figure number + toolbar : qt.QToolBar + The qt.QToolBar + window : qt.QMainWindow + The qt.QMainWindow + + """ + + def __init__(self, canvas, num): + FigureManagerBase.__init__(self, canvas, num) + self.canvas = canvas + self.window = MainWindow() + self.window.closing.connect(canvas.close_event) + self.window.closing.connect(self._widgetclosed) + + self.window.setWindowTitle("Figure %d" % num) + image = os.path.join(matplotlib.rcParams['datapath'], + 'images', 'matplotlib.svg') + self.window.setWindowIcon(QtGui.QIcon(image)) + + # Give the keyboard focus to the figure instead of the + # manager; StrongFocus accepts both tab and click to focus and + # will enable the canvas to process event w/o clicking. + # ClickFocus only takes the focus is the window has been + # clicked + # on. http://qt-project.org/doc/qt-4.8/qt.html#FocusPolicy-enum or + # http://doc.qt.digia.com/qt/qt.html#FocusPolicy-enum + self.canvas.setFocusPolicy(QtCore.Qt.StrongFocus) + self.canvas.setFocus() + + self.window._destroying = False + + self.toolmanager = self._get_toolmanager() + self.toolbar = self._get_toolbar(self.canvas, self.window) + self.statusbar = None + + if self.toolmanager: + backend_tools.add_tools_to_manager(self.toolmanager) + if self.toolbar: + backend_tools.add_tools_to_container(self.toolbar) + self.statusbar = StatusbarQt(self.window, self.toolmanager) + + if self.toolbar is not None: + self.window.addToolBar(self.toolbar) + if not self.toolmanager: + # add text label to status bar + statusbar_label = QtWidgets.QLabel() + self.window.statusBar().addWidget(statusbar_label) + self.toolbar.message.connect(statusbar_label.setText) + tbs_height = self.toolbar.sizeHint().height() + else: + tbs_height = 0 + + # resize the main window so it will display the canvas with the + # requested size: + cs = canvas.sizeHint() + sbs = self.window.statusBar().sizeHint() + self._status_and_tool_height = tbs_height + sbs.height() + height = cs.height() + self._status_and_tool_height + self.window.resize(cs.width(), height) + + self.window.setCentralWidget(self.canvas) + + if matplotlib.is_interactive(): + self.window.show() + self.canvas.draw_idle() + + def notify_axes_change(fig): + # This will be called whenever the current axes is changed + if self.toolbar is not None: + self.toolbar.update() + self.canvas.figure.add_axobserver(notify_axes_change) + self.window.raise_() + + def full_screen_toggle(self): + if self.window.isFullScreen(): + self.window.showNormal() + else: + self.window.showFullScreen() + + def _widgetclosed(self): + if self.window._destroying: + return + self.window._destroying = True + try: + Gcf.destroy(self.num) + except AttributeError: + pass + # It seems that when the python session is killed, + # Gcf can get destroyed before the Gcf.destroy + # line is run, leading to a useless AttributeError. + + def _get_toolbar(self, canvas, parent): + # must be inited after the window, drawingArea and figure + # attrs are set + if matplotlib.rcParams['toolbar'] == 'toolbar2': + toolbar = NavigationToolbar2QT(canvas, parent, False) + elif matplotlib.rcParams['toolbar'] == 'toolmanager': + toolbar = ToolbarQt(self.toolmanager, self.window) + else: + toolbar = None + return toolbar + + def _get_toolmanager(self): + if matplotlib.rcParams['toolbar'] == 'toolmanager': + toolmanager = ToolManager(self.canvas.figure) + else: + toolmanager = None + return toolmanager + + def resize(self, width, height): + 'set the canvas size in pixels' + self.window.resize(width, height + self._status_and_tool_height) + + def show(self): + self.window.show() + self.window.activateWindow() + self.window.raise_() + + def destroy(self, *args): + # check for qApp first, as PySide deletes it in its atexit handler + if QtWidgets.QApplication.instance() is None: + return + if self.window._destroying: + return + self.window._destroying = True + if self.toolbar: + self.toolbar.destroy() + self.window.close() + + def get_window_title(self): + return six.text_type(self.window.windowTitle()) + + def set_window_title(self, title): + self.window.setWindowTitle(title) + + +class NavigationToolbar2QT(NavigationToolbar2, QtWidgets.QToolBar): + message = QtCore.Signal(str) + + def __init__(self, canvas, parent, coordinates=True): + """ coordinates: should we show the coordinates on the right? """ + self.canvas = canvas + self.parent = parent + self.coordinates = coordinates + self._actions = {} + """A mapping of toolitem method names to their QActions""" + + QtWidgets.QToolBar.__init__(self, parent) + NavigationToolbar2.__init__(self, canvas) + + def _icon(self, name): + if is_pyqt5(): + name = name.replace('.png', '_large.png') + pm = QtGui.QPixmap(os.path.join(self.basedir, name)) + if hasattr(pm, 'setDevicePixelRatio'): + pm.setDevicePixelRatio(self.canvas._dpi_ratio) + return QtGui.QIcon(pm) + + def _init_toolbar(self): + self.basedir = os.path.join(matplotlib.rcParams['datapath'], 'images') + + for text, tooltip_text, image_file, callback in self.toolitems: + if text is None: + self.addSeparator() + else: + a = self.addAction(self._icon(image_file + '.png'), + text, getattr(self, callback)) + self._actions[callback] = a + if callback in ['zoom', 'pan']: + a.setCheckable(True) + if tooltip_text is not None: + a.setToolTip(tooltip_text) + if text == 'Subplots': + a = self.addAction(self._icon("qt4_editor_options.png"), + 'Customize', self.edit_parameters) + a.setToolTip('Edit axis, curve and image parameters') + + self.buttons = {} + + # Add the x,y location widget at the right side of the toolbar + # The stretch factor is 1 which means any resizing of the toolbar + # will resize this label instead of the buttons. + if self.coordinates: + self.locLabel = QtWidgets.QLabel("", self) + self.locLabel.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignTop) + self.locLabel.setSizePolicy( + QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, + QtWidgets.QSizePolicy.Ignored)) + labelAction = self.addWidget(self.locLabel) + labelAction.setVisible(True) + + # reference holder for subplots_adjust window + self.adj_window = None + + # Esthetic adjustments - we need to set these explicitly in PyQt5 + # otherwise the layout looks different - but we don't want to set it if + # not using HiDPI icons otherwise they look worse than before. + if is_pyqt5(): + self.setIconSize(QtCore.QSize(24, 24)) + self.layout().setSpacing(12) + + if is_pyqt5(): + # For some reason, self.setMinimumHeight doesn't seem to carry over to + # the actual sizeHint, so override it instead in order to make the + # aesthetic adjustments noted above. + def sizeHint(self): + size = super(NavigationToolbar2QT, self).sizeHint() + size.setHeight(max(48, size.height())) + return size + + def edit_parameters(self): + allaxes = self.canvas.figure.get_axes() + if not allaxes: + QtWidgets.QMessageBox.warning( + self.parent, "Error", "There are no axes to edit.") + return + elif len(allaxes) == 1: + axes, = allaxes + else: + titles = [] + for axes in allaxes: + name = (axes.get_title() or + " - ".join(filter(None, [axes.get_xlabel(), + axes.get_ylabel()])) or + "".format( + type(axes).__name__, id(axes))) + titles.append(name) + item, ok = QtWidgets.QInputDialog.getItem( + self.parent, 'Customize', 'Select axes:', titles, 0, False) + if ok: + axes = allaxes[titles.index(six.text_type(item))] + else: + return + + figureoptions.figure_edit(axes, self) + + def _update_buttons_checked(self): + # sync button checkstates to match active mode + self._actions['pan'].setChecked(self._active == 'PAN') + self._actions['zoom'].setChecked(self._active == 'ZOOM') + + def pan(self, *args): + super(NavigationToolbar2QT, self).pan(*args) + self._update_buttons_checked() + + def zoom(self, *args): + super(NavigationToolbar2QT, self).zoom(*args) + self._update_buttons_checked() + + def set_message(self, s): + self.message.emit(s) + if self.coordinates: + self.locLabel.setText(s) + + def set_cursor(self, cursor): + self.canvas.setCursor(cursord[cursor]) + + def draw_rubberband(self, event, x0, y0, x1, y1): + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)] + self.canvas.drawRectangle(rect) + + def remove_rubberband(self): + self.canvas.drawRectangle(None) + + def configure_subplots(self): + image = os.path.join(matplotlib.rcParams['datapath'], + 'images', 'matplotlib.png') + dia = SubplotToolQt(self.canvas.figure, self.parent) + dia.setWindowIcon(QtGui.QIcon(image)) + dia.exec_() + + def save_figure(self, *args): + filetypes = self.canvas.get_supported_filetypes_grouped() + sorted_filetypes = sorted(six.iteritems(filetypes)) + default_filetype = self.canvas.get_default_filetype() + + startpath = os.path.expanduser( + matplotlib.rcParams['savefig.directory']) + start = os.path.join(startpath, self.canvas.get_default_filename()) + filters = [] + selectedFilter = None + for name, exts in sorted_filetypes: + exts_list = " ".join(['*.%s' % ext for ext in exts]) + filter = '%s (%s)' % (name, exts_list) + if default_filetype in exts: + selectedFilter = filter + filters.append(filter) + filters = ';;'.join(filters) + + fname, filter = _getSaveFileName(self.parent, + "Choose a filename to save to", + start, filters, selectedFilter) + if fname: + # Save dir for next time, unless empty str (i.e., use cwd). + if startpath != "": + matplotlib.rcParams['savefig.directory'] = ( + os.path.dirname(six.text_type(fname))) + try: + self.canvas.figure.savefig(six.text_type(fname)) + except Exception as e: + QtWidgets.QMessageBox.critical( + self, "Error saving file", six.text_type(e), + QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton) + + +class SubplotToolQt(UiSubplotTool): + def __init__(self, targetfig, parent): + UiSubplotTool.__init__(self, None) + + self._figure = targetfig + + for lower, higher in [("bottom", "top"), ("left", "right")]: + self._widgets[lower].valueChanged.connect( + lambda val: self._widgets[higher].setMinimum(val + .001)) + self._widgets[higher].valueChanged.connect( + lambda val: self._widgets[lower].setMaximum(val - .001)) + + self._attrs = ["top", "bottom", "left", "right", "hspace", "wspace"] + self._defaults = {attr: vars(self._figure.subplotpars)[attr] + for attr in self._attrs} + + # Set values after setting the range callbacks, but before setting up + # the redraw callbacks. + self._reset() + + for attr in self._attrs: + self._widgets[attr].valueChanged.connect(self._on_value_changed) + for action, method in [("Export values", self._export_values), + ("Tight layout", self._tight_layout), + ("Reset", self._reset), + ("Close", self.close)]: + self._widgets[action].clicked.connect(method) + + def _export_values(self): + # Explicitly round to 3 decimals (which is also the spinbox precision) + # to avoid numbers of the form 0.100...001. + dialog = QtWidgets.QDialog() + layout = QtWidgets.QVBoxLayout() + dialog.setLayout(layout) + text = QtWidgets.QPlainTextEdit() + text.setReadOnly(True) + layout.addWidget(text) + text.setPlainText( + ",\n".join("{}={:.3}".format(attr, self._widgets[attr].value()) + for attr in self._attrs)) + # Adjust the height of the text widget to fit the whole text, plus + # some padding. + size = text.maximumSize() + size.setHeight( + QtGui.QFontMetrics(text.document().defaultFont()) + .size(0, text.toPlainText()).height() + 20) + text.setMaximumSize(size) + dialog.exec_() + + def _on_value_changed(self): + self._figure.subplots_adjust(**{attr: self._widgets[attr].value() + for attr in self._attrs}) + self._figure.canvas.draw_idle() + + def _tight_layout(self): + self._figure.tight_layout() + for attr in self._attrs: + widget = self._widgets[attr] + widget.blockSignals(True) + widget.setValue(vars(self._figure.subplotpars)[attr]) + widget.blockSignals(False) + self._figure.canvas.draw_idle() + + def _reset(self): + for attr, value in self._defaults.items(): + self._widgets[attr].setValue(value) + + +class ToolbarQt(ToolContainerBase, QtWidgets.QToolBar): + def __init__(self, toolmanager, parent): + ToolContainerBase.__init__(self, toolmanager) + QtWidgets.QToolBar.__init__(self, parent) + self._toolitems = {} + self._groups = {} + self._last = None + + @property + def _icon_extension(self): + if is_pyqt5(): + return '_large.png' + return '.png' + + def add_toolitem( + self, name, group, position, image_file, description, toggle): + + button = QtWidgets.QToolButton(self) + button.setIcon(self._icon(image_file)) + button.setText(name) + if description: + button.setToolTip(description) + + def handler(): + self.trigger_tool(name) + if toggle: + button.setCheckable(True) + button.toggled.connect(handler) + else: + button.clicked.connect(handler) + + self._last = button + self._toolitems.setdefault(name, []) + self._add_to_group(group, name, button, position) + self._toolitems[name].append((button, handler)) + + def _add_to_group(self, group, name, button, position): + gr = self._groups.get(group, []) + if not gr: + sep = self.addSeparator() + gr.append(sep) + before = gr[position] + widget = self.insertWidget(before, button) + gr.insert(position, widget) + self._groups[group] = gr + + def _icon(self, name): + pm = QtGui.QPixmap(name) + if hasattr(pm, 'setDevicePixelRatio'): + pm.setDevicePixelRatio(self.toolmanager.canvas._dpi_ratio) + return QtGui.QIcon(pm) + + def toggle_toolitem(self, name, toggled): + if name not in self._toolitems: + return + for button, handler in self._toolitems[name]: + button.toggled.disconnect(handler) + button.setChecked(toggled) + button.toggled.connect(handler) + + def remove_toolitem(self, name): + for button, handler in self._toolitems[name]: + button.setParent(None) + del self._toolitems[name] + + +class StatusbarQt(StatusbarBase, QtWidgets.QLabel): + def __init__(self, window, *args, **kwargs): + StatusbarBase.__init__(self, *args, **kwargs) + QtWidgets.QLabel.__init__(self) + window.statusBar().addWidget(self) + + def set_message(self, s): + self.setText(s) + + +class ConfigureSubplotsQt(backend_tools.ConfigureSubplotsBase): + def trigger(self, *args): + image = os.path.join(matplotlib.rcParams['datapath'], + 'images', 'matplotlib.png') + parent = self.canvas.manager.window + dia = SubplotToolQt(self.figure, parent) + dia.setWindowIcon(QtGui.QIcon(image)) + dia.exec_() + + +class SaveFigureQt(backend_tools.SaveFigureBase): + def trigger(self, *args): + filetypes = self.canvas.get_supported_filetypes_grouped() + sorted_filetypes = sorted(six.iteritems(filetypes)) + default_filetype = self.canvas.get_default_filetype() + + startpath = os.path.expanduser( + matplotlib.rcParams['savefig.directory']) + start = os.path.join(startpath, self.canvas.get_default_filename()) + filters = [] + selectedFilter = None + for name, exts in sorted_filetypes: + exts_list = " ".join(['*.%s' % ext for ext in exts]) + filter = '%s (%s)' % (name, exts_list) + if default_filetype in exts: + selectedFilter = filter + filters.append(filter) + filters = ';;'.join(filters) + + parent = self.canvas.manager.window + fname, filter = _getSaveFileName(parent, + "Choose a filename to save to", + start, filters, selectedFilter) + if fname: + # Save dir for next time, unless empty str (i.e., use cwd). + if startpath != "": + matplotlib.rcParams['savefig.directory'] = ( + os.path.dirname(six.text_type(fname))) + try: + self.canvas.figure.savefig(six.text_type(fname)) + except Exception as e: + QtWidgets.QMessageBox.critical( + self, "Error saving file", six.text_type(e), + QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton) + + +class SetCursorQt(backend_tools.SetCursorBase): + def set_cursor(self, cursor): + self.canvas.setCursor(cursord[cursor]) + + +class RubberbandQt(backend_tools.RubberbandBase): + def draw_rubberband(self, x0, y0, x1, y1): + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)] + self.canvas.drawRectangle(rect) + + def remove_rubberband(self): + self.canvas.drawRectangle(None) + + +backend_tools.ToolSaveFigure = SaveFigureQt +backend_tools.ToolConfigureSubplots = ConfigureSubplotsQt +backend_tools.ToolSetCursor = SetCursorQt +backend_tools.ToolRubberband = RubberbandQt + + +def error_msg_qt(msg, parent=None): + if not isinstance(msg, six.string_types): + msg = ','.join(map(str, msg)) + + QtWidgets.QMessageBox.warning(None, "Matplotlib", + msg, QtGui.QMessageBox.Ok) + + +def exception_handler(type, value, tb): + """Handle uncaught exceptions + It does not catch SystemExit + """ + msg = '' + # get the filename attribute if available (for IOError) + if hasattr(value, 'filename') and value.filename is not None: + msg = value.filename + ': ' + if hasattr(value, 'strerror') and value.strerror is not None: + msg += value.strerror + else: + msg += six.text_type(value) + + if len(msg): + error_msg_qt(msg) + + +@_Backend.export +class _BackendQT5(_Backend): + FigureCanvas = FigureCanvasQT + FigureManager = FigureManagerQT + + @staticmethod + def trigger_manager_draw(manager): + manager.canvas.draw_idle() + + @staticmethod + def mainloop(): + # allow KeyboardInterrupt exceptions to close the plot window. + signal.signal(signal.SIGINT, signal.SIG_DFL) + qApp.exec_() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5agg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5agg.py new file mode 100644 index 00000000000..d2166d58c88 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5agg.py @@ -0,0 +1,105 @@ +""" +Render to qt from agg +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import ctypes + +from matplotlib import cbook +from matplotlib.transforms import Bbox + +from .backend_agg import FigureCanvasAgg +from .backend_qt5 import ( + QtCore, QtGui, QtWidgets, _BackendQT5, FigureCanvasQT, FigureManagerQT, + NavigationToolbar2QT, backend_version) +from .qt_compat import QT_API + + +class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT): + + def __init__(self, figure): + super(FigureCanvasQTAgg, self).__init__(figure=figure) + self._bbox_queue = [] + + @property + @cbook.deprecated("2.1") + def blitbox(self): + return self._bbox_queue + + def paintEvent(self, e): + """Copy the image from the Agg canvas to the qt.drawable. + + In Qt, all drawing should be done inside of here when a widget is + shown onscreen. + """ + if self._update_dpi(): + # The dpi update triggered its own paintEvent. + return + self._draw_idle() # Only does something if a draw is pending. + + # if the canvas does not have a renderer, then give up and wait for + # FigureCanvasAgg.draw(self) to be called + if not hasattr(self, 'renderer'): + return + + painter = QtGui.QPainter(self) + + if self._bbox_queue: + bbox_queue = self._bbox_queue + else: + painter.eraseRect(self.rect()) + bbox_queue = [ + Bbox([[0, 0], [self.renderer.width, self.renderer.height]])] + self._bbox_queue = [] + for bbox in bbox_queue: + l, b, r, t = map(int, bbox.extents) + w = r - l + h = t - b + reg = self.copy_from_bbox(bbox) + buf = reg.to_string_argb() + qimage = QtGui.QImage(buf, w, h, QtGui.QImage.Format_ARGB32) + # Adjust the buf reference count to work around a memory leak bug + # in QImage under PySide on Python 3. + if QT_API in ('PySide', 'PySide2') and six.PY3: + ctypes.c_long.from_address(id(buf)).value = 1 + if hasattr(qimage, 'setDevicePixelRatio'): + # Not available on Qt4 or some older Qt5. + qimage.setDevicePixelRatio(self._dpi_ratio) + origin = QtCore.QPoint(int(l), int(self.renderer.height - t)) + painter.drawImage(origin / self._dpi_ratio, qimage) + + self._draw_rect_callback(painter) + + painter.end() + + def blit(self, bbox=None): + """Blit the region in bbox. + """ + # If bbox is None, blit the entire canvas. Otherwise + # blit only the area defined by the bbox. + if bbox is None and self.figure: + bbox = self.figure.bbox + + self._bbox_queue.append(bbox) + + # repaint uses logical pixels, not physical pixels like the renderer. + l, b, w, h = [pt / self._dpi_ratio for pt in bbox.bounds] + t = b + h + self.repaint(l, self.renderer.height / self._dpi_ratio - t, w, h) + + def print_figure(self, *args, **kwargs): + super(FigureCanvasQTAgg, self).print_figure(*args, **kwargs) + self.draw() + + +@cbook.deprecated("2.2") +class FigureCanvasQTAggBase(FigureCanvasQTAgg): + pass + + +@_BackendQT5.export +class _BackendQT5Agg(_BackendQT5): + FigureCanvas = FigureCanvasQTAgg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5cairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5cairo.py new file mode 100644 index 00000000000..1108707c3a0 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_qt5cairo.py @@ -0,0 +1,49 @@ + +import six + +from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo +from .backend_qt5 import QtCore, QtGui, _BackendQT5, FigureCanvasQT +from .qt_compat import QT_API + + +class FigureCanvasQTCairo(FigureCanvasQT, FigureCanvasCairo): + def __init__(self, figure): + super(FigureCanvasQTCairo, self).__init__(figure=figure) + self._renderer = RendererCairo(self.figure.dpi) + self._renderer.set_width_height(-1, -1) # Invalid values. + + def draw(self): + if hasattr(self._renderer.gc, "ctx"): + self.figure.draw(self._renderer) + super(FigureCanvasQTCairo, self).draw() + + def paintEvent(self, event): + self._update_dpi() + dpi_ratio = self._dpi_ratio + width = dpi_ratio * self.width() + height = dpi_ratio * self.height() + if (width, height) != self._renderer.get_canvas_width_height(): + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + self._renderer.set_ctx_from_surface(surface) + self._renderer.set_width_height(width, height) + self.figure.draw(self._renderer) + buf = self._renderer.gc.ctx.get_target().get_data() + qimage = QtGui.QImage(buf, width, height, + QtGui.QImage.Format_ARGB32_Premultiplied) + # Adjust the buf reference count to work around a memory leak bug in + # QImage under PySide on Python 3. + if QT_API == 'PySide' and six.PY3: + import ctypes + ctypes.c_long.from_address(id(buf)).value = 1 + if hasattr(qimage, 'setDevicePixelRatio'): + # Not available on Qt4 or some older Qt5. + qimage.setDevicePixelRatio(dpi_ratio) + painter = QtGui.QPainter(self) + painter.drawImage(0, 0, qimage) + self._draw_rect_callback(painter) + painter.end() + + +@_BackendQT5.export +class _BackendQT5Cairo(_BackendQT5): + FigureCanvas = FigureCanvasQTCairo diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_svg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_svg.py new file mode 100644 index 00000000000..b38c6850dad --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_svg.py @@ -0,0 +1,1261 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from collections import OrderedDict + +import six +from six import unichr +from six.moves import xrange + +import base64 +import codecs +import gzip +import hashlib +import io +import logging +import re +import uuid + +import numpy as np + +from matplotlib import cbook, __version__, rcParams +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, RendererBase) +from matplotlib.backends.backend_mixed import MixedModeRenderer +from matplotlib.cbook import is_writable_file_like, maxdict +from matplotlib.colors import rgb2hex +from matplotlib.font_manager import findfont, get_font +from matplotlib.ft2font import LOAD_NO_HINTING +from matplotlib.mathtext import MathTextParser +from matplotlib.path import Path +from matplotlib import _path +from matplotlib.transforms import Affine2D, Affine2DBase +from matplotlib import _png + +_log = logging.getLogger(__name__) + +backend_version = __version__ + +# ---------------------------------------------------------------------- +# SimpleXMLWriter class +# +# Based on an original by Fredrik Lundh, but modified here to: +# 1. Support modern Python idioms +# 2. Remove encoding support (it's handled by the file writer instead) +# 3. Support proper indentation +# 4. Minify things a little bit + +# -------------------------------------------------------------------- +# The SimpleXMLWriter module is +# +# Copyright (c) 2001-2004 by Fredrik Lundh +# +# By obtaining, using, and/or copying this software and/or its +# associated documentation, you agree that you have read, understood, +# and will comply with the following terms and conditions: +# +# Permission to use, copy, modify, and distribute this software and +# its associated documentation for any purpose and without fee is +# hereby granted, provided that the above copyright notice appears in +# all copies, and that both that copyright notice and this permission +# notice appear in supporting documentation, and that the name of +# Secret Labs AB or the author not be used in advertising or publicity +# pertaining to distribution of the software without specific, written +# prior permission. +# +# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD +# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- +# ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR +# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# -------------------------------------------------------------------- + +def escape_cdata(s): + s = s.replace("&", "&") + s = s.replace("<", "<") + s = s.replace(">", ">") + return s + +_escape_xml_comment = re.compile(r'-(?=-)') +def escape_comment(s): + s = escape_cdata(s) + return _escape_xml_comment.sub('- ', s) + +def escape_attrib(s): + s = s.replace("&", "&") + s = s.replace("'", "'") + s = s.replace("\"", """) + s = s.replace("<", "<") + s = s.replace(">", ">") + return s + +def short_float_fmt(x): + """ + Create a short string representation of a float, which is %f + formatting with trailing zeros and the decimal point removed. + """ + return '{0:f}'.format(x).rstrip('0').rstrip('.') + +## +# XML writer class. +# +# @param file A file or file-like object. This object must implement +# a write method that takes an 8-bit string. + +class XMLWriter(object): + def __init__(self, file): + self.__write = file.write + if hasattr(file, "flush"): + self.flush = file.flush + self.__open = 0 # true if start tag is open + self.__tags = [] + self.__data = [] + self.__indentation = " " * 64 + + def __flush(self, indent=True): + # flush internal buffers + if self.__open: + if indent: + self.__write(">\n") + else: + self.__write(">") + self.__open = 0 + if self.__data: + data = ''.join(self.__data) + self.__write(escape_cdata(data)) + self.__data = [] + + ## Opens a new element. Attributes can be given as keyword + # arguments, or as a string/string dictionary. The method returns + # an opaque identifier that can be passed to the close + # method, to close all open elements up to and including this one. + # + # @param tag Element tag. + # @param attrib Attribute dictionary. Alternatively, attributes + # can be given as keyword arguments. + # @return An element identifier. + + def start(self, tag, attrib={}, **extra): + self.__flush() + tag = escape_cdata(tag) + self.__data = [] + self.__tags.append(tag) + self.__write(self.__indentation[:len(self.__tags) - 1]) + self.__write("<%s" % tag) + if attrib or extra: + attrib = attrib.copy() + attrib.update(extra) + attrib = sorted(six.iteritems(attrib)) + for k, v in attrib: + if not v == '': + k = escape_cdata(k) + v = escape_attrib(v) + self.__write(" %s=\"%s\"" % (k, v)) + self.__open = 1 + return len(self.__tags)-1 + + ## + # Adds a comment to the output stream. + # + # @param comment Comment text, as a Unicode string. + + def comment(self, comment): + self.__flush() + self.__write(self.__indentation[:len(self.__tags)]) + self.__write("\n" % escape_comment(comment)) + + ## + # Adds character data to the output stream. + # + # @param text Character data, as a Unicode string. + + def data(self, text): + self.__data.append(text) + + ## + # Closes the current element (opened by the most recent call to + # start). + # + # @param tag Element tag. If given, the tag must match the start + # tag. If omitted, the current element is closed. + + def end(self, tag=None, indent=True): + if tag: + assert self.__tags, "unbalanced end(%s)" % tag + assert escape_cdata(tag) == self.__tags[-1],\ + "expected end(%s), got %s" % (self.__tags[-1], tag) + else: + assert self.__tags, "unbalanced end()" + tag = self.__tags.pop() + if self.__data: + self.__flush(indent) + elif self.__open: + self.__open = 0 + self.__write("/>\n") + return + if indent: + self.__write(self.__indentation[:len(self.__tags)]) + self.__write("\n" % tag) + + ## + # Closes open elements, up to (and including) the element identified + # by the given identifier. + # + # @param id Element identifier, as returned by the start method. + + def close(self, id): + while len(self.__tags) > id: + self.end() + + ## + # Adds an entire element. This is the same as calling start, + # data, and end in sequence. The text argument + # can be omitted. + + def element(self, tag, text=None, attrib={}, **extra): + self.start(*(tag, attrib), **extra) + if text: + self.data(text) + self.end(indent=False) + + ## + # Flushes the output stream. + + def flush(self): + pass # replaced by the constructor + +# ---------------------------------------------------------------------- + +def generate_transform(transform_list=[]): + if len(transform_list): + output = io.StringIO() + for type, value in transform_list: + if type == 'scale' and (value == (1.0,) or value == (1.0, 1.0)): + continue + if type == 'translate' and value == (0.0, 0.0): + continue + if type == 'rotate' and value == (0.0,): + continue + if type == 'matrix' and isinstance(value, Affine2DBase): + value = value.to_values() + + output.write('%s(%s)' % ( + type, ' '.join(short_float_fmt(x) for x in value))) + return output.getvalue() + return '' + +def generate_css(attrib={}): + if attrib: + output = io.StringIO() + attrib = sorted(six.iteritems(attrib)) + for k, v in attrib: + k = escape_attrib(k) + v = escape_attrib(v) + output.write("%s:%s;" % (k, v)) + return output.getvalue() + return '' + +_capstyle_d = {'projecting' : 'square', 'butt' : 'butt', 'round': 'round',} +class RendererSVG(RendererBase): + FONT_SCALE = 100.0 + fontd = maxdict(50) + + def __init__(self, width, height, svgwriter, basename=None, image_dpi=72): + self.width = width + self.height = height + self.writer = XMLWriter(svgwriter) + self.image_dpi = image_dpi # the actual dpi we want to rasterize stuff with + + self._groupd = {} + if not rcParams['svg.image_inline']: + assert basename is not None + self.basename = basename + self._imaged = {} + self._clipd = OrderedDict() + self._char_defs = {} + self._markers = {} + self._path_collection_id = 0 + self._imaged = {} + self._hatchd = OrderedDict() + self._has_gouraud = False + self._n_gradients = 0 + self._fonts = OrderedDict() + self.mathtext_parser = MathTextParser('SVG') + + RendererBase.__init__(self) + self._glyph_map = dict() + str_height = short_float_fmt(height) + str_width = short_float_fmt(width) + svgwriter.write(svgProlog) + self._start_id = self.writer.start( + 'svg', + width='%spt' % str_width, + height='%spt' % str_height, + viewBox='0 0 %s %s' % (str_width, str_height), + xmlns="http://www.w3.org/2000/svg", + version="1.1", + attrib={'xmlns:xlink': "http://www.w3.org/1999/xlink"}) + self._write_default_style() + + def finalize(self): + self._write_clips() + self._write_hatches() + self._write_svgfonts() + self.writer.close(self._start_id) + self.writer.flush() + + def _write_default_style(self): + writer = self.writer + default_style = generate_css({ + 'stroke-linejoin': 'round', + 'stroke-linecap': 'butt'}) + writer.start('defs') + writer.start('style', type='text/css') + writer.data('*{%s}\n' % default_style) + writer.end('style') + writer.end('defs') + + def _make_id(self, type, content): + content = str(content) + if rcParams['svg.hashsalt'] is None: + salt = str(uuid.uuid4()) + else: + salt = rcParams['svg.hashsalt'] + if six.PY3: + content = content.encode('utf8') + salt = salt.encode('utf8') + m = hashlib.md5() + m.update(salt) + m.update(content) + return '%s%s' % (type, m.hexdigest()[:10]) + + def _make_flip_transform(self, transform): + return (transform + + Affine2D() + .scale(1.0, -1.0) + .translate(0.0, self.height)) + + def _get_font(self, prop): + fname = findfont(prop) + font = get_font(fname) + font.clear() + size = prop.get_size_in_points() + font.set_size(size, 72.0) + return font + + def _get_hatch(self, gc, rgbFace): + """ + Create a new hatch pattern + """ + if rgbFace is not None: + rgbFace = tuple(rgbFace) + edge = gc.get_hatch_color() + if edge is not None: + edge = tuple(edge) + dictkey = (gc.get_hatch(), rgbFace, edge) + oid = self._hatchd.get(dictkey) + if oid is None: + oid = self._make_id('h', dictkey) + self._hatchd[dictkey] = ((gc.get_hatch_path(), rgbFace, edge), oid) + else: + _, oid = oid + return oid + + def _write_hatches(self): + if not len(self._hatchd): + return + HATCH_SIZE = 72 + writer = self.writer + writer.start('defs') + for ((path, face, stroke), oid) in six.itervalues(self._hatchd): + writer.start( + 'pattern', + id=oid, + patternUnits="userSpaceOnUse", + x="0", y="0", width=six.text_type(HATCH_SIZE), + height=six.text_type(HATCH_SIZE)) + path_data = self._convert_path( + path, + Affine2D().scale(HATCH_SIZE).scale(1.0, -1.0).translate(0, HATCH_SIZE), + simplify=False) + if face is None: + fill = 'none' + else: + fill = rgb2hex(face) + writer.element( + 'rect', + x="0", y="0", width=six.text_type(HATCH_SIZE+1), + height=six.text_type(HATCH_SIZE+1), + fill=fill) + writer.element( + 'path', + d=path_data, + style=generate_css({ + 'fill': rgb2hex(stroke), + 'stroke': rgb2hex(stroke), + 'stroke-width': six.text_type(rcParams['hatch.linewidth']), + 'stroke-linecap': 'butt', + 'stroke-linejoin': 'miter' + }) + ) + writer.end('pattern') + writer.end('defs') + + def _get_style_dict(self, gc, rgbFace): + """ + return the style string. style is generated from the + GraphicsContext and rgbFace + """ + attrib = {} + + forced_alpha = gc.get_forced_alpha() + + if gc.get_hatch() is not None: + attrib['fill'] = "url(#%s)" % self._get_hatch(gc, rgbFace) + if rgbFace is not None and len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha: + attrib['fill-opacity'] = short_float_fmt(rgbFace[3]) + else: + if rgbFace is None: + attrib['fill'] = 'none' + else: + if tuple(rgbFace[:3]) != (0, 0, 0): + attrib['fill'] = rgb2hex(rgbFace) + if len(rgbFace) == 4 and rgbFace[3] != 1.0 and not forced_alpha: + attrib['fill-opacity'] = short_float_fmt(rgbFace[3]) + + if forced_alpha and gc.get_alpha() != 1.0: + attrib['opacity'] = short_float_fmt(gc.get_alpha()) + + offset, seq = gc.get_dashes() + if seq is not None: + attrib['stroke-dasharray'] = ','.join([short_float_fmt(val) for val in seq]) + attrib['stroke-dashoffset'] = short_float_fmt(float(offset)) + + linewidth = gc.get_linewidth() + if linewidth: + rgb = gc.get_rgb() + attrib['stroke'] = rgb2hex(rgb) + if not forced_alpha and rgb[3] != 1.0: + attrib['stroke-opacity'] = short_float_fmt(rgb[3]) + if linewidth != 1.0: + attrib['stroke-width'] = short_float_fmt(linewidth) + if gc.get_joinstyle() != 'round': + attrib['stroke-linejoin'] = gc.get_joinstyle() + if gc.get_capstyle() != 'butt': + attrib['stroke-linecap'] = _capstyle_d[gc.get_capstyle()] + + return attrib + + def _get_style(self, gc, rgbFace): + return generate_css(self._get_style_dict(gc, rgbFace)) + + def _get_clip(self, gc): + cliprect = gc.get_clip_rectangle() + clippath, clippath_trans = gc.get_clip_path() + if clippath is not None: + clippath_trans = self._make_flip_transform(clippath_trans) + dictkey = (id(clippath), str(clippath_trans)) + elif cliprect is not None: + x, y, w, h = cliprect.bounds + y = self.height-(y+h) + dictkey = (x, y, w, h) + else: + return None + + clip = self._clipd.get(dictkey) + if clip is None: + oid = self._make_id('p', dictkey) + if clippath is not None: + self._clipd[dictkey] = ((clippath, clippath_trans), oid) + else: + self._clipd[dictkey] = (dictkey, oid) + else: + clip, oid = clip + return oid + + def _write_clips(self): + if not len(self._clipd): + return + writer = self.writer + writer.start('defs') + for clip, oid in six.itervalues(self._clipd): + writer.start('clipPath', id=oid) + if len(clip) == 2: + clippath, clippath_trans = clip + path_data = self._convert_path(clippath, clippath_trans, simplify=False) + writer.element('path', d=path_data) + else: + x, y, w, h = clip + writer.element( + 'rect', + x=short_float_fmt(x), + y=short_float_fmt(y), + width=short_float_fmt(w), + height=short_float_fmt(h)) + writer.end('clipPath') + writer.end('defs') + + def _write_svgfonts(self): + if not rcParams['svg.fonttype'] == 'svgfont': + return + + writer = self.writer + writer.start('defs') + for font_fname, chars in six.iteritems(self._fonts): + font = get_font(font_fname) + font.set_size(72, 72) + sfnt = font.get_sfnt() + writer.start('font', id=sfnt[1, 0, 0, 4].decode("mac_roman")) + writer.element( + 'font-face', + attrib={ + 'font-family': font.family_name, + 'font-style': font.style_name.lower(), + 'units-per-em': '72', + 'bbox': ' '.join( + short_float_fmt(x / 64.0) for x in font.bbox)}) + for char in chars: + glyph = font.load_char(char, flags=LOAD_NO_HINTING) + verts, codes = font.get_path() + path = Path(verts, codes) + path_data = self._convert_path(path) + # name = font.get_glyph_name(char) + writer.element( + 'glyph', + d=path_data, + attrib={ + # 'glyph-name': name, + 'unicode': unichr(char), + 'horiz-adv-x': + short_float_fmt(glyph.linearHoriAdvance / 65536.0)}) + writer.end('font') + writer.end('defs') + + def open_group(self, s, gid=None): + """ + Open a grouping element with label *s*. If *gid* is given, use + *gid* as the id of the group. + """ + if gid: + self.writer.start('g', id=gid) + else: + self._groupd[s] = self._groupd.get(s, 0) + 1 + self.writer.start('g', id="%s_%d" % (s, self._groupd[s])) + + def close_group(self, s): + self.writer.end('g') + + def option_image_nocomposite(self): + """ + return whether to generate a composite image from multiple images on + a set of axes + """ + return not rcParams['image.composite_image'] + + def _convert_path(self, path, transform=None, clip=None, simplify=None, + sketch=None): + if clip: + clip = (0.0, 0.0, self.width, self.height) + else: + clip = None + return _path.convert_to_string( + path, transform, clip, simplify, sketch, 6, + [b'M', b'L', b'Q', b'C', b'z'], False).decode('ascii') + + def draw_path(self, gc, path, transform, rgbFace=None): + trans_and_flip = self._make_flip_transform(transform) + clip = (rgbFace is None and gc.get_hatch_path() is None) + simplify = path.should_simplify and clip + path_data = self._convert_path( + path, trans_and_flip, clip=clip, simplify=simplify, + sketch=gc.get_sketch_params()) + + attrib = {} + attrib['style'] = self._get_style(gc, rgbFace) + + clipid = self._get_clip(gc) + if clipid is not None: + attrib['clip-path'] = 'url(#%s)' % clipid + + if gc.get_url() is not None: + self.writer.start('a', {'xlink:href': gc.get_url()}) + self.writer.element('path', d=path_data, attrib=attrib) + if gc.get_url() is not None: + self.writer.end('a') + + def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): + if not len(path.vertices): + return + + writer = self.writer + path_data = self._convert_path( + marker_path, + marker_trans + Affine2D().scale(1.0, -1.0), + simplify=False) + style = self._get_style_dict(gc, rgbFace) + dictkey = (path_data, generate_css(style)) + oid = self._markers.get(dictkey) + style = generate_css({k: v for k, v in six.iteritems(style) + if k.startswith('stroke')}) + + if oid is None: + oid = self._make_id('m', dictkey) + writer.start('defs') + writer.element('path', id=oid, d=path_data, style=style) + writer.end('defs') + self._markers[dictkey] = oid + + attrib = {} + clipid = self._get_clip(gc) + if clipid is not None: + attrib['clip-path'] = 'url(#%s)' % clipid + writer.start('g', attrib=attrib) + + trans_and_flip = self._make_flip_transform(trans) + attrib = {'xlink:href': '#%s' % oid} + clip = (0, 0, self.width*72, self.height*72) + for vertices, code in path.iter_segments( + trans_and_flip, clip=clip, simplify=False): + if len(vertices): + x, y = vertices[-2:] + attrib['x'] = short_float_fmt(x) + attrib['y'] = short_float_fmt(y) + attrib['style'] = self._get_style(gc, rgbFace) + writer.element('use', attrib=attrib) + writer.end('g') + + def draw_path_collection(self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position): + # Is the optimization worth it? Rough calculation: + # cost of emitting a path in-line is + # (len_path + 5) * uses_per_path + # cost of definition+use is + # (len_path + 3) + 9 * uses_per_path + len_path = len(paths[0].vertices) if len(paths) > 0 else 0 + uses_per_path = self._iter_collection_uses_per_path( + paths, all_transforms, offsets, facecolors, edgecolors) + should_do_optimization = \ + len_path + 9 * uses_per_path + 3 < (len_path + 5) * uses_per_path + if not should_do_optimization: + return RendererBase.draw_path_collection( + self, gc, master_transform, paths, all_transforms, + offsets, offsetTrans, facecolors, edgecolors, + linewidths, linestyles, antialiaseds, urls, + offset_position) + + writer = self.writer + path_codes = [] + writer.start('defs') + for i, (path, transform) in enumerate(self._iter_collection_raw_paths( + master_transform, paths, all_transforms)): + transform = Affine2D(transform.get_matrix()).scale(1.0, -1.0) + d = self._convert_path(path, transform, simplify=False) + oid = 'C%x_%x_%s' % (self._path_collection_id, i, + self._make_id('', d)) + writer.element('path', id=oid, d=d) + path_codes.append(oid) + writer.end('defs') + + for xo, yo, path_id, gc0, rgbFace in self._iter_collection( + gc, master_transform, all_transforms, path_codes, offsets, + offsetTrans, facecolors, edgecolors, linewidths, linestyles, + antialiaseds, urls, offset_position): + clipid = self._get_clip(gc0) + url = gc0.get_url() + if url is not None: + writer.start('a', attrib={'xlink:href': url}) + if clipid is not None: + writer.start('g', attrib={'clip-path': 'url(#%s)' % clipid}) + attrib = { + 'xlink:href': '#%s' % path_id, + 'x': short_float_fmt(xo), + 'y': short_float_fmt(self.height - yo), + 'style': self._get_style(gc0, rgbFace) + } + writer.element('use', attrib=attrib) + if clipid is not None: + writer.end('g') + if url is not None: + writer.end('a') + + self._path_collection_id += 1 + + def draw_gouraud_triangle(self, gc, points, colors, trans): + # This uses a method described here: + # + # http://www.svgopen.org/2005/papers/Converting3DFaceToSVG/index.html + # + # that uses three overlapping linear gradients to simulate a + # Gouraud triangle. Each gradient goes from fully opaque in + # one corner to fully transparent along the opposite edge. + # The line between the stop points is perpendicular to the + # opposite edge. Underlying these three gradients is a solid + # triangle whose color is the average of all three points. + + writer = self.writer + if not self._has_gouraud: + self._has_gouraud = True + writer.start( + 'filter', + id='colorAdd') + writer.element( + 'feComposite', + attrib={'in': 'SourceGraphic'}, + in2='BackgroundImage', + operator='arithmetic', + k2="1", k3="1") + writer.end('filter') + + avg_color = np.sum(colors[:, :], axis=0) / 3.0 + # Just skip fully-transparent triangles + if avg_color[-1] == 0.0: + return + + trans_and_flip = self._make_flip_transform(trans) + tpoints = trans_and_flip.transform(points) + + writer.start('defs') + for i in range(3): + x1, y1 = tpoints[i] + x2, y2 = tpoints[(i + 1) % 3] + x3, y3 = tpoints[(i + 2) % 3] + c = colors[i][:] + + if x2 == x3: + xb = x2 + yb = y1 + elif y2 == y3: + xb = x1 + yb = y2 + else: + m1 = (y2 - y3) / (x2 - x3) + b1 = y2 - (m1 * x2) + m2 = -(1.0 / m1) + b2 = y1 - (m2 * x1) + xb = (-b1 + b2) / (m1 - m2) + yb = m2 * xb + b2 + + writer.start( + 'linearGradient', + id="GR%x_%d" % (self._n_gradients, i), + x1=short_float_fmt(x1), y1=short_float_fmt(y1), + x2=short_float_fmt(xb), y2=short_float_fmt(yb)) + writer.element( + 'stop', + offset='0', + style=generate_css({'stop-color': rgb2hex(c), + 'stop-opacity': short_float_fmt(c[-1])})) + writer.element( + 'stop', + offset='1', + style=generate_css({'stop-color': rgb2hex(c), + 'stop-opacity': "0"})) + writer.end('linearGradient') + + writer.element( + 'polygon', + id='GT%x' % self._n_gradients, + points=" ".join([short_float_fmt(x) + for x in (x1, y1, x2, y2, x3, y3)])) + writer.end('defs') + + avg_color = np.sum(colors[:, :], axis=0) / 3.0 + href = '#GT%x' % self._n_gradients + writer.element( + 'use', + attrib={'xlink:href': href, + 'fill': rgb2hex(avg_color), + 'fill-opacity': short_float_fmt(avg_color[-1])}) + for i in range(3): + writer.element( + 'use', + attrib={'xlink:href': href, + 'fill': 'url(#GR%x_%d)' % (self._n_gradients, i), + 'fill-opacity': '1', + 'filter': 'url(#colorAdd)'}) + + self._n_gradients += 1 + + def draw_gouraud_triangles(self, gc, triangles_array, colors_array, + transform): + attrib = {} + clipid = self._get_clip(gc) + if clipid is not None: + attrib['clip-path'] = 'url(#%s)' % clipid + + self.writer.start('g', attrib=attrib) + + transform = transform.frozen() + for tri, col in zip(triangles_array, colors_array): + self.draw_gouraud_triangle(gc, tri, col, transform) + + self.writer.end('g') + + def option_scale_image(self): + return True + + def get_image_magnification(self): + return self.image_dpi / 72.0 + + def draw_image(self, gc, x, y, im, transform=None): + h, w = im.shape[:2] + + if w == 0 or h == 0: + return + + attrib = {} + clipid = self._get_clip(gc) + if clipid is not None: + # Can't apply clip-path directly to the image because the + # image has a transformation, which would also be applied + # to the clip-path + self.writer.start('g', attrib={'clip-path': 'url(#%s)' % clipid}) + + oid = gc.get_gid() + url = gc.get_url() + if url is not None: + self.writer.start('a', attrib={'xlink:href': url}) + if rcParams['svg.image_inline']: + bytesio = io.BytesIO() + _png.write_png(im, bytesio) + oid = oid or self._make_id('image', bytesio.getvalue()) + attrib['xlink:href'] = ( + "data:image/png;base64,\n" + + base64.b64encode(bytesio.getvalue()).decode('ascii')) + else: + self._imaged[self.basename] = self._imaged.get(self.basename, 0) + 1 + filename = '%s.image%d.png'%(self.basename, self._imaged[self.basename]) + _log.info('Writing image file for inclusion: %s', filename) + _png.write_png(im, filename) + oid = oid or 'Im_' + self._make_id('image', filename) + attrib['xlink:href'] = filename + + attrib['id'] = oid + + if transform is None: + w = 72.0 * w / self.image_dpi + h = 72.0 * h / self.image_dpi + + self.writer.element( + 'image', + transform=generate_transform([ + ('scale', (1, -1)), ('translate', (0, -h))]), + x=short_float_fmt(x), + y=short_float_fmt(-(self.height - y - h)), + width=short_float_fmt(w), height=short_float_fmt(h), + attrib=attrib) + else: + alpha = gc.get_alpha() + if alpha != 1.0: + attrib['opacity'] = short_float_fmt(alpha) + + flipped = ( + Affine2D().scale(1.0 / w, 1.0 / h) + + transform + + Affine2D() + .translate(x, y) + .scale(1.0, -1.0) + .translate(0.0, self.height)) + + attrib['transform'] = generate_transform( + [('matrix', flipped.frozen())]) + self.writer.element( + 'image', + width=short_float_fmt(w), height=short_float_fmt(h), + attrib=attrib) + + if url is not None: + self.writer.end('a') + if clipid is not None: + self.writer.end('g') + + def _adjust_char_id(self, char_id): + return char_id.replace("%20", "_") + + def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath, mtext=None): + """ + draw the text by converting them to paths using textpath module. + + Parameters + ---------- + prop : `matplotlib.font_manager.FontProperties` + font property + + s : str + text to be converted + + usetex : bool + If True, use matplotlib usetex mode. + + ismath : bool + If True, use mathtext parser. If "TeX", use *usetex* mode. + + """ + writer = self.writer + + writer.comment(s) + + glyph_map=self._glyph_map + + text2path = self._text2path + color = rgb2hex(gc.get_rgb()) + fontsize = prop.get_size_in_points() + + style = {} + if color != '#000000': + style['fill'] = color + if gc.get_alpha() != 1.0: + style['opacity'] = short_float_fmt(gc.get_alpha()) + + if not ismath: + font = text2path._get_font(prop) + _glyphs = text2path.get_glyphs_with_font( + font, s, glyph_map=glyph_map, return_new_glyphs_only=True) + glyph_info, glyph_map_new, rects = _glyphs + + if glyph_map_new: + writer.start('defs') + for char_id, glyph_path in six.iteritems(glyph_map_new): + path = Path(*glyph_path) + path_data = self._convert_path(path, simplify=False) + writer.element('path', id=char_id, d=path_data) + writer.end('defs') + + glyph_map.update(glyph_map_new) + + attrib = {} + attrib['style'] = generate_css(style) + font_scale = fontsize / text2path.FONT_SCALE + attrib['transform'] = generate_transform([ + ('translate', (x, y)), + ('rotate', (-angle,)), + ('scale', (font_scale, -font_scale))]) + + writer.start('g', attrib=attrib) + for glyph_id, xposition, yposition, scale in glyph_info: + attrib={'xlink:href': '#%s' % glyph_id} + if xposition != 0.0: + attrib['x'] = short_float_fmt(xposition) + if yposition != 0.0: + attrib['y'] = short_float_fmt(yposition) + writer.element( + 'use', + attrib=attrib) + + writer.end('g') + else: + if ismath == "TeX": + _glyphs = text2path.get_glyphs_tex(prop, s, glyph_map=glyph_map, + return_new_glyphs_only=True) + else: + _glyphs = text2path.get_glyphs_mathtext(prop, s, glyph_map=glyph_map, + return_new_glyphs_only=True) + + glyph_info, glyph_map_new, rects = _glyphs + + # we store the character glyphs w/o flipping. Instead, the + # coordinate will be flipped when this characters are + # used. + if glyph_map_new: + writer.start('defs') + for char_id, glyph_path in six.iteritems(glyph_map_new): + char_id = self._adjust_char_id(char_id) + # Some characters are blank + if not len(glyph_path[0]): + path_data = "" + else: + path = Path(*glyph_path) + path_data = self._convert_path(path, simplify=False) + writer.element('path', id=char_id, d=path_data) + writer.end('defs') + + glyph_map.update(glyph_map_new) + + attrib = {} + font_scale = fontsize / text2path.FONT_SCALE + attrib['style'] = generate_css(style) + attrib['transform'] = generate_transform([ + ('translate', (x, y)), + ('rotate', (-angle,)), + ('scale', (font_scale, -font_scale))]) + + writer.start('g', attrib=attrib) + for char_id, xposition, yposition, scale in glyph_info: + char_id = self._adjust_char_id(char_id) + + writer.element( + 'use', + transform=generate_transform([ + ('translate', (xposition, yposition)), + ('scale', (scale,)), + ]), + attrib={'xlink:href': '#%s' % char_id}) + + for verts, codes in rects: + path = Path(verts, codes) + path_data = self._convert_path(path, simplify=False) + writer.element('path', d=path_data) + + writer.end('g') + + def _draw_text_as_text(self, gc, x, y, s, prop, angle, ismath, mtext=None): + writer = self.writer + + color = rgb2hex(gc.get_rgb()) + style = {} + if color != '#000000': + style['fill'] = color + if gc.get_alpha() != 1.0: + style['opacity'] = short_float_fmt(gc.get_alpha()) + + if not ismath: + font = self._get_font(prop) + font.set_text(s, 0.0, flags=LOAD_NO_HINTING) + + fontsize = prop.get_size_in_points() + + fontfamily = font.family_name + fontstyle = prop.get_style() + + attrib = {} + # Must add "px" to workaround a Firefox bug + style['font-size'] = short_float_fmt(fontsize) + 'px' + style['font-family'] = six.text_type(fontfamily) + style['font-style'] = prop.get_style().lower() + style['font-weight'] = six.text_type(prop.get_weight()).lower() + attrib['style'] = generate_css(style) + + if mtext and (angle == 0 or mtext.get_rotation_mode() == "anchor"): + # If text anchoring can be supported, get the original + # coordinates and add alignment information. + + # Get anchor coordinates. + transform = mtext.get_transform() + ax, ay = transform.transform_point(mtext.get_position()) + ay = self.height - ay + + # Don't do vertical anchor alignment. Most applications do not + # support 'alignment-baseline' yet. Apply the vertical layout + # to the anchor point manually for now. + angle_rad = np.deg2rad(angle) + dir_vert = np.array([np.sin(angle_rad), np.cos(angle_rad)]) + v_offset = np.dot(dir_vert, [(x - ax), (y - ay)]) + ax = ax + v_offset * dir_vert[0] + ay = ay + v_offset * dir_vert[1] + + ha_mpl_to_svg = {'left': 'start', 'right': 'end', + 'center': 'middle'} + style['text-anchor'] = ha_mpl_to_svg[mtext.get_ha()] + + attrib['x'] = short_float_fmt(ax) + attrib['y'] = short_float_fmt(ay) + attrib['style'] = generate_css(style) + attrib['transform'] = "rotate(%s, %s, %s)" % ( + short_float_fmt(-angle), + short_float_fmt(ax), + short_float_fmt(ay)) + writer.element('text', s, attrib=attrib) + else: + attrib['transform'] = generate_transform([ + ('translate', (x, y)), + ('rotate', (-angle,))]) + + writer.element('text', s, attrib=attrib) + + if rcParams['svg.fonttype'] == 'svgfont': + fontset = self._fonts.setdefault(font.fname, set()) + for c in s: + fontset.add(ord(c)) + else: + writer.comment(s) + + width, height, descent, svg_elements, used_characters = \ + self.mathtext_parser.parse(s, 72, prop) + svg_glyphs = svg_elements.svg_glyphs + svg_rects = svg_elements.svg_rects + + attrib = {} + attrib['style'] = generate_css(style) + attrib['transform'] = generate_transform([ + ('translate', (x, y)), + ('rotate', (-angle,))]) + + # Apply attributes to 'g', not 'text', because we likely + # have some rectangles as well with the same style and + # transformation + writer.start('g', attrib=attrib) + + writer.start('text') + + # Sort the characters by font, and output one tspan for + # each + spans = OrderedDict() + for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs: + style = generate_css({ + 'font-size': short_float_fmt(fontsize) + 'px', + 'font-family': font.family_name, + 'font-style': font.style_name.lower(), + 'font-weight': font.style_name.lower()}) + if thetext == 32: + thetext = 0xa0 # non-breaking space + spans.setdefault(style, []).append((new_x, -new_y, thetext)) + + if rcParams['svg.fonttype'] == 'svgfont': + for font, fontsize, thetext, new_x, new_y, metrics in svg_glyphs: + fontset = self._fonts.setdefault(font.fname, set()) + fontset.add(thetext) + + for style, chars in six.iteritems(spans): + chars.sort() + + same_y = True + if len(chars) > 1: + last_y = chars[0][1] + for i in xrange(1, len(chars)): + if chars[i][1] != last_y: + same_y = False + break + if same_y: + ys = six.text_type(chars[0][1]) + else: + ys = ' '.join(six.text_type(c[1]) for c in chars) + + attrib = { + 'style': style, + 'x': ' '.join(short_float_fmt(c[0]) for c in chars), + 'y': ys + } + + writer.element( + 'tspan', + ''.join(unichr(c[2]) for c in chars), + attrib=attrib) + + writer.end('text') + + if len(svg_rects): + for x, y, width, height in svg_rects: + writer.element( + 'rect', + x=short_float_fmt(x), + y=short_float_fmt(-y + height), + width=short_float_fmt(width), + height=short_float_fmt(height) + ) + + writer.end('g') + + def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None): + self._draw_text_as_path(gc, x, y, s, prop, angle, ismath="TeX") + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + clipid = self._get_clip(gc) + if clipid is not None: + # Cannot apply clip-path directly to the text, because + # is has a transformation + self.writer.start( + 'g', attrib={'clip-path': 'url(#%s)' % clipid}) + + if gc.get_url() is not None: + self.writer.start('a', {'xlink:href': gc.get_url()}) + + if rcParams['svg.fonttype'] == 'path': + self._draw_text_as_path(gc, x, y, s, prop, angle, ismath, mtext) + else: + self._draw_text_as_text(gc, x, y, s, prop, angle, ismath, mtext) + + if gc.get_url() is not None: + self.writer.end('a') + + if clipid is not None: + self.writer.end('g') + + def flipy(self): + return True + + def get_canvas_width_height(self): + return self.width, self.height + + def get_text_width_height_descent(self, s, prop, ismath): + return self._text2path.get_text_width_height_descent(s, prop, ismath) + + +class FigureCanvasSVG(FigureCanvasBase): + filetypes = {'svg': 'Scalable Vector Graphics', + 'svgz': 'Scalable Vector Graphics'} + + fixed_dpi = 72 + + def print_svg(self, filename, *args, **kwargs): + with cbook.open_file_cm(filename, "w", encoding="utf-8") as fh: + + filename = getattr(fh, 'name', '') + if not isinstance(filename, six.string_types): + filename = '' + + if cbook.file_requires_unicode(fh): + detach = False + else: + if six.PY3: + fh = io.TextIOWrapper(fh, 'utf-8') + else: + fh = codecs.getwriter('utf-8')(fh) + detach = True + + result = self._print_svg(filename, fh, **kwargs) + + # Detach underlying stream from wrapper so that it remains open in + # the caller. + if detach: + if six.PY3: + fh.detach() + else: + fh.reset() + fh.stream = io.BytesIO() + + return result + + def print_svgz(self, filename, *args, **kwargs): + with cbook.open_file_cm(filename, "wb") as fh, \ + gzip.GzipFile(mode='w', fileobj=fh) as gzipwriter: + return self.print_svg(gzipwriter) + + def _print_svg(self, filename, fh, **kwargs): + image_dpi = kwargs.pop("dpi", 72) + self.figure.set_dpi(72.0) + width, height = self.figure.get_size_inches() + w, h = width * 72, height * 72 + + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer( + self.figure, width, height, image_dpi, + RendererSVG(w, h, fh, filename, image_dpi), + bbox_inches_restore=_bbox_inches_restore) + + self.figure.draw(renderer) + renderer.finalize() + + def get_default_filetype(self): + return 'svg' + +class FigureManagerSVG(FigureManagerBase): + pass + + +svgProlog = """\ + + + +""" + + +@_Backend.export +class _BackendSVG(_Backend): + FigureCanvas = FigureCanvasSVG + FigureManager = FigureManagerSVG diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_template.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_template.py new file mode 100644 index 00000000000..524ca73285c --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_template.py @@ -0,0 +1,278 @@ +""" +This is a fully functional do nothing backend to provide a template to +backend writers. It is fully functional in that you can select it as +a backend with + + import matplotlib + matplotlib.use('Template') + +and your matplotlib scripts will (should!) run without error, though +no output is produced. This provides a nice starting point for +backend writers because you can selectively implement methods +(draw_rectangle, draw_lines, etc...) and slowly see your figure come +to life w/o having to have a full blown implementation before getting +any results. + +Copy this to backend_xxx.py and replace all instances of 'template' +with 'xxx'. Then implement the class methods and functions below, and +add 'xxx' to the switchyard in matplotlib/backends/__init__.py and +'xxx' to the backends list in the validate_backend methon in +matplotlib/__init__.py and you're off. You can use your backend with:: + + import matplotlib + matplotlib.use('xxx') + from pylab import * + plot([1,2,3]) + show() + +matplotlib also supports external backends, so you can place you can +use any module in your PYTHONPATH with the syntax:: + + import matplotlib + matplotlib.use('module://my_backend') + +where my_backend.py is your module name. This syntax is also +recognized in the rc file and in the -d argument in pylab, e.g.,:: + + python simple_plot.py -dmodule://my_backend + +If your backend implements support for saving figures (i.e. has a print_xyz() +method) you can register it as the default handler for a given file type + + from matplotlib.backend_bases import register_backend + register_backend('xyz', 'my_backend', 'XYZ File Format') + ... + plt.savefig("figure.xyz") + +The files that are most relevant to backend_writers are + + matplotlib/backends/backend_your_backend.py + matplotlib/backend_bases.py + matplotlib/backends/__init__.py + matplotlib/__init__.py + matplotlib/_pylab_helpers.py + +Naming Conventions + + * classes Upper or MixedUpperCase + + * variables lower or lowerUpper + + * functions lower or underscore_separated + +""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from matplotlib._pylab_helpers import Gcf +from matplotlib.backend_bases import ( + FigureCanvasBase, FigureManagerBase, GraphicsContextBase, RendererBase) +from matplotlib.figure import Figure + + +class RendererTemplate(RendererBase): + """ + The renderer handles drawing/rendering operations. + + This is a minimal do-nothing class that can be used to get started when + writing a new backend. Refer to backend_bases.RendererBase for + documentation of the classes methods. + """ + def __init__(self, dpi): + self.dpi = dpi + + def draw_path(self, gc, path, transform, rgbFace=None): + pass + + # draw_markers is optional, and we get more correct relative + # timings by leaving it out. backend implementers concerned with + # performance will probably want to implement it +# def draw_markers(self, gc, marker_path, marker_trans, path, trans, +# rgbFace=None): +# pass + + # draw_path_collection is optional, and we get more correct + # relative timings by leaving it out. backend implementers concerned with + # performance will probably want to implement it +# def draw_path_collection(self, gc, master_transform, paths, +# all_transforms, offsets, offsetTrans, +# facecolors, edgecolors, linewidths, linestyles, +# antialiaseds): +# pass + + # draw_quad_mesh is optional, and we get more correct + # relative timings by leaving it out. backend implementers concerned with + # performance will probably want to implement it +# def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight, +# coordinates, offsets, offsetTrans, facecolors, +# antialiased, edgecolors): +# pass + + def draw_image(self, gc, x, y, im): + pass + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + pass + + def flipy(self): + return True + + def get_canvas_width_height(self): + return 100, 100 + + def get_text_width_height_descent(self, s, prop, ismath): + return 1, 1, 1 + + def new_gc(self): + return GraphicsContextTemplate() + + def points_to_pixels(self, points): + # if backend doesn't have dpi, e.g., postscript or svg + return points + # elif backend assumes a value for pixels_per_inch + #return points/72.0 * self.dpi.get() * pixels_per_inch/72.0 + # else + #return points/72.0 * self.dpi.get() + + +class GraphicsContextTemplate(GraphicsContextBase): + """ + The graphics context provides the color, line styles, etc... See the gtk + and postscript backends for examples of mapping the graphics context + attributes (cap styles, join styles, line widths, colors) to a particular + backend. In GTK this is done by wrapping a gtk.gdk.GC object and + forwarding the appropriate calls to it using a dictionary mapping styles + to gdk constants. In Postscript, all the work is done by the renderer, + mapping line styles to postscript calls. + + If it's more appropriate to do the mapping at the renderer level (as in + the postscript backend), you don't need to override any of the GC methods. + If it's more appropriate to wrap an instance (as in the GTK backend) and + do the mapping here, you'll need to override several of the setter + methods. + + The base GraphicsContext stores colors as a RGB tuple on the unit + interval, e.g., (0.5, 0.0, 1.0). You may need to map this to colors + appropriate for your backend. + """ + pass + + + +######################################################################## +# +# The following functions and classes are for pylab and implement +# window/figure managers, etc... +# +######################################################################## + +def draw_if_interactive(): + """ + For image backends - is not required + For GUI backends - this should be overridden if drawing should be done in + interactive python mode + """ + + +def show(block=None): + """ + For image backends - is not required + For GUI backends - show() is usually the last line of a pylab script and + tells the backend that it is time to draw. In interactive mode, this may + be a do nothing func. See the GTK backend for an example of how to handle + interactive versus batch mode + """ + for manager in Gcf.get_all_fig_managers(): + # do something to display the GUI + pass + + +def new_figure_manager(num, *args, **kwargs): + """ + Create a new figure manager instance + """ + # May be implemented via the `_new_figure_manager_template` helper. + # If a main-level app must be created, this (and + # new_figure_manager_given_figure) is the usual place to do it -- see + # backend_wx, backend_wxagg and backend_tkagg for examples. Not all GUIs + # require explicit instantiation of a main-level app (egg backend_gtk, + # backend_gtkagg) for pylab. + FigureClass = kwargs.pop('FigureClass', Figure) + thisFig = FigureClass(*args, **kwargs) + return new_figure_manager_given_figure(num, thisFig) + + +def new_figure_manager_given_figure(num, figure): + """ + Create a new figure manager instance for the given figure. + """ + # May be implemented via the `_new_figure_manager_template` helper. + canvas = FigureCanvasTemplate(figure) + manager = FigureManagerTemplate(canvas, num) + return manager + + +class FigureCanvasTemplate(FigureCanvasBase): + """ + The canvas the figure renders into. Calls the draw and print fig + methods, creates the renderers, etc... + + Note GUI templates will want to connect events for button presses, + mouse movements and key presses to functions that call the base + class methods button_press_event, button_release_event, + motion_notify_event, key_press_event, and key_release_event. See, + e.g., backend_gtk.py, backend_wx.py and backend_tkagg.py + + Attributes + ---------- + figure : `matplotlib.figure.Figure` + A high-level Figure instance + + """ + + def draw(self): + """ + Draw the figure using the renderer + """ + renderer = RendererTemplate(self.figure.dpi) + self.figure.draw(renderer) + + # You should provide a print_xxx function for every file format + # you can write. + + # If the file type is not in the base set of filetypes, + # you should add it to the class-scope filetypes dictionary as follows: + filetypes = FigureCanvasBase.filetypes.copy() + filetypes['foo'] = 'My magic Foo format' + + def print_foo(self, filename, *args, **kwargs): + """ + Write out format foo. The dpi, facecolor and edgecolor are restored + to their original values after this call, so you don't need to + save and restore them. + """ + pass + + def get_default_filetype(self): + return 'foo' + + +class FigureManagerTemplate(FigureManagerBase): + """ + Wrap everything up into a window for the pylab interface + + For non interactive backends, the base class does all the work + """ + pass + +######################################################################## +# +# Now just provide the standard names that backend.__init__ is expecting +# +######################################################################## + +FigureCanvas = FigureCanvasTemplate +FigureManager = FigureManagerTemplate diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkagg.py new file mode 100644 index 00000000000..9511326e4a5 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkagg.py @@ -0,0 +1,34 @@ +from __future__ import absolute_import, division, print_function + +from .. import cbook +from . import tkagg # Paint image to Tk photo blitter extension. +from .backend_agg import FigureCanvasAgg +from ._backend_tk import ( + _BackendTk, FigureCanvasTk, FigureManagerTk, NavigationToolbar2Tk) + + +class FigureCanvasTkAgg(FigureCanvasAgg, FigureCanvasTk): + def draw(self): + super(FigureCanvasTkAgg, self).draw() + tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2) + self._master.update_idletasks() + + def blit(self, bbox=None): + tkagg.blit( + self._tkphoto, self.renderer._renderer, bbox=bbox, colormode=2) + self._master.update_idletasks() + + +@cbook.deprecated("2.2") +class FigureManagerTkAgg(FigureManagerTk): + pass + + +@cbook.deprecated("2.2") +class NavigationToolbar2TkAgg(NavigationToolbar2Tk): + pass + + +@_BackendTk.export +class _BackendTkAgg(_BackendTk): + FigureCanvas = FigureCanvasTkAgg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkcairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkcairo.py new file mode 100644 index 00000000000..c4edfb97ed1 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_tkcairo.py @@ -0,0 +1,37 @@ +from __future__ import absolute_import, division, print_function + +import sys + +import numpy as np + +from . import tkagg # Paint image to Tk photo blitter extension. +from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo +from ._backend_tk import _BackendTk, FigureCanvasTk + + +class FigureCanvasTkCairo(FigureCanvasCairo, FigureCanvasTk): + def __init__(self, *args, **kwargs): + super(FigureCanvasTkCairo, self).__init__(*args, **kwargs) + self._renderer = RendererCairo(self.figure.dpi) + + def draw(self): + width = int(self.figure.bbox.width) + height = int(self.figure.bbox.height) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + self._renderer.set_ctx_from_surface(surface) + self._renderer.set_width_height(width, height) + self.figure.draw(self._renderer) + buf = np.reshape(surface.get_data(), (height, width, 4)) + # Convert from ARGB32 to RGBA8888. Using .take() instead of directly + # indexing ensures C-contiguity of the result, which is needed by + # tkagg. + buf = buf.take( + [2, 1, 0, 3] if sys.byteorder == "little" else [1, 2, 3, 0], + axis=2) + tkagg.blit(self._tkphoto, buf, colormode=2) + self._master.update_idletasks() + + +@_BackendTk.export +class _BackendTkCairo(_BackendTk): + FigureCanvas = FigureCanvasTkCairo diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg.py new file mode 100644 index 00000000000..c917a162ab1 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg.py @@ -0,0 +1,350 @@ +""" +Displays Agg images in the browser, with interactivity +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +# The WebAgg backend is divided into two modules: +# +# - `backend_webagg_core.py` contains code necessary to embed a WebAgg +# plot inside of a web application, and communicate in an abstract +# way over a web socket. +# +# - `backend_webagg.py` contains a concrete implementation of a basic +# application, implemented with tornado. + +import six + +from contextlib import contextmanager +import errno +import json +import os +import random +import sys +import signal +import socket +import threading + +try: + import tornado +except ImportError: + raise RuntimeError("The WebAgg backend requires Tornado.") + +import tornado.web +import tornado.ioloop +import tornado.websocket + +from matplotlib import rcParams +from matplotlib.backend_bases import _Backend +from matplotlib._pylab_helpers import Gcf +from . import backend_webagg_core as core +from .backend_webagg_core import TimerTornado + + +class ServerThread(threading.Thread): + def run(self): + tornado.ioloop.IOLoop.instance().start() + +webagg_server_thread = ServerThread() + + +class FigureCanvasWebAgg(core.FigureCanvasWebAggCore): + def show(self): + # show the figure window + show() + + def new_timer(self, *args, **kwargs): + return TimerTornado(*args, **kwargs) + + +class WebAggApplication(tornado.web.Application): + initialized = False + started = False + + class FavIcon(tornado.web.RequestHandler): + def get(self): + image_path = os.path.join( + os.path.dirname(os.path.dirname(__file__)), + 'mpl-data', 'images') + + self.set_header('Content-Type', 'image/png') + with open(os.path.join(image_path, + 'matplotlib.png'), 'rb') as fd: + self.write(fd.read()) + + class SingleFigurePage(tornado.web.RequestHandler): + def __init__(self, application, request, **kwargs): + self.url_prefix = kwargs.pop('url_prefix', '') + tornado.web.RequestHandler.__init__(self, application, + request, **kwargs) + + def get(self, fignum): + fignum = int(fignum) + manager = Gcf.get_fig_manager(fignum) + + ws_uri = 'ws://{req.host}{prefix}/'.format(req=self.request, + prefix=self.url_prefix) + self.render( + "single_figure.html", + prefix=self.url_prefix, + ws_uri=ws_uri, + fig_id=fignum, + toolitems=core.NavigationToolbar2WebAgg.toolitems, + canvas=manager.canvas) + + class AllFiguresPage(tornado.web.RequestHandler): + def __init__(self, application, request, **kwargs): + self.url_prefix = kwargs.pop('url_prefix', '') + tornado.web.RequestHandler.__init__(self, application, + request, **kwargs) + + def get(self): + ws_uri = 'ws://{req.host}{prefix}/'.format(req=self.request, + prefix=self.url_prefix) + self.render( + "all_figures.html", + prefix=self.url_prefix, + ws_uri=ws_uri, + figures=sorted(Gcf.figs.items()), + toolitems=core.NavigationToolbar2WebAgg.toolitems) + + class MplJs(tornado.web.RequestHandler): + def get(self): + self.set_header('Content-Type', 'application/javascript') + + js_content = core.FigureManagerWebAgg.get_javascript() + + self.write(js_content) + + class Download(tornado.web.RequestHandler): + def get(self, fignum, fmt): + fignum = int(fignum) + manager = Gcf.get_fig_manager(fignum) + + # TODO: Move this to a central location + mimetypes = { + 'ps': 'application/postscript', + 'eps': 'application/postscript', + 'pdf': 'application/pdf', + 'svg': 'image/svg+xml', + 'png': 'image/png', + 'jpeg': 'image/jpeg', + 'tif': 'image/tiff', + 'emf': 'application/emf' + } + + self.set_header('Content-Type', mimetypes.get(fmt, 'binary')) + + buff = six.BytesIO() + manager.canvas.figure.savefig(buff, format=fmt) + self.write(buff.getvalue()) + + class WebSocket(tornado.websocket.WebSocketHandler): + supports_binary = True + + def open(self, fignum): + self.fignum = int(fignum) + self.manager = Gcf.get_fig_manager(self.fignum) + self.manager.add_web_socket(self) + if hasattr(self, 'set_nodelay'): + self.set_nodelay(True) + + def on_close(self): + self.manager.remove_web_socket(self) + + def on_message(self, message): + message = json.loads(message) + # The 'supports_binary' message is on a client-by-client + # basis. The others affect the (shared) canvas as a + # whole. + if message['type'] == 'supports_binary': + self.supports_binary = message['value'] + else: + manager = Gcf.get_fig_manager(self.fignum) + # It is possible for a figure to be closed, + # but a stale figure UI is still sending messages + # from the browser. + if manager is not None: + manager.handle_json(message) + + def send_json(self, content): + self.write_message(json.dumps(content)) + + def send_binary(self, blob): + if self.supports_binary: + self.write_message(blob, binary=True) + else: + data_uri = "data:image/png;base64,{0}".format( + blob.encode('base64').replace('\n', '')) + self.write_message(data_uri) + + def __init__(self, url_prefix=''): + if url_prefix: + assert url_prefix[0] == '/' and url_prefix[-1] != '/', \ + 'url_prefix must start with a "/" and not end with one.' + + super(WebAggApplication, self).__init__( + [ + # Static files for the CSS and JS + (url_prefix + r'/_static/(.*)', + tornado.web.StaticFileHandler, + {'path': core.FigureManagerWebAgg.get_static_file_path()}), + + # An MPL favicon + (url_prefix + r'/favicon.ico', self.FavIcon), + + # The page that contains all of the pieces + (url_prefix + r'/([0-9]+)', self.SingleFigurePage, + {'url_prefix': url_prefix}), + + # The page that contains all of the figures + (url_prefix + r'/?', self.AllFiguresPage, + {'url_prefix': url_prefix}), + + (url_prefix + r'/js/mpl.js', self.MplJs), + + # Sends images and events to the browser, and receives + # events from the browser + (url_prefix + r'/([0-9]+)/ws', self.WebSocket), + + # Handles the downloading (i.e., saving) of static images + (url_prefix + r'/([0-9]+)/download.([a-z0-9.]+)', + self.Download), + ], + template_path=core.FigureManagerWebAgg.get_static_file_path()) + + @classmethod + def initialize(cls, url_prefix='', port=None, address=None): + if cls.initialized: + return + + # Create the class instance + app = cls(url_prefix=url_prefix) + + cls.url_prefix = url_prefix + + # This port selection algorithm is borrowed, more or less + # verbatim, from IPython. + def random_ports(port, n): + """ + Generate a list of n random ports near the given port. + + The first 5 ports will be sequential, and the remaining n-5 will be + randomly selected in the range [port-2*n, port+2*n]. + """ + for i in range(min(5, n)): + yield port + i + for i in range(n - 5): + yield port + random.randint(-2 * n, 2 * n) + + success = None + + if address is None: + cls.address = rcParams['webagg.address'] + else: + cls.address = address + cls.port = rcParams['webagg.port'] + for port in random_ports(cls.port, rcParams['webagg.port_retries']): + try: + app.listen(port, cls.address) + except socket.error as e: + if e.errno != errno.EADDRINUSE: + raise + else: + cls.port = port + success = True + break + + if not success: + raise SystemExit( + "The webagg server could not be started because an available " + "port could not be found") + + cls.initialized = True + + @classmethod + def start(cls): + if cls.started: + return + + """ + IOLoop.running() was removed as of Tornado 2.4; see for example + https://groups.google.com/forum/#!topic/python-tornado/QLMzkpQBGOY + Thus there is no correct way to check if the loop has already been + launched. We may end up with two concurrently running loops in that + unlucky case with all the expected consequences. + """ + ioloop = tornado.ioloop.IOLoop.instance() + + def shutdown(): + ioloop.stop() + print("Server is stopped") + sys.stdout.flush() + cls.started = False + + @contextmanager + def catch_sigint(): + old_handler = signal.signal( + signal.SIGINT, + lambda sig, frame: ioloop.add_callback_from_signal(shutdown)) + try: + yield + finally: + signal.signal(signal.SIGINT, old_handler) + + # Set the flag to True *before* blocking on ioloop.start() + cls.started = True + + print("Press Ctrl+C to stop WebAgg server") + sys.stdout.flush() + with catch_sigint(): + ioloop.start() + + +def ipython_inline_display(figure): + import tornado.template + + WebAggApplication.initialize() + if not webagg_server_thread.is_alive(): + webagg_server_thread.start() + + with open(os.path.join( + core.FigureManagerWebAgg.get_static_file_path(), + 'ipython_inline_figure.html')) as fd: + tpl = fd.read() + + fignum = figure.number + + t = tornado.template.Template(tpl) + return t.generate( + prefix=WebAggApplication.url_prefix, + fig_id=fignum, + toolitems=core.NavigationToolbar2WebAgg.toolitems, + canvas=figure.canvas, + port=WebAggApplication.port).decode('utf-8') + + +@_Backend.export +class _BackendWebAgg(_Backend): + FigureCanvas = FigureCanvasWebAgg + FigureManager = core.FigureManagerWebAgg + + @staticmethod + def trigger_manager_draw(manager): + manager.canvas.draw_idle() + + @staticmethod + def show(): + WebAggApplication.initialize() + + url = "http://127.0.0.1:{port}{prefix}".format( + port=WebAggApplication.port, + prefix=WebAggApplication.url_prefix) + + if rcParams['webagg.open_in_browser']: + import webbrowser + webbrowser.open(url) + else: + print("To view figure, visit {0}".format(url)) + + WebAggApplication.start() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg_core.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg_core.py new file mode 100644 index 00000000000..e75014b1e63 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_webagg_core.py @@ -0,0 +1,543 @@ +""" +Displays Agg images in the browser, with interactivity +""" +# The WebAgg backend is divided into two modules: +# +# - `backend_webagg_core.py` contains code necessary to embed a WebAgg +# plot inside of a web application, and communicate in an abstract +# way over a web socket. +# +# - `backend_webagg.py` contains a concrete implementation of a basic +# application, implemented with tornado. + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import datetime +import io +import json +import os +import warnings + +import numpy as np +import tornado + +from matplotlib.backends import backend_agg +from matplotlib.backend_bases import _Backend +from matplotlib import backend_bases +from matplotlib import _png + + +# http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes +_SHIFT_LUT = {59: ':', + 61: '+', + 173: '_', + 186: ':', + 187: '+', + 188: '<', + 189: '_', + 190: '>', + 191: '?', + 192: '~', + 219: '{', + 220: '|', + 221: '}', + 222: '"'} + +_LUT = {8: 'backspace', + 9: 'tab', + 13: 'enter', + 16: 'shift', + 17: 'control', + 18: 'alt', + 19: 'pause', + 20: 'caps', + 27: 'escape', + 32: ' ', + 33: 'pageup', + 34: 'pagedown', + 35: 'end', + 36: 'home', + 37: 'left', + 38: 'up', + 39: 'right', + 40: 'down', + 45: 'insert', + 46: 'delete', + 91: 'super', + 92: 'super', + 93: 'select', + 106: '*', + 107: '+', + 109: '-', + 110: '.', + 111: '/', + 144: 'num_lock', + 145: 'scroll_lock', + 186: ':', + 187: '=', + 188: ',', + 189: '-', + 190: '.', + 191: '/', + 192: '`', + 219: '[', + 220: '\\', + 221: ']', + 222: "'"} + + +def _handle_key(key): + """Handle key codes""" + code = int(key[key.index('k') + 1:]) + value = chr(code) + # letter keys + if code >= 65 and code <= 90: + if 'shift+' in key: + key = key.replace('shift+', '') + else: + value = value.lower() + # number keys + elif code >= 48 and code <= 57: + if 'shift+' in key: + value = ')!@#$%^&*('[int(value)] + key = key.replace('shift+', '') + # function keys + elif code >= 112 and code <= 123: + value = 'f%s' % (code - 111) + # number pad keys + elif code >= 96 and code <= 105: + value = '%s' % (code - 96) + # keys with shift alternatives + elif code in _SHIFT_LUT and 'shift+' in key: + key = key.replace('shift+', '') + value = _SHIFT_LUT[code] + elif code in _LUT: + value = _LUT[code] + key = key[:key.index('k')] + value + return key + + +class FigureCanvasWebAggCore(backend_agg.FigureCanvasAgg): + supports_blit = False + + def __init__(self, *args, **kwargs): + backend_agg.FigureCanvasAgg.__init__(self, *args, **kwargs) + + # Set to True when the renderer contains data that is newer + # than the PNG buffer. + self._png_is_old = True + + # Set to True by the `refresh` message so that the next frame + # sent to the clients will be a full frame. + self._force_full = True + + # Store the current image mode so that at any point, clients can + # request the information. This should be changed by calling + # self.set_image_mode(mode) so that the notification can be given + # to the connected clients. + self._current_image_mode = 'full' + + # Store the DPI ratio of the browser. This is the scaling that + # occurs automatically for all images on a HiDPI display. + self._dpi_ratio = 1 + + def show(self): + # show the figure window + from matplotlib.pyplot import show + show() + + def draw(self): + renderer = self.get_renderer(cleared=True) + + self._png_is_old = True + + backend_agg.RendererAgg.lock.acquire() + try: + self.figure.draw(renderer) + finally: + backend_agg.RendererAgg.lock.release() + # Swap the frames + self.manager.refresh_all() + + def draw_idle(self): + self.send_event("draw") + + def set_image_mode(self, mode): + """ + Set the image mode for any subsequent images which will be sent + to the clients. The modes may currently be either 'full' or 'diff'. + + Note: diff images may not contain transparency, therefore upon + draw this mode may be changed if the resulting image has any + transparent component. + + """ + if mode not in ['full', 'diff']: + raise ValueError('image mode must be either full or diff.') + if self._current_image_mode != mode: + self._current_image_mode = mode + self.handle_send_image_mode(None) + + def get_diff_image(self): + if self._png_is_old: + renderer = self.get_renderer() + + # The buffer is created as type uint32 so that entire + # pixels can be compared in one numpy call, rather than + # needing to compare each plane separately. + buff = (np.frombuffer(renderer.buffer_rgba(), dtype=np.uint32) + .reshape((renderer.height, renderer.width))) + + # If any pixels have transparency, we need to force a full + # draw as we cannot overlay new on top of old. + pixels = buff.view(dtype=np.uint8).reshape(buff.shape + (4,)) + + if self._force_full or np.any(pixels[:, :, 3] != 255): + self.set_image_mode('full') + output = buff + else: + self.set_image_mode('diff') + last_buffer = (np.frombuffer(self._last_renderer.buffer_rgba(), + dtype=np.uint32) + .reshape((renderer.height, renderer.width))) + diff = buff != last_buffer + output = np.where(diff, buff, 0) + + # TODO: We should write a new version of write_png that + # handles the differencing inline + buff = _png.write_png( + output.view(dtype=np.uint8).reshape(output.shape + (4,)), + None, compression=6, filter=_png.PNG_FILTER_NONE) + + # Swap the renderer frames + self._renderer, self._last_renderer = ( + self._last_renderer, renderer) + self._force_full = False + self._png_is_old = False + return buff + + def get_renderer(self, cleared=None): + # Mirrors super.get_renderer, but caches the old one + # so that we can do things such as produce a diff image + # in get_diff_image + _, _, w, h = self.figure.bbox.bounds + w, h = int(w), int(h) + key = w, h, self.figure.dpi + try: + self._lastKey, self._renderer + except AttributeError: + need_new_renderer = True + else: + need_new_renderer = (self._lastKey != key) + + if need_new_renderer: + self._renderer = backend_agg.RendererAgg( + w, h, self.figure.dpi) + self._last_renderer = backend_agg.RendererAgg( + w, h, self.figure.dpi) + self._lastKey = key + + elif cleared: + self._renderer.clear() + + return self._renderer + + def handle_event(self, event): + e_type = event['type'] + handler = getattr(self, 'handle_{0}'.format(e_type), + self.handle_unknown_event) + return handler(event) + + def handle_unknown_event(self, event): + warnings.warn('Unhandled message type {0}. {1}'.format( + event['type'], event)) + + def handle_ack(self, event): + # Network latency tends to decrease if traffic is flowing + # in both directions. Therefore, the browser sends back + # an "ack" message after each image frame is received. + # This could also be used as a simple sanity check in the + # future, but for now the performance increase is enough + # to justify it, even if the server does nothing with it. + pass + + def handle_draw(self, event): + self.draw() + + def _handle_mouse(self, event): + x = event['x'] + y = event['y'] + y = self.get_renderer().height - y + + # Javascript button numbers and matplotlib button numbers are + # off by 1 + button = event['button'] + 1 + + # The right mouse button pops up a context menu, which + # doesn't work very well, so use the middle mouse button + # instead. It doesn't seem that it's possible to disable + # the context menu in recent versions of Chrome. If this + # is resolved, please also adjust the docstring in MouseEvent. + if button == 2: + button = 3 + + e_type = event['type'] + guiEvent = event.get('guiEvent', None) + if e_type == 'button_press': + self.button_press_event(x, y, button, guiEvent=guiEvent) + elif e_type == 'button_release': + self.button_release_event(x, y, button, guiEvent=guiEvent) + elif e_type == 'motion_notify': + self.motion_notify_event(x, y, guiEvent=guiEvent) + elif e_type == 'figure_enter': + self.enter_notify_event(xy=(x, y), guiEvent=guiEvent) + elif e_type == 'figure_leave': + self.leave_notify_event() + elif e_type == 'scroll': + self.scroll_event(x, y, event['step'], guiEvent=guiEvent) + handle_button_press = handle_button_release = handle_motion_notify = \ + handle_figure_enter = handle_figure_leave = handle_scroll = \ + _handle_mouse + + def _handle_key(self, event): + key = _handle_key(event['key']) + e_type = event['type'] + guiEvent = event.get('guiEvent', None) + if e_type == 'key_press': + self.key_press_event(key, guiEvent=guiEvent) + elif e_type == 'key_release': + self.key_release_event(key, guiEvent=guiEvent) + handle_key_press = handle_key_release = _handle_key + + def handle_toolbar_button(self, event): + # TODO: Be more suspicious of the input + getattr(self.toolbar, event['name'])() + + def handle_refresh(self, event): + figure_label = self.figure.get_label() + if not figure_label: + figure_label = "Figure {0}".format(self.manager.num) + self.send_event('figure_label', label=figure_label) + self._force_full = True + self.draw_idle() + + def handle_resize(self, event): + x, y = event.get('width', 800), event.get('height', 800) + x, y = int(x) * self._dpi_ratio, int(y) * self._dpi_ratio + fig = self.figure + # An attempt at approximating the figure size in pixels. + fig.set_size_inches(x / fig.dpi, y / fig.dpi, forward=False) + + _, _, w, h = self.figure.bbox.bounds + # Acknowledge the resize, and force the viewer to update the + # canvas size to the figure's new size (which is hopefully + # identical or within a pixel or so). + self._png_is_old = True + self.manager.resize(w, h) + self.resize_event() + + def handle_send_image_mode(self, event): + # The client requests notification of what the current image mode is. + self.send_event('image_mode', mode=self._current_image_mode) + + def handle_set_dpi_ratio(self, event): + dpi_ratio = event.get('dpi_ratio', 1) + if dpi_ratio != self._dpi_ratio: + # We don't want to scale up the figure dpi more than once. + if not hasattr(self.figure, '_original_dpi'): + self.figure._original_dpi = self.figure.dpi + self.figure.dpi = dpi_ratio * self.figure._original_dpi + self._dpi_ratio = dpi_ratio + self._force_full = True + self.draw_idle() + + def send_event(self, event_type, **kwargs): + self.manager._send_event(event_type, **kwargs) + + +_JQUERY_ICON_CLASSES = { + 'home': 'ui-icon ui-icon-home', + 'back': 'ui-icon ui-icon-circle-arrow-w', + 'forward': 'ui-icon ui-icon-circle-arrow-e', + 'zoom_to_rect': 'ui-icon ui-icon-search', + 'move': 'ui-icon ui-icon-arrow-4', + 'download': 'ui-icon ui-icon-disk', + None: None, +} + + +class NavigationToolbar2WebAgg(backend_bases.NavigationToolbar2): + + # Use the standard toolbar items + download button + toolitems = [(text, tooltip_text, _JQUERY_ICON_CLASSES[image_file], + name_of_method) + for text, tooltip_text, image_file, name_of_method + in (backend_bases.NavigationToolbar2.toolitems + + (('Download', 'Download plot', 'download', 'download'),)) + if image_file in _JQUERY_ICON_CLASSES] + + def _init_toolbar(self): + self.message = '' + self.cursor = 0 + + def set_message(self, message): + if message != self.message: + self.canvas.send_event("message", message=message) + self.message = message + + def set_cursor(self, cursor): + if cursor != self.cursor: + self.canvas.send_event("cursor", cursor=cursor) + self.cursor = cursor + + def draw_rubberband(self, event, x0, y0, x1, y1): + self.canvas.send_event( + "rubberband", x0=x0, y0=y0, x1=x1, y1=y1) + + def release_zoom(self, event): + backend_bases.NavigationToolbar2.release_zoom(self, event) + self.canvas.send_event( + "rubberband", x0=-1, y0=-1, x1=-1, y1=-1) + + def save_figure(self, *args): + """Save the current figure""" + self.canvas.send_event('save') + + +class FigureManagerWebAgg(backend_bases.FigureManagerBase): + ToolbarCls = NavigationToolbar2WebAgg + + def __init__(self, canvas, num): + backend_bases.FigureManagerBase.__init__(self, canvas, num) + + self.web_sockets = set() + + self.toolbar = self._get_toolbar(canvas) + + def show(self): + pass + + def _get_toolbar(self, canvas): + toolbar = self.ToolbarCls(canvas) + return toolbar + + def resize(self, w, h): + self._send_event( + 'resize', + size=(w / self.canvas._dpi_ratio, h / self.canvas._dpi_ratio)) + + def set_window_title(self, title): + self._send_event('figure_label', label=title) + + # The following methods are specific to FigureManagerWebAgg + + def add_web_socket(self, web_socket): + assert hasattr(web_socket, 'send_binary') + assert hasattr(web_socket, 'send_json') + + self.web_sockets.add(web_socket) + + _, _, w, h = self.canvas.figure.bbox.bounds + self.resize(w, h) + self._send_event('refresh') + + def remove_web_socket(self, web_socket): + self.web_sockets.remove(web_socket) + + def handle_json(self, content): + self.canvas.handle_event(content) + + def refresh_all(self): + if self.web_sockets: + diff = self.canvas.get_diff_image() + if diff is not None: + for s in self.web_sockets: + s.send_binary(diff) + + @classmethod + def get_javascript(cls, stream=None): + if stream is None: + output = io.StringIO() + else: + output = stream + + with io.open(os.path.join( + os.path.dirname(__file__), + "web_backend", "js", + "mpl.js"), encoding='utf8') as fd: + output.write(fd.read()) + + toolitems = [] + for name, tooltip, image, method in cls.ToolbarCls.toolitems: + if name is None: + toolitems.append(['', '', '', '']) + else: + toolitems.append([name, tooltip, image, method]) + output.write("mpl.toolbar_items = {0};\n\n".format( + json.dumps(toolitems))) + + extensions = [] + for filetype, ext in sorted(FigureCanvasWebAggCore. + get_supported_filetypes_grouped(). + items()): + if not ext[0] == 'pgf': # pgf does not support BytesIO + extensions.append(ext[0]) + output.write("mpl.extensions = {0};\n\n".format( + json.dumps(extensions))) + + output.write("mpl.default_extension = {0};".format( + json.dumps(FigureCanvasWebAggCore.get_default_filetype()))) + + if stream is None: + return output.getvalue() + + @classmethod + def get_static_file_path(cls): + return os.path.join(os.path.dirname(__file__), 'web_backend') + + def _send_event(self, event_type, **kwargs): + payload = {'type': event_type} + payload.update(kwargs) + for s in self.web_sockets: + s.send_json(payload) + + +class TimerTornado(backend_bases.TimerBase): + def _timer_start(self): + self._timer_stop() + if self._single: + ioloop = tornado.ioloop.IOLoop.instance() + self._timer = ioloop.add_timeout( + datetime.timedelta(milliseconds=self.interval), + self._on_timer) + else: + self._timer = tornado.ioloop.PeriodicCallback( + self._on_timer, + self.interval) + self._timer.start() + + def _timer_stop(self): + if self._timer is None: + return + elif self._single: + ioloop = tornado.ioloop.IOLoop.instance() + ioloop.remove_timeout(self._timer) + else: + self._timer.stop() + + self._timer = None + + def _timer_set_interval(self): + # Only stop and restart it if the timer has already been started + if self._timer is not None: + self._timer_stop() + self._timer_start() + + +@_Backend.export +class _BackendWebAggCoreAgg(_Backend): + FigureCanvas = FigureCanvasWebAggCore + FigureManager = FigureManagerWebAgg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_wx.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wx.py new file mode 100644 index 00000000000..2ecc1a4b3b4 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wx.py @@ -0,0 +1,2002 @@ +""" + A wxPython backend for matplotlib, based (very heavily) on + backend_template.py and backend_gtk.py + + Author: Jeremy O'Donoghue (jeremy@o-donoghue.com) + + Derived from original copyright work by John Hunter + (jdhunter@ace.bsd.uchicago.edu) + + Copyright (C) Jeremy O'Donoghue & John Hunter, 2003-4 + + License: This work is licensed under a PSF compatible license. A copy + should be included with this source code. + +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import xrange +import six + +import sys +import os +import os.path +import math +import weakref +import warnings + +import matplotlib +from matplotlib.backend_bases import ( + _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase, + NavigationToolbar2, RendererBase, TimerBase, cursors) +from matplotlib.backend_bases import _has_pil + +from matplotlib._pylab_helpers import Gcf +from matplotlib.cbook import is_writable_file_like, warn_deprecated +from matplotlib.figure import Figure +from matplotlib.path import Path +from matplotlib.transforms import Affine2D +from matplotlib.widgets import SubplotTool +from matplotlib import cbook, rcParams, backend_tools + +from . import wx_compat as wxc +import wx + +# Debugging settings here... +# Debug level set here. If the debug level is less than 5, information +# messages (progressively more info for lower value) are printed. In addition, +# traceback is performed, and pdb activated, for all uncaught exceptions in +# this case +_DEBUG = 5 +if _DEBUG < 5: + import traceback + import pdb +_DEBUG_lvls = {1: 'Low ', 2: 'Med ', 3: 'High', 4: 'Error'} + + +def DEBUG_MSG(string, lvl=3, o=None): + if lvl >= _DEBUG: + cls = o.__class__ + # Jeremy, often times the commented line won't print but the + # one below does. I think WX is redefining stderr, damned + # beast + # print("%s- %s in %s" % (_DEBUG_lvls[lvl], string, cls), + # file=sys.stderr) + print("%s- %s in %s" % (_DEBUG_lvls[lvl], string, cls)) + + +def debug_on_error(type, value, tb): + """Code due to Thomas Heller - published in Python Cookbook (O'Reilley)""" + traceback.print_exception(type, value, tb) + print() + pdb.pm() # jdh uncomment + + +class fake_stderr(object): + """ + Wx does strange things with stderr, as it makes the assumption that + there is probably no console. This redirects stderr to the console, since + we know that there is one! + """ + + def write(self, msg): + print("Stderr: %s\n\r" % msg) + + +# the True dots per inch on the screen; should be display dependent +# see +# http://groups.google.com/groups?q=screen+dpi+x11&hl=en&lr=&ie=UTF-8&oe=UTF-8&safe=off&selm=7077.26e81ad5%40swift.cs.tcd.ie&rnum=5 +# for some info about screen dpi +PIXELS_PER_INCH = 75 + +# Delay time for idle checks +IDLE_DELAY = 5 + + +def error_msg_wx(msg, parent=None): + """ + Signal an error condition -- in a GUI, popup a error dialog + """ + dialog = wx.MessageDialog(parent=parent, + message=msg, + caption='Matplotlib backend_wx error', + style=wx.OK | wx.CENTRE) + dialog.ShowModal() + dialog.Destroy() + return None + + +def raise_msg_to_str(msg): + """msg is a return arg from a raise. Join with new lines.""" + if not isinstance(msg, six.string_types): + msg = '\n'.join(map(str, msg)) + return msg + + +class TimerWx(TimerBase): + ''' + Subclass of :class:`backend_bases.TimerBase` that uses WxTimer events. + + Attributes + ---------- + interval : int + The time between timer events in milliseconds. Default is 1000 ms. + single_shot : bool + Boolean flag indicating whether this timer should operate as single + shot (run once and then stop). Defaults to False. + callbacks : list + Stores list of (func, args) tuples that will be called upon timer + events. This list can be manipulated directly, or the functions + `add_callback` and `remove_callback` can be used. + + ''' + + def __init__(self, parent, *args, **kwargs): + TimerBase.__init__(self, *args, **kwargs) + + # Create a new timer and connect the timer event to our handler. + # For WX, the events have to use a widget for binding. + self.parent = parent + self._timer = wx.Timer(self.parent, wx.NewId()) + self.parent.Bind(wx.EVT_TIMER, self._on_timer, self._timer) + + # Unbinding causes Wx to stop for some reason. Disabling for now. +# def __del__(self): +# TimerBase.__del__(self) +# self.parent.Bind(wx.EVT_TIMER, None, self._timer) + + def _timer_start(self): + self._timer.Start(self._interval, self._single) + + def _timer_stop(self): + self._timer.Stop() + + def _timer_set_interval(self): + self._timer_start() + + def _timer_set_single_shot(self): + self._timer.Start() + + def _on_timer(self, *args): + TimerBase._on_timer(self) + + +class RendererWx(RendererBase): + """ + The renderer handles all the drawing primitives using a graphics + context instance that controls the colors/styles. It acts as the + 'renderer' instance used by many classes in the hierarchy. + """ + # In wxPython, drawing is performed on a wxDC instance, which will + # generally be mapped to the client aread of the window displaying + # the plot. Under wxPython, the wxDC instance has a wx.Pen which + # describes the colour and weight of any lines drawn, and a wxBrush + # which describes the fill colour of any closed polygon. + + fontweights = wxc.fontweights + fontangles = wxc.fontangles + + # wxPython allows for portable font styles, choosing them appropriately + # for the target platform. Map some standard font names to the portable + # styles + # QUESTION: Is it be wise to agree standard fontnames across all backends? + fontnames = wxc.fontnames + + def __init__(self, bitmap, dpi): + """ + Initialise a wxWindows renderer instance. + """ + warn_deprecated('2.0', message="The WX backend is " + "deprecated. It's untested " + "and will be removed in Matplotlib 3.0. " + "Use the WXAgg backend instead. " + "See Matplotlib usage FAQ for more info on backends.", + alternative='WXAgg') + RendererBase.__init__(self) + DEBUG_MSG("__init__()", 1, self) + self.width = bitmap.GetWidth() + self.height = bitmap.GetHeight() + self.bitmap = bitmap + self.fontd = {} + self.dpi = dpi + self.gc = None + + def flipy(self): + return True + + def offset_text_height(self): + return True + + def get_text_width_height_descent(self, s, prop, ismath): + """ + get the width and height in display coords of the string s + with FontPropertry prop + """ + # return 1, 1 + if ismath: + s = self.strip_math(s) + + if self.gc is None: + gc = self.new_gc() + else: + gc = self.gc + gfx_ctx = gc.gfx_ctx + font = self.get_wx_font(s, prop) + gfx_ctx.SetFont(font, wx.BLACK) + w, h, descent, leading = gfx_ctx.GetFullTextExtent(s) + + return w, h, descent + + def get_canvas_width_height(self): + 'return the canvas width and height in display coords' + return self.width, self.height + + def handle_clip_rectangle(self, gc): + new_bounds = gc.get_clip_rectangle() + if new_bounds is not None: + new_bounds = new_bounds.bounds + gfx_ctx = gc.gfx_ctx + if gfx_ctx._lastcliprect != new_bounds: + gfx_ctx._lastcliprect = new_bounds + if new_bounds is None: + gfx_ctx.ResetClip() + else: + gfx_ctx.Clip(new_bounds[0], + self.height - new_bounds[1] - new_bounds[3], + new_bounds[2], new_bounds[3]) + + @staticmethod + def convert_path(gfx_ctx, path, transform): + wxpath = gfx_ctx.CreatePath() + for points, code in path.iter_segments(transform): + if code == Path.MOVETO: + wxpath.MoveToPoint(*points) + elif code == Path.LINETO: + wxpath.AddLineToPoint(*points) + elif code == Path.CURVE3: + wxpath.AddQuadCurveToPoint(*points) + elif code == Path.CURVE4: + wxpath.AddCurveToPoint(*points) + elif code == Path.CLOSEPOLY: + wxpath.CloseSubpath() + return wxpath + + def draw_path(self, gc, path, transform, rgbFace=None): + gc.select() + self.handle_clip_rectangle(gc) + gfx_ctx = gc.gfx_ctx + transform = transform + \ + Affine2D().scale(1.0, -1.0).translate(0.0, self.height) + wxpath = self.convert_path(gfx_ctx, path, transform) + if rgbFace is not None: + gfx_ctx.SetBrush(wx.Brush(gc.get_wxcolour(rgbFace))) + gfx_ctx.DrawPath(wxpath) + else: + gfx_ctx.StrokePath(wxpath) + gc.unselect() + + def draw_image(self, gc, x, y, im): + bbox = gc.get_clip_rectangle() + if bbox is not None: + l, b, w, h = bbox.bounds + else: + l = 0 + b = 0 + w = self.width + h = self.height + rows, cols = im.shape[:2] + bitmap = wxc.BitmapFromBuffer(cols, rows, im.tostring()) + gc = self.get_gc() + gc.select() + gc.gfx_ctx.DrawBitmap(bitmap, int(l), int(self.height - b), + int(w), int(-h)) + gc.unselect() + + def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None): + if ismath: + s = self.strip_math(s) + DEBUG_MSG("draw_text()", 1, self) + gc.select() + self.handle_clip_rectangle(gc) + gfx_ctx = gc.gfx_ctx + + font = self.get_wx_font(s, prop) + color = gc.get_wxcolour(gc.get_rgb()) + gfx_ctx.SetFont(font, color) + + w, h, d = self.get_text_width_height_descent(s, prop, ismath) + x = int(x) + y = int(y - h) + + if angle == 0.0: + gfx_ctx.DrawText(s, x, y) + else: + rads = math.radians(angle) + xo = h * math.sin(rads) + yo = h * math.cos(rads) + gfx_ctx.DrawRotatedText(s, x - xo, y - yo, rads) + + gc.unselect() + + def new_gc(self): + """ + Return an instance of a GraphicsContextWx, and sets the current gc copy + """ + DEBUG_MSG('new_gc()', 2, self) + self.gc = GraphicsContextWx(self.bitmap, self) + self.gc.select() + self.gc.unselect() + return self.gc + + def get_gc(self): + """ + Fetch the locally cached gc. + """ + # This is a dirty hack to allow anything with access to a renderer to + # access the current graphics context + assert self.gc is not None, "gc must be defined" + return self.gc + + def get_wx_font(self, s, prop): + """ + Return a wx font. Cache instances in a font dictionary for + efficiency + """ + DEBUG_MSG("get_wx_font()", 1, self) + + key = hash(prop) + fontprop = prop + fontname = fontprop.get_name() + + font = self.fontd.get(key) + if font is not None: + return font + + # Allow use of platform independent and dependent font names + wxFontname = self.fontnames.get(fontname, wx.ROMAN) + wxFacename = '' # Empty => wxPython chooses based on wx_fontname + + # Font colour is determined by the active wx.Pen + # TODO: It may be wise to cache font information + size = self.points_to_pixels(fontprop.get_size_in_points()) + + font = wx.Font(int(size + 0.5), # Size + wxFontname, # 'Generic' name + self.fontangles[fontprop.get_style()], # Angle + self.fontweights[fontprop.get_weight()], # Weight + False, # Underline + wxFacename) # Platform font name + + # cache the font and gc and return it + self.fontd[key] = font + + return font + + def points_to_pixels(self, points): + """ + convert point measures to pixes using dpi and the pixels per + inch of the display + """ + return points * (PIXELS_PER_INCH / 72.0 * self.dpi / 72.0) + + +class GraphicsContextWx(GraphicsContextBase): + """ + The graphics context provides the color, line styles, etc... + + This class stores a reference to a wxMemoryDC, and a + wxGraphicsContext that draws to it. Creating a wxGraphicsContext + seems to be fairly heavy, so these objects are cached based on the + bitmap object that is passed in. + + The base GraphicsContext stores colors as a RGB tuple on the unit + interval, e.g., (0.5, 0.0, 1.0). wxPython uses an int interval, but + since wxPython colour management is rather simple, I have not chosen + to implement a separate colour manager class. + """ + _capd = {'butt': wx.CAP_BUTT, + 'projecting': wx.CAP_PROJECTING, + 'round': wx.CAP_ROUND} + + _joind = {'bevel': wx.JOIN_BEVEL, + 'miter': wx.JOIN_MITER, + 'round': wx.JOIN_ROUND} + + _cache = weakref.WeakKeyDictionary() + + def __init__(self, bitmap, renderer): + GraphicsContextBase.__init__(self) + # assert self.Ok(), "wxMemoryDC not OK to use" + DEBUG_MSG("__init__()", 1, self) + DEBUG_MSG("__init__() 2: %s" % bitmap, 1, self) + + dc, gfx_ctx = self._cache.get(bitmap, (None, None)) + if dc is None: + dc = wx.MemoryDC() + dc.SelectObject(bitmap) + gfx_ctx = wx.GraphicsContext.Create(dc) + gfx_ctx._lastcliprect = None + self._cache[bitmap] = dc, gfx_ctx + + self.bitmap = bitmap + self.dc = dc + self.gfx_ctx = gfx_ctx + self._pen = wx.Pen('BLACK', 1, wx.SOLID) + gfx_ctx.SetPen(self._pen) + self._style = wx.SOLID + self.renderer = renderer + + def select(self): + """ + Select the current bitmap into this wxDC instance + """ + + if sys.platform == 'win32': + self.dc.SelectObject(self.bitmap) + self.IsSelected = True + + def unselect(self): + """ + Select a Null bitmasp into this wxDC instance + """ + if sys.platform == 'win32': + self.dc.SelectObject(wx.NullBitmap) + self.IsSelected = False + + def set_foreground(self, fg, isRGBA=None): + """ + Set the foreground color. fg can be a matlab format string, a + html hex color string, an rgb unit tuple, or a float between 0 + and 1. In the latter case, grayscale is used. + """ + # Implementation note: wxPython has a separate concept of pen and + # brush - the brush fills any outline trace left by the pen. + # Here we set both to the same colour - if a figure is not to be + # filled, the renderer will set the brush to be transparent + # Same goes for text foreground... + DEBUG_MSG("set_foreground()", 1, self) + self.select() + GraphicsContextBase.set_foreground(self, fg, isRGBA) + + self._pen.SetColour(self.get_wxcolour(self.get_rgb())) + self.gfx_ctx.SetPen(self._pen) + self.unselect() + + def set_linewidth(self, w): + """ + Set the line width. + """ + w = float(w) + DEBUG_MSG("set_linewidth()", 1, self) + self.select() + if w > 0 and w < 1: + w = 1 + GraphicsContextBase.set_linewidth(self, w) + lw = int(self.renderer.points_to_pixels(self._linewidth)) + if lw == 0: + lw = 1 + self._pen.SetWidth(lw) + self.gfx_ctx.SetPen(self._pen) + self.unselect() + + def set_capstyle(self, cs): + """ + Set the capstyle as a string in ('butt', 'round', 'projecting') + """ + DEBUG_MSG("set_capstyle()", 1, self) + self.select() + GraphicsContextBase.set_capstyle(self, cs) + self._pen.SetCap(GraphicsContextWx._capd[self._capstyle]) + self.gfx_ctx.SetPen(self._pen) + self.unselect() + + def set_joinstyle(self, js): + """ + Set the join style to be one of ('miter', 'round', 'bevel') + """ + DEBUG_MSG("set_joinstyle()", 1, self) + self.select() + GraphicsContextBase.set_joinstyle(self, js) + self._pen.SetJoin(GraphicsContextWx._joind[self._joinstyle]) + self.gfx_ctx.SetPen(self._pen) + self.unselect() + + @cbook.deprecated("2.1") + def set_linestyle(self, ls): + """ + Set the line style to be one of + """ + DEBUG_MSG("set_linestyle()", 1, self) + self.select() + GraphicsContextBase.set_linestyle(self, ls) + try: + self._style = wxc.dashd_wx[ls] + except KeyError: + self._style = wx.LONG_DASH # Style not used elsewhere... + + # On MS Windows platform, only line width of 1 allowed for dash lines + if wx.Platform == '__WXMSW__': + self.set_linewidth(1) + + self._pen.SetStyle(self._style) + self.gfx_ctx.SetPen(self._pen) + self.unselect() + + def get_wxcolour(self, color): + """return a wx.Colour from RGB format""" + DEBUG_MSG("get_wx_color()", 1, self) + if len(color) == 3: + r, g, b = color + r *= 255 + g *= 255 + b *= 255 + return wx.Colour(red=int(r), green=int(g), blue=int(b)) + else: + r, g, b, a = color + r *= 255 + g *= 255 + b *= 255 + a *= 255 + return wx.Colour( + red=int(r), + green=int(g), + blue=int(b), + alpha=int(a)) + + +class _FigureCanvasWxBase(FigureCanvasBase, wx.Panel): + """ + The FigureCanvas contains the figure and does event handling. + + In the wxPython backend, it is derived from wxPanel, and (usually) lives + inside a frame instantiated by a FigureManagerWx. The parent window + probably implements a wx.Sizer to control the displayed control size - but + we give a hint as to our preferred minimum size. + """ + + keyvald = { + wx.WXK_CONTROL: 'control', + wx.WXK_SHIFT: 'shift', + wx.WXK_ALT: 'alt', + wx.WXK_LEFT: 'left', + wx.WXK_UP: 'up', + wx.WXK_RIGHT: 'right', + wx.WXK_DOWN: 'down', + wx.WXK_ESCAPE: 'escape', + wx.WXK_F1: 'f1', + wx.WXK_F2: 'f2', + wx.WXK_F3: 'f3', + wx.WXK_F4: 'f4', + wx.WXK_F5: 'f5', + wx.WXK_F6: 'f6', + wx.WXK_F7: 'f7', + wx.WXK_F8: 'f8', + wx.WXK_F9: 'f9', + wx.WXK_F10: 'f10', + wx.WXK_F11: 'f11', + wx.WXK_F12: 'f12', + wx.WXK_SCROLL: 'scroll_lock', + wx.WXK_PAUSE: 'break', + wx.WXK_BACK: 'backspace', + wx.WXK_RETURN: 'enter', + wx.WXK_INSERT: 'insert', + wx.WXK_DELETE: 'delete', + wx.WXK_HOME: 'home', + wx.WXK_END: 'end', + wx.WXK_PAGEUP: 'pageup', + wx.WXK_PAGEDOWN: 'pagedown', + wx.WXK_NUMPAD0: '0', + wx.WXK_NUMPAD1: '1', + wx.WXK_NUMPAD2: '2', + wx.WXK_NUMPAD3: '3', + wx.WXK_NUMPAD4: '4', + wx.WXK_NUMPAD5: '5', + wx.WXK_NUMPAD6: '6', + wx.WXK_NUMPAD7: '7', + wx.WXK_NUMPAD8: '8', + wx.WXK_NUMPAD9: '9', + wx.WXK_NUMPAD_ADD: '+', + wx.WXK_NUMPAD_SUBTRACT: '-', + wx.WXK_NUMPAD_MULTIPLY: '*', + wx.WXK_NUMPAD_DIVIDE: '/', + wx.WXK_NUMPAD_DECIMAL: 'dec', + wx.WXK_NUMPAD_ENTER: 'enter', + wx.WXK_NUMPAD_UP: 'up', + wx.WXK_NUMPAD_RIGHT: 'right', + wx.WXK_NUMPAD_DOWN: 'down', + wx.WXK_NUMPAD_LEFT: 'left', + wx.WXK_NUMPAD_PAGEUP: 'pageup', + wx.WXK_NUMPAD_PAGEDOWN: 'pagedown', + wx.WXK_NUMPAD_HOME: 'home', + wx.WXK_NUMPAD_END: 'end', + wx.WXK_NUMPAD_INSERT: 'insert', + wx.WXK_NUMPAD_DELETE: 'delete', + } + + def __init__(self, parent, id, figure): + """ + Initialise a FigureWx instance. + + - Initialise the FigureCanvasBase and wxPanel parents. + - Set event handlers for: + EVT_SIZE (Resize event) + EVT_PAINT (Paint event) + """ + + FigureCanvasBase.__init__(self, figure) + # Set preferred window size hint - helps the sizer (if one is + # connected) + l, b, w, h = figure.bbox.bounds + w = int(math.ceil(w)) + h = int(math.ceil(h)) + + wx.Panel.__init__(self, parent, id, size=wx.Size(w, h)) + + def do_nothing(*args, **kwargs): + warnings.warn( + "could not find a setinitialsize function for backend_wx; " + "please report your wxpython version=%s " + "to the matplotlib developers list" % + wxc.backend_version) + pass + + # try to find the set size func across wx versions + try: + getattr(self, 'SetInitialSize') + except AttributeError: + self.SetInitialSize = getattr(self, 'SetBestFittingSize', + do_nothing) + + if not hasattr(self, 'IsShownOnScreen'): + self.IsShownOnScreen = getattr(self, 'IsVisible', + lambda *args: True) + + # Create the drawing bitmap + self.bitmap = wxc.EmptyBitmap(w, h) + DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w, h), 2, self) + # TODO: Add support for 'point' inspection and plot navigation. + self._isDrawn = False + + self.Bind(wx.EVT_SIZE, self._onSize) + self.Bind(wx.EVT_PAINT, self._onPaint) + self.Bind(wx.EVT_KEY_DOWN, self._onKeyDown) + self.Bind(wx.EVT_KEY_UP, self._onKeyUp) + self.Bind(wx.EVT_RIGHT_DOWN, self._onRightButtonDown) + self.Bind(wx.EVT_RIGHT_DCLICK, self._onRightButtonDClick) + self.Bind(wx.EVT_RIGHT_UP, self._onRightButtonUp) + self.Bind(wx.EVT_MOUSEWHEEL, self._onMouseWheel) + self.Bind(wx.EVT_LEFT_DOWN, self._onLeftButtonDown) + self.Bind(wx.EVT_LEFT_DCLICK, self._onLeftButtonDClick) + self.Bind(wx.EVT_LEFT_UP, self._onLeftButtonUp) + self.Bind(wx.EVT_MOTION, self._onMotion) + self.Bind(wx.EVT_LEAVE_WINDOW, self._onLeave) + self.Bind(wx.EVT_ENTER_WINDOW, self._onEnter) + # Add middle button events + self.Bind(wx.EVT_MIDDLE_DOWN, self._onMiddleButtonDown) + self.Bind(wx.EVT_MIDDLE_DCLICK, self._onMiddleButtonDClick) + self.Bind(wx.EVT_MIDDLE_UP, self._onMiddleButtonUp) + + self.Bind(wx.EVT_MOUSE_CAPTURE_CHANGED, self._onCaptureLost) + self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self._onCaptureLost) + + self.SetBackgroundStyle(wx.BG_STYLE_PAINT) # Reduce flicker. + self.SetBackgroundColour(wx.WHITE) + + self.macros = {} # dict from wx id to seq of macros + + def Destroy(self, *args, **kwargs): + wx.Panel.Destroy(self, *args, **kwargs) + + def Copy_to_Clipboard(self, event=None): + "copy bitmap of canvas to system clipboard" + bmp_obj = wx.BitmapDataObject() + bmp_obj.SetBitmap(self.bitmap) + + if not wx.TheClipboard.IsOpened(): + open_success = wx.TheClipboard.Open() + if open_success: + wx.TheClipboard.SetData(bmp_obj) + wx.TheClipboard.Close() + wx.TheClipboard.Flush() + + def draw_idle(self): + """ + Delay rendering until the GUI is idle. + """ + DEBUG_MSG("draw_idle()", 1, self) + self._isDrawn = False # Force redraw + # Triggering a paint event is all that is needed to defer drawing + # until later. The platform will send the event when it thinks it is + # a good time (usually as soon as there are no other events pending). + self.Refresh(eraseBackground=False) + + def new_timer(self, *args, **kwargs): + """ + Creates a new backend-specific subclass of + :class:`backend_bases.Timer`. This is useful for getting periodic + events through the backend's native event loop. Implemented only + for backends with GUIs. + + Other Parameters + ---------------- + interval : scalar + Timer interval in milliseconds + callbacks : list + Sequence of (func, args, kwargs) where ``func(*args, **kwargs)`` + will be executed by the timer every *interval*. + + """ + return TimerWx(self, *args, **kwargs) + + def flush_events(self): + wx.Yield() + + def start_event_loop(self, timeout=0): + """ + Start an event loop. This is used to start a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. This should not be + confused with the main GUI event loop, which is always running + and has nothing to do with this. + + This call blocks until a callback function triggers + stop_event_loop() or *timeout* is reached. If *timeout* is + <=0, never timeout. + + Raises RuntimeError if event loop is already running. + """ + if hasattr(self, '_event_loop'): + raise RuntimeError("Event loop already running") + id = wx.NewId() + timer = wx.Timer(self, id=id) + if timeout > 0: + timer.Start(timeout * 1000, oneShot=True) + self.Bind(wx.EVT_TIMER, self.stop_event_loop, id=id) + + # Event loop handler for start/stop event loop + self._event_loop = wxc.EventLoop() + self._event_loop.Run() + timer.Stop() + + def stop_event_loop(self, event=None): + """ + Stop an event loop. This is used to stop a blocking event + loop so that interactive functions, such as ginput and + waitforbuttonpress, can wait for events. + + """ + if hasattr(self, '_event_loop'): + if self._event_loop.IsRunning(): + self._event_loop.Exit() + del self._event_loop + + def _get_imagesave_wildcards(self): + 'return the wildcard string for the filesave dialog' + default_filetype = self.get_default_filetype() + filetypes = self.get_supported_filetypes_grouped() + sorted_filetypes = sorted(filetypes.items()) + wildcards = [] + extensions = [] + filter_index = 0 + for i, (name, exts) in enumerate(sorted_filetypes): + ext_list = ';'.join(['*.%s' % ext for ext in exts]) + extensions.append(exts[0]) + wildcard = '%s (%s)|%s' % (name, ext_list, ext_list) + if default_filetype in exts: + filter_index = i + wildcards.append(wildcard) + wildcards = '|'.join(wildcards) + return wildcards, extensions, filter_index + + def gui_repaint(self, drawDC=None, origin='WX'): + """ + Performs update of the displayed image on the GUI canvas, using the + supplied wx.PaintDC device context. + + The 'WXAgg' backend sets origin accordingly. + """ + DEBUG_MSG("gui_repaint()", 1, self) + if self.IsShownOnScreen(): + if not drawDC: + # not called from OnPaint use a ClientDC + drawDC = wx.ClientDC(self) + + # following is for 'WX' backend on Windows + # the bitmap can not be in use by another DC, + # see GraphicsContextWx._cache + if wx.Platform == '__WXMSW__' and origin == 'WX': + img = self.bitmap.ConvertToImage() + bmp = img.ConvertToBitmap() + drawDC.DrawBitmap(bmp, 0, 0) + else: + drawDC.DrawBitmap(self.bitmap, 0, 0) + + filetypes = FigureCanvasBase.filetypes.copy() + filetypes['bmp'] = 'Windows bitmap' + filetypes['jpeg'] = 'JPEG' + filetypes['jpg'] = 'JPEG' + filetypes['pcx'] = 'PCX' + filetypes['png'] = 'Portable Network Graphics' + filetypes['tif'] = 'Tagged Image Format File' + filetypes['tiff'] = 'Tagged Image Format File' + filetypes['xpm'] = 'X pixmap' + + def print_figure(self, filename, *args, **kwargs): + super(_FigureCanvasWxBase, self).print_figure( + filename, *args, **kwargs) + # Restore the current view; this is needed because the artist contains + # methods rely on particular attributes of the rendered figure for + # determining things like bounding boxes. + if self._isDrawn: + self.draw() + + def _onPaint(self, evt): + """ + Called when wxPaintEvt is generated + """ + + DEBUG_MSG("_onPaint()", 1, self) + drawDC = wx.PaintDC(self) + if not self._isDrawn: + self.draw(drawDC=drawDC) + else: + self.gui_repaint(drawDC=drawDC) + drawDC.Destroy() + + def _onSize(self, evt): + """ + Called when wxEventSize is generated. + + In this application we attempt to resize to fit the window, so it + is better to take the performance hit and redraw the whole window. + """ + + DEBUG_MSG("_onSize()", 2, self) + sz = self.GetParent().GetSizer() + if sz: + si = sz.GetItem(self) + if sz and si and not si.Proportion and not si.Flag & wx.EXPAND: + # managed by a sizer, but with a fixed size + size = self.GetMinSize() + else: + # variable size + size = self.GetClientSize() + if getattr(self, "_width", None): + if size == (self._width, self._height): + # no change in size + return + self._width, self._height = size + # Create a new, correctly sized bitmap + self.bitmap = wxc.EmptyBitmap(self._width, self._height) + + self._isDrawn = False + + if self._width <= 1 or self._height <= 1: + return # Empty figure + + dpival = self.figure.dpi + winch = self._width / dpival + hinch = self._height / dpival + self.figure.set_size_inches(winch, hinch, forward=False) + + # Rendering will happen on the associated paint event + # so no need to do anything here except to make sure + # the whole background is repainted. + self.Refresh(eraseBackground=False) + FigureCanvasBase.resize_event(self) + + def _get_key(self, evt): + + keyval = evt.KeyCode + if keyval in self.keyvald: + key = self.keyvald[keyval] + elif keyval < 256: + key = chr(keyval) + # wx always returns an uppercase, so make it lowercase if the shift + # key is not depressed (NOTE: this will not handle Caps Lock) + if not evt.ShiftDown(): + key = key.lower() + else: + key = None + + for meth, prefix in ( + [evt.AltDown, 'alt'], + [evt.ControlDown, 'ctrl'], ): + if meth(): + key = '{0}+{1}'.format(prefix, key) + + return key + + def _onKeyDown(self, evt): + """Capture key press.""" + key = self._get_key(evt) + FigureCanvasBase.key_press_event(self, key, guiEvent=evt) + if self: + evt.Skip() + + def _onKeyUp(self, evt): + """Release key.""" + key = self._get_key(evt) + FigureCanvasBase.key_release_event(self, key, guiEvent=evt) + if self: + evt.Skip() + + def _set_capture(self, capture=True): + """control wx mouse capture """ + if self.HasCapture(): + self.ReleaseMouse() + if capture: + self.CaptureMouse() + + def _onCaptureLost(self, evt): + """Capture changed or lost""" + self._set_capture(False) + + def _onRightButtonDown(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 3, guiEvent=evt) + + def _onRightButtonDClick(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 3, + dblclick=True, guiEvent=evt) + + def _onRightButtonUp(self, evt): + """End measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(False) + FigureCanvasBase.button_release_event(self, x, y, 3, guiEvent=evt) + + def _onLeftButtonDown(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 1, guiEvent=evt) + + def _onLeftButtonDClick(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 1, + dblclick=True, guiEvent=evt) + + def _onLeftButtonUp(self, evt): + """End measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(False) + FigureCanvasBase.button_release_event(self, x, y, 1, guiEvent=evt) + + # Add middle button events + def _onMiddleButtonDown(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 2, guiEvent=evt) + + def _onMiddleButtonDClick(self, evt): + """Start measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(True) + FigureCanvasBase.button_press_event(self, x, y, 2, + dblclick=True, guiEvent=evt) + + def _onMiddleButtonUp(self, evt): + """End measuring on an axis.""" + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + self._set_capture(False) + FigureCanvasBase.button_release_event(self, x, y, 2, guiEvent=evt) + + def _onMouseWheel(self, evt): + """Translate mouse wheel events into matplotlib events""" + + # Determine mouse location + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + + # Convert delta/rotation/rate into a floating point step size + delta = evt.GetWheelDelta() + rotation = evt.GetWheelRotation() + rate = evt.GetLinesPerAction() + step = rate * rotation / delta + + # Done handling event + evt.Skip() + + # Mac is giving two events for every wheel event + # Need to skip every second one + if wx.Platform == '__WXMAC__': + if not hasattr(self, '_skipwheelevent'): + self._skipwheelevent = True + elif self._skipwheelevent: + self._skipwheelevent = False + return # Return without processing event + else: + self._skipwheelevent = True + + # Convert to mpl event + FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=evt) + + def _onMotion(self, evt): + """Start measuring on an axis.""" + + x = evt.GetX() + y = self.figure.bbox.height - evt.GetY() + evt.Skip() + FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=evt) + + def _onLeave(self, evt): + """Mouse has left the window.""" + + evt.Skip() + FigureCanvasBase.leave_notify_event(self, guiEvent=evt) + + def _onEnter(self, evt): + """Mouse has entered the window.""" + FigureCanvasBase.enter_notify_event(self, guiEvent=evt) + + +class FigureCanvasWx(_FigureCanvasWxBase): + # Rendering to a Wx canvas using the deprecated Wx renderer. + + def draw(self, drawDC=None): + """ + Render the figure using RendererWx instance renderer, or using a + previously defined renderer if none is specified. + """ + DEBUG_MSG("draw()", 1, self) + self.renderer = RendererWx(self.bitmap, self.figure.dpi) + self.figure.draw(self.renderer) + self._isDrawn = True + self.gui_repaint(drawDC=drawDC) + + def print_bmp(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs) + + if not _has_pil: + def print_jpeg(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_JPEG, + *args, **kwargs) + print_jpg = print_jpeg + + def print_pcx(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_PCX, *args, **kwargs) + + def print_png(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_PNG, *args, **kwargs) + + if not _has_pil: + def print_tiff(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_TIF, + *args, **kwargs) + print_tif = print_tiff + + def print_xpm(self, filename, *args, **kwargs): + return self._print_image(filename, wx.BITMAP_TYPE_XPM, *args, **kwargs) + + def _print_image(self, filename, filetype, *args, **kwargs): + origBitmap = self.bitmap + + l, b, width, height = self.figure.bbox.bounds + width = int(math.ceil(width)) + height = int(math.ceil(height)) + + self.bitmap = wxc.EmptyBitmap(width, height) + + renderer = RendererWx(self.bitmap, self.figure.dpi) + + gc = renderer.new_gc() + + self.figure.draw(renderer) + + # image is the object that we call SaveFile on. + image = self.bitmap + # set the JPEG quality appropriately. Unfortunately, it is only + # possible to set the quality on a wx.Image object. So if we + # are saving a JPEG, convert the wx.Bitmap to a wx.Image, + # and set the quality. + if filetype == wx.BITMAP_TYPE_JPEG: + jpeg_quality = kwargs.get('quality', + rcParams['savefig.jpeg_quality']) + image = self.bitmap.ConvertToImage() + image.SetOption(wx.IMAGE_OPTION_QUALITY, str(jpeg_quality)) + + # Now that we have rendered into the bitmap, save it + # to the appropriate file type and clean up + if isinstance(filename, six.string_types): + if not image.SaveFile(filename, filetype): + DEBUG_MSG('print_figure() file save error', 4, self) + raise RuntimeError( + 'Could not save figure to %s\n' % + (filename)) + elif is_writable_file_like(filename): + if not isinstance(image, wx.Image): + image = image.ConvertToImage() + if not image.SaveStream(filename, filetype): + DEBUG_MSG('print_figure() file save error', 4, self) + raise RuntimeError( + 'Could not save figure to %s\n' % + (filename)) + + # Restore everything to normal + self.bitmap = origBitmap + + # Note: draw is required here since bits of state about the + # last renderer are strewn about the artist draw methods. Do + # not remove the draw without first verifying that these have + # been cleaned up. The artist contains() methods will fail + # otherwise. + if self._isDrawn: + self.draw() + self.Refresh() + + +######################################################################## +# +# The following functions and classes are for pylab compatibility +# mode (matplotlib.pylab) and implement figure managers, etc... +# +######################################################################## + + +class FigureFrameWx(wx.Frame): + def __init__(self, num, fig): + # On non-Windows platform, explicitly set the position - fix + # positioning bug on some Linux platforms + if wx.Platform == '__WXMSW__': + pos = wx.DefaultPosition + else: + pos = wx.Point(20, 20) + l, b, w, h = fig.bbox.bounds + wx.Frame.__init__(self, parent=None, id=-1, pos=pos, + title="Figure %d" % num) + # Frame will be sized later by the Fit method + DEBUG_MSG("__init__()", 1, self) + self.num = num + + statbar = StatusBarWx(self) + self.SetStatusBar(statbar) + self.canvas = self.get_canvas(fig) + self.canvas.SetInitialSize(wx.Size(fig.bbox.width, fig.bbox.height)) + self.canvas.SetFocus() + self.sizer = wx.BoxSizer(wx.VERTICAL) + self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND) + # By adding toolbar in sizer, we are able to put it at the bottom + # of the frame - so appearance is closer to GTK version + + self.toolbar = self._get_toolbar(statbar) + + if self.toolbar is not None: + self.toolbar.Realize() + # On Windows platform, default window size is incorrect, so set + # toolbar width to figure width. + if wxc.is_phoenix: + tw, th = self.toolbar.GetSize() + fw, fh = self.canvas.GetSize() + else: + tw, th = self.toolbar.GetSizeTuple() + fw, fh = self.canvas.GetSizeTuple() + # By adding toolbar in sizer, we are able to put it at the bottom + # of the frame - so appearance is closer to GTK version. + self.toolbar.SetSize(wx.Size(fw, th)) + self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) + self.SetSizer(self.sizer) + self.Fit() + + self.canvas.SetMinSize((2, 2)) + + # give the window a matplotlib icon rather than the stock one. + # This is not currently working on Linux and is untested elsewhere. + # icon_path = os.path.join(matplotlib.rcParams['datapath'], + # 'images', 'matplotlib.png') + # icon = wx.IconFromBitmap(wx.Bitmap(icon_path)) + # for xpm type icons try: + # icon = wx.Icon(icon_path, wx.BITMAP_TYPE_XPM) + # self.SetIcon(icon) + + self.figmgr = FigureManagerWx(self.canvas, num, self) + + self.Bind(wx.EVT_CLOSE, self._onClose) + + def _get_toolbar(self, statbar): + if rcParams['toolbar'] == 'toolbar2': + toolbar = NavigationToolbar2Wx(self.canvas) + toolbar.set_status_bar(statbar) + else: + toolbar = None + return toolbar + + def get_canvas(self, fig): + return FigureCanvasWx(self, -1, fig) + + def get_figure_manager(self): + DEBUG_MSG("get_figure_manager()", 1, self) + return self.figmgr + + def _onClose(self, evt): + DEBUG_MSG("onClose()", 1, self) + self.canvas.close_event() + self.canvas.stop_event_loop() + Gcf.destroy(self.num) + # self.Destroy() + + def GetToolBar(self): + """Override wxFrame::GetToolBar as we don't have managed toolbar""" + return self.toolbar + + def Destroy(self, *args, **kwargs): + try: + self.canvas.mpl_disconnect(self.toolbar._idDrag) + # Rationale for line above: see issue 2941338. + except AttributeError: + pass # classic toolbar lacks the attribute + if not self.IsBeingDeleted(): + wx.Frame.Destroy(self, *args, **kwargs) + if self.toolbar is not None: + self.toolbar.Destroy() + wxapp = wx.GetApp() + if wxapp: + wxapp.Yield() + return True + + +class FigureManagerWx(FigureManagerBase): + """ + This class contains the FigureCanvas and GUI frame + + It is instantiated by GcfWx whenever a new figure is created. GcfWx is + responsible for managing multiple instances of FigureManagerWx. + + Attributes + ---------- + canvas : `FigureCanvas` + a FigureCanvasWx(wx.Panel) instance + window : wxFrame + a wxFrame instance - wxpython.org/Phoenix/docs/html/Frame.html + + """ + + def __init__(self, canvas, num, frame): + DEBUG_MSG("__init__()", 1, self) + FigureManagerBase.__init__(self, canvas, num) + self.frame = frame + self.window = frame + + self.tb = frame.GetToolBar() + self.toolbar = self.tb # consistent with other backends + + def notify_axes_change(fig): + 'this will be called whenever the current axes is changed' + if self.tb is not None: + self.tb.update() + self.canvas.figure.add_axobserver(notify_axes_change) + + def show(self): + self.frame.Show() + self.canvas.draw() + + def destroy(self, *args): + DEBUG_MSG("destroy()", 1, self) + self.frame.Destroy() + wxapp = wx.GetApp() + if wxapp: + wxapp.Yield() + + def get_window_title(self): + return self.window.GetTitle() + + def set_window_title(self, title): + self.window.SetTitle(title) + + def resize(self, width, height): + 'Set the canvas size in pixels' + self.canvas.SetInitialSize(wx.Size(width, height)) + self.window.GetSizer().Fit(self.window) + +# Identifiers for toolbar controls - images_wx contains bitmaps for the images +# used in the controls. wxWindows does not provide any stock images, so I've +# 'stolen' those from GTK2, and transformed them into the appropriate format. +# import images_wx + + +_NTB_AXISMENU = wx.NewId() +_NTB_AXISMENU_BUTTON = wx.NewId() +_NTB_X_PAN_LEFT = wx.NewId() +_NTB_X_PAN_RIGHT = wx.NewId() +_NTB_X_ZOOMIN = wx.NewId() +_NTB_X_ZOOMOUT = wx.NewId() +_NTB_Y_PAN_UP = wx.NewId() +_NTB_Y_PAN_DOWN = wx.NewId() +_NTB_Y_ZOOMIN = wx.NewId() +_NTB_Y_ZOOMOUT = wx.NewId() +# _NTB_SUBPLOT =wx.NewId() +_NTB_SAVE = wx.NewId() +_NTB_CLOSE = wx.NewId() + + +def _load_bitmap(filename): + """ + Load a bitmap file from the backends/images subdirectory in which the + matplotlib library is installed. The filename parameter should not + contain any path information as this is determined automatically. + + Returns a wx.Bitmap object + """ + + basedir = os.path.join(rcParams['datapath'], 'images') + + bmpFilename = os.path.normpath(os.path.join(basedir, filename)) + if not os.path.exists(bmpFilename): + raise IOError('Could not find bitmap file "%s"; dying' % bmpFilename) + + bmp = wx.Bitmap(bmpFilename) + return bmp + + +class MenuButtonWx(wx.Button): + """ + wxPython does not permit a menu to be incorporated directly into a toolbar. + This class simulates the effect by associating a pop-up menu with a button + in the toolbar, and managing this as though it were a menu. + """ + + def __init__(self, parent): + + wx.Button.__init__(self, parent, _NTB_AXISMENU_BUTTON, "Axes: ", + style=wx.BU_EXACTFIT) + self._toolbar = parent + self._menu = wx.Menu() + self._axisId = [] + # First two menu items never change... + self._allId = wx.NewId() + self._invertId = wx.NewId() + self._menu.Append(self._allId, "All", "Select all axes", False) + self._menu.Append(self._invertId, "Invert", "Invert axes selected", + False) + self._menu.AppendSeparator() + + self.Bind(wx.EVT_BUTTON, self._onMenuButton, id=_NTB_AXISMENU_BUTTON) + self.Bind(wx.EVT_MENU, self._handleSelectAllAxes, id=self._allId) + self.Bind(wx.EVT_MENU, self._handleInvertAxesSelected, + id=self._invertId) + + def Destroy(self): + self._menu.Destroy() + self.Destroy() + + def _onMenuButton(self, evt): + """Handle menu button pressed.""" + if wxc.is_phoenix: + x, y = self.GetPosition() + w, h = self.GetSize() + else: + x, y = self.GetPositionTuple() + w, h = self.GetSizeTuple() + self.PopupMenuXY(self._menu, x, y + h - 4) + # When menu returned, indicate selection in button + evt.Skip() + + def _handleSelectAllAxes(self, evt): + """Called when the 'select all axes' menu item is selected.""" + if len(self._axisId) == 0: + return + for i in range(len(self._axisId)): + self._menu.Check(self._axisId[i], True) + self._toolbar.set_active(self.getActiveAxes()) + evt.Skip() + + def _handleInvertAxesSelected(self, evt): + """Called when the invert all menu item is selected""" + if len(self._axisId) == 0: + return + for i in range(len(self._axisId)): + if self._menu.IsChecked(self._axisId[i]): + self._menu.Check(self._axisId[i], False) + else: + self._menu.Check(self._axisId[i], True) + self._toolbar.set_active(self.getActiveAxes()) + evt.Skip() + + def _onMenuItemSelected(self, evt): + """Called whenever one of the specific axis menu items is selected""" + current = self._menu.IsChecked(evt.GetId()) + if current: + new = False + else: + new = True + self._menu.Check(evt.GetId(), new) + # Lines above would be deleted based on svn tracker ID 2841525; + # not clear whether this matters or not. + self._toolbar.set_active(self.getActiveAxes()) + evt.Skip() + + def updateAxes(self, maxAxis): + """Ensures that there are entries for max_axis axes in the menu + (selected by default).""" + if maxAxis > len(self._axisId): + for i in range(len(self._axisId) + 1, maxAxis + 1, 1): + menuId = wx.NewId() + self._axisId.append(menuId) + self._menu.Append(menuId, "Axis %d" % i, + "Select axis %d" % i, + True) + self._menu.Check(menuId, True) + self.Bind(wx.EVT_MENU, self._onMenuItemSelected, id=menuId) + elif maxAxis < len(self._axisId): + for menuId in self._axisId[maxAxis:]: + self._menu.Delete(menuId) + self._axisId = self._axisId[:maxAxis] + self._toolbar.set_active(list(xrange(maxAxis))) + + def getActiveAxes(self): + """Return a list of the selected axes.""" + active = [] + for i in range(len(self._axisId)): + if self._menu.IsChecked(self._axisId[i]): + active.append(i) + return active + + def updateButtonText(self, lst): + """Update the list of selected axes in the menu button.""" + self.SetLabel( + 'Axes: ' + ','.join('%d' % (e + 1) for e in lst)) + + +cursord = { + cursors.MOVE: wx.CURSOR_HAND, + cursors.HAND: wx.CURSOR_HAND, + cursors.POINTER: wx.CURSOR_ARROW, + cursors.SELECT_REGION: wx.CURSOR_CROSS, + cursors.WAIT: wx.CURSOR_WAIT, +} + + +@cbook.deprecated("2.2") +class SubplotToolWX(wx.Frame): + def __init__(self, targetfig): + wx.Frame.__init__(self, None, -1, "Configure subplots") + + toolfig = Figure((6, 3)) + canvas = FigureCanvasWx(self, -1, toolfig) + + # Create a figure manager to manage things + figmgr = FigureManager(canvas, 1, self) + + # Now put all into a sizer + sizer = wx.BoxSizer(wx.VERTICAL) + # This way of adding to sizer allows resizing + sizer.Add(canvas, 1, wx.LEFT | wx.TOP | wx.GROW) + self.SetSizer(sizer) + self.Fit() + tool = SubplotTool(targetfig, toolfig) + + +class NavigationToolbar2Wx(NavigationToolbar2, wx.ToolBar): + def __init__(self, canvas): + wx.ToolBar.__init__(self, canvas.GetParent(), -1) + NavigationToolbar2.__init__(self, canvas) + self.canvas = canvas + self._idle = True + self.statbar = None + self.prevZoomRect = None + # for now, use alternate zoom-rectangle drawing on all + # Macs. N.B. In future versions of wx it may be possible to + # detect Retina displays with window.GetContentScaleFactor() + # and/or dc.GetContentScaleFactor() + self.retinaFix = 'wxMac' in wx.PlatformInfo + + def get_canvas(self, frame, fig): + return type(self.canvas)(frame, -1, fig) + + def _init_toolbar(self): + DEBUG_MSG("_init_toolbar", 1, self) + + self._parent = self.canvas.GetParent() + + self.wx_ids = {} + for text, tooltip_text, image_file, callback in self.toolitems: + if text is None: + self.AddSeparator() + continue + self.wx_ids[text] = wx.NewId() + wxc._AddTool(self, self.wx_ids, text, + _load_bitmap(image_file + '.png'), + tooltip_text) + + self.Bind(wx.EVT_TOOL, getattr(self, callback), + id=self.wx_ids[text]) + + self.Realize() + + def zoom(self, *args): + self.ToggleTool(self.wx_ids['Pan'], False) + NavigationToolbar2.zoom(self, *args) + + def pan(self, *args): + self.ToggleTool(self.wx_ids['Zoom'], False) + NavigationToolbar2.pan(self, *args) + + def configure_subplots(self, evt): + frame = wx.Frame(None, -1, "Configure subplots") + + toolfig = Figure((6, 3)) + canvas = self.get_canvas(frame, toolfig) + + # Create a figure manager to manage things + figmgr = FigureManager(canvas, 1, frame) + + # Now put all into a sizer + sizer = wx.BoxSizer(wx.VERTICAL) + # This way of adding to sizer allows resizing + sizer.Add(canvas, 1, wx.LEFT | wx.TOP | wx.GROW) + frame.SetSizer(sizer) + frame.Fit() + tool = SubplotTool(self.canvas.figure, toolfig) + frame.Show() + + def save_figure(self, *args): + # Fetch the required filename and file type. + filetypes, exts, filter_index = self.canvas._get_imagesave_wildcards() + default_file = self.canvas.get_default_filename() + dlg = wx.FileDialog(self._parent, "Save to file", "", default_file, + filetypes, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + dlg.SetFilterIndex(filter_index) + if dlg.ShowModal() == wx.ID_OK: + dirname = dlg.GetDirectory() + filename = dlg.GetFilename() + DEBUG_MSG( + 'Save file dir:%s name:%s' % + (dirname, filename), 3, self) + format = exts[dlg.GetFilterIndex()] + basename, ext = os.path.splitext(filename) + if ext.startswith('.'): + ext = ext[1:] + if ext in ('svg', 'pdf', 'ps', 'eps', 'png') and format != ext: + # looks like they forgot to set the image type drop + # down, going with the extension. + warnings.warn( + 'extension %s did not match the selected ' + 'image type %s; going with %s' % + (ext, format, ext), stacklevel=0) + format = ext + try: + self.canvas.figure.savefig( + os.path.join(dirname, filename), format=format) + except Exception as e: + error_msg_wx(str(e)) + + def set_cursor(self, cursor): + cursor = wxc.Cursor(cursord[cursor]) + self.canvas.SetCursor(cursor) + self.canvas.Update() + + @cbook.deprecated("2.1", alternative="canvas.draw_idle") + def dynamic_update(self): + d = self._idle + self._idle = False + if d: + self.canvas.draw() + self._idle = True + + def press(self, event): + if self._active == 'ZOOM': + if not self.retinaFix: + self.wxoverlay = wx.Overlay() + else: + if event.inaxes is not None: + self.savedRetinaImage = self.canvas.copy_from_bbox( + event.inaxes.bbox) + self.zoomStartX = event.xdata + self.zoomStartY = event.ydata + self.zoomAxes = event.inaxes + + def release(self, event): + if self._active == 'ZOOM': + # When the mouse is released we reset the overlay and it + # restores the former content to the window. + if not self.retinaFix: + self.wxoverlay.Reset() + del self.wxoverlay + else: + del self.savedRetinaImage + if self.prevZoomRect: + self.prevZoomRect.pop(0).remove() + self.prevZoomRect = None + if self.zoomAxes: + self.zoomAxes = None + + def draw_rubberband(self, event, x0, y0, x1, y1): + if self.retinaFix: # On Macs, use the following code + # wx.DCOverlay does not work properly on Retina displays. + rubberBandColor = '#C0C0FF' + if self.prevZoomRect: + self.prevZoomRect.pop(0).remove() + self.canvas.restore_region(self.savedRetinaImage) + X0, X1 = self.zoomStartX, event.xdata + Y0, Y1 = self.zoomStartY, event.ydata + lineX = (X0, X0, X1, X1, X0) + lineY = (Y0, Y1, Y1, Y0, Y0) + self.prevZoomRect = self.zoomAxes.plot( + lineX, lineY, '-', color=rubberBandColor) + self.zoomAxes.draw_artist(self.prevZoomRect[0]) + self.canvas.blit(self.zoomAxes.bbox) + return + + # Use an Overlay to draw a rubberband-like bounding box. + + dc = wx.ClientDC(self.canvas) + odc = wx.DCOverlay(self.wxoverlay, dc) + odc.Clear() + + # Mac's DC is already the same as a GCDC, and it causes + # problems with the overlay if we try to use an actual + # wx.GCDC so don't try it. + if 'wxMac' not in wx.PlatformInfo: + dc = wx.GCDC(dc) + + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + + if y1 < y0: + y0, y1 = y1, y0 + if x1 < x0: + x0, x1 = x1, x0 + + w = x1 - x0 + h = y1 - y0 + rect = wx.Rect(x0, y0, w, h) + + rubberBandColor = '#C0C0FF' # or load from config? + + # Set a pen for the border + color = wxc.NamedColour(rubberBandColor) + dc.SetPen(wx.Pen(color, 1)) + + # use the same color, plus alpha for the brush + r, g, b, a = color.Get(True) + color.Set(r, g, b, 0x60) + dc.SetBrush(wx.Brush(color)) + if wxc.is_phoenix: + dc.DrawRectangle(rect) + else: + dc.DrawRectangleRect(rect) + + def set_status_bar(self, statbar): + self.statbar = statbar + + def set_message(self, s): + if self.statbar is not None: + self.statbar.set_function(s) + + def set_history_buttons(self): + can_backward = self._nav_stack._pos > 0 + can_forward = self._nav_stack._pos < len(self._nav_stack._elements) - 1 + self.EnableTool(self.wx_ids['Back'], can_backward) + self.EnableTool(self.wx_ids['Forward'], can_forward) + + +@cbook.deprecated("2.2", alternative="NavigationToolbar2Wx") +class Toolbar(NavigationToolbar2Wx): + pass + + +class StatusBarWx(wx.StatusBar): + """ + A status bar is added to _FigureFrame to allow measurements and the + previously selected scroll function to be displayed as a user + convenience. + """ + + def __init__(self, parent): + wx.StatusBar.__init__(self, parent, -1) + self.SetFieldsCount(2) + self.SetStatusText("None", 1) + # self.SetStatusText("Measurement: None", 2) + # self.Reposition() + + def set_function(self, string): + self.SetStatusText("%s" % string, 1) + + # def set_measurement(self, string): + # self.SetStatusText("Measurement: %s" % string, 2) + + +# tools for matplotlib.backend_managers.ToolManager: +# for now only SaveFigure, SetCursor and Rubberband are implemented +# once a ToolbarWx is implemented, also FigureManagerWx needs to be +# modified, similar to pull request #9934 + +class SaveFigureWx(backend_tools.SaveFigureBase): + def trigger(self, *args): + # Fetch the required filename and file type. + filetypes, exts, filter_index = self.canvas._get_imagesave_wildcards() + default_dir = os.path.expanduser( + matplotlib.rcParams['savefig.directory']) + default_file = self.canvas.get_default_filename() + dlg = wx.FileDialog(self.canvas.GetTopLevelParent(), "Save to file", + default_dir, default_file, filetypes, + wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + dlg.SetFilterIndex(filter_index) + if dlg.ShowModal() != wx.ID_OK: + return + + dirname = dlg.GetDirectory() + filename = dlg.GetFilename() + DEBUG_MSG('Save file dir:%s name:%s' % (dirname, filename), 3, self) + format = exts[dlg.GetFilterIndex()] + basename, ext = os.path.splitext(filename) + if ext.startswith('.'): + ext = ext[1:] + if ext in ('svg', 'pdf', 'ps', 'eps', 'png') and format != ext: + # looks like they forgot to set the image type drop + # down, going with the extension. + warnings.warn( + 'extension %s did not match the selected ' + 'image type %s; going with %s' % + (ext, format, ext), stacklevel=0) + format = ext + if default_dir != "": + matplotlib.rcParams['savefig.directory'] = dirname + try: + self.canvas.figure.savefig( + os.path.join(dirname, filename), format=format) + except Exception as e: + error_msg_wx(str(e)) + + +class SetCursorWx(backend_tools.SetCursorBase): + def set_cursor(self, cursor): + cursor = wxc.Cursor(cursord[cursor]) + self.canvas.SetCursor(cursor) + self.canvas.Update() + + +if 'wxMac' not in wx.PlatformInfo: + # on most platforms, use overlay + class RubberbandWx(backend_tools.RubberbandBase): + def __init__(self, *args, **kwargs): + backend_tools.RubberbandBase.__init__(self, *args, **kwargs) + self.wxoverlay = None + + def draw_rubberband(self, x0, y0, x1, y1): + # Use an Overlay to draw a rubberband-like bounding box. + if self.wxoverlay is None: + self.wxoverlay = wx.Overlay() + dc = wx.ClientDC(self.canvas) + odc = wx.DCOverlay(self.wxoverlay, dc) + odc.Clear() + + dc = wx.GCDC(dc) + + height = self.canvas.figure.bbox.height + y1 = height - y1 + y0 = height - y0 + + if y1 < y0: + y0, y1 = y1, y0 + if x1 < x0: + x0, x1 = x1, x0 + + w = x1 - x0 + h = y1 - y0 + rect = wx.Rect(x0, y0, w, h) + + rubberBandColor = '#C0C0FF' # or load from config? + + # Set a pen for the border + color = wxc.NamedColour(rubberBandColor) + dc.SetPen(wx.Pen(color, 1)) + + # use the same color, plus alpha for the brush + r, g, b, a = color.Get(True) + color.Set(r, g, b, 0x60) + dc.SetBrush(wx.Brush(color)) + if wxc.is_phoenix: + dc.DrawRectangle(rect) + else: + dc.DrawRectangleRect(rect) + + def remove_rubberband(self): + if self.wxoverlay is None: + return + self.wxoverlay.Reset() + self.wxoverlay = None + +else: + # on Mac OS retina displays DCOverlay does not work + # and dc.SetLogicalFunction does not have an effect on any display + # the workaround is to blit the full image for remove_rubberband + class RubberbandWx(backend_tools.RubberbandBase): + def __init__(self, *args, **kwargs): + backend_tools.RubberbandBase.__init__(self, *args, **kwargs) + self._rect = None + + def draw_rubberband(self, x0, y0, x1, y1): + dc = wx.ClientDC(self.canvas) + # this would be required if the Canvas is a ScrolledWindow, + # which is not the case for now + # self.PrepareDC(dc) + + # delete old rubberband + if self._rect: + self.remove_rubberband(dc) + + # draw new rubberband + dc.SetPen(wx.Pen(wx.BLACK, 1, wx.SOLID)) + dc.SetBrush(wx.TRANSPARENT_BRUSH) + self._rect = (x0, self.canvas._height-y0, x1-x0, -y1+y0) + if wxc.is_phoenix: + dc.DrawRectangle(self._rect) + else: + dc.DrawRectangleRect(self._rect) + + def remove_rubberband(self, dc=None): + if not self._rect: + return + if self.canvas.bitmap: + if dc is None: + dc = wx.ClientDC(self.canvas) + dc.DrawBitmap(self.canvas.bitmap, 0, 0) + # for testing the method on Windows, use this code instead: + # img = self.canvas.bitmap.ConvertToImage() + # bmp = img.ConvertToBitmap() + # dc.DrawBitmap(bmp, 0, 0) + self._rect = None + + +backend_tools.ToolSaveFigure = SaveFigureWx +backend_tools.ToolSetCursor = SetCursorWx +backend_tools.ToolRubberband = RubberbandWx + + +# < Additions for printing support: Matt Newville + +class PrintoutWx(wx.Printout): + """ + Simple wrapper around wx Printout class -- all the real work + here is scaling the matplotlib canvas bitmap to the current + printer's definition. + """ + + def __init__(self, canvas, width=5.5, margin=0.5, title='matplotlib'): + wx.Printout.__init__(self, title=title) + self.canvas = canvas + # width, in inches of output figure (approximate) + self.width = width + self.margin = margin + + def HasPage(self, page): + # current only supports 1 page print + return page == 1 + + def GetPageInfo(self): + return (1, 1, 1, 1) + + def OnPrintPage(self, page): + self.canvas.draw() + + dc = self.GetDC() + (ppw, pph) = self.GetPPIPrinter() # printer's pixels per in + (pgw, pgh) = self.GetPageSizePixels() # page size in pixels + (dcw, dch) = dc.GetSize() + if wxc.is_phoenix: + (grw, grh) = self.canvas.GetSize() + else: + (grw, grh) = self.canvas.GetSizeTuple() + + # save current figure dpi resolution and bg color, + # so that we can temporarily set them to the dpi of + # the printer, and the bg color to white + bgcolor = self.canvas.figure.get_facecolor() + fig_dpi = self.canvas.figure.dpi + + # draw the bitmap, scaled appropriately + vscale = float(ppw) / fig_dpi + + # set figure resolution,bg color for printer + self.canvas.figure.dpi = ppw + self.canvas.figure.set_facecolor('#FFFFFF') + + renderer = RendererWx(self.canvas.bitmap, self.canvas.figure.dpi) + self.canvas.figure.draw(renderer) + self.canvas.bitmap.SetWidth( + int(self.canvas.bitmap.GetWidth() * vscale)) + self.canvas.bitmap.SetHeight( + int(self.canvas.bitmap.GetHeight() * vscale)) + self.canvas.draw() + + # page may need additional scaling on preview + page_scale = 1.0 + if self.IsPreview(): + page_scale = float(dcw) / pgw + + # get margin in pixels = (margin in in) * (pixels/in) + top_margin = int(self.margin * pph * page_scale) + left_margin = int(self.margin * ppw * page_scale) + + # set scale so that width of output is self.width inches + # (assuming grw is size of graph in inches....) + user_scale = (self.width * fig_dpi * page_scale) / float(grw) + + dc.SetDeviceOrigin(left_margin, top_margin) + dc.SetUserScale(user_scale, user_scale) + + # this cute little number avoid API inconsistencies in wx + try: + dc.DrawBitmap(self.canvas.bitmap, 0, 0) + except Exception: + try: + dc.DrawBitmap(self.canvas.bitmap, (0, 0)) + except Exception: + pass + + # restore original figure resolution + self.canvas.figure.set_facecolor(bgcolor) + self.canvas.figure.dpi = fig_dpi + self.canvas.draw() + return True +# > + + +@_Backend.export +class _BackendWx(_Backend): + FigureCanvas = FigureCanvasWx + FigureManager = FigureManagerWx + _frame_class = FigureFrameWx + + @staticmethod + def trigger_manager_draw(manager): + manager.canvas.draw_idle() + + @classmethod + def new_figure_manager(cls, num, *args, **kwargs): + # Create a wx.App instance if it has not been created sofar. + wxapp = wx.GetApp() + if wxapp is None: + wxapp = wx.App(False) + wxapp.SetExitOnFrameDelete(True) + # Retain a reference to the app object so that it does not get + # garbage collected. + _BackendWx._theWxApp = wxapp + return super(_BackendWx, cls).new_figure_manager(num, *args, **kwargs) + + @classmethod + def new_figure_manager_given_figure(cls, num, figure): + frame = cls._frame_class(num, figure) + figmgr = frame.get_figure_manager() + if matplotlib.is_interactive(): + figmgr.frame.Show() + figure.canvas.draw_idle() + return figmgr + + @staticmethod + def mainloop(): + if not wx.App.IsMainLoopRunning(): + wxapp = wx.GetApp() + if wxapp is not None: + wxapp.MainLoop() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxagg.py new file mode 100644 index 00000000000..041f274a78b --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxagg.py @@ -0,0 +1,147 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import wx + +import matplotlib +from matplotlib import cbook +from . import wx_compat as wxc +from .backend_agg import FigureCanvasAgg +from .backend_wx import ( + _BackendWx, _FigureCanvasWxBase, FigureFrameWx, + NavigationToolbar2Wx as NavigationToolbar2WxAgg) + + +class FigureFrameWxAgg(FigureFrameWx): + def get_canvas(self, fig): + return FigureCanvasWxAgg(self, -1, fig) + + +class FigureCanvasWxAgg(FigureCanvasAgg, _FigureCanvasWxBase): + """ + The FigureCanvas contains the figure and does event handling. + + In the wxPython backend, it is derived from wxPanel, and (usually) + lives inside a frame instantiated by a FigureManagerWx. The parent + window probably implements a wxSizer to control the displayed + control size - but we give a hint as to our preferred minimum + size. + """ + + def draw(self, drawDC=None): + """ + Render the figure using agg. + """ + FigureCanvasAgg.draw(self) + + self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None) + self._isDrawn = True + self.gui_repaint(drawDC=drawDC, origin='WXAgg') + + def blit(self, bbox=None): + """ + Transfer the region of the agg buffer defined by bbox to the display. + If bbox is None, the entire buffer is transferred. + """ + if bbox is None: + self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None) + self.gui_repaint() + return + + l, b, w, h = bbox.bounds + r = l + w + t = b + h + x = int(l) + y = int(self.bitmap.GetHeight() - t) + + srcBmp = _convert_agg_to_wx_bitmap(self.get_renderer(), None) + srcDC = wx.MemoryDC() + srcDC.SelectObject(srcBmp) + + destDC = wx.MemoryDC() + destDC.SelectObject(self.bitmap) + + destDC.Blit(x, y, int(w), int(h), srcDC, x, y) + + destDC.SelectObject(wx.NullBitmap) + srcDC.SelectObject(wx.NullBitmap) + self.gui_repaint() + + filetypes = FigureCanvasAgg.filetypes + + +@cbook.deprecated("2.2", alternative="NavigationToolbar2WxAgg") +class Toolbar(NavigationToolbar2WxAgg): + pass + + +# agg/wxPython image conversion functions (wxPython >= 2.8) + +def _convert_agg_to_wx_image(agg, bbox): + """ + Convert the region of the agg buffer bounded by bbox to a wx.Image. If + bbox is None, the entire buffer is converted. + + Note: agg must be a backend_agg.RendererAgg instance. + """ + if bbox is None: + # agg => rgb -> image + image = wxc.EmptyImage(int(agg.width), int(agg.height)) + image.SetData(agg.tostring_rgb()) + return image + else: + # agg => rgba buffer -> bitmap => clipped bitmap => image + return wx.ImageFromBitmap(_WX28_clipped_agg_as_bitmap(agg, bbox)) + + +def _convert_agg_to_wx_bitmap(agg, bbox): + """ + Convert the region of the agg buffer bounded by bbox to a wx.Bitmap. If + bbox is None, the entire buffer is converted. + + Note: agg must be a backend_agg.RendererAgg instance. + """ + if bbox is None: + # agg => rgba buffer -> bitmap + return wxc.BitmapFromBuffer(int(agg.width), int(agg.height), + agg.buffer_rgba()) + else: + # agg => rgba buffer -> bitmap => clipped bitmap + return _WX28_clipped_agg_as_bitmap(agg, bbox) + + +def _WX28_clipped_agg_as_bitmap(agg, bbox): + """ + Convert the region of a the agg buffer bounded by bbox to a wx.Bitmap. + + Note: agg must be a backend_agg.RendererAgg instance. + """ + l, b, width, height = bbox.bounds + r = l + width + t = b + height + + srcBmp = wxc.BitmapFromBuffer(int(agg.width), int(agg.height), + agg.buffer_rgba()) + srcDC = wx.MemoryDC() + srcDC.SelectObject(srcBmp) + + destBmp = wxc.EmptyBitmap(int(width), int(height)) + destDC = wx.MemoryDC() + destDC.SelectObject(destBmp) + + x = int(l) + y = int(int(agg.height) - t) + destDC.Blit(0, 0, int(width), int(height), srcDC, x, y) + + srcDC.SelectObject(wx.NullBitmap) + destDC.SelectObject(wx.NullBitmap) + + return destBmp + + +@_BackendWx.export +class _BackendWxAgg(_BackendWx): + FigureCanvas = FigureCanvasWxAgg + _frame_class = FigureFrameWxAgg diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxcairo.py b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxcairo.py new file mode 100644 index 00000000000..fb3290f2bbc --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/backend_wxcairo.py @@ -0,0 +1,53 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import wx + +from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo +from .backend_wx import ( + _BackendWx, _FigureCanvasWxBase, FigureFrameWx, + NavigationToolbar2Wx as NavigationToolbar2WxCairo) +import wx.lib.wxcairo as wxcairo + + +class FigureFrameWxCairo(FigureFrameWx): + def get_canvas(self, fig): + return FigureCanvasWxCairo(self, -1, fig) + + +class FigureCanvasWxCairo(_FigureCanvasWxBase, FigureCanvasCairo): + """ + The FigureCanvas contains the figure and does event handling. + + In the wxPython backend, it is derived from wxPanel, and (usually) lives + inside a frame instantiated by a FigureManagerWx. The parent window + probably implements a wxSizer to control the displayed control size - but + we give a hint as to our preferred minimum size. + """ + + def __init__(self, parent, id, figure): + # _FigureCanvasWxBase should be fixed to have the same signature as + # every other FigureCanvas and use cooperative inheritance, but in the + # meantime the following will make do. + _FigureCanvasWxBase.__init__(self, parent, id, figure) + FigureCanvasCairo.__init__(self, figure) + self._renderer = RendererCairo(self.figure.dpi) + + def draw(self, drawDC=None): + width = int(self.figure.bbox.width) + height = int(self.figure.bbox.height) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + self._renderer.set_ctx_from_surface(surface) + self._renderer.set_width_height(width, height) + self.figure.draw(self._renderer) + self.bitmap = wxcairo.BitmapFromImageSurface(surface) + self._isDrawn = True + self.gui_repaint(drawDC=drawDC, origin='WXCairo') + + +@_BackendWx.export +class _BackendWxCairo(_BackendWx): + FigureCanvas = FigureCanvasWxCairo + _frame_class = FigureFrameWxCairo diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/qt_compat.py b/contrib/python/matplotlib/py2/matplotlib/backends/qt_compat.py new file mode 100644 index 00000000000..6b386143a30 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/qt_compat.py @@ -0,0 +1,176 @@ +""" +Qt binding and backend selector. + +The selection logic is as follows: +- if any of PyQt5, PySide2, PyQt4 or PySide have already been imported + (checked in that order), use it; +- otherwise, if the QT_API environment variable (used by Enthought) is + set, use it to determine which binding to use (but do not change the + backend based on it; i.e. if the Qt4Agg backend is requested but QT_API + is set to "pyqt5", then actually use Qt4 with the binding specified by + ``rcParams["backend.qt4"]``; +- otherwise, use whatever the rcParams indicate. +""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +from distutils.version import LooseVersion +import os +import sys + +from matplotlib import rcParams + +QT_API_PYQT5 = "PyQt5" +QT_API_PYSIDE2 = "PySide2" +QT_API_PYQTv2 = "PyQt4v2" +QT_API_PYSIDE = "PySide" +QT_API_PYQT = "PyQt4" # Use the old sip v1 API (Py3 defaults to v2). +QT_API_ENV = os.environ.get("QT_API") +# Mapping of QT_API_ENV to requested binding. ETS does not support PyQt4v1. +# (https://github.com/enthought/pyface/blob/master/pyface/qt/__init__.py) +_ETS = {"pyqt5": QT_API_PYQT5, "pyside2": QT_API_PYSIDE2, + "pyqt": QT_API_PYQTv2, "pyside": QT_API_PYSIDE, + None: None} +# First, check if anything is already imported. +if "PyQt5" in sys.modules: + QT_API = QT_API_PYQT5 + dict.__setitem__(rcParams, "backend.qt5", QT_API) +elif "PySide2" in sys.modules: + QT_API = QT_API_PYSIDE2 + dict.__setitem__(rcParams, "backend.qt5", QT_API) +elif "PyQt4" in sys.modules: + QT_API = QT_API_PYQTv2 + dict.__setitem__(rcParams, "backend.qt4", QT_API) +elif "PySide" in sys.modules: + QT_API = QT_API_PYSIDE + dict.__setitem__(rcParams, "backend.qt4", QT_API) +# Otherwise, check the QT_API environment variable (from Enthought). This can +# only override the binding, not the backend (in other words, we check that the +# requested backend actually matches). +elif rcParams["backend"] in ["Qt5Agg", "Qt5Cairo"]: + if QT_API_ENV == "pyqt5": + dict.__setitem__(rcParams, "backend.qt5", QT_API_PYQT5) + elif QT_API_ENV == "pyside2": + dict.__setitem__(rcParams, "backend.qt5", QT_API_PYSIDE2) + QT_API = dict.__getitem__(rcParams, "backend.qt5") +elif rcParams["backend"] in ["Qt4Agg", "Qt4Cairo"]: + if QT_API_ENV == "pyqt4": + dict.__setitem__(rcParams, "backend.qt4", QT_API_PYQTv2) + elif QT_API_ENV == "pyside": + dict.__setitem__(rcParams, "backend.qt4", QT_API_PYSIDE) + QT_API = dict.__getitem__(rcParams, "backend.qt4") +# A non-Qt backend was selected but we still got there (possible, e.g., when +# fully manually embedding Matplotlib in a Qt app without using pyplot). +else: + try: + QT_API = _ETS[QT_API_ENV] + except KeyError: + raise RuntimeError( + "The environment variable QT_API has the unrecognized value {!r};" + "valid values are 'pyqt5', 'pyside2', 'pyqt', and 'pyside'") + + +def _setup_pyqt5(): + global QtCore, QtGui, QtWidgets, __version__, is_pyqt5, _getSaveFileName + + if QT_API == QT_API_PYQT5: + from PyQt5 import QtCore, QtGui, QtWidgets + __version__ = QtCore.PYQT_VERSION_STR + QtCore.Signal = QtCore.pyqtSignal + QtCore.Slot = QtCore.pyqtSlot + QtCore.Property = QtCore.pyqtProperty + elif QT_API == QT_API_PYSIDE2: + from PySide2 import QtCore, QtGui, QtWidgets, __version__ + else: + raise ValueError("Unexpected value for the 'backend.qt5' rcparam") + _getSaveFileName = QtWidgets.QFileDialog.getSaveFileName + + def is_pyqt5(): + return True + + +def _setup_pyqt4(): + global QtCore, QtGui, QtWidgets, __version__, is_pyqt5, _getSaveFileName + + def _setup_pyqt4_internal(api): + global QtCore, QtGui, QtWidgets, \ + __version__, is_pyqt5, _getSaveFileName + # List of incompatible APIs: + # http://pyqt.sourceforge.net/Docs/PyQt4/incompatible_apis.html + _sip_apis = ["QDate", "QDateTime", "QString", "QTextStream", "QTime", + "QUrl", "QVariant"] + try: + import sip + except ImportError: + pass + else: + for _sip_api in _sip_apis: + try: + sip.setapi(_sip_api, api) + except ValueError: + pass + from PyQt4 import QtCore, QtGui + __version__ = QtCore.PYQT_VERSION_STR + # PyQt 4.6 introduced getSaveFileNameAndFilter: + # https://riverbankcomputing.com/news/pyqt-46 + if __version__ < LooseVersion("4.6"): + raise ImportError("PyQt<4.6 is not supported") + QtCore.Signal = QtCore.pyqtSignal + QtCore.Slot = QtCore.pyqtSlot + QtCore.Property = QtCore.pyqtProperty + _getSaveFileName = QtGui.QFileDialog.getSaveFileNameAndFilter + + if QT_API == QT_API_PYQTv2: + _setup_pyqt4_internal(api=2) + elif QT_API == QT_API_PYSIDE: + from PySide import QtCore, QtGui, __version__, __version_info__ + # PySide 1.0.3 fixed the following: + # https://srinikom.github.io/pyside-bz-archive/809.html + if __version_info__ < (1, 0, 3): + raise ImportError("PySide<1.0.3 is not supported") + _getSaveFileName = QtGui.QFileDialog.getSaveFileName + elif QT_API == QT_API_PYQT: + _setup_pyqt4_internal(api=1) + else: + raise ValueError("Unexpected value for the 'backend.qt4' rcparam") + QtWidgets = QtGui + + def is_pyqt5(): + return False + + +if QT_API in [QT_API_PYQT5, QT_API_PYSIDE2]: + _setup_pyqt5() +elif QT_API in [QT_API_PYQTv2, QT_API_PYSIDE, QT_API_PYQT]: + _setup_pyqt4() +elif QT_API is None: + if rcParams["backend"] == "Qt4Agg": + _candidates = [(_setup_pyqt4, QT_API_PYQTv2), + (_setup_pyqt4, QT_API_PYSIDE), + (_setup_pyqt4, QT_API_PYQT), + (_setup_pyqt5, QT_API_PYQT5), + (_setup_pyqt5, QT_API_PYSIDE2)] + else: + _candidates = [(_setup_pyqt5, QT_API_PYQT5), + (_setup_pyqt5, QT_API_PYSIDE2), + (_setup_pyqt4, QT_API_PYQTv2), + (_setup_pyqt4, QT_API_PYSIDE), + (_setup_pyqt4, QT_API_PYQT)] + for _setup, QT_API in _candidates: + try: + _setup() + except ImportError: + continue + break + else: + raise ImportError("Failed to import any qt binding") +else: # We should not get there. + raise AssertionError("Unexpected QT_API: {}".format(QT_API)) + + +# These globals are only defined for backcompatibilty purposes. +ETS = dict(pyqt=(QT_API_PYQTv2, 4), pyside=(QT_API_PYSIDE, 4), + pyqt5=(QT_API_PYQT5, 5), pyside2=(QT_API_PYSIDE2, 5)) +QT_RC_MAJOR_VERSION = 5 if is_pyqt5() else 4 diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/__init__.py b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/__init__.py new file mode 100644 index 00000000000..800d82e7ee0 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/__init__.py @@ -0,0 +1,2 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/figureoptions.py b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/figureoptions.py new file mode 100644 index 00000000000..f0050d36750 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/figureoptions.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +# +# Copyright © 2009 Pierre Raybaut +# Licensed under the terms of the MIT License +# see the mpl licenses directory for a copy of the license + + +"""Module that provides a GUI-based editor for matplotlib's figure options""" + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six + +import os.path as osp +import re + +import matplotlib +from matplotlib import cm, colors as mcolors, markers, image as mimage +import matplotlib.backends.qt_editor.formlayout as formlayout +from matplotlib.backends.qt_compat import QtGui + + +def get_icon(name): + basedir = osp.join(matplotlib.rcParams['datapath'], 'images') + return QtGui.QIcon(osp.join(basedir, name)) + + +LINESTYLES = {'-': 'Solid', + '--': 'Dashed', + '-.': 'DashDot', + ':': 'Dotted', + 'None': 'None', + } + +DRAWSTYLES = { + 'default': 'Default', + 'steps-pre': 'Steps (Pre)', 'steps': 'Steps (Pre)', + 'steps-mid': 'Steps (Mid)', + 'steps-post': 'Steps (Post)'} + +MARKERS = markers.MarkerStyle.markers + + +def figure_edit(axes, parent=None): + """Edit matplotlib figure options""" + sep = (None, None) # separator + + # Get / General + # Cast to builtin floats as they have nicer reprs. + xmin, xmax = map(float, axes.get_xlim()) + ymin, ymax = map(float, axes.get_ylim()) + general = [('Title', axes.get_title()), + sep, + (None, "X-Axis"), + ('Left', xmin), ('Right', xmax), + ('Label', axes.get_xlabel()), + ('Scale', [axes.get_xscale(), 'linear', 'log', 'logit']), + sep, + (None, "Y-Axis"), + ('Bottom', ymin), ('Top', ymax), + ('Label', axes.get_ylabel()), + ('Scale', [axes.get_yscale(), 'linear', 'log', 'logit']), + sep, + ('(Re-)Generate automatic legend', False), + ] + + # Save the unit data + xconverter = axes.xaxis.converter + yconverter = axes.yaxis.converter + xunits = axes.xaxis.get_units() + yunits = axes.yaxis.get_units() + + # Sorting for default labels (_lineXXX, _imageXXX). + def cmp_key(label): + match = re.match(r"(_line|_image)(\d+)", label) + if match: + return match.group(1), int(match.group(2)) + else: + return label, 0 + + # Get / Curves + linedict = {} + for line in axes.get_lines(): + label = line.get_label() + if label == '_nolegend_': + continue + linedict[label] = line + curves = [] + + def prepare_data(d, init): + """Prepare entry for FormLayout. + + `d` is a mapping of shorthands to style names (a single style may + have multiple shorthands, in particular the shorthands `None`, + `"None"`, `"none"` and `""` are synonyms); `init` is one shorthand + of the initial style. + + This function returns an list suitable for initializing a + FormLayout combobox, namely `[initial_name, (shorthand, + style_name), (shorthand, style_name), ...]`. + """ + # Drop duplicate shorthands from dict (by overwriting them during + # the dict comprehension). + name2short = {name: short for short, name in d.items()} + # Convert back to {shorthand: name}. + short2name = {short: name for name, short in name2short.items()} + # Find the kept shorthand for the style specified by init. + canonical_init = name2short[d[init]] + # Sort by representation and prepend the initial value. + return ([canonical_init] + + sorted(short2name.items(), + key=lambda short_and_name: short_and_name[1])) + + curvelabels = sorted(linedict, key=cmp_key) + for label in curvelabels: + line = linedict[label] + color = mcolors.to_hex( + mcolors.to_rgba(line.get_color(), line.get_alpha()), + keep_alpha=True) + ec = mcolors.to_hex( + mcolors.to_rgba(line.get_markeredgecolor(), line.get_alpha()), + keep_alpha=True) + fc = mcolors.to_hex( + mcolors.to_rgba(line.get_markerfacecolor(), line.get_alpha()), + keep_alpha=True) + curvedata = [ + ('Label', label), + sep, + (None, 'Line'), + ('Line style', prepare_data(LINESTYLES, line.get_linestyle())), + ('Draw style', prepare_data(DRAWSTYLES, line.get_drawstyle())), + ('Width', line.get_linewidth()), + ('Color (RGBA)', color), + sep, + (None, 'Marker'), + ('Style', prepare_data(MARKERS, line.get_marker())), + ('Size', line.get_markersize()), + ('Face color (RGBA)', fc), + ('Edge color (RGBA)', ec)] + curves.append([curvedata, label, ""]) + # Is there a curve displayed? + has_curve = bool(curves) + + # Get / Images + imagedict = {} + for image in axes.get_images(): + label = image.get_label() + if label == '_nolegend_': + continue + imagedict[label] = image + imagelabels = sorted(imagedict, key=cmp_key) + images = [] + cmaps = [(cmap, name) for name, cmap in sorted(cm.cmap_d.items())] + for label in imagelabels: + image = imagedict[label] + cmap = image.get_cmap() + if cmap not in cm.cmap_d.values(): + cmaps = [(cmap, cmap.name)] + cmaps + low, high = image.get_clim() + imagedata = [ + ('Label', label), + ('Colormap', [cmap.name] + cmaps), + ('Min. value', low), + ('Max. value', high), + ('Interpolation', + [image.get_interpolation()] + + [(name, name) for name in sorted(mimage.interpolations_names)])] + images.append([imagedata, label, ""]) + # Is there an image displayed? + has_image = bool(images) + + datalist = [(general, "Axes", "")] + if curves: + datalist.append((curves, "Curves", "")) + if images: + datalist.append((images, "Images", "")) + + def apply_callback(data): + """This function will be called to apply changes""" + orig_xlim = axes.get_xlim() + orig_ylim = axes.get_ylim() + + general = data.pop(0) + curves = data.pop(0) if has_curve else [] + images = data.pop(0) if has_image else [] + if data: + raise ValueError("Unexpected field") + + # Set / General + (title, xmin, xmax, xlabel, xscale, ymin, ymax, ylabel, yscale, + generate_legend) = general + + if axes.get_xscale() != xscale: + axes.set_xscale(xscale) + if axes.get_yscale() != yscale: + axes.set_yscale(yscale) + + axes.set_title(title) + axes.set_xlim(xmin, xmax) + axes.set_xlabel(xlabel) + axes.set_ylim(ymin, ymax) + axes.set_ylabel(ylabel) + + # Restore the unit data + axes.xaxis.converter = xconverter + axes.yaxis.converter = yconverter + axes.xaxis.set_units(xunits) + axes.yaxis.set_units(yunits) + axes.xaxis._update_axisinfo() + axes.yaxis._update_axisinfo() + + # Set / Curves + for index, curve in enumerate(curves): + line = linedict[curvelabels[index]] + (label, linestyle, drawstyle, linewidth, color, marker, markersize, + markerfacecolor, markeredgecolor) = curve + line.set_label(label) + line.set_linestyle(linestyle) + line.set_drawstyle(drawstyle) + line.set_linewidth(linewidth) + rgba = mcolors.to_rgba(color) + line.set_alpha(None) + line.set_color(rgba) + if marker != 'none': + line.set_marker(marker) + line.set_markersize(markersize) + line.set_markerfacecolor(markerfacecolor) + line.set_markeredgecolor(markeredgecolor) + + # Set / Images + for index, image_settings in enumerate(images): + image = imagedict[imagelabels[index]] + label, cmap, low, high, interpolation = image_settings + image.set_label(label) + image.set_cmap(cm.get_cmap(cmap)) + image.set_clim(*sorted([low, high])) + image.set_interpolation(interpolation) + + # re-generate legend, if checkbox is checked + if generate_legend: + draggable = None + ncol = 1 + if axes.legend_ is not None: + old_legend = axes.get_legend() + draggable = old_legend._draggable is not None + ncol = old_legend._ncol + new_legend = axes.legend(ncol=ncol) + if new_legend: + new_legend.draggable(draggable) + + # Redraw + figure = axes.get_figure() + figure.canvas.draw() + if not (axes.get_xlim() == orig_xlim and axes.get_ylim() == orig_ylim): + figure.canvas.toolbar.push_current() + + data = formlayout.fedit(datalist, title="Figure options", parent=parent, + icon=get_icon('qt4_editor_options.svg'), + apply=apply_callback) + if data is not None: + apply_callback(data) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formlayout.py b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formlayout.py new file mode 100644 index 00000000000..d5fcdfc901d --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formlayout.py @@ -0,0 +1,544 @@ +# -*- coding: utf-8 -*- +""" +formlayout +========== + +Module creating Qt form dialogs/layouts to edit various type of parameters + + +formlayout License Agreement (MIT License) +------------------------------------------ + +Copyright (c) 2009 Pierre Raybaut + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +""" + +# History: +# 1.0.10: added float validator (disable "Ok" and "Apply" button when not valid) +# 1.0.7: added support for "Apply" button +# 1.0.6: code cleaning + +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +__version__ = '1.0.10' +__license__ = __doc__ + +import copy +import datetime +import warnings + +import six + +from matplotlib import colors as mcolors +from matplotlib.backends.qt_compat import QtGui, QtWidgets, QtCore + + +BLACKLIST = {"title", "label"} + + +class ColorButton(QtWidgets.QPushButton): + """ + Color choosing push button + """ + colorChanged = QtCore.Signal(QtGui.QColor) + + def __init__(self, parent=None): + QtWidgets.QPushButton.__init__(self, parent) + self.setFixedSize(20, 20) + self.setIconSize(QtCore.QSize(12, 12)) + self.clicked.connect(self.choose_color) + self._color = QtGui.QColor() + + def choose_color(self): + color = QtWidgets.QColorDialog.getColor( + self._color, self.parentWidget(), "", + QtWidgets.QColorDialog.ShowAlphaChannel) + if color.isValid(): + self.set_color(color) + + def get_color(self): + return self._color + + @QtCore.Slot(QtGui.QColor) + def set_color(self, color): + if color != self._color: + self._color = color + self.colorChanged.emit(self._color) + pixmap = QtGui.QPixmap(self.iconSize()) + pixmap.fill(color) + self.setIcon(QtGui.QIcon(pixmap)) + + color = QtCore.Property(QtGui.QColor, get_color, set_color) + + +def to_qcolor(color): + """Create a QColor from a matplotlib color""" + qcolor = QtGui.QColor() + try: + rgba = mcolors.to_rgba(color) + except ValueError: + warnings.warn('Ignoring invalid color %r' % color) + return qcolor # return invalid QColor + qcolor.setRgbF(*rgba) + return qcolor + + +class ColorLayout(QtWidgets.QHBoxLayout): + """Color-specialized QLineEdit layout""" + def __init__(self, color, parent=None): + QtWidgets.QHBoxLayout.__init__(self) + assert isinstance(color, QtGui.QColor) + self.lineedit = QtWidgets.QLineEdit( + mcolors.to_hex(color.getRgbF(), keep_alpha=True), parent) + self.lineedit.editingFinished.connect(self.update_color) + self.addWidget(self.lineedit) + self.colorbtn = ColorButton(parent) + self.colorbtn.color = color + self.colorbtn.colorChanged.connect(self.update_text) + self.addWidget(self.colorbtn) + + def update_color(self): + color = self.text() + qcolor = to_qcolor(color) + self.colorbtn.color = qcolor # defaults to black if not qcolor.isValid() + + def update_text(self, color): + self.lineedit.setText(mcolors.to_hex(color.getRgbF(), keep_alpha=True)) + + def text(self): + return self.lineedit.text() + + +def font_is_installed(font): + """Check if font is installed""" + return [fam for fam in QtGui.QFontDatabase().families() + if six.text_type(fam) == font] + + +def tuple_to_qfont(tup): + """ + Create a QFont from tuple: + (family [string], size [int], italic [bool], bold [bool]) + """ + if not (isinstance(tup, tuple) and len(tup) == 4 + and font_is_installed(tup[0]) + and isinstance(tup[1], int) + and isinstance(tup[2], bool) + and isinstance(tup[3], bool)): + return None + font = QtGui.QFont() + family, size, italic, bold = tup + font.setFamily(family) + font.setPointSize(size) + font.setItalic(italic) + font.setBold(bold) + return font + + +def qfont_to_tuple(font): + return (six.text_type(font.family()), int(font.pointSize()), + font.italic(), font.bold()) + + +class FontLayout(QtWidgets.QGridLayout): + """Font selection""" + def __init__(self, value, parent=None): + QtWidgets.QGridLayout.__init__(self) + font = tuple_to_qfont(value) + assert font is not None + + # Font family + self.family = QtWidgets.QFontComboBox(parent) + self.family.setCurrentFont(font) + self.addWidget(self.family, 0, 0, 1, -1) + + # Font size + self.size = QtWidgets.QComboBox(parent) + self.size.setEditable(True) + sizelist = list(range(6, 12)) + list(range(12, 30, 2)) + [36, 48, 72] + size = font.pointSize() + if size not in sizelist: + sizelist.append(size) + sizelist.sort() + self.size.addItems([str(s) for s in sizelist]) + self.size.setCurrentIndex(sizelist.index(size)) + self.addWidget(self.size, 1, 0) + + # Italic or not + self.italic = QtWidgets.QCheckBox(self.tr("Italic"), parent) + self.italic.setChecked(font.italic()) + self.addWidget(self.italic, 1, 1) + + # Bold or not + self.bold = QtWidgets.QCheckBox(self.tr("Bold"), parent) + self.bold.setChecked(font.bold()) + self.addWidget(self.bold, 1, 2) + + def get_font(self): + font = self.family.currentFont() + font.setItalic(self.italic.isChecked()) + font.setBold(self.bold.isChecked()) + font.setPointSize(int(self.size.currentText())) + return qfont_to_tuple(font) + + +def is_edit_valid(edit): + text = edit.text() + state = edit.validator().validate(text, 0)[0] + + return state == QtGui.QDoubleValidator.Acceptable + + +class FormWidget(QtWidgets.QWidget): + update_buttons = QtCore.Signal() + def __init__(self, data, comment="", parent=None): + QtWidgets.QWidget.__init__(self, parent) + self.data = copy.deepcopy(data) + self.widgets = [] + self.formlayout = QtWidgets.QFormLayout(self) + if comment: + self.formlayout.addRow(QtWidgets.QLabel(comment)) + self.formlayout.addRow(QtWidgets.QLabel(" ")) + + def get_dialog(self): + """Return FormDialog instance""" + dialog = self.parent() + while not isinstance(dialog, QtWidgets.QDialog): + dialog = dialog.parent() + return dialog + + def setup(self): + for label, value in self.data: + if label is None and value is None: + # Separator: (None, None) + self.formlayout.addRow(QtWidgets.QLabel(" "), QtWidgets.QLabel(" ")) + self.widgets.append(None) + continue + elif label is None: + # Comment + self.formlayout.addRow(QtWidgets.QLabel(value)) + self.widgets.append(None) + continue + elif tuple_to_qfont(value) is not None: + field = FontLayout(value, self) + elif (label.lower() not in BLACKLIST + and mcolors.is_color_like(value)): + field = ColorLayout(to_qcolor(value), self) + elif isinstance(value, six.string_types): + field = QtWidgets.QLineEdit(value, self) + elif isinstance(value, (list, tuple)): + if isinstance(value, tuple): + value = list(value) + selindex = value.pop(0) + field = QtWidgets.QComboBox(self) + if isinstance(value[0], (list, tuple)): + keys = [key for key, _val in value] + value = [val for _key, val in value] + else: + keys = value + field.addItems(value) + if selindex in value: + selindex = value.index(selindex) + elif selindex in keys: + selindex = keys.index(selindex) + elif not isinstance(selindex, int): + warnings.warn( + "index '%s' is invalid (label: %s, value: %s)" % + (selindex, label, value)) + selindex = 0 + field.setCurrentIndex(selindex) + elif isinstance(value, bool): + field = QtWidgets.QCheckBox(self) + if value: + field.setCheckState(QtCore.Qt.Checked) + else: + field.setCheckState(QtCore.Qt.Unchecked) + elif isinstance(value, float): + field = QtWidgets.QLineEdit(repr(value), self) + field.setCursorPosition(0) + field.setValidator(QtGui.QDoubleValidator(field)) + field.validator().setLocale(QtCore.QLocale("C")) + dialog = self.get_dialog() + dialog.register_float_field(field) + field.textChanged.connect(lambda text: dialog.update_buttons()) + elif isinstance(value, int): + field = QtWidgets.QSpinBox(self) + field.setRange(-1e9, 1e9) + field.setValue(value) + elif isinstance(value, datetime.datetime): + field = QtWidgets.QDateTimeEdit(self) + field.setDateTime(value) + elif isinstance(value, datetime.date): + field = QtWidgets.QDateEdit(self) + field.setDate(value) + else: + field = QtWidgets.QLineEdit(repr(value), self) + self.formlayout.addRow(label, field) + self.widgets.append(field) + + def get(self): + valuelist = [] + for index, (label, value) in enumerate(self.data): + field = self.widgets[index] + if label is None: + # Separator / Comment + continue + elif tuple_to_qfont(value) is not None: + value = field.get_font() + elif (isinstance(value, six.string_types) + or mcolors.is_color_like(value)): + value = six.text_type(field.text()) + elif isinstance(value, (list, tuple)): + index = int(field.currentIndex()) + if isinstance(value[0], (list, tuple)): + value = value[index][0] + else: + value = value[index] + elif isinstance(value, bool): + value = field.checkState() == QtCore.Qt.Checked + elif isinstance(value, float): + value = float(str(field.text())) + elif isinstance(value, int): + value = int(field.value()) + elif isinstance(value, datetime.datetime): + value = field.dateTime().toPyDateTime() + elif isinstance(value, datetime.date): + value = field.date().toPyDate() + else: + value = eval(str(field.text())) + valuelist.append(value) + return valuelist + + +class FormComboWidget(QtWidgets.QWidget): + update_buttons = QtCore.Signal() + + def __init__(self, datalist, comment="", parent=None): + QtWidgets.QWidget.__init__(self, parent) + layout = QtWidgets.QVBoxLayout() + self.setLayout(layout) + self.combobox = QtWidgets.QComboBox() + layout.addWidget(self.combobox) + + self.stackwidget = QtWidgets.QStackedWidget(self) + layout.addWidget(self.stackwidget) + self.combobox.currentIndexChanged.connect(self.stackwidget.setCurrentIndex) + + self.widgetlist = [] + for data, title, comment in datalist: + self.combobox.addItem(title) + widget = FormWidget(data, comment=comment, parent=self) + self.stackwidget.addWidget(widget) + self.widgetlist.append(widget) + + def setup(self): + for widget in self.widgetlist: + widget.setup() + + def get(self): + return [widget.get() for widget in self.widgetlist] + + +class FormTabWidget(QtWidgets.QWidget): + update_buttons = QtCore.Signal() + + def __init__(self, datalist, comment="", parent=None): + QtWidgets.QWidget.__init__(self, parent) + layout = QtWidgets.QVBoxLayout() + self.tabwidget = QtWidgets.QTabWidget() + layout.addWidget(self.tabwidget) + self.setLayout(layout) + self.widgetlist = [] + for data, title, comment in datalist: + if len(data[0]) == 3: + widget = FormComboWidget(data, comment=comment, parent=self) + else: + widget = FormWidget(data, comment=comment, parent=self) + index = self.tabwidget.addTab(widget, title) + self.tabwidget.setTabToolTip(index, comment) + self.widgetlist.append(widget) + + def setup(self): + for widget in self.widgetlist: + widget.setup() + + def get(self): + return [widget.get() for widget in self.widgetlist] + + +class FormDialog(QtWidgets.QDialog): + """Form Dialog""" + def __init__(self, data, title="", comment="", + icon=None, parent=None, apply=None): + QtWidgets.QDialog.__init__(self, parent) + + self.apply_callback = apply + + # Form + if isinstance(data[0][0], (list, tuple)): + self.formwidget = FormTabWidget(data, comment=comment, + parent=self) + elif len(data[0]) == 3: + self.formwidget = FormComboWidget(data, comment=comment, + parent=self) + else: + self.formwidget = FormWidget(data, comment=comment, + parent=self) + layout = QtWidgets.QVBoxLayout() + layout.addWidget(self.formwidget) + + self.float_fields = [] + self.formwidget.setup() + + # Button box + self.bbox = bbox = QtWidgets.QDialogButtonBox( + QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) + self.formwidget.update_buttons.connect(self.update_buttons) + if self.apply_callback is not None: + apply_btn = bbox.addButton(QtWidgets.QDialogButtonBox.Apply) + apply_btn.clicked.connect(self.apply) + + bbox.accepted.connect(self.accept) + bbox.rejected.connect(self.reject) + layout.addWidget(bbox) + + self.setLayout(layout) + + self.setWindowTitle(title) + if not isinstance(icon, QtGui.QIcon): + icon = QtWidgets.QWidget().style().standardIcon(QtWidgets.QStyle.SP_MessageBoxQuestion) + self.setWindowIcon(icon) + + def register_float_field(self, field): + self.float_fields.append(field) + + def update_buttons(self): + valid = True + for field in self.float_fields: + if not is_edit_valid(field): + valid = False + for btn_type in (QtWidgets.QDialogButtonBox.Ok, + QtWidgets.QDialogButtonBox.Apply): + btn = self.bbox.button(btn_type) + if btn is not None: + btn.setEnabled(valid) + + def accept(self): + self.data = self.formwidget.get() + QtWidgets.QDialog.accept(self) + + def reject(self): + self.data = None + QtWidgets.QDialog.reject(self) + + def apply(self): + self.apply_callback(self.formwidget.get()) + + def get(self): + """Return form result""" + return self.data + + +def fedit(data, title="", comment="", icon=None, parent=None, apply=None): + """ + Create form dialog and return result + (if Cancel button is pressed, return None) + + data: datalist, datagroup + title: string + comment: string + icon: QIcon instance + parent: parent QWidget + apply: apply callback (function) + + datalist: list/tuple of (field_name, field_value) + datagroup: list/tuple of (datalist *or* datagroup, title, comment) + + -> one field for each member of a datalist + -> one tab for each member of a top-level datagroup + -> one page (of a multipage widget, each page can be selected with a combo + box) for each member of a datagroup inside a datagroup + + Supported types for field_value: + - int, float, str, unicode, bool + - colors: in Qt-compatible text form, i.e. in hex format or name (red,...) + (automatically detected from a string) + - list/tuple: + * the first element will be the selected index (or value) + * the other elements can be couples (key, value) or only values + """ + + # Create a QApplication instance if no instance currently exists + # (e.g., if the module is used directly from the interpreter) + if QtWidgets.QApplication.startingUp(): + _app = QtWidgets.QApplication([]) + dialog = FormDialog(data, title, comment, icon, parent, apply) + if dialog.exec_(): + return dialog.get() + + +if __name__ == "__main__": + + def create_datalist_example(): + return [('str', 'this is a string'), + ('list', [0, '1', '3', '4']), + ('list2', ['--', ('none', 'None'), ('--', 'Dashed'), + ('-.', 'DashDot'), ('-', 'Solid'), + ('steps', 'Steps'), (':', 'Dotted')]), + ('float', 1.2), + (None, 'Other:'), + ('int', 12), + ('font', ('Arial', 10, False, True)), + ('color', '#123409'), + ('bool', True), + ('date', datetime.date(2010, 10, 10)), + ('datetime', datetime.datetime(2010, 10, 10)), + ] + + def create_datagroup_example(): + datalist = create_datalist_example() + return ((datalist, "Category 1", "Category 1 comment"), + (datalist, "Category 2", "Category 2 comment"), + (datalist, "Category 3", "Category 3 comment")) + + #--------- datalist example + datalist = create_datalist_example() + + def apply_test(data): + print("data:", data) + print("result:", fedit(datalist, title="Example", + comment="This is just an example.", + apply=apply_test)) + + #--------- datagroup example + datagroup = create_datagroup_example() + print("result:", fedit(datagroup, "Global title")) + + #--------- datagroup inside a datagroup example + datalist = create_datalist_example() + datagroup = create_datagroup_example() + print("result:", fedit(((datagroup, "Title 1", "Tab 1 comment"), + (datalist, "Title 2", "Tab 2 comment"), + (datalist, "Title 3", "Tab 3 comment")), + "Global title")) diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formsubplottool.py b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formsubplottool.py new file mode 100644 index 00000000000..4906af588a7 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/qt_editor/formsubplottool.py @@ -0,0 +1,56 @@ +from matplotlib.backends.qt_compat import QtWidgets + + +class UiSubplotTool(QtWidgets.QDialog): + + def __init__(self, *args, **kwargs): + super(UiSubplotTool, self).__init__(*args, **kwargs) + self.setObjectName("SubplotTool") + self._widgets = {} + + layout = QtWidgets.QHBoxLayout() + self.setLayout(layout) + + left = QtWidgets.QVBoxLayout() + layout.addLayout(left) + right = QtWidgets.QVBoxLayout() + layout.addLayout(right) + + box = QtWidgets.QGroupBox("Borders") + left.addWidget(box) + inner = QtWidgets.QFormLayout(box) + for side in ["top", "bottom", "left", "right"]: + self._widgets[side] = widget = QtWidgets.QDoubleSpinBox() + widget.setMinimum(0) + widget.setMaximum(1) + widget.setDecimals(3) + widget.setSingleStep(.005) + widget.setKeyboardTracking(False) + inner.addRow(side, widget) + left.addStretch(1) + + box = QtWidgets.QGroupBox("Spacings") + right.addWidget(box) + inner = QtWidgets.QFormLayout(box) + for side in ["hspace", "wspace"]: + self._widgets[side] = widget = QtWidgets.QDoubleSpinBox() + widget.setMinimum(0) + widget.setMaximum(1) + widget.setDecimals(3) + widget.setSingleStep(.005) + widget.setKeyboardTracking(False) + inner.addRow(side, widget) + right.addStretch(1) + + widget = QtWidgets.QPushButton("Export values") + self._widgets["Export values"] = widget + # Don't trigger on , which is used to input values. + widget.setAutoDefault(False) + left.addWidget(widget) + + for action in ["Tight layout", "Reset", "Close"]: + self._widgets[action] = widget = QtWidgets.QPushButton(action) + widget.setAutoDefault(False) + right.addWidget(widget) + + self._widgets["Close"].setFocus() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/tkagg.py b/contrib/python/matplotlib/py2/matplotlib/backends/tkagg.py new file mode 100644 index 00000000000..072fcb48fee --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/tkagg.py @@ -0,0 +1,44 @@ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +import six +from six.moves import tkinter as Tk + +import numpy as np + +from matplotlib.backends import _tkagg + +def blit(photoimage, aggimage, bbox=None, colormode=1): + tk = photoimage.tk + + if bbox is not None: + bbox_array = bbox.__array__() + # x1, x2, y1, y2 + bboxptr = (bbox_array[0, 0], bbox_array[1, 0], + bbox_array[0, 1], bbox_array[1, 1]) + else: + bboxptr = 0 + data = np.asarray(aggimage) + dataptr = (data.shape[0], data.shape[1], data.ctypes.data) + try: + tk.call( + "PyAggImagePhoto", photoimage, + dataptr, colormode, bboxptr) + except Tk.TclError: + if hasattr(tk, 'interpaddr'): + _tkagg.tkinit(tk.interpaddr(), 1) + else: + # very old python? + _tkagg.tkinit(tk, 0) + tk.call("PyAggImagePhoto", photoimage, + dataptr, colormode, bboxptr) + +def test(aggimage): + r = Tk.Tk() + c = Tk.Canvas(r, width=aggimage.width, height=aggimage.height) + c.pack() + p = Tk.PhotoImage(width=aggimage.width, height=aggimage.height) + blit(p, aggimage) + c.create_image(aggimage.width,aggimage.height,image=p) + blit(p, aggimage) + while True: r.update_idletasks() diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/all_figures.html b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/all_figures.html new file mode 100644 index 00000000000..41f48dc6d22 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/all_figures.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + MPL | WebAgg current figures + + + +
+ +
+ + + diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/boilerplate.css b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/boilerplate.css new file mode 100644 index 00000000000..2b1535f4495 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/boilerplate.css @@ -0,0 +1,77 @@ +/** + * HTML5 ✰ Boilerplate + * + * style.css contains a reset, font normalization and some base styles. + * + * Credit is left where credit is due. + * Much inspiration was taken from these projects: + * - yui.yahooapis.com/2.8.1/build/base/base.css + * - camendesign.com/design/ + * - praegnanz.de/weblog/htmlcssjs-kickstart + */ + + +/** + * html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline) + * v1.6.1 2010-09-17 | Authors: Eric Meyer & Richard Clark + * html5doctor.com/html-5-reset-stylesheet/ + */ + +html, body, div, span, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, +small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, figcaption, figure, +footer, header, hgroup, menu, nav, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +sup { vertical-align: super; } +sub { vertical-align: sub; } + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} + +blockquote, q { quotes: none; } + +blockquote:before, blockquote:after, +q:before, q:after { content: ""; content: none; } + +ins { background-color: #ff9; color: #000; text-decoration: none; } + +mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; } + +del { text-decoration: line-through; } + +abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; } + +table { border-collapse: collapse; border-spacing: 0; } + +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } + +input, select { vertical-align: middle; } + + +/** + * Font normalization inspired by YUI Library's fonts.css: developer.yahoo.com/yui/ + */ + +body { font:13px/1.231 sans-serif; *font-size:small; } /* Hack retained to preserve specificity */ +select, input, textarea, button { font:99% sans-serif; } + +/* Normalize monospace sizing: + en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome */ +pre, code, kbd, samp { font-family: monospace, sans-serif; } + +em,i { font-style: italic; } +b,strong { font-weight: bold; } diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/fbm.css b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/fbm.css new file mode 100644 index 00000000000..0e21d19ae80 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/fbm.css @@ -0,0 +1,97 @@ + +/* Flexible box model classes */ +/* Taken from Alex Russell http://infrequently.org/2009/08/css-3-progress/ */ + +.hbox { + display: -webkit-box; + -webkit-box-orient: horizontal; + -webkit-box-align: stretch; + + display: -moz-box; + -moz-box-orient: horizontal; + -moz-box-align: stretch; + + display: box; + box-orient: horizontal; + box-align: stretch; +} + +.hbox > * { + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; +} + +.vbox { + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-box-align: stretch; + + display: -moz-box; + -moz-box-orient: vertical; + -moz-box-align: stretch; + + display: box; + box-orient: vertical; + box-align: stretch; +} + +.vbox > * { + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; +} + +.reverse { + -webkit-box-direction: reverse; + -moz-box-direction: reverse; + box-direction: reverse; +} + +.box-flex0 { + -webkit-box-flex: 0; + -moz-box-flex: 0; + box-flex: 0; +} + +.box-flex1, .box-flex { + -webkit-box-flex: 1; + -moz-box-flex: 1; + box-flex: 1; +} + +.box-flex2 { + -webkit-box-flex: 2; + -moz-box-flex: 2; + box-flex: 2; +} + +.box-group1 { + -webkit-box-flex-group: 1; + -moz-box-flex-group: 1; + box-flex-group: 1; +} + +.box-group2 { + -webkit-box-flex-group: 2; + -moz-box-flex-group: 2; + box-flex-group: 2; +} + +.start { + -webkit-box-pack: start; + -moz-box-pack: start; + box-pack: start; +} + +.end { + -webkit-box-pack: end; + -moz-box-pack: end; + box-pack: end; +} + +.center { + -webkit-box-pack: center; + -moz-box-pack: center; + box-pack: center; +} diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/page.css b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/page.css new file mode 100644 index 00000000000..d284be1f59c --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/css/page.css @@ -0,0 +1,82 @@ +/** + * Primary styles + * + * Author: IPython Development Team + */ + + +body { + background-color: white; + /* This makes sure that the body covers the entire window and needs to + be in a different element than the display: box in wrapper below */ + position: absolute; + left: 0px; + right: 0px; + top: 0px; + bottom: 0px; + overflow: visible; +} + + +div#header { + /* Initially hidden to prevent FLOUC */ + display: none; + position: relative; + height: 40px; + padding: 5px; + margin: 0px; + width: 100%; +} + +span#ipython_notebook { + position: absolute; + padding: 2px 2px 2px 5px; +} + +span#ipython_notebook img { + font-family: Verdana, "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif; + height: 24px; + text-decoration:none; + display: inline; + color: black; +} + +#site { + width: 100%; + display: none; +} + +/* We set the fonts by hand here to override the values in the theme */ +.ui-widget { + font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif; +} + +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { + font-family: "Lucinda Grande", "Lucinda Sans Unicode", Helvetica, Arial, Verdana, sans-serif; +} + +/* Smaller buttons */ +.ui-button .ui-button-text { + padding: 0.2em 0.8em; + font-size: 77%; +} + +input.ui-button { + padding: 0.3em 0.9em; +} + +span#login_widget { + float: right; +} + +.border-box-sizing { + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +#figure-div { + display: inline-block; + margin: 10px; +} + diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/ipython_inline_figure.html b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/ipython_inline_figure.html new file mode 100644 index 00000000000..eed5af0f434 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/ipython_inline_figure.html @@ -0,0 +1,34 @@ + + diff --git a/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/jquery/js/jquery-1.11.3.js b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/jquery/js/jquery-1.11.3.js new file mode 100644 index 00000000000..6feb11086f4 --- /dev/null +++ b/contrib/python/matplotlib/py2/matplotlib/backends/web_backend/jquery/js/jquery-1.11.3.js @@ -0,0 +1,10351 @@ +/*! + * jQuery JavaScript Library v1.11.3 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2015-04-28T16:19Z + */ + +(function( global, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // For CommonJS and CommonJS-like environments where a proper window is present, + // execute the factory and get jQuery + // For environments that do not inherently posses a window with a document + // (such as Node.js), expose a jQuery-making factory as module.exports + // This accentuates the need for the creation of a real window + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +// + +var deletedIds = []; + +var slice = deletedIds.slice; + +var concat = deletedIds.concat; + +var push = deletedIds.push; + +var indexOf = deletedIds.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var support = {}; + + + +var + version = "1.11.3", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android<4.1, IE<9 + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: deletedIds.sort, + splice: deletedIds.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + /* jshint eqeqeq: false */ + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + // parseFloat NaNs numeric-cast false positives (null|true|false|"") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + // adding 1 corrects loss of precision from parseFloat (#15100) + return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + isPlainObject: function( obj ) { + var key; + + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); + } + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call(obj) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Support: Android<4.1, IE<9 + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( indexOf ) { + return indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + while ( j < len ) { + first[ i++ ] = second[ j++ ]; + } + + // Support: IE<9 + // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists) + if ( len !== len ) { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: function() { + return +( new Date() ); + }, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.2.0-pre + * http://sizzlejs.com/ + * + * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-12-16 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // General-purpose constants + MAX_NEGATIVE = 1 << 31, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + characterEncoding + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + rescape = /'|\\/g, + + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }; + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + nodeType = context.nodeType; + + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + if ( !seed && documentIsHTML ) { + + // Try to shortcut find operations when possible (e.g., not under DocumentFragment) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document (jQuery #6963) + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getElementsByClassName ) { + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // QSA path + if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + nid = old = expando; + newContext = context; + newSelector = nodeType !== 1 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ +function assert( fn ) { + var div = document.createElement("div"); + + try { + return !!fn( div ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( div.parentNode ) { + div.parentNode.removeChild( div ); + } + // release memory in IE + div = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = attrs.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + ( ~b.sourceIndex || MAX_NEGATIVE ) - + ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + parent = doc.defaultView; + + // Support: IE>8 + // If iframe document is assigned to "document" variable and if iframe has been reloaded, + // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 + // IE6-8 do not support the defaultView property so parent will be undefined + if ( parent && parent !== parent.top ) { + // IE11 does not have attachEvent, so all must suffer + if ( parent.addEventListener ) { + parent.addEventListener( "unload", unloadHandler, false ); + } else if ( parent.attachEvent ) { + parent.attachEvent( "onunload", unloadHandler ); + } + } + + /* Support tests + ---------------------------------------------------------------------- */ + documentIsHTML = !isXML( doc ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( div ) { + div.className = "i"; + return !div.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( div ) { + docElem.appendChild( div ).id = expando; + return !doc.getElementsByName || !doc.getElementsByName( expando ).length; + }); + + // ID find and filter + if ( support.getById ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [ m ] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + // Support: IE6/7 + // getElementById is not reliable as a find shortcut + delete Expr.find["ID"]; + + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See http://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + docElem.appendChild( div ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( div.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( div ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = doc.createElement("input"); + input.setAttribute( "type", "hidden" ); + div.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( div.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === doc ? -1 : + b === doc ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return doc; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (oldCache = outerCache[ dir ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + outerCache[ dir ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context !== document && context; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is no seed and only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + support.getById && context.nodeType === 9 && documentIsHTML && + Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( div1 ) { + // Should return 1, but returns 4 (following) + return div1.compareDocumentPosition( document.createElement("div") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( div ) { + div.innerHTML = ""; + return div.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( div ) { + div.innerHTML = ""; + div.firstChild.setAttribute( "value", "" ); + return div.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( div ) { + return div.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + + +var rneedsContext = jQuery.expr.match.needsContext; + +var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not; + }); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); +}; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +}); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + init = jQuery.fn.init = function( selector, context ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return typeof rootjQuery.ready !== "undefined" ? + rootjQuery.ready( selector ) : + // Execute immediately if ready is not present + selector( jQuery ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.extend({ + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +jQuery.fn.extend({ + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.unique( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + ret = jQuery.unique( ret ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + } + + return this.pushStack( ret ); + }; +}); +var rnotwhite = (/\S+/g); + + + +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + + } else if ( !(--remaining) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); + + +// The deferred used on DOM ready +var readyList; + +jQuery.fn.ready = function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; +}; + +jQuery.extend({ + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.triggerHandler ) { + jQuery( document ).triggerHandler( "ready" ); + jQuery( document ).off( "ready" ); + } + } +}); + +/** + * Clean-up method for dom ready events + */ +function detach() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } +} + +/** + * The ready event handler and self cleanup method + */ +function completed() { + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } +} + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + + +var strundefined = typeof undefined; + + + +// Support: IE<9 +// Iteration over object's inherited properties before its own +var i; +for ( i in jQuery( support ) ) { + break; +} +support.ownLast = i !== "0"; + +// Note: most support tests are defined in their respective modules. +// false until the test is run +support.inlineBlockNeedsLayout = false; + +// Execute ASAP in case we need to set body.style.zoom +jQuery(function() { + // Minified: var a,b,c,d + var val, div, body, container; + + body = document.getElementsByTagName( "body" )[ 0 ]; + if ( !body || !body.style ) { + // Return for frameset docs that don't have a body + return; + } + + // Setup + div = document.createElement( "div" ); + container = document.createElement( "div" ); + container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px"; + body.appendChild( container ).appendChild( div ); + + if ( typeof div.style.zoom !== strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1"; + + support.inlineBlockNeedsLayout = val = div.offsetWidth === 3; + if ( val ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); +}); + + + + +(function() { + var div = document.createElement( "div" ); + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +/** + * Determines whether an object can have data + */ +jQuery.acceptData = function( elem ) { + var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ], + nodeType = +elem.nodeType || 1; + + // Do not set data on non-element DOM nodes because it will not be cleared (#8335). + return nodeType !== 1 && nodeType !== 9 ? + false : + + // Nodes accept data unless otherwise specified; rejection can be conditional + !noData || noData !== true && elem.getAttribute("classid") === noData; +}; + + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /([A-Z])/g; + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + +function internalData( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var ret, thisCache, + internalKey = jQuery.expando, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + // Avoid exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + cache[ id ] = isNode ? {} : { toJSON: jQuery.noop }; + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( typeof name === "string" ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; +} + +function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + i = name.length; + while ( i-- ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + /* jshint eqeqeq: false */ + } else if ( support.deleteExpando || cache != cache.window ) { + /* jshint eqeqeq: true */ + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } +} + +jQuery.extend({ + cache: {}, + + // The following elements (space-suffixed to avoid Object.prototype collisions) + // throw uncatchable exceptions if you attempt to set expando properties + noData: { + "applet ": true, + "embed ": true, + // ...but Flash objects (which have this classid) *can* handle expandos + "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var i, name, data, + elem = this[0], + attrs = elem && elem.attributes; + + // Special expections of .data basically thwart jQuery.access, + // so implement the relevant behavior ourselves + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE11+ + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return arguments.length > 1 ? + + // Sets one value + this.each(function() { + jQuery.data( this, key, value ); + }) : + + // Gets one value + // Try to fetch any internally stored data first + elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined; + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + + +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHidden = function( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + }; + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; +}; +var rcheckableType = (/^(?:checkbox|radio)$/i); + + + +(function() { + // Minified: var a,b,c + var input = document.createElement( "input" ), + div = document.createElement( "div" ), + fragment = document.createDocumentFragment(); + + // Setup + div.innerHTML = "
a"; + + // IE strips leading whitespace when .innerHTML is used + support.leadingWhitespace = div.firstChild.nodeType === 3; + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + support.tbody = !div.getElementsByTagName( "tbody" ).length; + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + support.htmlSerialize = !!div.getElementsByTagName( "link" ).length; + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + support.html5Clone = + document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav>"; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + input.type = "checkbox"; + input.checked = true; + fragment.appendChild( input ); + support.appendChecked = input.checked; + + // Make sure textarea (and checkbox) defaultValue is properly cloned + // Support: IE6-IE11+ + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // #11217 - WebKit loses check when the name is after the checked attribute + fragment.appendChild( div ); + div.innerHTML = ""; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + support.noCloneEvent = true; + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Execute the test only if not already executed in another module. + if (support.deleteExpando == null) { + // Support: IE<9 + support.deleteExpando = true; + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + } +})(); + + +(function() { + var i, eventName, + div = document.createElement( "div" ); + + // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event) + for ( i in { submit: true, change: true, focusin: true }) { + eventName = "on" + i; + + if ( !(support[ i + "Bubbles" ] = eventName in window) ) { + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + div.setAttribute( eventName, "t" ); + support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false; + } + } + + // Null elements to avoid leaks in IE. + div = null; +})(); + + +var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnotwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && jQuery.acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + /* jshint eqeqeq: false */ + for ( ; cur != this; cur = cur.parentNode || this ) { + /* jshint eqeqeq: true */ + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + // Support: IE < 9, Android < 4.0 + src.returnValue === false ? + returnTrue : + returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && e.stopImmediatePropagation ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + jQuery._data( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = jQuery._data( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + jQuery._removeData( doc, fix ); + } else { + jQuery._data( doc, fix, attaches ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); + + +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; +} + +// Used in buildFragment, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +// Support: IE<8 +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!support.noCloneEvent || !support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + + // Ensure a safe fragment + safe = createSafeFragment( context ), + + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + deletedIds.push( id ); + } + } + } + } + } +}); + +jQuery.fn.extend({ + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + remove: function( selector, keepData /* Internal Use Only */ ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map(function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var arg = arguments[ 0 ]; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + arg = this.parentNode; + + jQuery.cleanData( getAll( this ) ); + + if ( arg ) { + arg.replaceChild( elem, this ); + } + }); + + // Force removal if there was no new content (e.g., from empty arguments) + return arg && (arg.length || arg.nodeType) ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, self.html() ); + } + self.domManip( args, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[i], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + + +var iframe, + elemdisplay = {}; + +/** + * Retrieve the actual display of a element + * @param {String} name nodeName of the element + * @param {Object} doc Document object + */ +// Called only from within defaultDisplay +function actualDisplay( name, doc ) { + var style, + elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + + // getDefaultComputedStyle might be reliably used only on attached element + display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? + + // Use of this method is a temporary fix (more like optmization) until something better comes along, + // since it was removed from specification and supported only in FF + style.display : jQuery.css( elem[ 0 ], "display" ); + + // We don't have any data stored on the element, + // so use "detach" method as fast way to get rid of the element + elem.detach(); + + return display; +} + +/** + * Try to determine the default display value of an element + * @param {String} nodeName + */ +function defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + + // Use the already-created iframe if possible + iframe = (iframe || jQuery( "