From f895bba65827952ed934b2b46f9a45e30a191fd2 Mon Sep 17 00:00:00 2001 From: maxim-yurchuk Date: Tue, 11 Feb 2025 13:26:52 +0300 Subject: Remove deps on pandas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit \-- аналогичные правки в gh Хочу залить в обход синка, чтобы посмотреть удалится ли pandas в нашей gh репе через piglet commit_hash:abca127aa37d4dbb94b07e1e18cdb8eb5b711860 --- contrib/python/matplotlib/py3/src/_backend_agg.cpp | 176 -- contrib/python/matplotlib/py3/src/_backend_agg.h | 1280 ------------ .../matplotlib/py3/src/_backend_agg_basic_types.h | 123 -- .../matplotlib/py3/src/_backend_agg_wrapper.cpp | 646 ------ .../python/matplotlib/py3/src/_c_internal_utils.c | 211 -- .../python/matplotlib/py3/src/_image_resample.h | 834 -------- .../python/matplotlib/py3/src/_image_wrapper.cpp | 297 --- contrib/python/matplotlib/py3/src/_path.h | 1251 ------------ .../python/matplotlib/py3/src/_path_wrapper.cpp | 772 -------- .../python/matplotlib/py3/src/_qhull_wrapper.cpp | 340 ---- contrib/python/matplotlib/py3/src/_tkagg.cpp | 370 ---- contrib/python/matplotlib/py3/src/_tkmini.h | 110 -- contrib/python/matplotlib/py3/src/_ttconv.cpp | 96 - contrib/python/matplotlib/py3/src/agg_workaround.h | 85 - contrib/python/matplotlib/py3/src/array.h | 80 - .../python/matplotlib/py3/src/checkdep_freetype2.c | 19 - contrib/python/matplotlib/py3/src/ft2font.cpp | 840 -------- contrib/python/matplotlib/py3/src/ft2font.h | 159 -- .../python/matplotlib/py3/src/ft2font_wrapper.cpp | 1578 --------------- contrib/python/matplotlib/py3/src/mplutils.h | 99 - contrib/python/matplotlib/py3/src/numpy_cpp.h | 578 ------ .../python/matplotlib/py3/src/path_converters.h | 1106 ----------- contrib/python/matplotlib/py3/src/py_adaptors.h | 248 --- .../python/matplotlib/py3/src/py_converters.cpp | 558 ------ contrib/python/matplotlib/py3/src/py_converters.h | 48 - contrib/python/matplotlib/py3/src/py_exceptions.h | 72 - contrib/python/matplotlib/py3/src/tri/_tri.cpp | 2074 -------------------- contrib/python/matplotlib/py3/src/tri/_tri.h | 799 -------- .../python/matplotlib/py3/src/tri/_tri_wrapper.cpp | 58 - 29 files changed, 14907 deletions(-) delete mode 100644 contrib/python/matplotlib/py3/src/_backend_agg.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_backend_agg.h delete mode 100644 contrib/python/matplotlib/py3/src/_backend_agg_basic_types.h delete mode 100644 contrib/python/matplotlib/py3/src/_backend_agg_wrapper.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_c_internal_utils.c delete mode 100644 contrib/python/matplotlib/py3/src/_image_resample.h delete mode 100644 contrib/python/matplotlib/py3/src/_image_wrapper.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_path.h delete mode 100644 contrib/python/matplotlib/py3/src/_path_wrapper.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_qhull_wrapper.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_tkagg.cpp delete mode 100644 contrib/python/matplotlib/py3/src/_tkmini.h delete mode 100644 contrib/python/matplotlib/py3/src/_ttconv.cpp delete mode 100644 contrib/python/matplotlib/py3/src/agg_workaround.h delete mode 100644 contrib/python/matplotlib/py3/src/array.h delete mode 100644 contrib/python/matplotlib/py3/src/checkdep_freetype2.c delete mode 100644 contrib/python/matplotlib/py3/src/ft2font.cpp delete mode 100644 contrib/python/matplotlib/py3/src/ft2font.h delete mode 100644 contrib/python/matplotlib/py3/src/ft2font_wrapper.cpp delete mode 100644 contrib/python/matplotlib/py3/src/mplutils.h delete mode 100644 contrib/python/matplotlib/py3/src/numpy_cpp.h delete mode 100644 contrib/python/matplotlib/py3/src/path_converters.h delete mode 100644 contrib/python/matplotlib/py3/src/py_adaptors.h delete mode 100644 contrib/python/matplotlib/py3/src/py_converters.cpp delete mode 100644 contrib/python/matplotlib/py3/src/py_converters.h delete mode 100644 contrib/python/matplotlib/py3/src/py_exceptions.h delete mode 100644 contrib/python/matplotlib/py3/src/tri/_tri.cpp delete mode 100644 contrib/python/matplotlib/py3/src/tri/_tri.h delete mode 100644 contrib/python/matplotlib/py3/src/tri/_tri_wrapper.cpp (limited to 'contrib/python/matplotlib/py3/src') diff --git a/contrib/python/matplotlib/py3/src/_backend_agg.cpp b/contrib/python/matplotlib/py3/src/_backend_agg.cpp deleted file mode 100644 index 335e4097194..00000000000 --- a/contrib/python/matplotlib/py3/src/_backend_agg.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -#define NO_IMPORT_ARRAY - -#include "_backend_agg.h" -#include "mplutils.h" - -void BufferRegion::to_string_argb(uint8_t *buf) -{ - unsigned char *pix; - unsigned char tmp; - size_t i, j; - - memcpy(buf, data, (size_t) height * stride); - - for (i = 0; i < (size_t)height; ++i) { - pix = buf + i * stride; - for (j = 0; j < (size_t)width; ++j) { - // Convert rgba to argb - tmp = pix[2]; - pix[2] = pix[0]; - pix[0] = tmp; - pix += 4; - } - } -} - -RendererAgg::RendererAgg(unsigned int width, unsigned int height, double dpi) - : width(width), - height(height), - dpi(dpi), - NUMBYTES((size_t)width * (size_t)height * 4), - pixBuffer(NULL), - renderingBuffer(), - alphaBuffer(NULL), - alphaMaskRenderingBuffer(), - alphaMask(alphaMaskRenderingBuffer), - pixfmtAlphaMask(alphaMaskRenderingBuffer), - rendererBaseAlphaMask(), - rendererAlphaMask(), - scanlineAlphaMask(), - slineP8(), - slineBin(), - pixFmt(), - rendererBase(), - rendererAA(), - rendererBin(), - theRasterizer(32768), - lastclippath(NULL), - _fill_color(agg::rgba(1, 1, 1, 0)) -{ - unsigned stride(width * 4); - - pixBuffer = new agg::int8u[NUMBYTES]; - renderingBuffer.attach(pixBuffer, width, height, stride); - pixFmt.attach(renderingBuffer); - rendererBase.attach(pixFmt); - rendererBase.clear(_fill_color); - rendererAA.attach(rendererBase); - rendererBin.attach(rendererBase); - hatch_size = int(dpi); - hatchBuffer = new agg::int8u[hatch_size * hatch_size * 4]; - hatchRenderingBuffer.attach(hatchBuffer, hatch_size, hatch_size, hatch_size * 4); -} - -RendererAgg::~RendererAgg() -{ - delete[] hatchBuffer; - delete[] alphaBuffer; - delete[] pixBuffer; -} - -void RendererAgg::create_alpha_buffers() -{ - if (!alphaBuffer) { - alphaBuffer = new agg::int8u[width * height]; - alphaMaskRenderingBuffer.attach(alphaBuffer, width, height, width); - rendererBaseAlphaMask.attach(pixfmtAlphaMask); - rendererAlphaMask.attach(rendererBaseAlphaMask); - } -} - -BufferRegion *RendererAgg::copy_from_bbox(agg::rect_d in_rect) -{ - agg::rect_i rect( - (int)in_rect.x1, height - (int)in_rect.y2, (int)in_rect.x2, height - (int)in_rect.y1); - - BufferRegion *reg = NULL; - reg = new BufferRegion(rect); - - agg::rendering_buffer rbuf; - rbuf.attach(reg->get_data(), reg->get_width(), reg->get_height(), reg->get_stride()); - - pixfmt pf(rbuf); - renderer_base rb(pf); - rb.copy_from(renderingBuffer, &rect, -rect.x1, -rect.y1); - - return reg; -} - -void RendererAgg::restore_region(BufferRegion ®ion) -{ - if (region.get_data() == NULL) { - throw std::runtime_error("Cannot restore_region from NULL data"); - } - - agg::rendering_buffer rbuf; - rbuf.attach(region.get_data(), region.get_width(), region.get_height(), region.get_stride()); - - rendererBase.copy_from(rbuf, 0, region.get_rect().x1, region.get_rect().y1); -} - -// Restore the part of the saved region with offsets -void -RendererAgg::restore_region(BufferRegion ®ion, int xx1, int yy1, int xx2, int yy2, int x, int y ) -{ - if (region.get_data() == NULL) { - throw std::runtime_error("Cannot restore_region from NULL data"); - } - - agg::rect_i &rrect = region.get_rect(); - - agg::rect_i rect(xx1 - rrect.x1, (yy1 - rrect.y1), xx2 - rrect.x1, (yy2 - rrect.y1)); - - agg::rendering_buffer rbuf; - rbuf.attach(region.get_data(), region.get_width(), region.get_height(), region.get_stride()); - - rendererBase.copy_from(rbuf, &rect, x, y); -} - -bool RendererAgg::render_clippath(py::PathIterator &clippath, - const agg::trans_affine &clippath_trans, - e_snap_mode snap_mode) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removed_t; - /* Unlike normal Paths, the clip path cannot be clipped to the Figure bbox, - * because it needs to remain a complete closed path, so there is no - * PathClipper step. */ - typedef PathSnapper snapped_t; - typedef PathSimplifier simplify_t; - typedef agg::conv_curve curve_t; - - bool has_clippath = (clippath.total_vertices() != 0); - - if (has_clippath && - (clippath.get_id() != lastclippath || clippath_trans != lastclippath_transform)) { - create_alpha_buffers(); - agg::trans_affine trans(clippath_trans); - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); - - rendererBaseAlphaMask.clear(agg::gray8(0, 0)); - transformed_path_t transformed_clippath(clippath, trans); - nan_removed_t nan_removed_clippath(transformed_clippath, true, clippath.has_codes()); - snapped_t snapped_clippath(nan_removed_clippath, snap_mode, clippath.total_vertices(), 0.0); - simplify_t simplified_clippath(snapped_clippath, - clippath.should_simplify() && !clippath.has_codes(), - clippath.simplify_threshold()); - curve_t curved_clippath(simplified_clippath); - theRasterizer.add_path(curved_clippath); - rendererAlphaMask.color(agg::gray8(255, 255)); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, rendererAlphaMask); - lastclippath = clippath.get_id(); - lastclippath_transform = clippath_trans; - } - - return has_clippath; -} - -void RendererAgg::clear() -{ - //"clear the rendered buffer"; - - rendererBase.clear(_fill_color); -} diff --git a/contrib/python/matplotlib/py3/src/_backend_agg.h b/contrib/python/matplotlib/py3/src/_backend_agg.h deleted file mode 100644 index 61c24232a86..00000000000 --- a/contrib/python/matplotlib/py3/src/_backend_agg.h +++ /dev/null @@ -1,1280 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -/* _backend_agg.h -*/ - -#ifndef MPL_BACKEND_AGG_H -#define MPL_BACKEND_AGG_H - -#include -#include -#include - -#include "agg_alpha_mask_u8.h" -#include "agg_conv_curve.h" -#include "agg_conv_dash.h" -#include "agg_conv_stroke.h" -#include "agg_image_accessors.h" -#include "agg_pixfmt_amask_adaptor.h" -#include "agg_pixfmt_gray.h" -#include "agg_pixfmt_rgba.h" -#include "agg_rasterizer_scanline_aa.h" -#include "agg_renderer_base.h" -#include "agg_renderer_scanline.h" -#include "agg_rendering_buffer.h" -#include "agg_scanline_bin.h" -#include "agg_scanline_p.h" -#include "agg_scanline_storage_aa.h" -#include "agg_scanline_storage_bin.h" -#include "agg_scanline_u.h" -#include "agg_span_allocator.h" -#include "agg_span_converter.h" -#include "agg_span_gouraud_rgba.h" -#include "agg_span_image_filter_gray.h" -#include "agg_span_image_filter_rgba.h" -#include "agg_span_interpolator_linear.h" -#include "agg_span_pattern_rgba.h" -#include "util/agg_color_conv_rgb8.h" - -#include "_backend_agg_basic_types.h" -#include "path_converters.h" -#include "array.h" -#include "agg_workaround.h" - -/**********************************************************************/ - -// a helper class to pass agg::buffer objects around. - -class BufferRegion -{ - public: - BufferRegion(const agg::rect_i &r) : rect(r) - { - width = r.x2 - r.x1; - height = r.y2 - r.y1; - stride = width * 4; - data = new agg::int8u[stride * height]; - } - - virtual ~BufferRegion() - { - delete[] data; - }; - - agg::int8u *get_data() - { - return data; - } - - agg::rect_i &get_rect() - { - return rect; - } - - int get_width() - { - return width; - } - - int get_height() - { - return height; - } - - int get_stride() - { - return stride; - } - - void to_string_argb(uint8_t *buf); - - private: - agg::int8u *data; - agg::rect_i rect; - int width; - int height; - int stride; - - private: - // prevent copying - BufferRegion(const BufferRegion &); - BufferRegion &operator=(const BufferRegion &); -}; - -#define MARKER_CACHE_SIZE 512 - -// the renderer -class RendererAgg -{ - public: - - typedef fixed_blender_rgba_plain fixed_blender_rgba32_plain; - typedef agg::pixfmt_alpha_blend_rgba pixfmt; - typedef agg::renderer_base renderer_base; - typedef agg::renderer_scanline_aa_solid renderer_aa; - typedef agg::renderer_scanline_bin_solid renderer_bin; - typedef agg::rasterizer_scanline_aa rasterizer; - - typedef agg::scanline_p8 scanline_p8; - typedef agg::scanline_bin scanline_bin; - typedef agg::amask_no_clip_gray8 alpha_mask_type; - typedef agg::scanline_u8_am scanline_am; - - typedef agg::renderer_base renderer_base_alpha_mask_type; - typedef agg::renderer_scanline_aa_solid renderer_alpha_mask_type; - - /* TODO: Remove facepair_t */ - typedef std::pair facepair_t; - - RendererAgg(unsigned int width, unsigned int height, double dpi); - - virtual ~RendererAgg(); - - unsigned int get_width() - { - return width; - } - - unsigned int get_height() - { - return height; - } - - template - void draw_path(GCAgg &gc, PathIterator &path, agg::trans_affine &trans, agg::rgba &color); - - template - void draw_markers(GCAgg &gc, - PathIterator &marker_path, - agg::trans_affine &marker_path_trans, - PathIterator &path, - agg::trans_affine &trans, - agg::rgba face); - - template - void draw_text_image(GCAgg &gc, ImageArray &image, int x, int y, double angle); - - template - void draw_image(GCAgg &gc, - double x, - double y, - ImageArray &image); - - template - void draw_path_collection(GCAgg &gc, - agg::trans_affine &master_transform, - PathGenerator &path, - TransformArray &transforms, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - ColorArray &facecolors, - ColorArray &edgecolors, - LineWidthArray &linewidths, - DashesVector &linestyles, - AntialiasedArray &antialiaseds); - - template - void draw_quad_mesh(GCAgg &gc, - agg::trans_affine &master_transform, - unsigned int mesh_width, - unsigned int mesh_height, - CoordinateArray &coordinates, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - ColorArray &facecolors, - bool antialiased, - ColorArray &edgecolors); - - template - void draw_gouraud_triangle(GCAgg &gc, - PointArray &points, - ColorArray &colors, - agg::trans_affine &trans); - - template - void draw_gouraud_triangles(GCAgg &gc, - PointArray &points, - ColorArray &colors, - agg::trans_affine &trans); - - agg::rect_i get_content_extents(); - void clear(); - - BufferRegion *copy_from_bbox(agg::rect_d in_rect); - void restore_region(BufferRegion ®); - void restore_region(BufferRegion ®ion, int xx1, int yy1, int xx2, int yy2, int x, int y); - - unsigned int width, height; - double dpi; - size_t NUMBYTES; // the number of bytes in buffer - - agg::int8u *pixBuffer; - agg::rendering_buffer renderingBuffer; - - agg::int8u *alphaBuffer; - agg::rendering_buffer alphaMaskRenderingBuffer; - alpha_mask_type alphaMask; - agg::pixfmt_gray8 pixfmtAlphaMask; - renderer_base_alpha_mask_type rendererBaseAlphaMask; - renderer_alpha_mask_type rendererAlphaMask; - scanline_am scanlineAlphaMask; - - scanline_p8 slineP8; - scanline_bin slineBin; - pixfmt pixFmt; - renderer_base rendererBase; - renderer_aa rendererAA; - renderer_bin rendererBin; - rasterizer theRasterizer; - - void *lastclippath; - agg::trans_affine lastclippath_transform; - - size_t hatch_size; - agg::int8u *hatchBuffer; - agg::rendering_buffer hatchRenderingBuffer; - - agg::rgba _fill_color; - - protected: - inline double points_to_pixels(double points) - { - return points * dpi / 72.0; - } - - template - void set_clipbox(const agg::rect_d &cliprect, R &rasterizer); - - bool render_clippath(py::PathIterator &clippath, const agg::trans_affine &clippath_trans, e_snap_mode snap_mode); - - template - void _draw_path(PathIteratorType &path, bool has_clippath, const facepair_t &face, GCAgg &gc); - - template - void _draw_path_collection_generic(GCAgg &gc, - agg::trans_affine master_transform, - const agg::rect_d &cliprect, - PathIterator &clippath, - const agg::trans_affine &clippath_trans, - PathGenerator &path_generator, - TransformArray &transforms, - OffsetArray &offsets, - const agg::trans_affine &offset_trans, - ColorArray &facecolors, - ColorArray &edgecolors, - LineWidthArray &linewidths, - DashesVector &linestyles, - AntialiasedArray &antialiaseds, - bool check_snap, - bool has_codes); - - template - void _draw_gouraud_triangle(PointArray &points, - ColorArray &colors, - agg::trans_affine trans, - bool has_clippath); - - private: - void create_alpha_buffers(); - - // prevent copying - RendererAgg(const RendererAgg &); - RendererAgg &operator=(const RendererAgg &); -}; - -/*************************************************************************** - * Implementation - */ - -template -inline void -RendererAgg::_draw_path(path_t &path, bool has_clippath, const facepair_t &face, GCAgg &gc) -{ - typedef agg::conv_stroke stroke_t; - typedef agg::conv_dash dash_t; - typedef agg::conv_stroke stroke_dash_t; - typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; - typedef agg::renderer_base amask_ren_type; - typedef agg::renderer_scanline_aa_solid amask_aa_renderer_type; - typedef agg::renderer_scanline_bin_solid amask_bin_renderer_type; - - // Render face - if (face.first) { - theRasterizer.add_path(path); - - if (gc.isaa) { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); - ren.color(face.second); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ren); - } else { - rendererAA.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, rendererAA); - } - } else { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_bin_renderer_type ren(r); - ren.color(face.second); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ren); - } else { - rendererBin.color(face.second); - agg::render_scanlines(theRasterizer, slineP8, rendererBin); - } - } - } - - // Render hatch - if (gc.has_hatchpath()) { - // Reset any clipping that may be in effect, since we'll be - // drawing the hatch in a scratch buffer at origin (0, 0) - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - - // Create and transform the path - typedef agg::conv_transform hatch_path_trans_t; - typedef agg::conv_curve hatch_path_curve_t; - typedef agg::conv_stroke hatch_path_stroke_t; - - py::PathIterator hatch_path(gc.hatchpath); - agg::trans_affine hatch_trans; - hatch_trans *= agg::trans_affine_scaling(1.0, -1.0); - hatch_trans *= agg::trans_affine_translation(0.0, 1.0); - hatch_trans *= agg::trans_affine_scaling(hatch_size, hatch_size); - hatch_path_trans_t hatch_path_trans(hatch_path, hatch_trans); - hatch_path_curve_t hatch_path_curve(hatch_path_trans); - hatch_path_stroke_t hatch_path_stroke(hatch_path_curve); - hatch_path_stroke.width(points_to_pixels(gc.hatch_linewidth)); - hatch_path_stroke.line_cap(agg::square_cap); - - // Render the path into the hatch buffer - pixfmt hatch_img_pixf(hatchRenderingBuffer); - renderer_base rb(hatch_img_pixf); - renderer_aa rs(rb); - rb.clear(_fill_color); - rs.color(gc.hatch_color); - - theRasterizer.add_path(hatch_path_curve); - agg::render_scanlines(theRasterizer, slineP8, rs); - theRasterizer.add_path(hatch_path_stroke); - agg::render_scanlines(theRasterizer, slineP8, rs); - - // Put clipping back on, if originally set on entry to this - // function - set_clipbox(gc.cliprect, theRasterizer); - if (has_clippath) { - render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - } - - // Transfer the hatch to the main image buffer - typedef agg::image_accessor_wrap img_source_type; - typedef agg::span_pattern_rgba span_gen_type; - agg::span_allocator sa; - img_source_type img_src(hatch_img_pixf); - span_gen_type sg(img_src, 0, 0); - theRasterizer.add_path(path); - - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type ren(pfa); - agg::render_scanlines_aa(theRasterizer, slineP8, ren, sa, sg); - } else { - agg::render_scanlines_aa(theRasterizer, slineP8, rendererBase, sa, sg); - } - } - - // Render stroke - if (gc.linewidth != 0.0) { - double linewidth = points_to_pixels(gc.linewidth); - if (!gc.isaa) { - linewidth = (linewidth < 0.5) ? 0.5 : mpl_round(linewidth); - } - if (gc.dashes.size() == 0) { - stroke_t stroke(path); - stroke.width(points_to_pixels(gc.linewidth)); - stroke.line_cap(gc.cap); - stroke.line_join(gc.join); - stroke.miter_limit(points_to_pixels(gc.linewidth)); - theRasterizer.add_path(stroke); - } else { - dash_t dash(path); - gc.dashes.dash_to_stroke(dash, dpi, gc.isaa); - stroke_dash_t stroke(dash); - stroke.line_cap(gc.cap); - stroke.line_join(gc.join); - stroke.width(linewidth); - stroke.miter_limit(points_to_pixels(gc.linewidth)); - theRasterizer.add_path(stroke); - } - - if (gc.isaa) { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); - ren.color(gc.color); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ren); - } else { - rendererAA.color(gc.color); - agg::render_scanlines(theRasterizer, slineP8, rendererAA); - } - } else { - if (has_clippath) { - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_bin_renderer_type ren(r); - ren.color(gc.color); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ren); - } else { - rendererBin.color(gc.color); - agg::render_scanlines(theRasterizer, slineBin, rendererBin); - } - } - } -} - -template -inline void -RendererAgg::draw_path(GCAgg &gc, PathIterator &path, agg::trans_affine &trans, agg::rgba &color) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removed_t; - typedef PathClipper clipped_t; - typedef PathSnapper snapped_t; - typedef PathSimplifier simplify_t; - typedef agg::conv_curve curve_t; - typedef Sketch sketch_t; - - facepair_t face(color.a != 0.0, color); - - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); - bool clip = !face.first && !gc.has_hatchpath(); - bool simplify = path.should_simplify() && clip; - double snapping_linewidth = points_to_pixels(gc.linewidth); - if (gc.color.a == 0.0) { - snapping_linewidth = 0.0; - } - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, path.has_codes()); - clipped_t clipped(nan_removed, clip, width, height); - snapped_t snapped(clipped, gc.snap_mode, path.total_vertices(), snapping_linewidth); - simplify_t simplified(snapped, simplify, path.simplify_threshold()); - curve_t curve(simplified); - sketch_t sketch(curve, gc.sketch.scale, gc.sketch.length, gc.sketch.randomness); - - _draw_path(sketch, has_clippath, face, gc); -} - -template -inline void RendererAgg::draw_markers(GCAgg &gc, - PathIterator &marker_path, - agg::trans_affine &marker_trans, - PathIterator &path, - agg::trans_affine &trans, - agg::rgba color) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removed_t; - typedef PathSnapper snap_t; - typedef agg::conv_curve curve_t; - typedef agg::conv_stroke stroke_t; - typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; - typedef agg::renderer_base amask_ren_type; - typedef agg::renderer_scanline_aa_solid amask_aa_renderer_type; - - // Deal with the difference in y-axis direction - marker_trans *= agg::trans_affine_scaling(1.0, -1.0); - - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.5, (double)height + 0.5); - - transformed_path_t marker_path_transformed(marker_path, marker_trans); - nan_removed_t marker_path_nan_removed(marker_path_transformed, true, marker_path.has_codes()); - snap_t marker_path_snapped(marker_path_nan_removed, - gc.snap_mode, - marker_path.total_vertices(), - points_to_pixels(gc.linewidth)); - curve_t marker_path_curve(marker_path_snapped); - - if (!marker_path_snapped.is_snapping()) { - // If the path snapper isn't in effect, at least make sure the marker - // at (0, 0) is in the center of a pixel. This, importantly, makes - // the circle markers look centered around the point they refer to. - marker_trans *= agg::trans_affine_translation(0.5, 0.5); - } - - transformed_path_t path_transformed(path, trans); - nan_removed_t path_nan_removed(path_transformed, false, false); - snap_t path_snapped(path_nan_removed, SNAP_FALSE, path.total_vertices(), 0.0); - curve_t path_curve(path_snapped); - path_curve.rewind(0); - - facepair_t face(color.a != 0.0, color); - - // maxim's suggestions for cached scanlines - agg::scanline_storage_aa8 scanlines; - theRasterizer.reset(); - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - agg::rect_i marker_size(0x7FFFFFFF, 0x7FFFFFFF, -0x7FFFFFFF, -0x7FFFFFFF); - - agg::int8u staticFillCache[MARKER_CACHE_SIZE]; - agg::int8u staticStrokeCache[MARKER_CACHE_SIZE]; - agg::int8u *fillCache = staticFillCache; - agg::int8u *strokeCache = staticStrokeCache; - - try - { - unsigned fillSize = 0; - if (face.first) { - theRasterizer.add_path(marker_path_curve); - agg::render_scanlines(theRasterizer, slineP8, scanlines); - fillSize = scanlines.byte_size(); - if (fillSize >= MARKER_CACHE_SIZE) { - fillCache = new agg::int8u[fillSize]; - } - scanlines.serialize(fillCache); - marker_size = agg::rect_i(scanlines.min_x(), - scanlines.min_y(), - scanlines.max_x(), - scanlines.max_y()); - } - - stroke_t stroke(marker_path_curve); - stroke.width(points_to_pixels(gc.linewidth)); - stroke.line_cap(gc.cap); - stroke.line_join(gc.join); - stroke.miter_limit(points_to_pixels(gc.linewidth)); - theRasterizer.reset(); - theRasterizer.add_path(stroke); - agg::render_scanlines(theRasterizer, slineP8, scanlines); - unsigned strokeSize = scanlines.byte_size(); - if (strokeSize >= MARKER_CACHE_SIZE) { - strokeCache = new agg::int8u[strokeSize]; - } - scanlines.serialize(strokeCache); - marker_size = agg::rect_i(std::min(marker_size.x1, scanlines.min_x()), - std::min(marker_size.y1, scanlines.min_y()), - std::max(marker_size.x2, scanlines.max_x()), - std::max(marker_size.y2, scanlines.max_y())); - - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, rendererBase); - bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - - double x, y; - - agg::serialized_scanlines_adaptor_aa8 sa; - agg::serialized_scanlines_adaptor_aa8::embedded_scanline sl; - - agg::rect_d clipping_rect(-1.0 - marker_size.x2, - -1.0 - marker_size.y2, - 1.0 + width - marker_size.x1, - 1.0 + height - marker_size.y1); - - if (has_clippath) { - while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) { - if (!(std::isfinite(x) && std::isfinite(y))) { - continue; - } - - /* These values are correctly snapped above -- so we don't want - to round here, we really only want to truncate */ - x = floor(x); - y = floor(y); - - // Cull points outside the boundary of the image. - // Values that are too large may overflow and create - // segfaults. - // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 - if (!clipping_rect.hit_test(x, y)) { - continue; - } - - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r); - - if (face.first) { - ren.color(face.second); - sa.init(fillCache, fillSize, x, y); - agg::render_scanlines(sa, sl, ren); - } - ren.color(gc.color); - sa.init(strokeCache, strokeSize, x, y); - agg::render_scanlines(sa, sl, ren); - } - } else { - while (path_curve.vertex(&x, &y) != agg::path_cmd_stop) { - if (!(std::isfinite(x) && std::isfinite(y))) { - continue; - } - - /* These values are correctly snapped above -- so we don't want - to round here, we really only want to truncate */ - x = floor(x); - y = floor(y); - - // Cull points outside the boundary of the image. - // Values that are too large may overflow and create - // segfaults. - // http://sourceforge.net/tracker/?func=detail&aid=2865490&group_id=80706&atid=560720 - if (!clipping_rect.hit_test(x, y)) { - continue; - } - - if (face.first) { - rendererAA.color(face.second); - sa.init(fillCache, fillSize, x, y); - agg::render_scanlines(sa, sl, rendererAA); - } - - rendererAA.color(gc.color); - sa.init(strokeCache, strokeSize, x, y); - agg::render_scanlines(sa, sl, rendererAA); - } - } - } - catch (...) - { - if (fillCache != staticFillCache) - delete[] fillCache; - if (strokeCache != staticStrokeCache) - delete[] strokeCache; - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - throw; - } - - if (fillCache != staticFillCache) - delete[] fillCache; - if (strokeCache != staticStrokeCache) - delete[] strokeCache; - - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); -} - -/** - * This is a custom span generator that converts spans in the - * 8-bit inverted greyscale font buffer to rgba that agg can use. - */ -template -class font_to_rgba -{ - public: - typedef ChildGenerator child_type; - typedef agg::rgba8 color_type; - typedef typename child_type::color_type child_color_type; - typedef agg::span_allocator span_alloc_type; - - private: - child_type *_gen; - color_type _color; - span_alloc_type _allocator; - - public: - font_to_rgba(child_type *gen, color_type color) : _gen(gen), _color(color) - { - } - - inline void generate(color_type *output_span, int x, int y, unsigned len) - { - _allocator.allocate(len); - child_color_type *input_span = _allocator.span(); - _gen->generate(input_span, x, y, len); - - do { - *output_span = _color; - output_span->a = ((unsigned int)_color.a * (unsigned int)input_span->v) >> 8; - ++output_span; - ++input_span; - } while (--len); - } - - void prepare() - { - _gen->prepare(); - } -}; - -template -inline void RendererAgg::draw_text_image(GCAgg &gc, ImageArray &image, int x, int y, double angle) -{ - typedef agg::span_allocator color_span_alloc_type; - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::image_accessor_clip image_accessor_type; - typedef agg::span_image_filter_gray image_span_gen_type; - typedef font_to_rgba span_gen_type; - typedef agg::renderer_scanline_aa - renderer_type; - - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - if (angle != 0.0) { - agg::rendering_buffer srcbuf( - image.data(), (unsigned)image.dim(1), - (unsigned)image.dim(0), (unsigned)image.dim(1)); - agg::pixfmt_gray8 pixf_img(srcbuf); - - set_clipbox(gc.cliprect, theRasterizer); - - agg::trans_affine mtx; - mtx *= agg::trans_affine_translation(0, -image.dim(0)); - mtx *= agg::trans_affine_rotation(-angle * (agg::pi / 180.0)); - mtx *= agg::trans_affine_translation(x, y); - - agg::path_storage rect; - rect.move_to(0, 0); - rect.line_to(image.dim(1), 0); - rect.line_to(image.dim(1), image.dim(0)); - rect.line_to(0, image.dim(0)); - rect.line_to(0, 0); - agg::conv_transform rect2(rect, mtx); - - agg::trans_affine inv_mtx(mtx); - inv_mtx.invert(); - - agg::image_filter_lut filter; - filter.calculate(agg::image_filter_spline36()); - interpolator_type interpolator(inv_mtx); - color_span_alloc_type sa; - image_accessor_type ia(pixf_img, agg::gray8(0)); - image_span_gen_type image_span_generator(ia, interpolator, filter); - span_gen_type output_span_generator(&image_span_generator, gc.color); - renderer_type ri(rendererBase, sa, output_span_generator); - - theRasterizer.add_path(rect2); - agg::render_scanlines(theRasterizer, slineP8, ri); - } else { - agg::rect_i fig, text; - - int deltay = y - image.dim(0); - - fig.init(0, 0, width, height); - text.init(x, deltay, x + image.dim(1), y); - text.clip(fig); - - if (gc.cliprect.x1 != 0.0 || gc.cliprect.y1 != 0.0 || gc.cliprect.x2 != 0.0 || gc.cliprect.y2 != 0.0) { - agg::rect_i clip; - - clip.init(mpl_round_to_int(gc.cliprect.x1), - mpl_round_to_int(height - gc.cliprect.y2), - mpl_round_to_int(gc.cliprect.x2), - mpl_round_to_int(height - gc.cliprect.y1)); - text.clip(clip); - } - - if (text.x2 > text.x1) { - int deltax = text.x2 - text.x1; - int deltax2 = text.x1 - x; - for (int yi = text.y1; yi < text.y2; ++yi) { - pixFmt.blend_solid_hspan(text.x1, yi, deltax, gc.color, - &image(yi - deltay, deltax2)); - } - } - } -} - -class span_conv_alpha -{ - public: - typedef agg::rgba8 color_type; - - double m_alpha; - - span_conv_alpha(double alpha) : m_alpha(alpha) - { - } - - void prepare() - { - } - void generate(color_type *span, int x, int y, unsigned len) const - { - do { - span->a = (agg::int8u)((double)span->a * m_alpha); - ++span; - } while (--len); - } -}; - -template -inline void RendererAgg::draw_image(GCAgg &gc, - double x, - double y, - ImageArray &image) -{ - double alpha = gc.alpha; - - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - - agg::rendering_buffer buffer; - buffer.attach( - image.data(), (unsigned)image.dim(1), (unsigned)image.dim(0), -(int)image.dim(1) * 4); - pixfmt pixf(buffer); - - if (has_clippath) { - agg::trans_affine mtx; - agg::path_storage rect; - - mtx *= agg::trans_affine_translation((int)x, (int)(height - (y + image.dim(0)))); - - rect.move_to(0, 0); - rect.line_to(image.dim(1), 0); - rect.line_to(image.dim(1), image.dim(0)); - rect.line_to(0, image.dim(0)); - rect.line_to(0, 0); - - agg::conv_transform rect2(rect, mtx); - - agg::trans_affine inv_mtx(mtx); - inv_mtx.invert(); - - typedef agg::span_allocator color_span_alloc_type; - typedef agg::image_accessor_clip image_accessor_type; - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::span_image_filter_rgba_nn - image_span_gen_type; - typedef agg::span_converter span_conv; - - color_span_alloc_type sa; - image_accessor_type ia(pixf, agg::rgba8(0, 0, 0, 0)); - interpolator_type interpolator(inv_mtx); - image_span_gen_type image_span_generator(ia, interpolator); - span_conv_alpha conv_alpha(alpha); - span_conv spans(image_span_generator, conv_alpha); - - typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; - typedef agg::renderer_base amask_ren_type; - typedef agg::renderer_scanline_aa - renderer_type_alpha; - - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - renderer_type_alpha ri(r, sa, spans); - - theRasterizer.add_path(rect2); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ri); - } else { - set_clipbox(gc.cliprect, rendererBase); - rendererBase.blend_from( - pixf, 0, (int)x, (int)(height - (y + image.dim(0))), (agg::int8u)(alpha * 255)); - } - - rendererBase.reset_clipping(true); -} - -template -inline void RendererAgg::_draw_path_collection_generic(GCAgg &gc, - agg::trans_affine master_transform, - const agg::rect_d &cliprect, - PathIterator &clippath, - const agg::trans_affine &clippath_trans, - PathGenerator &path_generator, - TransformArray &transforms, - OffsetArray &offsets, - const agg::trans_affine &offset_trans, - ColorArray &facecolors, - ColorArray &edgecolors, - LineWidthArray &linewidths, - DashesVector &linestyles, - AntialiasedArray &antialiaseds, - bool check_snap, - bool has_codes) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removed_t; - typedef PathClipper clipped_t; - typedef PathSnapper snapped_t; - typedef agg::conv_curve snapped_curve_t; - typedef agg::conv_curve curve_t; - - size_t Npaths = path_generator.num_paths(); - size_t Noffsets = offsets.size(); - size_t N = std::max(Npaths, Noffsets); - - size_t Ntransforms = transforms.size(); - size_t Nfacecolors = facecolors.size(); - size_t Nedgecolors = edgecolors.size(); - size_t Nlinewidths = linewidths.size(); - size_t Nlinestyles = std::min(linestyles.size(), N); - size_t Naa = antialiaseds.size(); - - if ((Nfacecolors == 0 && Nedgecolors == 0) || Npaths == 0) { - return; - } - - // Handle any clipping globally - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(cliprect, theRasterizer); - bool has_clippath = render_clippath(clippath, clippath_trans, gc.snap_mode); - - // Set some defaults, assuming no face or edge - gc.linewidth = 0.0; - facepair_t face; - face.first = Nfacecolors != 0; - agg::trans_affine trans; - bool do_clip = !face.first && !gc.has_hatchpath(); - - for (int i = 0; i < (int)N; ++i) { - typename PathGenerator::path_iterator path = path_generator(i); - - if (Ntransforms) { - int it = i % Ntransforms; - trans = agg::trans_affine(transforms(it, 0, 0), - transforms(it, 1, 0), - transforms(it, 0, 1), - transforms(it, 1, 1), - transforms(it, 0, 2), - transforms(it, 1, 2)); - trans *= master_transform; - } else { - trans = master_transform; - } - - if (Noffsets) { - double xo = offsets(i % Noffsets, 0); - double yo = offsets(i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - trans *= agg::trans_affine_translation(xo, yo); - } - - // These transformations must be done post-offsets - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); - - if (Nfacecolors) { - int ic = i % Nfacecolors; - face.second = agg::rgba(facecolors(ic, 0), facecolors(ic, 1), facecolors(ic, 2), facecolors(ic, 3)); - } - - if (Nedgecolors) { - int ic = i % Nedgecolors; - gc.color = agg::rgba(edgecolors(ic, 0), edgecolors(ic, 1), edgecolors(ic, 2), edgecolors(ic, 3)); - - if (Nlinewidths) { - gc.linewidth = linewidths(i % Nlinewidths); - } else { - gc.linewidth = 1.0; - } - if (Nlinestyles) { - gc.dashes = linestyles[i % Nlinestyles]; - } - } - - if (check_snap) { - gc.isaa = antialiaseds(i % Naa); - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, has_codes); - clipped_t clipped(nan_removed, do_clip, width, height); - snapped_t snapped( - clipped, gc.snap_mode, path.total_vertices(), points_to_pixels(gc.linewidth)); - if (has_codes) { - snapped_curve_t curve(snapped); - _draw_path(curve, has_clippath, face, gc); - } else { - _draw_path(snapped, has_clippath, face, gc); - } - } else { - gc.isaa = antialiaseds(i % Naa); - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, has_codes); - clipped_t clipped(nan_removed, do_clip, width, height); - if (has_codes) { - curve_t curve(clipped); - _draw_path(curve, has_clippath, face, gc); - } else { - _draw_path(clipped, has_clippath, face, gc); - } - } - } -} - -template -inline void RendererAgg::draw_path_collection(GCAgg &gc, - agg::trans_affine &master_transform, - PathGenerator &path, - TransformArray &transforms, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - ColorArray &facecolors, - ColorArray &edgecolors, - LineWidthArray &linewidths, - DashesVector &linestyles, - AntialiasedArray &antialiaseds) -{ - _draw_path_collection_generic(gc, - master_transform, - gc.cliprect, - gc.clippath.path, - gc.clippath.trans, - path, - transforms, - offsets, - offset_trans, - facecolors, - edgecolors, - linewidths, - linestyles, - antialiaseds, - true, - true); -} - -template -class QuadMeshGenerator -{ - unsigned m_meshWidth; - unsigned m_meshHeight; - CoordinateArray m_coordinates; - - class QuadMeshPathIterator - { - unsigned m_iterator; - unsigned m_m, m_n; - const CoordinateArray *m_coordinates; - - public: - QuadMeshPathIterator(unsigned m, unsigned n, const CoordinateArray *coordinates) - : m_iterator(0), m_m(m), m_n(n), m_coordinates(coordinates) - { - } - - private: - inline unsigned vertex(unsigned idx, double *x, double *y) - { - size_t m = m_m + ((idx & 0x2) >> 1); - size_t n = m_n + (((idx + 1) & 0x2) >> 1); - *x = (*m_coordinates)(n, m, 0); - *y = (*m_coordinates)(n, m, 1); - return (idx) ? agg::path_cmd_line_to : agg::path_cmd_move_to; - } - - public: - inline unsigned vertex(double *x, double *y) - { - if (m_iterator >= total_vertices()) { - return agg::path_cmd_stop; - } - return vertex(m_iterator++, x, y); - } - - inline void rewind(unsigned path_id) - { - m_iterator = path_id; - } - - inline unsigned total_vertices() - { - return 5; - } - - inline bool should_simplify() - { - return false; - } - }; - - public: - typedef QuadMeshPathIterator path_iterator; - - inline QuadMeshGenerator(unsigned meshWidth, unsigned meshHeight, CoordinateArray &coordinates) - : m_meshWidth(meshWidth), m_meshHeight(meshHeight), m_coordinates(coordinates) - { - } - - inline size_t num_paths() const - { - return (size_t) m_meshWidth * m_meshHeight; - } - - inline path_iterator operator()(size_t i) const - { - return QuadMeshPathIterator(i % m_meshWidth, i / m_meshWidth, &m_coordinates); - } -}; - -template -inline void RendererAgg::draw_quad_mesh(GCAgg &gc, - agg::trans_affine &master_transform, - unsigned int mesh_width, - unsigned int mesh_height, - CoordinateArray &coordinates, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - ColorArray &facecolors, - bool antialiased, - ColorArray &edgecolors) -{ - QuadMeshGenerator path_generator(mesh_width, mesh_height, coordinates); - - array::empty transforms; - array::scalar linewidths(gc.linewidth); - array::scalar antialiaseds(antialiased); - DashesVector linestyles; - - _draw_path_collection_generic(gc, - master_transform, - gc.cliprect, - gc.clippath.path, - gc.clippath.trans, - path_generator, - transforms, - offsets, - offset_trans, - facecolors, - edgecolors, - linewidths, - linestyles, - antialiaseds, - true, // check_snap - false); -} - -template -inline void RendererAgg::_draw_gouraud_triangle(PointArray &points, - ColorArray &colors, - agg::trans_affine trans, - bool has_clippath) -{ - typedef agg::rgba8 color_t; - typedef agg::span_gouraud_rgba span_gen_t; - typedef agg::span_allocator span_alloc_t; - - trans *= agg::trans_affine_scaling(1.0, -1.0); - trans *= agg::trans_affine_translation(0.0, (double)height); - - double tpoints[3][2]; - - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 2; ++j) { - tpoints[i][j] = points(i, j); - } - trans.transform(&tpoints[i][0], &tpoints[i][1]); - if(std::isnan(tpoints[i][0]) || std::isnan(tpoints[i][1])) { - return; - } - } - - span_alloc_t span_alloc; - span_gen_t span_gen; - - span_gen.colors(agg::rgba(colors(0, 0), colors(0, 1), colors(0, 2), colors(0, 3)), - agg::rgba(colors(1, 0), colors(1, 1), colors(1, 2), colors(1, 3)), - agg::rgba(colors(2, 0), colors(2, 1), colors(2, 2), colors(2, 3))); - span_gen.triangle(tpoints[0][0], - tpoints[0][1], - tpoints[1][0], - tpoints[1][1], - tpoints[2][0], - tpoints[2][1], - 0.5); - - theRasterizer.add_path(span_gen); - - if (has_clippath) { - typedef agg::pixfmt_amask_adaptor pixfmt_amask_type; - typedef agg::renderer_base amask_ren_type; - typedef agg::renderer_scanline_aa - amask_aa_renderer_type; - - pixfmt_amask_type pfa(pixFmt, alphaMask); - amask_ren_type r(pfa); - amask_aa_renderer_type ren(r, span_alloc, span_gen); - agg::render_scanlines(theRasterizer, scanlineAlphaMask, ren); - } else { - agg::render_scanlines_aa(theRasterizer, slineP8, rendererBase, span_alloc, span_gen); - } -} - -template -inline void RendererAgg::draw_gouraud_triangle(GCAgg &gc, - PointArray &points, - ColorArray &colors, - agg::trans_affine &trans) -{ - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - - _draw_gouraud_triangle(points, colors, trans, has_clippath); -} - -template -inline void RendererAgg::draw_gouraud_triangles(GCAgg &gc, - PointArray &points, - ColorArray &colors, - agg::trans_affine &trans) -{ - theRasterizer.reset_clipping(); - rendererBase.reset_clipping(true); - set_clipbox(gc.cliprect, theRasterizer); - bool has_clippath = render_clippath(gc.clippath.path, gc.clippath.trans, gc.snap_mode); - - for (int i = 0; i < points.dim(0); ++i) { - typename PointArray::sub_t point = points.subarray(i); - typename ColorArray::sub_t color = colors.subarray(i); - - _draw_gouraud_triangle(point, color, trans, has_clippath); - } -} - -template -void RendererAgg::set_clipbox(const agg::rect_d &cliprect, R &rasterizer) -{ - // set the clip rectangle from the gc - - if (cliprect.x1 != 0.0 || cliprect.y1 != 0.0 || cliprect.x2 != 0.0 || cliprect.y2 != 0.0) { - rasterizer.clip_box(std::max(int(floor(cliprect.x1 + 0.5)), 0), - std::max(int(floor(height - cliprect.y1 + 0.5)), 0), - std::min(int(floor(cliprect.x2 + 0.5)), int(width)), - std::min(int(floor(height - cliprect.y2 + 0.5)), int(height))); - } else { - rasterizer.clip_box(0, 0, width, height); - } -} - -#endif diff --git a/contrib/python/matplotlib/py3/src/_backend_agg_basic_types.h b/contrib/python/matplotlib/py3/src/_backend_agg_basic_types.h deleted file mode 100644 index 21a84bb6a5a..00000000000 --- a/contrib/python/matplotlib/py3/src/_backend_agg_basic_types.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef MPL_BACKEND_AGG_BASIC_TYPES_H -#define MPL_BACKEND_AGG_BASIC_TYPES_H - -/* Contains some simple types from the Agg backend that are also used - by other modules */ - -#include - -#include "agg_color_rgba.h" -#include "agg_math_stroke.h" -#include "path_converters.h" - -#include "py_adaptors.h" - -struct ClipPath -{ - py::PathIterator path; - agg::trans_affine trans; -}; - -struct SketchParams -{ - double scale; - double length; - double randomness; -}; - -class Dashes -{ - typedef std::vector > dash_t; - double dash_offset; - dash_t dashes; - - public: - double get_dash_offset() const - { - return dash_offset; - } - void set_dash_offset(double x) - { - dash_offset = x; - } - void add_dash_pair(double length, double skip) - { - dashes.push_back(std::make_pair(length, skip)); - } - size_t size() const - { - return dashes.size(); - } - - template - void dash_to_stroke(T &stroke, double dpi, bool isaa) - { - double scaleddpi = dpi / 72.0; - for (dash_t::const_iterator i = dashes.begin(); i != dashes.end(); ++i) { - double val0 = i->first; - double val1 = i->second; - val0 = val0 * scaleddpi; - val1 = val1 * scaleddpi; - if (!isaa) { - val0 = (int)val0 + 0.5; - val1 = (int)val1 + 0.5; - } - stroke.add_dash(val0, val1); - } - stroke.dash_start(get_dash_offset() * scaleddpi); - } -}; - -typedef std::vector DashesVector; - -class GCAgg -{ - public: - GCAgg() - : linewidth(1.0), - alpha(1.0), - cap(agg::butt_cap), - join(agg::round_join), - snap_mode(SNAP_FALSE) - { - } - - ~GCAgg() - { - } - - double linewidth; - double alpha; - bool forced_alpha; - agg::rgba color; - bool isaa; - - agg::line_cap_e cap; - agg::line_join_e join; - - agg::rect_d cliprect; - - ClipPath clippath; - - Dashes dashes; - - e_snap_mode snap_mode; - - py::PathIterator hatchpath; - agg::rgba hatch_color; - double hatch_linewidth; - - SketchParams sketch; - - bool has_hatchpath() - { - return hatchpath.total_vertices() != 0; - } - - private: - // prevent copying - GCAgg(const GCAgg &); - GCAgg &operator=(const GCAgg &); -}; - -#endif diff --git a/contrib/python/matplotlib/py3/src/_backend_agg_wrapper.cpp b/contrib/python/matplotlib/py3/src/_backend_agg_wrapper.cpp deleted file mode 100644 index ee69729be7e..00000000000 --- a/contrib/python/matplotlib/py3/src/_backend_agg_wrapper.cpp +++ /dev/null @@ -1,646 +0,0 @@ -#include "mplutils.h" -#include "numpy_cpp.h" -#include "py_converters.h" -#include "_backend_agg.h" - -typedef struct -{ - PyObject_HEAD - RendererAgg *x; - Py_ssize_t shape[3]; - Py_ssize_t strides[3]; - Py_ssize_t suboffsets[3]; -} PyRendererAgg; - -static PyTypeObject PyRendererAggType; - -typedef struct -{ - PyObject_HEAD - BufferRegion *x; - Py_ssize_t shape[3]; - Py_ssize_t strides[3]; - Py_ssize_t suboffsets[3]; -} PyBufferRegion; - -static PyTypeObject PyBufferRegionType; - - -/********************************************************************** - * BufferRegion - * */ - -static PyObject *PyBufferRegion_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyBufferRegion *self; - self = (PyBufferRegion *)type->tp_alloc(type, 0); - self->x = NULL; - return (PyObject *)self; -} - -static void PyBufferRegion_dealloc(PyBufferRegion *self) -{ - delete self->x; - Py_TYPE(self)->tp_free((PyObject *)self); -} - -static PyObject *PyBufferRegion_to_string(PyBufferRegion *self, PyObject *args) -{ - char const* msg = - "BufferRegion.to_string is deprecated since Matplotlib 3.7 and will " - "be removed two minor releases later; use np.asarray(region) instead."; - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1)) { - return NULL; - } - return PyBytes_FromStringAndSize((const char *)self->x->get_data(), - (Py_ssize_t) self->x->get_height() * self->x->get_stride()); -} - -/* TODO: This doesn't seem to be used internally. Remove? */ - -static PyObject *PyBufferRegion_set_x(PyBufferRegion *self, PyObject *args) -{ - int x; - if (!PyArg_ParseTuple(args, "i:set_x", &x)) { - return NULL; - } - self->x->get_rect().x1 = x; - - Py_RETURN_NONE; -} - -static PyObject *PyBufferRegion_set_y(PyBufferRegion *self, PyObject *args) -{ - int y; - if (!PyArg_ParseTuple(args, "i:set_y", &y)) { - return NULL; - } - self->x->get_rect().y1 = y; - - Py_RETURN_NONE; -} - -static PyObject *PyBufferRegion_get_extents(PyBufferRegion *self, PyObject *args) -{ - agg::rect_i rect = self->x->get_rect(); - - return Py_BuildValue("IIII", rect.x1, rect.y1, rect.x2, rect.y2); -} - -static PyObject *PyBufferRegion_to_string_argb(PyBufferRegion *self, PyObject *args) -{ - char const* msg = - "BufferRegion.to_string_argb is deprecated since Matplotlib 3.7 and " - "will be removed two minor releases later; use " - "np.take(region, [2, 1, 0, 3], axis=2) instead."; - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1)) { - return NULL; - } - PyObject *bufobj; - uint8_t *buf; - Py_ssize_t height, stride; - height = self->x->get_height(); - stride = self->x->get_stride(); - bufobj = PyBytes_FromStringAndSize(NULL, height * stride); - buf = (uint8_t *)PyBytes_AS_STRING(bufobj); - - CALL_CPP_CLEANUP("to_string_argb", (self->x->to_string_argb(buf)), Py_DECREF(bufobj)); - - return bufobj; -} - -int PyBufferRegion_get_buffer(PyBufferRegion *self, Py_buffer *buf, int flags) -{ - Py_INCREF(self); - buf->obj = (PyObject *)self; - buf->buf = self->x->get_data(); - buf->len = (Py_ssize_t)self->x->get_width() * (Py_ssize_t)self->x->get_height() * 4; - buf->readonly = 0; - buf->format = (char *)"B"; - buf->ndim = 3; - self->shape[0] = self->x->get_height(); - self->shape[1] = self->x->get_width(); - self->shape[2] = 4; - buf->shape = self->shape; - self->strides[0] = self->x->get_width() * 4; - self->strides[1] = 4; - self->strides[2] = 1; - buf->strides = self->strides; - buf->suboffsets = NULL; - buf->itemsize = 1; - buf->internal = NULL; - - return 1; -} - -static PyTypeObject *PyBufferRegion_init_type() -{ - static PyMethodDef methods[] = { - { "to_string", (PyCFunction)PyBufferRegion_to_string, METH_NOARGS, NULL }, - { "to_string_argb", (PyCFunction)PyBufferRegion_to_string_argb, METH_NOARGS, NULL }, - { "set_x", (PyCFunction)PyBufferRegion_set_x, METH_VARARGS, NULL }, - { "set_y", (PyCFunction)PyBufferRegion_set_y, METH_VARARGS, NULL }, - { "get_extents", (PyCFunction)PyBufferRegion_get_extents, METH_NOARGS, NULL }, - { NULL } - }; - - static PyBufferProcs buffer_procs; - buffer_procs.bf_getbuffer = (getbufferproc)PyBufferRegion_get_buffer; - - PyBufferRegionType.tp_name = "matplotlib.backends._backend_agg.BufferRegion"; - PyBufferRegionType.tp_basicsize = sizeof(PyBufferRegion); - PyBufferRegionType.tp_dealloc = (destructor)PyBufferRegion_dealloc; - PyBufferRegionType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; - PyBufferRegionType.tp_methods = methods; - PyBufferRegionType.tp_new = PyBufferRegion_new; - PyBufferRegionType.tp_as_buffer = &buffer_procs; - - return &PyBufferRegionType; -} - -/********************************************************************** - * RendererAgg - * */ - -static PyObject *PyRendererAgg_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyRendererAgg *self; - self = (PyRendererAgg *)type->tp_alloc(type, 0); - self->x = NULL; - return (PyObject *)self; -} - -static int PyRendererAgg_init(PyRendererAgg *self, PyObject *args, PyObject *kwds) -{ - unsigned int width; - unsigned int height; - double dpi; - int debug = 0; - - if (!PyArg_ParseTuple(args, "IId|i:RendererAgg", &width, &height, &dpi, &debug)) { - return -1; - } - - if (dpi <= 0.0) { - PyErr_SetString(PyExc_ValueError, "dpi must be positive"); - return -1; - } - - if (width >= 1 << 16 || height >= 1 << 16) { - PyErr_Format( - PyExc_ValueError, - "Image size of %dx%d pixels is too large. " - "It must be less than 2^16 in each direction.", - width, height); - return -1; - } - - CALL_CPP_INIT("RendererAgg", self->x = new RendererAgg(width, height, dpi)) - - return 0; -} - -static void PyRendererAgg_dealloc(PyRendererAgg *self) -{ - delete self->x; - Py_TYPE(self)->tp_free((PyObject *)self); -} - -static PyObject *PyRendererAgg_draw_path(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - py::PathIterator path; - agg::trans_affine trans; - PyObject *faceobj = NULL; - agg::rgba face; - - if (!PyArg_ParseTuple(args, - "O&O&O&|O:draw_path", - &convert_gcagg, - &gc, - &convert_path, - &path, - &convert_trans_affine, - &trans, - &faceobj)) { - return NULL; - } - - if (!convert_face(faceobj, gc, &face)) { - return NULL; - } - - CALL_CPP("draw_path", (self->x->draw_path(gc, path, trans, face))); - - Py_RETURN_NONE; -} - -static PyObject *PyRendererAgg_draw_text_image(PyRendererAgg *self, PyObject *args) -{ - numpy::array_view image; - double x; - double y; - double angle; - GCAgg gc; - - if (!PyArg_ParseTuple(args, - "O&dddO&:draw_text_image", - &image.converter_contiguous, - &image, - &x, - &y, - &angle, - &convert_gcagg, - &gc)) { - return NULL; - } - - CALL_CPP("draw_text_image", (self->x->draw_text_image(gc, image, x, y, angle))); - - Py_RETURN_NONE; -} - -PyObject *PyRendererAgg_draw_markers(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - py::PathIterator marker_path; - agg::trans_affine marker_path_trans; - py::PathIterator path; - agg::trans_affine trans; - PyObject *faceobj = NULL; - agg::rgba face; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&O&|O:draw_markers", - &convert_gcagg, - &gc, - &convert_path, - &marker_path, - &convert_trans_affine, - &marker_path_trans, - &convert_path, - &path, - &convert_trans_affine, - &trans, - &faceobj)) { - return NULL; - } - - if (!convert_face(faceobj, gc, &face)) { - return NULL; - } - - CALL_CPP("draw_markers", - (self->x->draw_markers(gc, marker_path, marker_path_trans, path, trans, face))); - - Py_RETURN_NONE; -} - -static PyObject *PyRendererAgg_draw_image(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - double x; - double y; - numpy::array_view image; - - if (!PyArg_ParseTuple(args, - "O&ddO&:draw_image", - &convert_gcagg, - &gc, - &x, - &y, - &image.converter_contiguous, - &image)) { - return NULL; - } - - x = mpl_round(x); - y = mpl_round(y); - - gc.alpha = 1.0; - CALL_CPP("draw_image", (self->x->draw_image(gc, x, y, image))); - - Py_RETURN_NONE; -} - -static PyObject * -PyRendererAgg_draw_path_collection(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - agg::trans_affine master_transform; - py::PathGenerator paths; - numpy::array_view transforms; - numpy::array_view offsets; - agg::trans_affine offset_trans; - numpy::array_view facecolors; - numpy::array_view edgecolors; - numpy::array_view linewidths; - DashesVector dashes; - numpy::array_view antialiaseds; - PyObject *ignored; - PyObject *offset_position; // offset position is no longer used - - if (!PyArg_ParseTuple(args, - "O&O&O&O&O&O&O&O&O&O&O&OO:draw_path_collection", - &convert_gcagg, - &gc, - &convert_trans_affine, - &master_transform, - &convert_pathgen, - &paths, - &convert_transforms, - &transforms, - &convert_points, - &offsets, - &convert_trans_affine, - &offset_trans, - &convert_colors, - &facecolors, - &convert_colors, - &edgecolors, - &linewidths.converter, - &linewidths, - &convert_dashes_vector, - &dashes, - &antialiaseds.converter, - &antialiaseds, - &ignored, - &offset_position)) { - return NULL; - } - - CALL_CPP("draw_path_collection", - (self->x->draw_path_collection(gc, - master_transform, - paths, - transforms, - offsets, - offset_trans, - facecolors, - edgecolors, - linewidths, - dashes, - antialiaseds))); - - Py_RETURN_NONE; -} - -static PyObject *PyRendererAgg_draw_quad_mesh(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - agg::trans_affine master_transform; - unsigned int mesh_width; - unsigned int mesh_height; - numpy::array_view coordinates; - numpy::array_view offsets; - agg::trans_affine offset_trans; - numpy::array_view facecolors; - bool antialiased; - numpy::array_view edgecolors; - - if (!PyArg_ParseTuple(args, - "O&O&IIO&O&O&O&O&O&:draw_quad_mesh", - &convert_gcagg, - &gc, - &convert_trans_affine, - &master_transform, - &mesh_width, - &mesh_height, - &coordinates.converter, - &coordinates, - &convert_points, - &offsets, - &convert_trans_affine, - &offset_trans, - &convert_colors, - &facecolors, - &convert_bool, - &antialiased, - &convert_colors, - &edgecolors)) { - return NULL; - } - - CALL_CPP("draw_quad_mesh", - (self->x->draw_quad_mesh(gc, - master_transform, - mesh_width, - mesh_height, - coordinates, - offsets, - offset_trans, - facecolors, - antialiased, - edgecolors))); - - Py_RETURN_NONE; -} - -static PyObject * -PyRendererAgg_draw_gouraud_triangle(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - numpy::array_view points; - numpy::array_view colors; - agg::trans_affine trans; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&|O:draw_gouraud_triangle", - &convert_gcagg, - &gc, - &points.converter, - &points, - &colors.converter, - &colors, - &convert_trans_affine, - &trans)) { - return NULL; - } - - if (points.dim(0) != 3 || points.dim(1) != 2) { - PyErr_Format(PyExc_ValueError, - "points must have shape (3, 2), " - "got (%" NPY_INTP_FMT ", %" NPY_INTP_FMT ")", - points.dim(0), points.dim(1)); - return NULL; - } - - if (colors.dim(0) != 3 || colors.dim(1) != 4) { - PyErr_Format(PyExc_ValueError, - "colors must have shape (3, 4), " - "got (%" NPY_INTP_FMT ", %" NPY_INTP_FMT ")", - colors.dim(0), colors.dim(1)); - return NULL; - } - - - CALL_CPP("draw_gouraud_triangle", (self->x->draw_gouraud_triangle(gc, points, colors, trans))); - - Py_RETURN_NONE; -} - -static PyObject * -PyRendererAgg_draw_gouraud_triangles(PyRendererAgg *self, PyObject *args) -{ - GCAgg gc; - numpy::array_view points; - numpy::array_view colors; - agg::trans_affine trans; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&|O:draw_gouraud_triangles", - &convert_gcagg, - &gc, - &points.converter, - &points, - &colors.converter, - &colors, - &convert_trans_affine, - &trans)) { - return NULL; - } - if (points.size() && !check_trailing_shape(points, "points", 3, 2)) { - return NULL; - } - if (colors.size() && !check_trailing_shape(colors, "colors", 3, 4)) { - return NULL; - } - if (points.size() != colors.size()) { - PyErr_Format(PyExc_ValueError, - "points and colors arrays must be the same length, got " - "%" NPY_INTP_FMT " points and %" NPY_INTP_FMT "colors", - points.dim(0), colors.dim(0)); - return NULL; - } - - CALL_CPP("draw_gouraud_triangles", self->x->draw_gouraud_triangles(gc, points, colors, trans)); - - Py_RETURN_NONE; -} - -int PyRendererAgg_get_buffer(PyRendererAgg *self, Py_buffer *buf, int flags) -{ - Py_INCREF(self); - buf->obj = (PyObject *)self; - buf->buf = self->x->pixBuffer; - buf->len = (Py_ssize_t)self->x->get_width() * (Py_ssize_t)self->x->get_height() * 4; - buf->readonly = 0; - buf->format = (char *)"B"; - buf->ndim = 3; - self->shape[0] = self->x->get_height(); - self->shape[1] = self->x->get_width(); - self->shape[2] = 4; - buf->shape = self->shape; - self->strides[0] = self->x->get_width() * 4; - self->strides[1] = 4; - self->strides[2] = 1; - buf->strides = self->strides; - buf->suboffsets = NULL; - buf->itemsize = 1; - buf->internal = NULL; - - return 1; -} - -static PyObject *PyRendererAgg_clear(PyRendererAgg *self, PyObject *args) -{ - CALL_CPP("clear", self->x->clear()); - - Py_RETURN_NONE; -} - -static PyObject *PyRendererAgg_copy_from_bbox(PyRendererAgg *self, PyObject *args) -{ - agg::rect_d bbox; - BufferRegion *reg; - PyObject *regobj; - - if (!PyArg_ParseTuple(args, "O&:copy_from_bbox", &convert_rect, &bbox)) { - return 0; - } - - CALL_CPP("copy_from_bbox", (reg = self->x->copy_from_bbox(bbox))); - - regobj = PyBufferRegion_new(&PyBufferRegionType, NULL, NULL); - ((PyBufferRegion *)regobj)->x = reg; - - return regobj; -} - -static PyObject *PyRendererAgg_restore_region(PyRendererAgg *self, PyObject *args) -{ - PyBufferRegion *regobj; - int xx1 = 0, yy1 = 0, xx2 = 0, yy2 = 0, x = 0, y = 0; - - if (!PyArg_ParseTuple(args, - "O!|iiiiii:restore_region", - &PyBufferRegionType, - ®obj, - &xx1, - &yy1, - &xx2, - &yy2, - &x, - &y)) { - return 0; - } - - if (PySequence_Size(args) == 1) { - CALL_CPP("restore_region", self->x->restore_region(*(regobj->x))); - } else { - CALL_CPP("restore_region", self->x->restore_region(*(regobj->x), xx1, yy1, xx2, yy2, x, y)); - } - - Py_RETURN_NONE; -} - -static PyTypeObject *PyRendererAgg_init_type() -{ - static PyMethodDef methods[] = { - {"draw_path", (PyCFunction)PyRendererAgg_draw_path, METH_VARARGS, NULL}, - {"draw_markers", (PyCFunction)PyRendererAgg_draw_markers, METH_VARARGS, NULL}, - {"draw_text_image", (PyCFunction)PyRendererAgg_draw_text_image, METH_VARARGS, NULL}, - {"draw_image", (PyCFunction)PyRendererAgg_draw_image, METH_VARARGS, NULL}, - {"draw_path_collection", (PyCFunction)PyRendererAgg_draw_path_collection, METH_VARARGS, NULL}, - {"draw_quad_mesh", (PyCFunction)PyRendererAgg_draw_quad_mesh, METH_VARARGS, NULL}, - {"draw_gouraud_triangle", (PyCFunction)PyRendererAgg_draw_gouraud_triangle, METH_VARARGS, NULL}, - {"draw_gouraud_triangles", (PyCFunction)PyRendererAgg_draw_gouraud_triangles, METH_VARARGS, NULL}, - - {"clear", (PyCFunction)PyRendererAgg_clear, METH_NOARGS, NULL}, - - {"copy_from_bbox", (PyCFunction)PyRendererAgg_copy_from_bbox, METH_VARARGS, NULL}, - {"restore_region", (PyCFunction)PyRendererAgg_restore_region, METH_VARARGS, NULL}, - {NULL} - }; - - static PyBufferProcs buffer_procs; - buffer_procs.bf_getbuffer = (getbufferproc)PyRendererAgg_get_buffer; - - PyRendererAggType.tp_name = "matplotlib.backends._backend_agg.RendererAgg"; - PyRendererAggType.tp_basicsize = sizeof(PyRendererAgg); - PyRendererAggType.tp_dealloc = (destructor)PyRendererAgg_dealloc; - PyRendererAggType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; - PyRendererAggType.tp_methods = methods; - PyRendererAggType.tp_init = (initproc)PyRendererAgg_init; - PyRendererAggType.tp_new = PyRendererAgg_new; - PyRendererAggType.tp_as_buffer = &buffer_procs; - - return &PyRendererAggType; -} - -static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_backend_agg" }; - -PyMODINIT_FUNC PyInit__backend_agg(void) -{ - import_array(); - PyObject *m; - if (!(m = PyModule_Create(&moduledef)) - || prepare_and_add_type(PyRendererAgg_init_type(), m) - // BufferRegion is not constructible from Python, thus not added to the module. - || PyType_Ready(PyBufferRegion_init_type()) - ) { - Py_XDECREF(m); - return NULL; - } - return m; -} diff --git a/contrib/python/matplotlib/py3/src/_c_internal_utils.c b/contrib/python/matplotlib/py3/src/_c_internal_utils.c deleted file mode 100644 index f1bd22a42c5..00000000000 --- a/contrib/python/matplotlib/py3/src/_c_internal_utils.c +++ /dev/null @@ -1,211 +0,0 @@ -#define PY_SSIZE_T_CLEAN -#include -#ifdef __linux__ -#include -#endif -#ifdef _WIN32 -#include -#include -#include -#endif - -static PyObject* -mpl_display_is_valid(PyObject* module) -{ -#ifdef __linux__ - void* libX11; - // The getenv check is redundant but helps performance as it is much faster - // than dlopen(). - if (getenv("DISPLAY") - && (libX11 = dlopen("libX11.so.6", RTLD_LAZY))) { - struct Display* display = NULL; - struct Display* (* XOpenDisplay)(char const*) = - dlsym(libX11, "XOpenDisplay"); - int (* XCloseDisplay)(struct Display*) = - dlsym(libX11, "XCloseDisplay"); - if (XOpenDisplay && XCloseDisplay - && (display = XOpenDisplay(NULL))) { - XCloseDisplay(display); - } - if (dlclose(libX11)) { - PyErr_SetString(PyExc_RuntimeError, dlerror()); - return NULL; - } - if (display) { - Py_RETURN_TRUE; - } - } - void* libwayland_client; - if (getenv("WAYLAND_DISPLAY") - && (libwayland_client = dlopen("libwayland-client.so.0", RTLD_LAZY))) { - struct wl_display* display = NULL; - struct wl_display* (* wl_display_connect)(char const*) = - dlsym(libwayland_client, "wl_display_connect"); - void (* wl_display_disconnect)(struct wl_display*) = - dlsym(libwayland_client, "wl_display_disconnect"); - if (wl_display_connect && wl_display_disconnect - && (display = wl_display_connect(NULL))) { - wl_display_disconnect(display); - } - if (dlclose(libwayland_client)) { - PyErr_SetString(PyExc_RuntimeError, dlerror()); - return NULL; - } - if (display) { - Py_RETURN_TRUE; - } - } - Py_RETURN_FALSE; -#else - Py_RETURN_TRUE; -#endif -} - -static PyObject* -mpl_GetCurrentProcessExplicitAppUserModelID(PyObject* module) -{ -#ifdef _WIN32 - wchar_t* appid = NULL; - HRESULT hr = GetCurrentProcessExplicitAppUserModelID(&appid); - if (FAILED(hr)) { - return PyErr_SetFromWindowsErr(hr); - } - PyObject* py_appid = PyUnicode_FromWideChar(appid, -1); - CoTaskMemFree(appid); - return py_appid; -#else - Py_RETURN_NONE; -#endif -} - -static PyObject* -mpl_SetCurrentProcessExplicitAppUserModelID(PyObject* module, PyObject* arg) -{ -#ifdef _WIN32 - wchar_t* appid = PyUnicode_AsWideCharString(arg, NULL); - if (!appid) { - return NULL; - } - HRESULT hr = SetCurrentProcessExplicitAppUserModelID(appid); - PyMem_Free(appid); - if (FAILED(hr)) { - return PyErr_SetFromWindowsErr(hr); - } - Py_RETURN_NONE; -#else - Py_RETURN_NONE; -#endif -} - -static PyObject* -mpl_GetForegroundWindow(PyObject* module) -{ -#ifdef _WIN32 - return PyLong_FromVoidPtr(GetForegroundWindow()); -#else - Py_RETURN_NONE; -#endif -} - -static PyObject* -mpl_SetForegroundWindow(PyObject* module, PyObject *arg) -{ -#ifdef _WIN32 - HWND handle = PyLong_AsVoidPtr(arg); - if (PyErr_Occurred()) { - return NULL; - } - if (!SetForegroundWindow(handle)) { - return PyErr_Format(PyExc_RuntimeError, "Error setting window"); - } - Py_RETURN_NONE; -#else - Py_RETURN_NONE; -#endif -} - -static PyObject* -mpl_SetProcessDpiAwareness_max(PyObject* module) -{ -#ifdef _WIN32 -#ifdef _DPI_AWARENESS_CONTEXTS_ - // These functions and options were added in later Windows 10 updates, so - // must be loaded dynamically. - typedef BOOL (WINAPI *IsValidDpiAwarenessContext_t)(DPI_AWARENESS_CONTEXT); - typedef BOOL (WINAPI *SetProcessDpiAwarenessContext_t)(DPI_AWARENESS_CONTEXT); - - HMODULE user32 = LoadLibrary("user32.dll"); - IsValidDpiAwarenessContext_t IsValidDpiAwarenessContextPtr = - (IsValidDpiAwarenessContext_t)GetProcAddress( - user32, "IsValidDpiAwarenessContext"); - SetProcessDpiAwarenessContext_t SetProcessDpiAwarenessContextPtr = - (SetProcessDpiAwarenessContext_t)GetProcAddress( - user32, "SetProcessDpiAwarenessContext"); - DPI_AWARENESS_CONTEXT ctxs[3] = { - DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, // Win10 Creators Update - DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE, // Win10 - DPI_AWARENESS_CONTEXT_SYSTEM_AWARE}; // Win10 - if (IsValidDpiAwarenessContextPtr != NULL - && SetProcessDpiAwarenessContextPtr != NULL) { - for (int i = 0; i < sizeof(ctxs) / sizeof(DPI_AWARENESS_CONTEXT); ++i) { - if (IsValidDpiAwarenessContextPtr(ctxs[i])) { - SetProcessDpiAwarenessContextPtr(ctxs[i]); - break; - } - } - } else { - // Added in Windows Vista. - SetProcessDPIAware(); - } - FreeLibrary(user32); -#else - // Added in Windows Vista. - SetProcessDPIAware(); -#endif -#endif - Py_RETURN_NONE; -} - -static PyMethodDef functions[] = { - {"display_is_valid", (PyCFunction)mpl_display_is_valid, METH_NOARGS, - "display_is_valid()\n--\n\n" - "Check whether the current X11 or Wayland display is valid.\n\n" - "On Linux, returns True if either $DISPLAY is set and XOpenDisplay(NULL)\n" - "succeeds, or $WAYLAND_DISPLAY is set and wl_display_connect(NULL)\n" - "succeeds.\n\n" - "On other platforms, always returns True."}, - {"Win32_GetCurrentProcessExplicitAppUserModelID", - (PyCFunction)mpl_GetCurrentProcessExplicitAppUserModelID, METH_NOARGS, - "Win32_GetCurrentProcessExplicitAppUserModelID()\n--\n\n" - "Wrapper for Windows's GetCurrentProcessExplicitAppUserModelID.\n\n" - "On non-Windows platforms, always returns None."}, - {"Win32_SetCurrentProcessExplicitAppUserModelID", - (PyCFunction)mpl_SetCurrentProcessExplicitAppUserModelID, METH_O, - "Win32_SetCurrentProcessExplicitAppUserModelID(appid, /)\n--\n\n" - "Wrapper for Windows's SetCurrentProcessExplicitAppUserModelID.\n\n" - "On non-Windows platforms, does nothing."}, - {"Win32_GetForegroundWindow", - (PyCFunction)mpl_GetForegroundWindow, METH_NOARGS, - "Win32_GetForegroundWindow()\n--\n\n" - "Wrapper for Windows' GetForegroundWindow.\n\n" - "On non-Windows platforms, always returns None."}, - {"Win32_SetForegroundWindow", - (PyCFunction)mpl_SetForegroundWindow, METH_O, - "Win32_SetForegroundWindow(hwnd, /)\n--\n\n" - "Wrapper for Windows' SetForegroundWindow.\n\n" - "On non-Windows platforms, does nothing."}, - {"Win32_SetProcessDpiAwareness_max", - (PyCFunction)mpl_SetProcessDpiAwareness_max, METH_NOARGS, - "Win32_SetProcessDpiAwareness_max()\n--\n\n" - "Set Windows' process DPI awareness to best option available.\n\n" - "On non-Windows platforms, does nothing."}, - {NULL, NULL}}; // sentinel. -static PyModuleDef util_module = { - PyModuleDef_HEAD_INIT, "_c_internal_utils", NULL, 0, functions -}; - -#pragma GCC visibility push(default) -PyMODINIT_FUNC PyInit__c_internal_utils(void) -{ - return PyModule_Create(&util_module); -} diff --git a/contrib/python/matplotlib/py3/src/_image_resample.h b/contrib/python/matplotlib/py3/src/_image_resample.h deleted file mode 100644 index 2c91da40873..00000000000 --- a/contrib/python/matplotlib/py3/src/_image_resample.h +++ /dev/null @@ -1,834 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -#ifndef MPL_RESAMPLE_H -#define MPL_RESAMPLE_H - -#include "agg_image_accessors.h" -#include "agg_path_storage.h" -#include "agg_pixfmt_gray.h" -#include "agg_pixfmt_rgb.h" -#include "agg_pixfmt_rgba.h" -#include "agg_renderer_base.h" -#include "agg_renderer_scanline.h" -#include "agg_rasterizer_scanline_aa.h" -#include "agg_scanline_u.h" -#include "agg_span_allocator.h" -#include "agg_span_converter.h" -#include "agg_span_image_filter_gray.h" -#include "agg_span_image_filter_rgba.h" -#include "agg_span_interpolator_adaptor.h" -#include "agg_span_interpolator_linear.h" - -#include "agg_workaround.h" - -#include - -// Based on: - -//---------------------------------------------------------------------------- -// Anti-Grain Geometry - Version 2.4 -// Copyright (C) 2002-2005 Maxim Shemanarev (http://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://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. -// - -//===================================================================gray64 -namespace agg -{ - struct gray64 - { - typedef double value_type; - typedef double calc_type; - typedef double long_type; - typedef gray64 self_type; - - value_type v; - value_type a; - - //-------------------------------------------------------------------- - gray64() {} - - //-------------------------------------------------------------------- - explicit gray64(value_type v_, value_type a_ = 1) : - v(v_), a(a_) {} - - //-------------------------------------------------------------------- - gray64(const self_type& c, value_type a_) : - v(c.v), a(a_) {} - - //-------------------------------------------------------------------- - gray64(const gray64& c) : - v(c.v), - a(c.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); } - }; - - - //====================================================================rgba32 - struct rgba64 - { - typedef double value_type; - typedef double calc_type; - typedef double long_type; - typedef rgba64 self_type; - - value_type r; - value_type g; - value_type b; - value_type a; - - //-------------------------------------------------------------------- - rgba64() {} - - //-------------------------------------------------------------------- - rgba64(value_type r_, value_type g_, value_type b_, value_type a_= 1) : - r(r_), g(g_), b(b_), a(a_) {} - - //-------------------------------------------------------------------- - rgba64(const self_type& c, float a_) : - r(c.r), g(c.g), b(c.b), a(a_) {} - - //-------------------------------------------------------------------- - rgba64(const rgba& c) : - r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {} - - //-------------------------------------------------------------------- - operator rgba() const - { - return rgba(r, g, b, 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() - { - 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; - } - - //-------------------------------------------------------------------- - static self_type no_color() { return self_type(0,0,0,0); } - }; -} - - -typedef enum { - NEAREST, - BILINEAR, - BICUBIC, - SPLINE16, - SPLINE36, - HANNING, - HAMMING, - HERMITE, - KAISER, - QUADRIC, - CATROM, - GAUSSIAN, - BESSEL, - MITCHELL, - SINC, - LANCZOS, - BLACKMAN, - _n_interpolation -} interpolation_e; - - -// T is rgba if and only if it has an T::r field. -template struct is_grayscale : std::true_type {}; -template struct is_grayscale : std::false_type {}; - - -template -struct type_mapping -{ - using blender_type = typename std::conditional< - is_grayscale::value, - agg::blender_gray, - typename std::conditional< - std::is_same::value, - fixed_blender_rgba_plain, - agg::blender_rgba_plain - >::type - >::type; - using pixfmt_type = typename std::conditional< - is_grayscale::value, - agg::pixfmt_alpha_blend_gray, - agg::pixfmt_alpha_blend_rgba - >::type; - using pixfmt_pre_type = typename std::conditional< - is_grayscale::value, - pixfmt_type, - agg::pixfmt_alpha_blend_rgba< - typename std::conditional< - std::is_same::value, - fixed_blender_rgba_pre, - agg::blender_rgba_pre - >::type, - agg::rendering_buffer> - >::type; - template using span_gen_affine_type = typename std::conditional< - is_grayscale::value, - agg::span_image_resample_gray_affine, - agg::span_image_resample_rgba_affine - >::type; - template using span_gen_filter_type = typename std::conditional< - is_grayscale::value, - agg::span_image_filter_gray, - agg::span_image_filter_rgba - >::type; - template using span_gen_nn_type = typename std::conditional< - is_grayscale::value, - agg::span_image_filter_gray_nn, - agg::span_image_filter_rgba_nn - >::type; -}; - - -template -class span_conv_alpha -{ -public: - span_conv_alpha(const double alpha) : - m_alpha(alpha) - { - } - - void prepare() {} - - void generate(color_type* span, int x, int y, unsigned len) const - { - if (m_alpha != 1.0) { - do { - span->a *= m_alpha; - ++span; - } while (--len); - } - } -private: - - const double m_alpha; -}; - - -/* A class to use a lookup table for a transformation */ -class lookup_distortion -{ -public: - lookup_distortion(const double *mesh, int in_width, int in_height, - int out_width, int out_height) : - m_mesh(mesh), - m_in_width(in_width), - m_in_height(in_height), - m_out_width(out_width), - m_out_height(out_height) - {} - - void calculate(int* x, int* y) { - if (m_mesh) { - double dx = double(*x) / agg::image_subpixel_scale; - double dy = double(*y) / agg::image_subpixel_scale; - if (dx >= 0 && dx < m_out_width && - dy >= 0 && dy < m_out_height) { - const double *coord = m_mesh + (int(dy) * m_out_width + int(dx)) * 2; - *x = int(coord[0] * agg::image_subpixel_scale); - *y = int(coord[1] * agg::image_subpixel_scale); - } - } - } - -protected: - const double *m_mesh; - int m_in_width; - int m_in_height; - int m_out_width; - int m_out_height; -}; - - -struct resample_params_t { - interpolation_e interpolation; - bool is_affine; - agg::trans_affine affine; - const double *transform_mesh; - bool resample; - bool norm; - double radius; - double alpha; -}; - - -static void get_filter(const resample_params_t ¶ms, - agg::image_filter_lut &filter) -{ - switch (params.interpolation) { - case NEAREST: - case _n_interpolation: - // Never should get here. Here to silence compiler warnings. - break; - - case HANNING: - filter.calculate(agg::image_filter_hanning(), params.norm); - break; - - case HAMMING: - filter.calculate(agg::image_filter_hamming(), params.norm); - break; - - case HERMITE: - filter.calculate(agg::image_filter_hermite(), params.norm); - break; - - case BILINEAR: - filter.calculate(agg::image_filter_bilinear(), params.norm); - break; - - case BICUBIC: - filter.calculate(agg::image_filter_bicubic(), params.norm); - break; - - case SPLINE16: - filter.calculate(agg::image_filter_spline16(), params.norm); - break; - - case SPLINE36: - filter.calculate(agg::image_filter_spline36(), params.norm); - break; - - case KAISER: - filter.calculate(agg::image_filter_kaiser(), params.norm); - break; - - case QUADRIC: - filter.calculate(agg::image_filter_quadric(), params.norm); - break; - - case CATROM: - filter.calculate(agg::image_filter_catrom(), params.norm); - break; - - case GAUSSIAN: - filter.calculate(agg::image_filter_gaussian(), params.norm); - break; - - case BESSEL: - filter.calculate(agg::image_filter_bessel(), params.norm); - break; - - case MITCHELL: - filter.calculate(agg::image_filter_mitchell(), params.norm); - break; - - case SINC: - filter.calculate(agg::image_filter_sinc(params.radius), params.norm); - break; - - case LANCZOS: - filter.calculate(agg::image_filter_lanczos(params.radius), params.norm); - break; - - case BLACKMAN: - filter.calculate(agg::image_filter_blackman(params.radius), params.norm); - break; - } -} - - -template -void resample( - const void *input, int in_width, int in_height, - void *output, int out_width, int out_height, - resample_params_t ¶ms) -{ - using type_mapping_t = type_mapping; - - using input_pixfmt_t = typename type_mapping_t::pixfmt_type; - using output_pixfmt_t = typename type_mapping_t::pixfmt_type; - - using renderer_t = agg::renderer_base; - using rasterizer_t = agg::rasterizer_scanline_aa; - - using reflect_t = agg::wrap_mode_reflect; - using image_accessor_t = agg::image_accessor_wrap; - - using span_alloc_t = agg::span_allocator; - using span_conv_alpha_t = span_conv_alpha; - - using affine_interpolator_t = agg::span_interpolator_linear<>; - using arbitrary_interpolator_t = - agg::span_interpolator_adaptor, lookup_distortion>; - - size_t itemsize = sizeof(color_type); - if (is_grayscale::value) { - itemsize /= 2; // agg::grayXX includes an alpha channel which we don't have. - } - - if (params.interpolation != NEAREST && - params.is_affine && - fabs(params.affine.sx) == 1.0 && - fabs(params.affine.sy) == 1.0 && - params.affine.shx == 0.0 && - params.affine.shy == 0.0) { - params.interpolation = NEAREST; - } - - span_alloc_t span_alloc; - rasterizer_t rasterizer; - agg::scanline_u8 scanline; - - span_conv_alpha_t conv_alpha(params.alpha); - - agg::rendering_buffer input_buffer; - input_buffer.attach( - (unsigned char *)input, in_width, in_height, in_width * itemsize); - input_pixfmt_t input_pixfmt(input_buffer); - image_accessor_t input_accessor(input_pixfmt); - - agg::rendering_buffer output_buffer; - output_buffer.attach( - (unsigned char *)output, out_width, out_height, out_width * itemsize); - output_pixfmt_t output_pixfmt(output_buffer); - renderer_t renderer(output_pixfmt); - - agg::trans_affine inverted = params.affine; - inverted.invert(); - - rasterizer.clip_box(0, 0, out_width, out_height); - - agg::path_storage path; - if (params.is_affine) { - path.move_to(0, 0); - path.line_to(in_width, 0); - path.line_to(in_width, in_height); - path.line_to(0, in_height); - path.close_polygon(); - agg::conv_transform rectangle(path, params.affine); - rasterizer.add_path(rectangle); - } else { - path.move_to(0, 0); - path.line_to(out_width, 0); - path.line_to(out_width, out_height); - path.line_to(0, out_height); - path.close_polygon(); - rasterizer.add_path(path); - } - - if (params.interpolation == NEAREST) { - if (params.is_affine) { - using span_gen_t = typename type_mapping_t::template span_gen_nn_type; - using span_conv_t = agg::span_converter; - using nn_renderer_t = agg::renderer_scanline_aa; - affine_interpolator_t interpolator(inverted); - span_gen_t span_gen(input_accessor, interpolator); - span_conv_t span_conv(span_gen, conv_alpha); - nn_renderer_t nn_renderer(renderer, span_alloc, span_conv); - agg::render_scanlines(rasterizer, scanline, nn_renderer); - } else { - using span_gen_t = typename type_mapping_t::template span_gen_nn_type; - using span_conv_t = agg::span_converter; - using nn_renderer_t = agg::renderer_scanline_aa; - lookup_distortion dist( - params.transform_mesh, in_width, in_height, out_width, out_height); - arbitrary_interpolator_t interpolator(inverted, dist); - span_gen_t span_gen(input_accessor, interpolator); - span_conv_t span_conv(span_gen, conv_alpha); - nn_renderer_t nn_renderer(renderer, span_alloc, span_conv); - agg::render_scanlines(rasterizer, scanline, nn_renderer); - } - } else { - agg::image_filter_lut filter; - get_filter(params, filter); - - if (params.is_affine && params.resample) { - using span_gen_t = typename type_mapping_t::template span_gen_affine_type; - using span_conv_t = agg::span_converter; - using int_renderer_t = agg::renderer_scanline_aa; - affine_interpolator_t interpolator(inverted); - span_gen_t span_gen(input_accessor, interpolator, filter); - span_conv_t span_conv(span_gen, conv_alpha); - int_renderer_t int_renderer(renderer, span_alloc, span_conv); - agg::render_scanlines(rasterizer, scanline, int_renderer); - } else { - using span_gen_t = typename type_mapping_t::template span_gen_filter_type; - using span_conv_t = agg::span_converter; - using int_renderer_t = agg::renderer_scanline_aa; - lookup_distortion dist( - params.transform_mesh, in_width, in_height, out_width, out_height); - arbitrary_interpolator_t interpolator(inverted, dist); - span_gen_t span_gen(input_accessor, interpolator, filter); - span_conv_t span_conv(span_gen, conv_alpha); - int_renderer_t int_renderer(renderer, span_alloc, span_conv); - agg::render_scanlines(rasterizer, scanline, int_renderer); - } - } -} - -#endif /* MPL_RESAMPLE_H */ diff --git a/contrib/python/matplotlib/py3/src/_image_wrapper.cpp b/contrib/python/matplotlib/py3/src/_image_wrapper.cpp deleted file mode 100644 index ca6ae8b2226..00000000000 --- a/contrib/python/matplotlib/py3/src/_image_wrapper.cpp +++ /dev/null @@ -1,297 +0,0 @@ -#include "mplutils.h" -#include "_image_resample.h" -#include "numpy_cpp.h" -#include "py_converters.h" - - -/********************************************************************** - * Free functions - * */ - -const char* image_resample__doc__ = -"resample(input_array, output_array, transform, interpolation=NEAREST, resample=False, alpha=1.0, norm=False, radius=1.0)\n" -"--\n\n" - -"Resample input_array, blending it in-place into output_array, using an\n" -"affine transformation.\n\n" - -"Parameters\n" -"----------\n" -"input_array : 2-d or 3-d NumPy array of float, double or `numpy.uint8`\n" -" If 2-d, the image is grayscale. If 3-d, the image must be of size\n" -" 4 in the last dimension and represents RGBA data.\n\n" - -"output_array : 2-d or 3-d NumPy array of float, double or `numpy.uint8`\n" -" The dtype and number of dimensions must match `input_array`.\n\n" - -"transform : matplotlib.transforms.Transform instance\n" -" The transformation from the input array to the output array.\n\n" - -"interpolation : int, default: NEAREST\n" -" The interpolation method. Must be one of the following constants\n" -" defined in this module:\n\n" - -" NEAREST, BILINEAR, BICUBIC, SPLINE16, SPLINE36,\n" -" HANNING, HAMMING, HERMITE, KAISER, QUADRIC, CATROM, GAUSSIAN,\n" -" BESSEL, MITCHELL, SINC, LANCZOS, BLACKMAN\n\n" - -"resample : bool, optional\n" -" When `True`, use a full resampling method. When `False`, only\n" -" resample when the output image is larger than the input image.\n\n" - -"alpha : float, default: 1\n" -" The transparency level, from 0 (transparent) to 1 (opaque).\n\n" - -"norm : bool, default: False\n" -" Whether to norm the interpolation function.\n\n" - -"radius: float, default: 1\n" -" The radius of the kernel, if method is SINC, LANCZOS or BLACKMAN.\n"; - - -static PyArrayObject * -_get_transform_mesh(PyObject *py_affine, npy_intp *dims) -{ - /* TODO: Could we get away with float, rather than double, arrays here? */ - - /* Given a non-affine transform object, create a mesh that maps - every pixel in the output image to the input image. This is used - as a lookup table during the actual resampling. */ - - PyObject *py_inverse = NULL; - npy_intp out_dims[3]; - - out_dims[0] = dims[0] * dims[1]; - out_dims[1] = 2; - - py_inverse = PyObject_CallMethod(py_affine, "inverted", NULL); - if (py_inverse == NULL) { - return NULL; - } - - numpy::array_view input_mesh(out_dims); - double *p = (double *)input_mesh.data(); - - for (npy_intp y = 0; y < dims[0]; ++y) { - for (npy_intp x = 0; x < dims[1]; ++x) { - *p++ = (double)x; - *p++ = (double)y; - } - } - - PyObject *output_mesh = PyObject_CallMethod( - py_inverse, "transform", "O", input_mesh.pyobj_steal()); - - Py_DECREF(py_inverse); - - if (output_mesh == NULL) { - return NULL; - } - - PyArrayObject *output_mesh_array = - (PyArrayObject *)PyArray_ContiguousFromAny( - output_mesh, NPY_DOUBLE, 2, 2); - - Py_DECREF(output_mesh); - - if (output_mesh_array == NULL) { - return NULL; - } - - return output_mesh_array; -} - - -static PyObject * -image_resample(PyObject *self, PyObject* args, PyObject *kwargs) -{ - PyObject *py_input = NULL; - PyObject *py_output = NULL; - PyObject *py_transform = NULL; - resample_params_t params; - - PyArrayObject *input = NULL; - PyArrayObject *output = NULL; - PyArrayObject *transform_mesh = NULL; - int ndim; - int type; - - params.interpolation = NEAREST; - params.transform_mesh = NULL; - params.resample = false; - params.norm = false; - params.radius = 1.0; - params.alpha = 1.0; - - const char *kwlist[] = { - "input_array", "output_array", "transform", "interpolation", - "resample", "alpha", "norm", "radius", NULL }; - - if (!PyArg_ParseTupleAndKeywords( - args, kwargs, "OOO|iO&dO&d:resample", (char **)kwlist, - &py_input, &py_output, &py_transform, - ¶ms.interpolation, &convert_bool, ¶ms.resample, - ¶ms.alpha, &convert_bool, ¶ms.norm, ¶ms.radius)) { - return NULL; - } - - if (params.interpolation < 0 || params.interpolation >= _n_interpolation) { - PyErr_Format(PyExc_ValueError, "Invalid interpolation value %d", - params.interpolation); - goto error; - } - - input = (PyArrayObject *)PyArray_FromAny( - py_input, NULL, 2, 3, NPY_ARRAY_C_CONTIGUOUS, NULL); - if (!input) { - goto error; - } - ndim = PyArray_NDIM(input); - type = PyArray_TYPE(input); - - if (!PyArray_Check(py_output)) { - PyErr_SetString(PyExc_ValueError, "Output array must be a NumPy array"); - goto error; - } - output = (PyArrayObject *)py_output; - if (PyArray_NDIM(output) != ndim) { - PyErr_Format( - PyExc_ValueError, - "Input (%dD) and output (%dD) have different dimensionalities.", - ndim, PyArray_NDIM(output)); - goto error; - } - // PyArray_FromAny above checks that input is 2D or 3D. - if (ndim == 3 && (PyArray_DIM(input, 2) != 4 || PyArray_DIM(output, 2) != 4)) { - PyErr_Format( - PyExc_ValueError, - "If 3D, input and output arrays must be RGBA with shape (M, N, 4); " - "got trailing dimensions of %" NPY_INTP_FMT " and %" NPY_INTP_FMT - " respectively", PyArray_DIM(input, 2), PyArray_DIM(output, 2)); - goto error; - } - if (PyArray_TYPE(output) != type) { - PyErr_SetString(PyExc_ValueError, "Mismatched types"); - goto error; - } - if (!PyArray_IS_C_CONTIGUOUS(output)) { - PyErr_SetString(PyExc_ValueError, "Output array must be C-contiguous"); - goto error; - } - - if (py_transform == NULL || py_transform == Py_None) { - params.is_affine = true; - } else { - PyObject *py_is_affine; - int py_is_affine2; - py_is_affine = PyObject_GetAttrString(py_transform, "is_affine"); - if (!py_is_affine) { - goto error; - } - - py_is_affine2 = PyObject_IsTrue(py_is_affine); - Py_DECREF(py_is_affine); - - if (py_is_affine2 == -1) { - goto error; - } else if (py_is_affine2) { - if (!convert_trans_affine(py_transform, ¶ms.affine)) { - goto error; - } - params.is_affine = true; - } else { - transform_mesh = _get_transform_mesh( - py_transform, PyArray_DIMS(output)); - if (!transform_mesh) { - goto error; - } - params.transform_mesh = (double *)PyArray_DATA(transform_mesh); - params.is_affine = false; - } - } - - if (auto resampler = - (ndim == 2) ? ( - (type == NPY_UINT8) ? resample : - (type == NPY_INT8) ? resample : - (type == NPY_UINT16) ? resample : - (type == NPY_INT16) ? resample : - (type == NPY_FLOAT32) ? resample : - (type == NPY_FLOAT64) ? resample : - nullptr) : ( - // ndim == 3 - (type == NPY_UINT8) ? resample : - (type == NPY_INT8) ? resample : - (type == NPY_UINT16) ? resample : - (type == NPY_INT16) ? resample : - (type == NPY_FLOAT32) ? resample : - (type == NPY_FLOAT64) ? resample : - nullptr)) { - Py_BEGIN_ALLOW_THREADS - resampler( - PyArray_DATA(input), PyArray_DIM(input, 1), PyArray_DIM(input, 0), - PyArray_DATA(output), PyArray_DIM(output, 1), PyArray_DIM(output, 0), - params); - Py_END_ALLOW_THREADS - } else { - PyErr_SetString( - PyExc_ValueError, - "arrays must be of dtype byte, short, float32 or float64"); - goto error; - } - - Py_DECREF(input); - Py_XDECREF(transform_mesh); - Py_RETURN_NONE; - - error: - Py_XDECREF(input); - Py_XDECREF(transform_mesh); - return NULL; -} - -static PyMethodDef module_functions[] = { - {"resample", (PyCFunction)image_resample, METH_VARARGS|METH_KEYWORDS, image_resample__doc__}, - {NULL} -}; - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, "_image", NULL, 0, module_functions, -}; - -PyMODINIT_FUNC PyInit__image(void) -{ - PyObject *m; - - import_array(); - - m = PyModule_Create(&moduledef); - - if (m == NULL) { - return NULL; - } - - if (PyModule_AddIntConstant(m, "NEAREST", NEAREST) || - PyModule_AddIntConstant(m, "BILINEAR", BILINEAR) || - PyModule_AddIntConstant(m, "BICUBIC", BICUBIC) || - PyModule_AddIntConstant(m, "SPLINE16", SPLINE16) || - PyModule_AddIntConstant(m, "SPLINE36", SPLINE36) || - PyModule_AddIntConstant(m, "HANNING", HANNING) || - PyModule_AddIntConstant(m, "HAMMING", HAMMING) || - PyModule_AddIntConstant(m, "HERMITE", HERMITE) || - PyModule_AddIntConstant(m, "KAISER", KAISER) || - PyModule_AddIntConstant(m, "QUADRIC", QUADRIC) || - PyModule_AddIntConstant(m, "CATROM", CATROM) || - PyModule_AddIntConstant(m, "GAUSSIAN", GAUSSIAN) || - PyModule_AddIntConstant(m, "BESSEL", BESSEL) || - PyModule_AddIntConstant(m, "MITCHELL", MITCHELL) || - PyModule_AddIntConstant(m, "SINC", SINC) || - PyModule_AddIntConstant(m, "LANCZOS", LANCZOS) || - PyModule_AddIntConstant(m, "BLACKMAN", BLACKMAN) || - PyModule_AddIntConstant(m, "_n_interpolation", _n_interpolation)) { - Py_DECREF(m); - return NULL; - } - - return m; -} diff --git a/contrib/python/matplotlib/py3/src/_path.h b/contrib/python/matplotlib/py3/src/_path.h deleted file mode 100644 index 61c4ed07d0d..00000000000 --- a/contrib/python/matplotlib/py3/src/_path.h +++ /dev/null @@ -1,1251 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -#ifndef MPL_PATH_H -#define MPL_PATH_H - -#include -#include -#include -#include -#include -#include - -#include "agg_conv_contour.h" -#include "agg_conv_curve.h" -#include "agg_conv_stroke.h" -#include "agg_conv_transform.h" -#include "agg_path_storage.h" -#include "agg_trans_affine.h" - -#include "path_converters.h" -#include "_backend_agg_basic_types.h" -#include "numpy_cpp.h" - -struct XY -{ - double x; - double y; - - XY(double x_, double y_) : x(x_), y(y_) - { - } - - bool operator==(const XY& o) - { - return (x == o.x && y == o.y); - } - - bool operator!=(const XY& o) - { - return (x != o.x || y != o.y); - } -}; - -typedef std::vector Polygon; - -void _finalize_polygon(std::vector &result, int closed_only) -{ - if (result.size() == 0) { - return; - } - - Polygon &polygon = result.back(); - - /* Clean up the last polygon in the result. */ - if (polygon.size() == 0) { - result.pop_back(); - } else if (closed_only) { - if (polygon.size() < 3) { - result.pop_back(); - } else if (polygon.front() != polygon.back()) { - polygon.push_back(polygon.front()); - } - } -} - -// -// The following function was found in the Agg 2.3 examples (interactive_polygon.cpp). -// It has been generalized to work on (possibly curved) polylines, rather than -// just polygons. The original comments have been kept intact. -// -- Michael Droettboom 2007-10-02 -// -//======= 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. -template -void point_in_path_impl(PointArray &points, PathIterator &path, ResultArray &inside_flag) -{ - uint8_t yflag1; - double vtx0, vty0, vtx1, vty1; - double tx, ty; - double sx, sy; - double x, y; - size_t i; - bool all_done; - - size_t n = points.size(); - - std::vector yflag0(n); - std::vector subpath_flag(n); - - path.rewind(0); - - for (i = 0; i < n; ++i) { - inside_flag[i] = 0; - } - - unsigned code = 0; - do { - if (code != agg::path_cmd_move_to) { - code = path.vertex(&x, &y); - if (code == agg::path_cmd_stop || - (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { - continue; - } - } - - sx = vtx0 = vtx1 = x; - sy = vty0 = vty1 = y; - - for (i = 0; i < n; ++i) { - ty = points(i, 1); - - if (std::isfinite(ty)) { - // get test bit for above/below X axis - yflag0[i] = (vty0 >= ty); - - subpath_flag[i] = 0; - } - } - - do { - code = path.vertex(&x, &y); - - // The following cases denote the beginning on a new subpath - if (code == agg::path_cmd_stop || - (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { - x = sx; - y = sy; - } else if (code == agg::path_cmd_move_to) { - break; - } - - for (i = 0; i < n; ++i) { - tx = points(i, 0); - ty = points(i, 1); - - if (!(std::isfinite(tx) && std::isfinite(ty))) { - continue; - } - - 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[i] != 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) { - subpath_flag[i] ^= 1; - } - } - - // Move to the next pair of vertices, retaining info as - // possible. - yflag0[i] = yflag1; - } - - vtx0 = vtx1; - vty0 = vty1; - - vtx1 = x; - vty1 = y; - } while (code != agg::path_cmd_stop && - (code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); - - all_done = true; - for (i = 0; i < n; ++i) { - tx = points(i, 0); - ty = points(i, 1); - - if (!(std::isfinite(tx) && std::isfinite(ty))) { - continue; - } - - yflag1 = (vty1 >= ty); - if (yflag0[i] != yflag1) { - if (((vty1 - ty) * (vtx0 - vtx1) >= (vtx1 - tx) * (vty0 - vty1)) == yflag1) { - subpath_flag[i] = subpath_flag[i] ^ true; - } - } - inside_flag[i] |= subpath_flag[i]; - if (inside_flag[i] == 0) { - all_done = false; - } - } - - if (all_done) { - break; - } - } while (code != agg::path_cmd_stop); -} - -template -inline void points_in_path(PointArray &points, - const double r, - PathIterator &path, - agg::trans_affine &trans, - ResultArray &result) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover no_nans_t; - typedef agg::conv_curve curve_t; - typedef agg::conv_contour contour_t; - - size_t i; - for (i = 0; i < points.size(); ++i) { - result[i] = false; - } - - if (path.total_vertices() < 3) { - return; - } - - transformed_path_t trans_path(path, trans); - no_nans_t no_nans_path(trans_path, true, path.has_codes()); - curve_t curved_path(no_nans_path); - if (r != 0.0) { - contour_t contoured_path(curved_path); - contoured_path.width(r); - point_in_path_impl(points, contoured_path, result); - } else { - point_in_path_impl(points, curved_path, result); - } -} - -template -inline bool point_in_path( - double x, double y, const double r, PathIterator &path, agg::trans_affine &trans) -{ - npy_intp shape[] = {1, 2}; - numpy::array_view points(shape); - points(0, 0) = x; - points(0, 1) = y; - - int result[1]; - result[0] = 0; - - points_in_path(points, r, path, trans, result); - - return result[0] != 0; -} - -template -inline bool point_on_path( - double x, double y, const double r, PathIterator &path, agg::trans_affine &trans) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover no_nans_t; - typedef agg::conv_curve curve_t; - typedef agg::conv_stroke stroke_t; - - npy_intp shape[] = {1, 2}; - numpy::array_view points(shape); - points(0, 0) = x; - points(0, 1) = y; - - int result[1]; - result[0] = 0; - - transformed_path_t trans_path(path, trans); - no_nans_t nan_removed_path(trans_path, true, path.has_codes()); - curve_t curved_path(nan_removed_path); - stroke_t stroked_path(curved_path); - stroked_path.width(r * 2.0); - point_in_path_impl(points, stroked_path, result); - return result[0] != 0; -} - -struct extent_limits -{ - double x0; - double y0; - double x1; - double y1; - double xm; - double ym; -}; - -void reset_limits(extent_limits &e) -{ - e.x0 = std::numeric_limits::infinity(); - e.y0 = std::numeric_limits::infinity(); - e.x1 = -std::numeric_limits::infinity(); - e.y1 = -std::numeric_limits::infinity(); - /* xm and ym are the minimum positive values in the data, used - by log scaling */ - e.xm = std::numeric_limits::infinity(); - e.ym = std::numeric_limits::infinity(); -} - -inline void update_limits(double x, double y, extent_limits &e) -{ - if (x < e.x0) - e.x0 = x; - if (y < e.y0) - e.y0 = y; - if (x > e.x1) - e.x1 = x; - if (y > e.y1) - e.y1 = y; - /* xm and ym are the minimum positive values in the data, used - by log scaling */ - if (x > 0.0 && x < e.xm) - e.xm = x; - if (y > 0.0 && y < e.ym) - e.ym = y; -} - -template -void update_path_extents(PathIterator &path, agg::trans_affine &trans, extent_limits &extents) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removed_t; - double x, y; - unsigned code; - - transformed_path_t tpath(path, trans); - nan_removed_t nan_removed(tpath, true, path.has_codes()); - - nan_removed.rewind(0); - - while ((code = nan_removed.vertex(&x, &y)) != agg::path_cmd_stop) { - if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { - continue; - } - update_limits(x, y, extents); - } -} - -template -void get_path_collection_extents(agg::trans_affine &master_transform, - PathGenerator &paths, - TransformArray &transforms, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - extent_limits &extent) -{ - if (offsets.size() != 0 && offsets.dim(1) != 2) { - throw std::runtime_error("Offsets array must have shape (N, 2)"); - } - - size_t Npaths = paths.size(); - size_t Noffsets = offsets.size(); - size_t N = std::max(Npaths, Noffsets); - size_t Ntransforms = std::min(transforms.size(), N); - size_t i; - - agg::trans_affine trans; - - reset_limits(extent); - - for (i = 0; i < N; ++i) { - typename PathGenerator::path_iterator path(paths(i % Npaths)); - if (Ntransforms) { - size_t ti = i % Ntransforms; - trans = agg::trans_affine(transforms(ti, 0, 0), - transforms(ti, 1, 0), - transforms(ti, 0, 1), - transforms(ti, 1, 1), - transforms(ti, 0, 2), - transforms(ti, 1, 2)); - } else { - trans = master_transform; - } - - if (Noffsets) { - double xo = offsets(i % Noffsets, 0); - double yo = offsets(i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - trans *= agg::trans_affine_translation(xo, yo); - } - - update_path_extents(path, trans, extent); - } -} - -template -void point_in_path_collection(double x, - double y, - double radius, - agg::trans_affine &master_transform, - PathGenerator &paths, - TransformArray &transforms, - OffsetArray &offsets, - agg::trans_affine &offset_trans, - bool filled, - std::vector &result) -{ - size_t Npaths = paths.size(); - - if (Npaths == 0) { - return; - } - - size_t Noffsets = offsets.size(); - size_t N = std::max(Npaths, Noffsets); - size_t Ntransforms = std::min(transforms.size(), N); - size_t i; - - agg::trans_affine trans; - - for (i = 0; i < N; ++i) { - typename PathGenerator::path_iterator path = paths(i % Npaths); - - if (Ntransforms) { - size_t ti = i % Ntransforms; - trans = agg::trans_affine(transforms(ti, 0, 0), - transforms(ti, 1, 0), - transforms(ti, 0, 1), - transforms(ti, 1, 1), - transforms(ti, 0, 2), - transforms(ti, 1, 2)); - trans *= master_transform; - } else { - trans = master_transform; - } - - if (Noffsets) { - double xo = offsets(i % Noffsets, 0); - double yo = offsets(i % Noffsets, 1); - offset_trans.transform(&xo, &yo); - trans *= agg::trans_affine_translation(xo, yo); - } - - if (filled) { - if (point_in_path(x, y, radius, path, trans)) { - result.push_back(i); - } - } else { - if (point_on_path(x, y, radius, path, trans)) { - result.push_back(i); - } - } - } -} - -template -bool path_in_path(PathIterator1 &a, - agg::trans_affine &atrans, - PathIterator2 &b, - agg::trans_affine &btrans) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover no_nans_t; - typedef agg::conv_curve curve_t; - - if (a.total_vertices() < 3) { - return false; - } - - transformed_path_t b_path_trans(b, btrans); - no_nans_t b_no_nans(b_path_trans, true, b.has_codes()); - curve_t b_curved(b_no_nans); - - double x, y; - b_curved.rewind(0); - while (b_curved.vertex(&x, &y) != agg::path_cmd_stop) { - if (!point_in_path(x, y, 0.0, a, atrans)) { - return false; - } - } - - return true; -} - -/** The clip_path_to_rect code here is a clean-room implementation of - the Sutherland-Hodgman clipping algorithm described here: - - https://en.wikipedia.org/wiki/Sutherland-Hodgman_clipping_algorithm -*/ - -namespace clip_to_rect_filters -{ -/* There are four different passes needed to create/remove - vertices (one for each side of the rectangle). The differences - between those passes are encapsulated in these functor classes. -*/ -struct bisectx -{ - double m_x; - - bisectx(double x) : m_x(x) - { - } - - inline void bisect(double sx, double sy, double px, double py, double *bx, double *by) const - { - *bx = m_x; - double dx = px - sx; - double dy = py - sy; - *by = sy + dy * ((m_x - sx) / dx); - } -}; - -struct xlt : public bisectx -{ - xlt(double x) : bisectx(x) - { - } - - inline bool is_inside(double x, double y) const - { - return x <= m_x; - } -}; - -struct xgt : public bisectx -{ - xgt(double x) : bisectx(x) - { - } - - inline bool is_inside(double x, double y) const - { - return x >= m_x; - } -}; - -struct bisecty -{ - double m_y; - - bisecty(double y) : m_y(y) - { - } - - inline void bisect(double sx, double sy, double px, double py, double *bx, double *by) const - { - *by = m_y; - double dx = px - sx; - double dy = py - sy; - *bx = sx + dx * ((m_y - sy) / dy); - } -}; - -struct ylt : public bisecty -{ - ylt(double y) : bisecty(y) - { - } - - inline bool is_inside(double x, double y) const - { - return y <= m_y; - } -}; - -struct ygt : public bisecty -{ - ygt(double y) : bisecty(y) - { - } - - inline bool is_inside(double x, double y) const - { - return y >= m_y; - } -}; -} - -template -inline void clip_to_rect_one_step(const Polygon &polygon, Polygon &result, const Filter &filter) -{ - double sx, sy, px, py, bx, by; - bool sinside, pinside; - result.clear(); - - if (polygon.size() == 0) { - return; - } - - sx = polygon.back().x; - sy = polygon.back().y; - for (Polygon::const_iterator i = polygon.begin(); i != polygon.end(); ++i) { - px = i->x; - py = i->y; - - sinside = filter.is_inside(sx, sy); - pinside = filter.is_inside(px, py); - - if (sinside ^ pinside) { - filter.bisect(sx, sy, px, py, &bx, &by); - result.push_back(XY(bx, by)); - } - - if (pinside) { - result.push_back(XY(px, py)); - } - - sx = px; - sy = py; - } -} - -template -void -clip_path_to_rect(PathIterator &path, agg::rect_d &rect, bool inside, std::vector &results) -{ - double xmin, ymin, xmax, ymax; - if (rect.x1 < rect.x2) { - xmin = rect.x1; - xmax = rect.x2; - } else { - xmin = rect.x2; - xmax = rect.x1; - } - - if (rect.y1 < rect.y2) { - ymin = rect.y1; - ymax = rect.y2; - } else { - ymin = rect.y2; - ymax = rect.y1; - } - - if (!inside) { - std::swap(xmin, xmax); - std::swap(ymin, ymax); - } - - typedef agg::conv_curve curve_t; - curve_t curve(path); - - Polygon polygon1, polygon2; - double x = 0, y = 0; - unsigned code = 0; - curve.rewind(0); - - do { - // Grab the next subpath and store it in polygon1 - polygon1.clear(); - do { - if (code == agg::path_cmd_move_to) { - polygon1.push_back(XY(x, y)); - } - - code = curve.vertex(&x, &y); - - if (code == agg::path_cmd_stop) { - break; - } - - if (code != agg::path_cmd_move_to) { - polygon1.push_back(XY(x, y)); - } - } while ((code & agg::path_cmd_end_poly) != agg::path_cmd_end_poly); - - // The result of each step is fed into the next (note the - // swapping of polygon1 and polygon2 at each step). - clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::xlt(xmax)); - clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::xgt(xmin)); - clip_to_rect_one_step(polygon1, polygon2, clip_to_rect_filters::ylt(ymax)); - clip_to_rect_one_step(polygon2, polygon1, clip_to_rect_filters::ygt(ymin)); - - // Empty polygons aren't very useful, so skip them - if (polygon1.size()) { - _finalize_polygon(results, 1); - results.push_back(polygon1); - } - } while (code != agg::path_cmd_stop); - - _finalize_polygon(results, 1); -} - -template -void affine_transform_2d(VerticesArray &vertices, agg::trans_affine &trans, ResultArray &result) -{ - if (vertices.size() != 0 && vertices.dim(1) != 2) { - throw std::runtime_error("Invalid vertices array."); - } - - size_t n = vertices.size(); - double x; - double y; - double t0; - double t1; - double t; - - for (size_t i = 0; i < n; ++i) { - x = vertices(i, 0); - y = vertices(i, 1); - - t0 = trans.sx * x; - t1 = trans.shx * y; - t = t0 + t1 + trans.tx; - result(i, 0) = t; - - t0 = trans.shy * x; - t1 = trans.sy * y; - t = t0 + t1 + trans.ty; - result(i, 1) = t; - } -} - -template -void affine_transform_1d(VerticesArray &vertices, agg::trans_affine &trans, ResultArray &result) -{ - if (vertices.dim(0) != 2) { - throw std::runtime_error("Invalid vertices array."); - } - - double x; - double y; - double t0; - double t1; - double t; - - x = vertices(0); - y = vertices(1); - - t0 = trans.sx * x; - t1 = trans.shx * y; - t = t0 + t1 + trans.tx; - result(0) = t; - - t0 = trans.shy * x; - t1 = trans.sy * y; - t = t0 + t1 + trans.ty; - result(1) = t; -} - -template -int count_bboxes_overlapping_bbox(agg::rect_d &a, BBoxArray &bboxes) -{ - agg::rect_d b; - int count = 0; - - if (a.x2 < a.x1) { - std::swap(a.x1, a.x2); - } - if (a.y2 < a.y1) { - std::swap(a.y1, a.y2); - } - - size_t num_bboxes = bboxes.size(); - for (size_t i = 0; i < num_bboxes; ++i) { - b = agg::rect_d(bboxes(i, 0, 0), bboxes(i, 0, 1), bboxes(i, 1, 0), bboxes(i, 1, 1)); - - if (b.x2 < b.x1) { - std::swap(b.x1, b.x2); - } - if (b.y2 < b.y1) { - std::swap(b.y1, b.y2); - } - if (!((b.x2 <= a.x1) || (b.y2 <= a.y1) || (b.x1 >= a.x2) || (b.y1 >= a.y2))) { - ++count; - } - } - - return count; -} - - -inline bool isclose(double a, double b) -{ - // relative and absolute tolerance values are chosen empirically - // it looks the atol value matters here because of round-off errors - const double rtol = 1e-10; - const double atol = 1e-13; - - // as per python's math.isclose - return fabs(a-b) <= fmax(rtol * fmax(fabs(a), fabs(b)), atol); -} - - -inline bool segments_intersect(const double &x1, - const double &y1, - const double &x2, - const double &y2, - const double &x3, - const double &y3, - const double &x4, - const double &y4) -{ - // determinant - double den = ((y4 - y3) * (x2 - x1)) - ((x4 - x3) * (y2 - y1)); - - // If den == 0 we have two possibilities: - if (isclose(den, 0.0)) { - double t_area = (x2*y3 - x3*y2) - x1*(y3 - y2) + y1*(x3 - x2); - // 1 - If the area of the triangle made by the 3 first points (2 from the first segment - // plus one from the second) is zero, they are collinear - if (isclose(t_area, 0.0)) { - if (x1 == x2 && x2 == x3) { // segments have infinite slope (vertical lines) - // and lie on the same line - return (fmin(y1, y2) <= fmin(y3, y4) && fmin(y3, y4) <= fmax(y1, y2)) || - (fmin(y3, y4) <= fmin(y1, y2) && fmin(y1, y2) <= fmax(y3, y4)); - } - else { - return (fmin(x1, x2) <= fmin(x3, x4) && fmin(x3, x4) <= fmax(x1, x2)) || - (fmin(x3, x4) <= fmin(x1, x2) && fmin(x1, x2) <= fmax(x3, x4)); - } - } - // 2 - If t_area is not zero, the segments are parallel, but not collinear - else { - return false; - } - } - - const double n1 = ((x4 - x3) * (y1 - y3)) - ((y4 - y3) * (x1 - x3)); - const double n2 = ((x2 - x1) * (y1 - y3)) - ((y2 - y1) * (x1 - x3)); - - const double u1 = n1 / den; - const double u2 = n2 / den; - - return ((u1 > 0.0 || isclose(u1, 0.0)) && - (u1 < 1.0 || isclose(u1, 1.0)) && - (u2 > 0.0 || isclose(u2, 0.0)) && - (u2 < 1.0 || isclose(u2, 1.0))); -} - -template -bool path_intersects_path(PathIterator1 &p1, PathIterator2 &p2) -{ - typedef PathNanRemover no_nans_t; - typedef agg::conv_curve curve_t; - - if (p1.total_vertices() < 2 || p2.total_vertices() < 2) { - return false; - } - - no_nans_t n1(p1, true, p1.has_codes()); - no_nans_t n2(p2, true, p2.has_codes()); - - curve_t c1(n1); - curve_t c2(n2); - - double x11, y11, x12, y12; - double x21, y21, x22, y22; - - c1.vertex(&x11, &y11); - while (c1.vertex(&x12, &y12) != agg::path_cmd_stop) { - // if the segment in path 1 is (almost) 0 length, skip to next vertex - if ((isclose((x11 - x12) * (x11 - x12) + (y11 - y12) * (y11 - y12), 0))){ - continue; - } - c2.rewind(0); - c2.vertex(&x21, &y21); - - while (c2.vertex(&x22, &y22) != agg::path_cmd_stop) { - // if the segment in path 2 is (almost) 0 length, skip to next vertex - if ((isclose((x21 - x22) * (x21 - x22) + (y21 - y22) * (y21 - y22), 0))){ - continue; - } - - if (segments_intersect(x11, y11, x12, y12, x21, y21, x22, y22)) { - return true; - } - x21 = x22; - y21 = y22; - } - x11 = x12; - y11 = y12; - } - - return false; -} - -// returns whether the segment from (x1,y1) to (x2,y2) -// intersects the rectangle centered at (cx,cy) with size (w,h) -// see doc/segment_intersects_rectangle.svg for a more detailed explanation -inline bool segment_intersects_rectangle(double x1, double y1, - double x2, double y2, - double cx, double cy, - double w, double h) -{ - return fabs(x1 + x2 - 2.0 * cx) < fabs(x1 - x2) + w && - fabs(y1 + y2 - 2.0 * cy) < fabs(y1 - y2) + h && - 2.0 * fabs((x1 - cx) * (y1 - y2) - (y1 - cy) * (x1 - x2)) < - w * fabs(y1 - y2) + h * fabs(x1 - x2); -} - -template -bool path_intersects_rectangle(PathIterator &path, - double rect_x1, double rect_y1, - double rect_x2, double rect_y2, - bool filled) -{ - typedef PathNanRemover no_nans_t; - typedef agg::conv_curve curve_t; - - if (path.total_vertices() == 0) { - return false; - } - - no_nans_t no_nans(path, true, path.has_codes()); - curve_t curve(no_nans); - - double cx = (rect_x1 + rect_x2) * 0.5, cy = (rect_y1 + rect_y2) * 0.5; - double w = fabs(rect_x1 - rect_x2), h = fabs(rect_y1 - rect_y2); - - double x1, y1, x2, y2; - - curve.vertex(&x1, &y1); - if (2.0 * fabs(x1 - cx) <= w && 2.0 * fabs(y1 - cy) <= h) { - return true; - } - - while (curve.vertex(&x2, &y2) != agg::path_cmd_stop) { - if (segment_intersects_rectangle(x1, y1, x2, y2, cx, cy, w, h)) { - return true; - } - x1 = x2; - y1 = y2; - } - - if (filled) { - agg::trans_affine trans; - if (point_in_path(cx, cy, 0.0, path, trans)) { - return true; - } - } - - return false; -} - -template -void convert_path_to_polygons(PathIterator &path, - agg::trans_affine &trans, - double width, - double height, - int closed_only, - std::vector &result) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removal_t; - typedef PathClipper clipped_t; - typedef PathSimplifier simplify_t; - typedef agg::conv_curve curve_t; - - bool do_clip = width != 0.0 && height != 0.0; - bool simplify = path.should_simplify(); - - transformed_path_t tpath(path, trans); - nan_removal_t nan_removed(tpath, true, path.has_codes()); - clipped_t clipped(nan_removed, do_clip, width, height); - simplify_t simplified(clipped, simplify, path.simplify_threshold()); - curve_t curve(simplified); - - result.push_back(Polygon()); - Polygon *polygon = &result.back(); - double x, y; - unsigned code; - - while ((code = curve.vertex(&x, &y)) != agg::path_cmd_stop) { - if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) { - _finalize_polygon(result, 1); - result.push_back(Polygon()); - polygon = &result.back(); - } else { - if (code == agg::path_cmd_move_to) { - _finalize_polygon(result, closed_only); - result.push_back(Polygon()); - polygon = &result.back(); - } - polygon->push_back(XY(x, y)); - } - } - - _finalize_polygon(result, closed_only); -} - -template -void -__cleanup_path(VertexSource &source, std::vector &vertices, std::vector &codes) -{ - unsigned code; - double x, y; - do { - code = source.vertex(&x, &y); - vertices.push_back(x); - vertices.push_back(y); - codes.push_back((npy_uint8)code); - } while (code != agg::path_cmd_stop); -} - -template -void cleanup_path(PathIterator &path, - agg::trans_affine &trans, - bool remove_nans, - bool do_clip, - const agg::rect_base &rect, - e_snap_mode snap_mode, - double stroke_width, - bool do_simplify, - bool return_curves, - SketchParams sketch_params, - std::vector &vertices, - std::vector &codes) -{ - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removal_t; - typedef PathClipper clipped_t; - typedef PathSnapper snapped_t; - typedef PathSimplifier simplify_t; - typedef agg::conv_curve curve_t; - typedef Sketch sketch_t; - - transformed_path_t tpath(path, trans); - nan_removal_t nan_removed(tpath, remove_nans, path.has_codes()); - clipped_t clipped(nan_removed, do_clip, rect); - snapped_t snapped(clipped, snap_mode, path.total_vertices(), stroke_width); - simplify_t simplified(snapped, do_simplify, path.simplify_threshold()); - - vertices.reserve(path.total_vertices() * 2); - codes.reserve(path.total_vertices()); - - if (return_curves && sketch_params.scale == 0.0) { - __cleanup_path(simplified, vertices, codes); - } else { - curve_t curve(simplified); - sketch_t sketch(curve, sketch_params.scale, sketch_params.length, sketch_params.randomness); - __cleanup_path(sketch, vertices, codes); - } -} - -void quad2cubic(double x0, double y0, - double x1, double y1, - double x2, double y2, - double *outx, double *outy) -{ - - outx[0] = x0 + 2./3. * (x1 - x0); - outy[0] = y0 + 2./3. * (y1 - y0); - outx[1] = outx[0] + 1./3. * (x2 - x0); - outy[1] = outy[0] + 1./3. * (y2 - y0); - outx[2] = x2; - outy[2] = y2; -} - - -void __add_number(double val, char format_code, int precision, - std::string& buffer) -{ - if (precision == -1) { - // Special-case for compat with old ttconv code, which *truncated* - // values with a cast to int instead of rounding them as printf - // would do. The only point where non-integer values arise is from - // quad2cubic conversion (as we already perform a first truncation - // on Python's side), which can introduce additional floating point - // error (by adding 2/3 delta-x and then 1/3 delta-x), so compensate by - // first rounding to the closest 1/3 and then truncating. - char str[255]; - PyOS_snprintf(str, 255, "%d", (int)(round(val * 3)) / 3); - buffer += str; - } else { - char *str = PyOS_double_to_string( - val, format_code, precision, Py_DTSF_ADD_DOT_0, NULL); - // Delete trailing zeros and decimal point - char *c = str + strlen(str) - 1; // Start at last character. - // Rewind through all the zeros and, if present, the trailing decimal - // point. Py_DTSF_ADD_DOT_0 ensures we won't go past the start of str. - while (*c == '0') { - --c; - } - if (*c == '.') { - --c; - } - try { - buffer.append(str, c + 1); - } catch (std::bad_alloc& e) { - PyMem_Free(str); - throw e; - } - PyMem_Free(str); - } -} - - -template -bool __convert_to_string(PathIterator &path, - int precision, - char **codes, - bool postfix, - std::string& buffer) -{ - const char format_code = 'f'; - - double x[3]; - double y[3]; - double last_x = 0.0; - double last_y = 0.0; - - unsigned code; - - while ((code = path.vertex(&x[0], &y[0])) != agg::path_cmd_stop) { - if (code == CLOSEPOLY) { - buffer += codes[4]; - } else if (code < 5) { - size_t size = NUM_VERTICES[code]; - - for (size_t i = 1; i < size; ++i) { - unsigned subcode = path.vertex(&x[i], &y[i]); - if (subcode != code) { - return false; - } - } - - /* For formats that don't support quad curves, convert to - cubic curves */ - if (code == CURVE3 && codes[code - 1][0] == '\0') { - quad2cubic(last_x, last_y, x[0], y[0], x[1], y[1], x, y); - code++; - size = 3; - } - - if (!postfix) { - buffer += codes[code - 1]; - buffer += ' '; - } - - for (size_t i = 0; i < size; ++i) { - __add_number(x[i], format_code, precision, buffer); - buffer += ' '; - __add_number(y[i], format_code, precision, buffer); - buffer += ' '; - } - - if (postfix) { - buffer += codes[code - 1]; - } - - last_x = x[size - 1]; - last_y = y[size - 1]; - } else { - // Unknown code value - return false; - } - - buffer += '\n'; - } - - return true; -} - -template -bool convert_to_string(PathIterator &path, - agg::trans_affine &trans, - agg::rect_d &clip_rect, - bool simplify, - SketchParams sketch_params, - int precision, - char **codes, - bool postfix, - std::string& buffer) -{ - size_t buffersize; - typedef agg::conv_transform transformed_path_t; - typedef PathNanRemover nan_removal_t; - typedef PathClipper clipped_t; - typedef PathSimplifier simplify_t; - typedef agg::conv_curve curve_t; - typedef Sketch sketch_t; - - bool do_clip = (clip_rect.x1 < clip_rect.x2 && clip_rect.y1 < clip_rect.y2); - - transformed_path_t tpath(path, trans); - nan_removal_t nan_removed(tpath, true, path.has_codes()); - clipped_t clipped(nan_removed, do_clip, clip_rect); - simplify_t simplified(clipped, simplify, path.simplify_threshold()); - - buffersize = (size_t) path.total_vertices() * (precision + 5) * 4; - if (buffersize == 0) { - return true; - } - - if (sketch_params.scale != 0.0) { - buffersize *= 10; - } - - buffer.reserve(buffersize); - - if (sketch_params.scale == 0.0) { - return __convert_to_string(simplified, precision, codes, postfix, buffer); - } else { - curve_t curve(simplified); - sketch_t sketch(curve, sketch_params.scale, sketch_params.length, sketch_params.randomness); - return __convert_to_string(sketch, precision, codes, postfix, buffer); - } - -} - -template -bool is_sorted_and_has_non_nan(PyArrayObject *array) -{ - char* ptr = PyArray_BYTES(array); - npy_intp size = PyArray_DIM(array, 0), - stride = PyArray_STRIDE(array, 0); - using limits = std::numeric_limits; - T last = limits::has_infinity ? -limits::infinity() : limits::min(); - bool found_non_nan = false; - - for (npy_intp i = 0; i < size; ++i, ptr += stride) { - T current = *(T*)ptr; - // The following tests !isnan(current), but also works for integral - // types. (The isnan(IntegralType) overload is absent on MSVC.) - if (current == current) { - found_non_nan = true; - if (current < last) { - return false; - } - last = current; - } - } - return found_non_nan; -}; - - -#endif diff --git a/contrib/python/matplotlib/py3/src/_path_wrapper.cpp b/contrib/python/matplotlib/py3/src/_path_wrapper.cpp deleted file mode 100644 index 369d9e03088..00000000000 --- a/contrib/python/matplotlib/py3/src/_path_wrapper.cpp +++ /dev/null @@ -1,772 +0,0 @@ -#include "numpy_cpp.h" - -#include "_path.h" - -#include "py_converters.h" -#include "py_adaptors.h" - -PyObject *convert_polygon_vector(std::vector &polygons) -{ - PyObject *pyresult = PyList_New(polygons.size()); - - for (size_t i = 0; i < polygons.size(); ++i) { - Polygon poly = polygons[i]; - npy_intp dims[2]; - dims[1] = 2; - - dims[0] = (npy_intp)poly.size(); - - numpy::array_view subresult(dims); - memcpy(subresult.data(), &poly[0], sizeof(double) * poly.size() * 2); - - if (PyList_SetItem(pyresult, i, subresult.pyobj())) { - Py_DECREF(pyresult); - return NULL; - } - } - - return pyresult; -} - -const char *Py_point_in_path__doc__ = - "point_in_path(x, y, radius, path, trans)\n" - "--\n\n"; - -static PyObject *Py_point_in_path(PyObject *self, PyObject *args) -{ - double x, y, r; - py::PathIterator path; - agg::trans_affine trans; - bool result; - - if (!PyArg_ParseTuple(args, - "dddO&O&:point_in_path", - &x, - &y, - &r, - &convert_path, - &path, - &convert_trans_affine, - &trans)) { - return NULL; - } - - CALL_CPP("point_in_path", (result = point_in_path(x, y, r, path, trans))); - - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -const char *Py_points_in_path__doc__ = - "points_in_path(points, radius, path, trans)\n" - "--\n\n"; - -static PyObject *Py_points_in_path(PyObject *self, PyObject *args) -{ - numpy::array_view points; - double r; - py::PathIterator path; - agg::trans_affine trans; - - if (!PyArg_ParseTuple(args, - "O&dO&O&:points_in_path", - &convert_points, - &points, - &r, - &convert_path, - &path, - &convert_trans_affine, - &trans)) { - return NULL; - } - - npy_intp dims[] = { (npy_intp)points.size() }; - numpy::array_view results(dims); - - CALL_CPP("points_in_path", (points_in_path(points, r, path, trans, results))); - - return results.pyobj(); -} - -const char *Py_update_path_extents__doc__ = - "update_path_extents(path, trans, rect, minpos, ignore)\n" - "--\n\n"; - -static PyObject *Py_update_path_extents(PyObject *self, PyObject *args) -{ - py::PathIterator path; - agg::trans_affine trans; - agg::rect_d rect; - numpy::array_view minpos; - int ignore; - int changed; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&i:update_path_extents", - &convert_path, - &path, - &convert_trans_affine, - &trans, - &convert_rect, - &rect, - &minpos.converter, - &minpos, - &ignore)) { - return NULL; - } - - if (minpos.dim(0) != 2) { - PyErr_Format(PyExc_ValueError, - "minpos must be of length 2, got %" NPY_INTP_FMT, - minpos.dim(0)); - return NULL; - } - - extent_limits e; - - if (ignore) { - CALL_CPP("update_path_extents", reset_limits(e)); - } else { - if (rect.x1 > rect.x2) { - e.x0 = std::numeric_limits::infinity(); - e.x1 = -std::numeric_limits::infinity(); - } else { - e.x0 = rect.x1; - e.x1 = rect.x2; - } - if (rect.y1 > rect.y2) { - e.y0 = std::numeric_limits::infinity(); - e.y1 = -std::numeric_limits::infinity(); - } else { - e.y0 = rect.y1; - e.y1 = rect.y2; - } - e.xm = minpos(0); - e.ym = minpos(1); - } - - CALL_CPP("update_path_extents", (update_path_extents(path, trans, e))); - - changed = (e.x0 != rect.x1 || e.y0 != rect.y1 || e.x1 != rect.x2 || e.y1 != rect.y2 || - e.xm != minpos(0) || e.ym != minpos(1)); - - npy_intp extentsdims[] = { 2, 2 }; - numpy::array_view outextents(extentsdims); - outextents(0, 0) = e.x0; - outextents(0, 1) = e.y0; - outextents(1, 0) = e.x1; - outextents(1, 1) = e.y1; - - npy_intp minposdims[] = { 2 }; - numpy::array_view outminpos(minposdims); - outminpos(0) = e.xm; - outminpos(1) = e.ym; - - return Py_BuildValue( - "NNi", outextents.pyobj(), outminpos.pyobj(), changed); -} - -const char *Py_get_path_collection_extents__doc__ = - "get_path_collection_extents(" - "master_transform, paths, transforms, offsets, offset_transform)\n" - "--\n\n"; - -static PyObject *Py_get_path_collection_extents(PyObject *self, PyObject *args) -{ - agg::trans_affine master_transform; - py::PathGenerator paths; - numpy::array_view transforms; - numpy::array_view offsets; - agg::trans_affine offset_trans; - extent_limits e; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&O&:get_path_collection_extents", - &convert_trans_affine, - &master_transform, - &convert_pathgen, - &paths, - &convert_transforms, - &transforms, - &convert_points, - &offsets, - &convert_trans_affine, - &offset_trans)) { - return NULL; - } - - CALL_CPP("get_path_collection_extents", - (get_path_collection_extents( - master_transform, paths, transforms, offsets, offset_trans, e))); - - npy_intp dims[] = { 2, 2 }; - numpy::array_view extents(dims); - extents(0, 0) = e.x0; - extents(0, 1) = e.y0; - extents(1, 0) = e.x1; - extents(1, 1) = e.y1; - - npy_intp minposdims[] = { 2 }; - numpy::array_view minpos(minposdims); - minpos(0) = e.xm; - minpos(1) = e.ym; - - return Py_BuildValue("NN", extents.pyobj(), minpos.pyobj()); -} - -const char *Py_point_in_path_collection__doc__ = - "point_in_path_collection(" - "x, y, radius, master_transform, paths, transforms, offsets, " - "offset_trans, filled)\n" - "--\n\n"; - -static PyObject *Py_point_in_path_collection(PyObject *self, PyObject *args) -{ - double x, y, radius; - agg::trans_affine master_transform; - py::PathGenerator paths; - numpy::array_view transforms; - numpy::array_view offsets; - agg::trans_affine offset_trans; - bool filled; - std::vector result; - - if (!PyArg_ParseTuple(args, - "dddO&O&O&O&O&O&:point_in_path_collection", - &x, - &y, - &radius, - &convert_trans_affine, - &master_transform, - &convert_pathgen, - &paths, - &convert_transforms, - &transforms, - &convert_points, - &offsets, - &convert_trans_affine, - &offset_trans, - &convert_bool, - &filled)) { - return NULL; - } - - CALL_CPP("point_in_path_collection", - (point_in_path_collection(x, - y, - radius, - master_transform, - paths, - transforms, - offsets, - offset_trans, - filled, - result))); - - npy_intp dims[] = {(npy_intp)result.size() }; - numpy::array_view pyresult(dims); - if (result.size() > 0) { - memcpy(pyresult.data(), &result[0], result.size() * sizeof(int)); - } - return pyresult.pyobj(); -} - -const char *Py_path_in_path__doc__ = - "path_in_path(path_a, trans_a, path_b, trans_b)\n" - "--\n\n"; - -static PyObject *Py_path_in_path(PyObject *self, PyObject *args) -{ - py::PathIterator a; - agg::trans_affine atrans; - py::PathIterator b; - agg::trans_affine btrans; - bool result; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&:path_in_path", - &convert_path, - &a, - &convert_trans_affine, - &atrans, - &convert_path, - &b, - &convert_trans_affine, - &btrans)) { - return NULL; - } - - CALL_CPP("path_in_path", (result = path_in_path(a, atrans, b, btrans))); - - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -const char *Py_clip_path_to_rect__doc__ = - "clip_path_to_rect(path, rect, inside)\n" - "--\n\n"; - -static PyObject *Py_clip_path_to_rect(PyObject *self, PyObject *args) -{ - py::PathIterator path; - agg::rect_d rect; - bool inside; - std::vector result; - - if (!PyArg_ParseTuple(args, - "O&O&O&:clip_path_to_rect", - &convert_path, - &path, - &convert_rect, - &rect, - &convert_bool, - &inside)) { - return NULL; - } - - CALL_CPP("clip_path_to_rect", (clip_path_to_rect(path, rect, inside, result))); - - return convert_polygon_vector(result); -} - -const char *Py_affine_transform__doc__ = - "affine_transform(points, trans)\n" - "--\n\n"; - -static PyObject *Py_affine_transform(PyObject *self, PyObject *args) -{ - PyObject *vertices_obj; - agg::trans_affine trans; - - if (!PyArg_ParseTuple(args, - "OO&:affine_transform", - &vertices_obj, - &convert_trans_affine, - &trans)) { - return NULL; - } - - PyArrayObject* vertices_arr = (PyArrayObject *)PyArray_ContiguousFromAny(vertices_obj, NPY_DOUBLE, 1, 2); - if (vertices_arr == NULL) { - return NULL; - } - - if (PyArray_NDIM(vertices_arr) == 2) { - numpy::array_view vertices(vertices_arr); - Py_DECREF(vertices_arr); - - npy_intp dims[] = { (npy_intp)vertices.size(), 2 }; - numpy::array_view result(dims); - CALL_CPP("affine_transform", (affine_transform_2d(vertices, trans, result))); - return result.pyobj(); - } else { // PyArray_NDIM(vertices_arr) == 1 - numpy::array_view vertices(vertices_arr); - Py_DECREF(vertices_arr); - - npy_intp dims[] = { (npy_intp)vertices.size() }; - numpy::array_view result(dims); - CALL_CPP("affine_transform", (affine_transform_1d(vertices, trans, result))); - return result.pyobj(); - } -} - -const char *Py_count_bboxes_overlapping_bbox__doc__ = - "count_bboxes_overlapping_bbox(bbox, bboxes)\n" - "--\n\n"; - -static PyObject *Py_count_bboxes_overlapping_bbox(PyObject *self, PyObject *args) -{ - agg::rect_d bbox; - numpy::array_view bboxes; - int result; - - if (!PyArg_ParseTuple(args, - "O&O&:count_bboxes_overlapping_bbox", - &convert_rect, - &bbox, - &convert_bboxes, - &bboxes)) { - return NULL; - } - - CALL_CPP("count_bboxes_overlapping_bbox", - (result = count_bboxes_overlapping_bbox(bbox, bboxes))); - - return PyLong_FromLong(result); -} - -const char *Py_path_intersects_path__doc__ = - "path_intersects_path(path1, path2, filled=False)\n" - "--\n\n"; - -static PyObject *Py_path_intersects_path(PyObject *self, PyObject *args, PyObject *kwds) -{ - py::PathIterator p1; - py::PathIterator p2; - agg::trans_affine t1; - agg::trans_affine t2; - int filled = 0; - const char *names[] = { "p1", "p2", "filled", NULL }; - bool result; - - if (!PyArg_ParseTupleAndKeywords(args, - kwds, - "O&O&i:path_intersects_path", - (char **)names, - &convert_path, - &p1, - &convert_path, - &p2, - &filled)) { - return NULL; - } - - CALL_CPP("path_intersects_path", (result = path_intersects_path(p1, p2))); - if (filled) { - if (!result) { - CALL_CPP("path_intersects_path", - (result = path_in_path(p1, t1, p2, t2))); - } - if (!result) { - CALL_CPP("path_intersects_path", - (result = path_in_path(p2, t1, p1, t2))); - } - } - - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -const char *Py_path_intersects_rectangle__doc__ = - "path_intersects_rectangle(" - "path, rect_x1, rect_y1, rect_x2, rect_y2, filled=False)\n" - "--\n\n"; - -static PyObject *Py_path_intersects_rectangle(PyObject *self, PyObject *args, PyObject *kwds) -{ - py::PathIterator path; - double rect_x1, rect_y1, rect_x2, rect_y2; - bool filled = false; - const char *names[] = { "path", "rect_x1", "rect_y1", "rect_x2", "rect_y2", "filled", NULL }; - bool result; - - if (!PyArg_ParseTupleAndKeywords(args, - kwds, - "O&dddd|O&:path_intersects_rectangle", - (char **)names, - &convert_path, - &path, - &rect_x1, - &rect_y1, - &rect_x2, - &rect_y2, - &convert_bool, - &filled)) { - return NULL; - } - - CALL_CPP("path_intersects_rectangle", (result = path_intersects_rectangle(path, rect_x1, rect_y1, rect_x2, rect_y2, filled))); - - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - -const char *Py_convert_path_to_polygons__doc__ = - "convert_path_to_polygons(path, trans, width=0, height=0)\n" - "--\n\n"; - -static PyObject *Py_convert_path_to_polygons(PyObject *self, PyObject *args, PyObject *kwds) -{ - py::PathIterator path; - agg::trans_affine trans; - double width = 0.0, height = 0.0; - int closed_only = 1; - std::vector result; - const char *names[] = { "path", "transform", "width", "height", "closed_only", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, - kwds, - "O&O&|ddi:convert_path_to_polygons", - (char **)names, - &convert_path, - &path, - &convert_trans_affine, - &trans, - &width, - &height, - &closed_only)) { - return NULL; - } - - CALL_CPP("convert_path_to_polygons", - (convert_path_to_polygons(path, trans, width, height, closed_only, result))); - - return convert_polygon_vector(result); -} - -const char *Py_cleanup_path__doc__ = - "cleanup_path(" - "path, trans, remove_nans, clip_rect, snap_mode, stroke_width, simplify, " - "return_curves, sketch)\n" - "--\n\n"; - -static PyObject *Py_cleanup_path(PyObject *self, PyObject *args) -{ - py::PathIterator path; - agg::trans_affine trans; - bool remove_nans; - agg::rect_d clip_rect; - e_snap_mode snap_mode; - double stroke_width; - PyObject *simplifyobj; - bool simplify = false; - bool return_curves; - SketchParams sketch; - - if (!PyArg_ParseTuple(args, - "O&O&O&O&O&dOO&O&:cleanup_path", - &convert_path, - &path, - &convert_trans_affine, - &trans, - &convert_bool, - &remove_nans, - &convert_rect, - &clip_rect, - &convert_snap, - &snap_mode, - &stroke_width, - &simplifyobj, - &convert_bool, - &return_curves, - &convert_sketch_params, - &sketch)) { - return NULL; - } - - if (simplifyobj == Py_None) { - simplify = path.should_simplify(); - } else { - switch (PyObject_IsTrue(simplifyobj)) { - case 0: simplify = false; break; - case 1: simplify = true; break; - default: return NULL; // errored. - } - } - - bool do_clip = (clip_rect.x1 < clip_rect.x2 && clip_rect.y1 < clip_rect.y2); - - std::vector vertices; - std::vector codes; - - CALL_CPP("cleanup_path", - (cleanup_path(path, - trans, - remove_nans, - do_clip, - clip_rect, - snap_mode, - stroke_width, - simplify, - return_curves, - sketch, - vertices, - codes))); - - size_t length = codes.size(); - - npy_intp vertices_dims[] = {(npy_intp)length, 2 }; - numpy::array_view pyvertices(vertices_dims); - - npy_intp codes_dims[] = {(npy_intp)length }; - numpy::array_view pycodes(codes_dims); - - memcpy(pyvertices.data(), &vertices[0], sizeof(double) * 2 * length); - memcpy(pycodes.data(), &codes[0], sizeof(unsigned char) * length); - - return Py_BuildValue("NN", pyvertices.pyobj(), pycodes.pyobj()); -} - -const char *Py_convert_to_string__doc__ = - "convert_to_string(" - "path, trans, clip_rect, simplify, sketch, precision, codes, postfix)\n" - "--\n\n" - "Convert *path* to a bytestring.\n" - "\n" - "The first five parameters (up to *sketch*) are interpreted as in\n" - "`.cleanup_path`. The following ones are detailed below.\n" - "\n" - "Parameters\n" - "----------\n" - "path : Path\n" - "trans : Transform or None\n" - "clip_rect : sequence of 4 floats, or None\n" - "simplify : bool\n" - "sketch : tuple of 3 floats, or None\n" - "precision : int\n" - " The precision used to \"%.*f\"-format the values. Trailing zeros\n" - " and decimal points are always removed. (precision=-1 is a special\n" - " case used to implement ttconv-back-compatible conversion.)\n" - "codes : sequence of 5 bytestrings\n" - " The bytes representation of each opcode (MOVETO, LINETO, CURVE3,\n" - " CURVE4, CLOSEPOLY), in that order. If the bytes for CURVE3 is\n" - " empty, quad segments are automatically converted to cubic ones\n" - " (this is used by backends such as pdf and ps, which do not support\n" - " quads).\n" - "postfix : bool\n" - " Whether the opcode comes after the values (True) or before (False).\n" - ; - -static PyObject *Py_convert_to_string(PyObject *self, PyObject *args) -{ - py::PathIterator path; - agg::trans_affine trans; - agg::rect_d cliprect; - PyObject *simplifyobj; - bool simplify = false; - SketchParams sketch; - int precision; - char *codes[5]; - bool postfix; - std::string buffer; - bool status; - - if (!PyArg_ParseTuple(args, - "O&O&O&OO&i(yyyyy)O&:convert_to_string", - &convert_path, - &path, - &convert_trans_affine, - &trans, - &convert_rect, - &cliprect, - &simplifyobj, - &convert_sketch_params, - &sketch, - &precision, - &codes[0], - &codes[1], - &codes[2], - &codes[3], - &codes[4], - &convert_bool, - &postfix)) { - return NULL; - } - - if (simplifyobj == Py_None) { - simplify = path.should_simplify(); - } else { - switch (PyObject_IsTrue(simplifyobj)) { - case 0: simplify = false; break; - case 1: simplify = true; break; - default: return NULL; // errored. - } - } - - CALL_CPP("convert_to_string", - (status = convert_to_string( - path, trans, cliprect, simplify, sketch, - precision, codes, postfix, buffer))); - - if (!status) { - PyErr_SetString(PyExc_ValueError, "Malformed path codes"); - return NULL; - } - - return PyBytes_FromStringAndSize(buffer.c_str(), buffer.size()); -} - - -const char *Py_is_sorted_and_has_non_nan__doc__ = - "is_sorted_and_has_non_nan(array, /)\n" - "--\n\n" - "Return whether the 1D *array* is monotonically increasing, ignoring NaNs,\n" - "and has at least one non-nan value."; - -static PyObject *Py_is_sorted_and_has_non_nan(PyObject *self, PyObject *obj) -{ - bool result; - - PyArrayObject *array = (PyArrayObject *)PyArray_FromAny( - obj, NULL, 1, 1, 0, NULL); - - if (array == NULL) { - return NULL; - } - - /* Handle just the most common types here, otherwise coerce to double */ - switch (PyArray_TYPE(array)) { - case NPY_INT: - result = is_sorted_and_has_non_nan(array); - break; - case NPY_LONG: - result = is_sorted_and_has_non_nan(array); - break; - case NPY_LONGLONG: - result = is_sorted_and_has_non_nan(array); - break; - case NPY_FLOAT: - result = is_sorted_and_has_non_nan(array); - break; - case NPY_DOUBLE: - result = is_sorted_and_has_non_nan(array); - break; - default: - Py_DECREF(array); - array = (PyArrayObject *)PyArray_FromObject(obj, NPY_DOUBLE, 1, 1); - if (array == NULL) { - return NULL; - } - result = is_sorted_and_has_non_nan(array); - } - - Py_DECREF(array); - - if (result) { - Py_RETURN_TRUE; - } else { - Py_RETURN_FALSE; - } -} - - -static PyMethodDef module_functions[] = { - {"point_in_path", (PyCFunction)Py_point_in_path, METH_VARARGS, Py_point_in_path__doc__}, - {"points_in_path", (PyCFunction)Py_points_in_path, METH_VARARGS, Py_points_in_path__doc__}, - {"update_path_extents", (PyCFunction)Py_update_path_extents, METH_VARARGS, Py_update_path_extents__doc__}, - {"get_path_collection_extents", (PyCFunction)Py_get_path_collection_extents, METH_VARARGS, Py_get_path_collection_extents__doc__}, - {"point_in_path_collection", (PyCFunction)Py_point_in_path_collection, METH_VARARGS, Py_point_in_path_collection__doc__}, - {"path_in_path", (PyCFunction)Py_path_in_path, METH_VARARGS, Py_path_in_path__doc__}, - {"clip_path_to_rect", (PyCFunction)Py_clip_path_to_rect, METH_VARARGS, Py_clip_path_to_rect__doc__}, - {"affine_transform", (PyCFunction)Py_affine_transform, METH_VARARGS, Py_affine_transform__doc__}, - {"count_bboxes_overlapping_bbox", (PyCFunction)Py_count_bboxes_overlapping_bbox, METH_VARARGS, Py_count_bboxes_overlapping_bbox__doc__}, - {"path_intersects_path", (PyCFunction)Py_path_intersects_path, METH_VARARGS|METH_KEYWORDS, Py_path_intersects_path__doc__}, - {"path_intersects_rectangle", (PyCFunction)Py_path_intersects_rectangle, METH_VARARGS|METH_KEYWORDS, Py_path_intersects_rectangle__doc__}, - {"convert_path_to_polygons", (PyCFunction)Py_convert_path_to_polygons, METH_VARARGS|METH_KEYWORDS, Py_convert_path_to_polygons__doc__}, - {"cleanup_path", (PyCFunction)Py_cleanup_path, METH_VARARGS, Py_cleanup_path__doc__}, - {"convert_to_string", (PyCFunction)Py_convert_to_string, METH_VARARGS, Py_convert_to_string__doc__}, - {"is_sorted_and_has_non_nan", (PyCFunction)Py_is_sorted_and_has_non_nan, METH_O, Py_is_sorted_and_has_non_nan__doc__}, - {NULL} -}; - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, "_path", NULL, 0, module_functions -}; - -PyMODINIT_FUNC PyInit__path(void) -{ - import_array(); - return PyModule_Create(&moduledef); -} diff --git a/contrib/python/matplotlib/py3/src/_qhull_wrapper.cpp b/contrib/python/matplotlib/py3/src/_qhull_wrapper.cpp deleted file mode 100644 index 7e4f306305b..00000000000 --- a/contrib/python/matplotlib/py3/src/_qhull_wrapper.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Wrapper module for libqhull, providing Delaunay triangulation. - * - * This module's methods should not be accessed directly. To obtain a Delaunay - * triangulation, construct an instance of the matplotlib.tri.Triangulation - * class without specifying a triangles array. - */ -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "numpy_cpp.h" -#ifdef _MSC_VER -/* The Qhull header does not declare this as extern "C", but only MSVC seems to - * do name mangling on global variables. We thus need to declare this before - * the header so that it treats it correctly, and doesn't mangle the name. */ -extern "C" { -extern const char qh_version[]; -} -#endif -#include "libqhull_r/qhull_ra.h" -#include -#include - - -#ifndef MPL_DEVNULL -#error "MPL_DEVNULL must be defined as the OS-equivalent of /dev/null" -#endif - -#define STRINGIFY(x) STR(x) -#define STR(x) #x - - -static const char* qhull_error_msg[6] = { - "", /* 0 = qh_ERRnone */ - "input inconsistency", /* 1 = qh_ERRinput */ - "singular input data", /* 2 = qh_ERRsingular */ - "precision error", /* 3 = qh_ERRprec */ - "insufficient memory", /* 4 = qh_ERRmem */ - "internal error"}; /* 5 = qh_ERRqhull */ - - -/* Return the indices of the 3 vertices that comprise the specified facet (i.e. - * triangle). */ -static void -get_facet_vertices(qhT* qh, const facetT* facet, int indices[3]) -{ - vertexT *vertex, **vertexp; - FOREACHvertex_(facet->vertices) { - *indices++ = qh_pointid(qh, vertex->point); - } -} - -/* Return the indices of the 3 triangles that are neighbors of the specified - * facet (triangle). */ -static void -get_facet_neighbours(const facetT* facet, std::vector& tri_indices, - int indices[3]) -{ - facetT *neighbor, **neighborp; - FOREACHneighbor_(facet) { - *indices++ = (neighbor->upperdelaunay ? -1 : tri_indices[neighbor->id]); - } -} - -/* Return true if the specified points arrays contain at least 3 unique points, - * or false otherwise. */ -static bool -at_least_3_unique_points(npy_intp npoints, const double* x, const double* y) -{ - int i; - const int unique1 = 0; /* First unique point has index 0. */ - int unique2 = 0; /* Second unique point index is 0 until set. */ - - if (npoints < 3) { - return false; - } - - for (i = 1; i < npoints; ++i) { - if (unique2 == 0) { - /* Looking for second unique point. */ - if (x[i] != x[unique1] || y[i] != y[unique1]) { - unique2 = i; - } - } - else { - /* Looking for third unique point. */ - if ( (x[i] != x[unique1] || y[i] != y[unique1]) && - (x[i] != x[unique2] || y[i] != y[unique2]) ) { - /* 3 unique points found, with indices 0, unique2 and i. */ - return true; - } - } - } - - /* Run out of points before 3 unique points found. */ - return false; -} - -/* Holds on to info from Qhull so that it can be destructed automatically. */ -class QhullInfo { -public: - QhullInfo(FILE *error_file, qhT* qh) { - this->error_file = error_file; - this->qh = qh; - } - - ~QhullInfo() { - qh_freeqhull(this->qh, !qh_ALL); - int curlong, totlong; /* Memory remaining. */ - qh_memfreeshort(this->qh, &curlong, &totlong); - if (curlong || totlong) { - PyErr_WarnEx(PyExc_RuntimeWarning, - "Qhull could not free all allocated memory", 1); - } - - if (this->error_file != stderr) { - fclose(error_file); - } - } - -private: - FILE* error_file; - qhT* qh; -}; - -/* Delaunay implementation method. - * If hide_qhull_errors is true then qhull error messages are discarded; - * if it is false then they are written to stderr. */ -static PyObject* -delaunay_impl(npy_intp npoints, const double* x, const double* y, - bool hide_qhull_errors) -{ - qhT qh_qh; /* qh variable type and name must be like */ - qhT* qh = &qh_qh; /* this for Qhull macros to work correctly. */ - facetT* facet; - int i, ntri, max_facet_id; - int exitcode; /* Value returned from qh_new_qhull(). */ - const int ndim = 2; - double x_mean = 0.0; - double y_mean = 0.0; - - QHULL_LIB_CHECK - - /* Allocate points. */ - std::vector points(npoints * ndim); - - /* Determine mean x, y coordinates. */ - for (i = 0; i < npoints; ++i) { - x_mean += x[i]; - y_mean += y[i]; - } - x_mean /= npoints; - y_mean /= npoints; - - /* Prepare points array to pass to qhull. */ - for (i = 0; i < npoints; ++i) { - points[2*i ] = x[i] - x_mean; - points[2*i+1] = y[i] - y_mean; - } - - /* qhull expects a FILE* to write errors to. */ - FILE* error_file = NULL; - if (hide_qhull_errors) { - /* qhull errors are ignored by writing to OS-equivalent of /dev/null. - * Rather than have OS-specific code here, instead it is determined by - * setupext.py and passed in via the macro MPL_DEVNULL. */ - error_file = fopen(STRINGIFY(MPL_DEVNULL), "w"); - if (error_file == NULL) { - throw std::runtime_error("Could not open devnull"); - } - } - else { - /* qhull errors written to stderr. */ - error_file = stderr; - } - - /* Perform Delaunay triangulation. */ - QhullInfo info(error_file, qh); - qh_zero(qh, error_file); - exitcode = qh_new_qhull(qh, ndim, (int)npoints, points.data(), False, - (char*)"qhull d Qt Qbb Qc Qz", NULL, error_file); - if (exitcode != qh_ERRnone) { - PyErr_Format(PyExc_RuntimeError, - "Error in qhull Delaunay triangulation calculation: %s (exitcode=%d)%s", - qhull_error_msg[exitcode], exitcode, - hide_qhull_errors ? "; use python verbose option (-v) to see original qhull error." : ""); - return NULL; - } - - /* Split facets so that they only have 3 points each. */ - qh_triangulate(qh); - - /* Determine ntri and max_facet_id. - Note that libqhull uses macros to iterate through collections. */ - ntri = 0; - FORALLfacets { - if (!facet->upperdelaunay) { - ++ntri; - } - } - - max_facet_id = qh->facet_id - 1; - - /* Create array to map facet id to triangle index. */ - std::vector tri_indices(max_facet_id+1); - - /* Allocate Python arrays to return. */ - npy_intp dims[2] = {ntri, 3}; - numpy::array_view triangles(dims); - int* triangles_ptr = triangles.data(); - - numpy::array_view neighbors(dims); - int* neighbors_ptr = neighbors.data(); - - /* Determine triangles array and set tri_indices array. */ - i = 0; - FORALLfacets { - if (!facet->upperdelaunay) { - int indices[3]; - tri_indices[facet->id] = i++; - get_facet_vertices(qh, facet, indices); - *triangles_ptr++ = (facet->toporient ? indices[0] : indices[2]); - *triangles_ptr++ = indices[1]; - *triangles_ptr++ = (facet->toporient ? indices[2] : indices[0]); - } - else { - tri_indices[facet->id] = -1; - } - } - - /* Determine neighbors array. */ - FORALLfacets { - if (!facet->upperdelaunay) { - int indices[3]; - get_facet_neighbours(facet, tri_indices, indices); - *neighbors_ptr++ = (facet->toporient ? indices[2] : indices[0]); - *neighbors_ptr++ = (facet->toporient ? indices[0] : indices[2]); - *neighbors_ptr++ = indices[1]; - } - } - - PyObject* tuple = PyTuple_New(2); - if (tuple == 0) { - throw std::runtime_error("Failed to create Python tuple"); - } - - PyTuple_SET_ITEM(tuple, 0, triangles.pyobj()); - PyTuple_SET_ITEM(tuple, 1, neighbors.pyobj()); - return tuple; -} - -/* Process Python arguments and call Delaunay implementation method. */ -static PyObject* -delaunay(PyObject *self, PyObject *args) -{ - numpy::array_view xarray; - numpy::array_view yarray; - PyObject* ret; - npy_intp npoints; - const double* x; - const double* y; - int verbose = 0; - - if (!PyArg_ParseTuple(args, "O&O&i:delaunay", - &xarray.converter_contiguous, &xarray, - &yarray.converter_contiguous, &yarray, - &verbose)) { - return NULL; - } - - npoints = xarray.dim(0); - if (npoints != yarray.dim(0)) { - PyErr_SetString(PyExc_ValueError, - "x and y must be 1D arrays of the same length"); - return NULL; - } - - if (npoints < 3) { - PyErr_SetString(PyExc_ValueError, - "x and y arrays must have a length of at least 3"); - return NULL; - } - - x = xarray.data(); - y = yarray.data(); - - if (!at_least_3_unique_points(npoints, x, y)) { - PyErr_SetString(PyExc_ValueError, - "x and y arrays must consist of at least 3 unique points"); - return NULL; - } - - CALL_CPP("qhull.delaunay", - (ret = delaunay_impl(npoints, x, y, verbose == 0))); - - return ret; -} - -/* Return qhull version string for assistance in debugging. */ -static PyObject* -version(PyObject *self, PyObject *arg) -{ - return PyBytes_FromString(qh_version); -} - -static PyMethodDef qhull_methods[] = { - {"delaunay", delaunay, METH_VARARGS, - "delaunay(x, y, verbose, /)\n" - "--\n\n" - "Compute a Delaunay triangulation.\n" - "\n" - "Parameters\n" - "----------\n" - "x, y : 1d arrays\n" - " The coordinates of the point set, which must consist of at least\n" - " three unique points.\n" - "verbose : int\n" - " Python's verbosity level.\n" - "\n" - "Returns\n" - "-------\n" - "triangles, neighbors : int arrays, shape (ntri, 3)\n" - " Indices of triangle vertices and indices of triangle neighbors.\n" - }, - {"version", version, METH_NOARGS, - "version()\n--\n\n" - "Return the qhull version string."}, - {NULL, NULL, 0, NULL} -}; - -static struct PyModuleDef qhull_module = { - PyModuleDef_HEAD_INIT, - "qhull", "Computing Delaunay triangulations.\n", -1, qhull_methods -}; - -PyMODINIT_FUNC -PyInit__qhull(void) -{ - import_array(); - return PyModule_Create(&qhull_module); -} diff --git a/contrib/python/matplotlib/py3/src/_tkagg.cpp b/contrib/python/matplotlib/py3/src/_tkagg.cpp deleted file mode 100644 index 5c36b3f07f5..00000000000 --- a/contrib/python/matplotlib/py3/src/_tkagg.cpp +++ /dev/null @@ -1,370 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -// Where is PIL? -// -// Many years ago, Matplotlib used to include code from PIL (the Python Imaging -// Library). Since then, the code has changed a lot - the organizing principle -// and methods of operation are now quite different. Because our review of -// the codebase showed that all the code that came from PIL was removed or -// rewritten, we have removed the PIL licensing information. If you want PIL, -// you can get it at https://python-pillow.org/ - -#define PY_SSIZE_T_CLEAN -#include - -#ifdef _WIN32 -#define WIN32_DLL -#endif -#ifdef __CYGWIN__ -/* - * Unfortunately cygwin's libdl inherits restrictions from the underlying - * Windows OS, at least currently. Therefore, a symbol may be loaded from a - * module by dlsym() only if it is really located in the given module, - * dependencies are not included. So we have to use native WinAPI on Cygwin - * also. - */ -#define WIN32_DLL -static inline PyObject *PyErr_SetFromWindowsErr(int ierr) { - PyErr_SetString(PyExc_OSError, "Call to EnumProcessModules failed"); - return NULL; -} -#endif - -#ifdef WIN32_DLL -#include -#include -#include -#define PSAPI_VERSION 1 -#include // Must be linked with 'psapi' library -#define dlsym GetProcAddress -#else -#include -#endif - -// Include our own excerpts from the Tcl / Tk headers -#include "_tkmini.h" - -static int convert_voidptr(PyObject *obj, void *p) -{ - void **val = (void **)p; - *val = PyLong_AsVoidPtr(obj); - return *val != NULL ? 1 : !PyErr_Occurred(); -} - -// Global vars for Tk functions. We load these symbols from the tkinter -// extension module or loaded Tk libraries at run-time. -static Tk_FindPhoto_t TK_FIND_PHOTO; -static Tk_PhotoPutBlock_t TK_PHOTO_PUT_BLOCK; -// Global vars for Tcl functions. We load these symbols from the tkinter -// extension module or loaded Tcl libraries at run-time. -static Tcl_SetVar_t TCL_SETVAR; - -static PyObject *mpl_tk_blit(PyObject *self, PyObject *args) -{ - Tcl_Interp *interp; - char const *photo_name; - int height, width; - unsigned char *data_ptr; - int comp_rule; - int put_retval; - int o0, o1, o2, o3; - int x1, x2, y1, y2; - Tk_PhotoHandle photo; - Tk_PhotoImageBlock block; - if (!PyArg_ParseTuple(args, "O&s(iiO&)i(iiii)(iiii):blit", - convert_voidptr, &interp, &photo_name, - &height, &width, convert_voidptr, &data_ptr, - &comp_rule, - &o0, &o1, &o2, &o3, - &x1, &x2, &y1, &y2)) { - goto exit; - } - if (!(photo = TK_FIND_PHOTO(interp, photo_name))) { - PyErr_SetString(PyExc_ValueError, "Failed to extract Tk_PhotoHandle"); - goto exit; - } - if (0 > y1 || y1 > y2 || y2 > height || 0 > x1 || x1 > x2 || x2 > width) { - PyErr_SetString(PyExc_ValueError, "Attempting to draw out of bounds"); - goto exit; - } - if (comp_rule != TK_PHOTO_COMPOSITE_OVERLAY && comp_rule != TK_PHOTO_COMPOSITE_SET) { - PyErr_SetString(PyExc_ValueError, "Invalid comp_rule argument"); - goto exit; - } - - Py_BEGIN_ALLOW_THREADS - block.pixelPtr = data_ptr + 4 * ((height - y2) * width + x1); - block.width = x2 - x1; - block.height = y2 - y1; - block.pitch = 4 * width; - block.pixelSize = 4; - block.offset[0] = o0; - block.offset[1] = o1; - block.offset[2] = o2; - block.offset[3] = o3; - put_retval = TK_PHOTO_PUT_BLOCK( - interp, photo, &block, x1, height - y2, x2 - x1, y2 - y1, comp_rule); - Py_END_ALLOW_THREADS - if (put_retval == TCL_ERROR) { - return PyErr_NoMemory(); - } - -exit: - if (PyErr_Occurred()) { - return NULL; - } else { - Py_RETURN_NONE; - } -} - -#ifdef WIN32_DLL -LRESULT CALLBACK -DpiSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, - UINT_PTR uIdSubclass, DWORD_PTR dwRefData) -{ - switch (uMsg) { - case WM_DPICHANGED: - // This function is a subclassed window procedure, and so is run during - // the Tcl/Tk event loop. Unfortunately, Tkinter has a *second* lock on - // Tcl threading that is not exposed publicly, but is currently taken - // while we're in the window procedure. So while we can take the GIL to - // call Python code, we must not also call *any* Tk code from Python. - // So stay with Tcl calls in C only. - { - // This variable naming must match the name used in - // lib/matplotlib/backends/_backend_tk.py:FigureManagerTk. - std::string var_name("window_dpi"); - var_name += std::to_string((unsigned long long)hwnd); - - // X is high word, Y is low word, but they are always equal. - std::string dpi = std::to_string(LOWORD(wParam)); - - Tcl_Interp* interp = (Tcl_Interp*)dwRefData; - TCL_SETVAR(interp, var_name.c_str(), dpi.c_str(), 0); - } - return 0; - case WM_NCDESTROY: - RemoveWindowSubclass(hwnd, DpiSubclassProc, uIdSubclass); - break; - } - - return DefSubclassProc(hwnd, uMsg, wParam, lParam); -} -#endif - -static PyObject* -mpl_tk_enable_dpi_awareness(PyObject* self, PyObject*const* args, - Py_ssize_t nargs) -{ - if (nargs != 2) { - return PyErr_Format(PyExc_TypeError, - "enable_dpi_awareness() takes 2 positional " - "arguments but %zd were given", - nargs); - } - -#ifdef WIN32_DLL - HWND frame_handle = NULL; - Tcl_Interp *interp = NULL; - - if (!convert_voidptr(args[0], &frame_handle)) { - return NULL; - } - if (!convert_voidptr(args[1], &interp)) { - return NULL; - } - -#ifdef _DPI_AWARENESS_CONTEXTS_ - HMODULE user32 = LoadLibrary("user32.dll"); - - typedef DPI_AWARENESS_CONTEXT (WINAPI *GetWindowDpiAwarenessContext_t)(HWND); - GetWindowDpiAwarenessContext_t GetWindowDpiAwarenessContextPtr = - (GetWindowDpiAwarenessContext_t)GetProcAddress( - user32, "GetWindowDpiAwarenessContext"); - if (GetWindowDpiAwarenessContextPtr == NULL) { - FreeLibrary(user32); - Py_RETURN_FALSE; - } - - typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual_t)(DPI_AWARENESS_CONTEXT, - DPI_AWARENESS_CONTEXT); - AreDpiAwarenessContextsEqual_t AreDpiAwarenessContextsEqualPtr = - (AreDpiAwarenessContextsEqual_t)GetProcAddress( - user32, "AreDpiAwarenessContextsEqual"); - if (AreDpiAwarenessContextsEqualPtr == NULL) { - FreeLibrary(user32); - Py_RETURN_FALSE; - } - - DPI_AWARENESS_CONTEXT ctx = GetWindowDpiAwarenessContextPtr(frame_handle); - bool per_monitor = ( - AreDpiAwarenessContextsEqualPtr( - ctx, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) || - AreDpiAwarenessContextsEqualPtr( - ctx, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)); - - if (per_monitor) { - // Per monitor aware means we need to handle WM_DPICHANGED by wrapping - // the Window Procedure, and the Python side needs to trace the Tk - // window_dpi variable stored on interp. - SetWindowSubclass(frame_handle, DpiSubclassProc, 0, (DWORD_PTR)interp); - } - FreeLibrary(user32); - return PyBool_FromLong(per_monitor); -#endif -#endif - - Py_RETURN_NONE; -} - -static PyMethodDef functions[] = { - { "blit", (PyCFunction)mpl_tk_blit, METH_VARARGS }, - { "enable_dpi_awareness", (PyCFunction)mpl_tk_enable_dpi_awareness, - METH_FASTCALL }, - { NULL, NULL } /* sentinel */ -}; - -// Functions to fill global Tcl/Tk function pointers by dynamic loading. - -template -bool load_tcl_tk(T lib) -{ - // Try to fill Tcl/Tk global vars with function pointers. Return whether - // all of them have been filled. - if (auto ptr = dlsym(lib, "Tcl_SetVar")) { - TCL_SETVAR = (Tcl_SetVar_t)ptr; - } - if (auto ptr = dlsym(lib, "Tk_FindPhoto")) { - TK_FIND_PHOTO = (Tk_FindPhoto_t)ptr; - } - if (auto ptr = dlsym(lib, "Tk_PhotoPutBlock")) { - TK_PHOTO_PUT_BLOCK = (Tk_PhotoPutBlock_t)ptr; - } - return TCL_SETVAR && TK_FIND_PHOTO && TK_PHOTO_PUT_BLOCK; -} - -#ifdef WIN32_DLL - -/* On Windows, we can't load the tkinter module to get the Tcl/Tk symbols, - * because Windows does not load symbols into the library name-space of - * importing modules. So, knowing that tkinter has already been imported by - * Python, we scan all modules in the running process for the Tcl/Tk function - * names. - */ - -void load_tkinter_funcs(void) -{ - HANDLE process = GetCurrentProcess(); // Pseudo-handle, doesn't need closing. - HMODULE* modules = NULL; - DWORD size; - if (!EnumProcessModules(process, NULL, 0, &size)) { - PyErr_SetFromWindowsErr(0); - goto exit; - } - if (!(modules = static_cast(malloc(size)))) { - PyErr_NoMemory(); - goto exit; - } - if (!EnumProcessModules(process, modules, size, &size)) { - PyErr_SetFromWindowsErr(0); - goto exit; - } - for (unsigned i = 0; i < size / sizeof(HMODULE); ++i) { - if (load_tcl_tk(modules[i])) { - return; - } - } -exit: - free(modules); -} - -#else // not Windows - -/* - * On Unix, we can get the Tk symbols from the tkinter module, because tkinter - * uses these symbols, and the symbols are therefore visible in the tkinter - * dynamic library (module). - */ - -void load_tkinter_funcs(void) -{ - // Load tkinter global funcs from tkinter compiled module. - void *main_program = NULL, *tkinter_lib = NULL; - PyObject *module = NULL, *py_path = NULL, *py_path_b = NULL; - char *path; - - // Try loading from the main program namespace first. - main_program = dlopen(NULL, RTLD_LAZY); - if (load_tcl_tk(main_program)) { - goto exit; - } - // Clear exception triggered when we didn't find symbols above. - PyErr_Clear(); - - // Handle PyPy first, as that import will correctly fail on CPython. - module = PyImport_ImportModule("_tkinter.tklib_cffi"); // PyPy - if (!module) { - PyErr_Clear(); - module = PyImport_ImportModule("_tkinter"); // CPython - } - if (!(module && - (py_path = PyObject_GetAttrString(module, "__file__")) && - (py_path_b = PyUnicode_EncodeFSDefault(py_path)) && - (path = PyBytes_AsString(py_path_b)))) { - goto exit; - } - tkinter_lib = dlopen(path, RTLD_LAZY); - if (!tkinter_lib) { - PyErr_SetString(PyExc_RuntimeError, dlerror()); - goto exit; - } - if (load_tcl_tk(tkinter_lib)) { - goto exit; - } - -exit: - // We don't need to keep a reference open as the main program & tkinter - // have been imported. Try to close each library separately (otherwise the - // second dlclose could clear a dlerror from the first dlclose). - bool raised_dlerror = false; - if (main_program && dlclose(main_program) && !raised_dlerror) { - PyErr_SetString(PyExc_RuntimeError, dlerror()); - raised_dlerror = true; - } - if (tkinter_lib && dlclose(tkinter_lib) && !raised_dlerror) { - PyErr_SetString(PyExc_RuntimeError, dlerror()); - raised_dlerror = true; - } - Py_XDECREF(module); - Py_XDECREF(py_path); - Py_XDECREF(py_path_b); -} -#endif // end not Windows - -static PyModuleDef _tkagg_module = { - PyModuleDef_HEAD_INIT, "_tkagg", NULL, -1, functions -}; - -PyMODINIT_FUNC PyInit__tkagg(void) -{ - load_tkinter_funcs(); - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - // Always raise ImportError (normalizing a previously set exception if - // needed) to interact properly with backend auto-fallback. - if (value) { - PyErr_NormalizeException(&type, &value, &traceback); - PyErr_SetObject(PyExc_ImportError, value); - return NULL; - } else if (!TCL_SETVAR) { - PyErr_SetString(PyExc_ImportError, "Failed to load Tcl_SetVar"); - return NULL; - } else if (!TK_FIND_PHOTO) { - PyErr_SetString(PyExc_ImportError, "Failed to load Tk_FindPhoto"); - return NULL; - } else if (!TK_PHOTO_PUT_BLOCK) { - PyErr_SetString(PyExc_ImportError, "Failed to load Tk_PhotoPutBlock"); - return NULL; - } - return PyModule_Create(&_tkagg_module); -} diff --git a/contrib/python/matplotlib/py3/src/_tkmini.h b/contrib/python/matplotlib/py3/src/_tkmini.h deleted file mode 100644 index 85f245815e4..00000000000 --- a/contrib/python/matplotlib/py3/src/_tkmini.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Small excerpts from the Tcl / Tk 8.6 headers - * - * License terms copied from: - * http://www.tcl.tk/software/tcltk/license.html - * as of 20 May 2016. - * - * Copyright (c) 1987-1994 The Regents of the University of California. - * Copyright (c) 1993-1996 Lucent Technologies. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 by Scriptics Corporation. - * Copyright (c) 2002 by Kevin B. Kenny. All rights reserved. - * - * This software is copyrighted by the Regents of the University - * of California, Sun Microsystems, Inc., Scriptics Corporation, - * and other parties. The following terms apply to all files - * associated with the software unless explicitly disclaimed in - * individual files. - * - * The authors hereby grant permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized uses. - * Modifications to this software may be copyrighted by their - * authors and need not follow the licensing terms described - * here, provided that the new terms are clearly indicated on - * the first page of each file where they apply. - * - * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO - * ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS - * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN - * IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON - * AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, - * ENHANCEMENTS, OR MODIFICATIONS. - * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license - */ - -/* - * Unless otherwise noted, these definitions are stable from Tcl / Tk 8.5 - * through Tck / Tk master as of 21 May 2016 - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Users of versions of Tcl >= 8.6 encouraged to treat Tcl_Interp as an opaque - * pointer. The following definition results when TCL_NO_DEPRECATED defined. - */ -typedef struct Tcl_Interp Tcl_Interp; - -/* Tk header excerpts */ - -typedef void *Tk_PhotoHandle; - -typedef struct Tk_PhotoImageBlock -{ - unsigned char *pixelPtr; - int width; - int height; - int pitch; - int pixelSize; - int offset[4]; -} Tk_PhotoImageBlock; - -#define TK_PHOTO_COMPOSITE_OVERLAY 0 // apply transparency rules pixel-wise -#define TK_PHOTO_COMPOSITE_SET 1 // set image buffer directly -#define TCL_OK 0 -#define TCL_ERROR 1 - -/* Typedefs derived from function signatures in Tk header */ -/* Tk_FindPhoto typedef */ -typedef Tk_PhotoHandle (*Tk_FindPhoto_t) (Tcl_Interp *interp, const char - *imageName); -/* Tk_PhotoPutBLock typedef */ -typedef int (*Tk_PhotoPutBlock_t) (Tcl_Interp *interp, Tk_PhotoHandle handle, - Tk_PhotoImageBlock *blockPtr, int x, int y, - int width, int height, int compRule); - -/* Typedefs derived from function signatures in Tcl header */ -/* Tcl_SetVar typedef */ -typedef const char *(*Tcl_SetVar_t)(Tcl_Interp *interp, const char *varName, - const char *newValue, int flags); - -#ifdef __cplusplus -} -#endif diff --git a/contrib/python/matplotlib/py3/src/_ttconv.cpp b/contrib/python/matplotlib/py3/src/_ttconv.cpp deleted file mode 100644 index 72fdfba6961..00000000000 --- a/contrib/python/matplotlib/py3/src/_ttconv.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -/* - _ttconv.c - - Python wrapper for TrueType conversion library in ../ttconv. - */ -#include "mplutils.h" - -#include -#include "ttconv/pprdrv.h" -#include - -namespace py = pybind11; - -/** - * An implementation of TTStreamWriter that writes to a Python - * file-like object. - */ -class PythonFileWriter : public TTStreamWriter -{ - py::function _write_method; - - public: - PythonFileWriter(py::object& file_object) - : _write_method(file_object.attr("write")) {} - - virtual void write(const char *a) - { - PyObject* decoded = PyUnicode_DecodeLatin1(a, strlen(a), ""); - if (decoded == NULL) { - throw py::error_already_set(); - } - _write_method(py::handle(decoded)); - Py_DECREF(decoded); - } -}; - -static void convert_ttf_to_ps( - const char *filename, - py::object &output, - int fonttype, - py::iterable* glyph_ids) -{ - PythonFileWriter output_(output); - - std::vector glyph_ids_; - if (glyph_ids) { - for (py::handle glyph_id: *glyph_ids) { - glyph_ids_.push_back(glyph_id.cast()); - } - } - - if (fonttype != 3 && fonttype != 42) { - throw py::value_error( - "fonttype must be either 3 (raw Postscript) or 42 (embedded Truetype)"); - } - - try - { - insert_ttfont(filename, output_, static_cast(fonttype), glyph_ids_); - } - catch (TTException &e) - { - throw std::runtime_error(e.getMessage()); - } - catch (...) - { - throw std::runtime_error("Unknown C++ exception"); - } -} - -PYBIND11_MODULE(_ttconv, m) { - m.doc() = "Module to handle converting and subsetting TrueType " - "fonts to Postscript Type 3, Postscript Type 42 and " - "Pdf Type 3 fonts."; - m.def("convert_ttf_to_ps", &convert_ttf_to_ps, - py::arg("filename"), - py::arg("output"), - py::arg("fonttype"), - py::arg("glyph_ids") = py::none(), - "Converts the Truetype font into a Type 3 or Type 42 Postscript font, " - "optionally subsetting the font to only the desired set of characters.\n" - "\n" - "filename is the path to a TTF font file.\n" - "output is a Python file-like object with a write method that the Postscript " - "font data will be written to.\n" - "fonttype may be either 3 or 42. Type 3 is a \"raw Postscript\" font. " - "Type 42 is an embedded Truetype font. Glyph subsetting is not supported " - "for Type 42 fonts within this module (needs to be done externally).\n" - "glyph_ids (optional) is a list of glyph ids (integers) to keep when " - "subsetting to a Type 3 font. If glyph_ids is not provided or is None, " - "then all glyphs will be included. If any of the glyphs specified are " - "composite glyphs, then the component glyphs will also be included." - ); -} diff --git a/contrib/python/matplotlib/py3/src/agg_workaround.h b/contrib/python/matplotlib/py3/src/agg_workaround.h deleted file mode 100644 index 47621951928..00000000000 --- a/contrib/python/matplotlib/py3/src/agg_workaround.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef MPL_AGG_WORKAROUND_H -#define MPL_AGG_WORKAROUND_H - -#include "agg_pixfmt_rgba.h" - -/********************************************************************** - WORKAROUND: This class is to workaround a bug in Agg SVN where the - blending of RGBA32 pixels does not preserve enough precision -*/ - -template -struct fixed_blender_rgba_pre : agg::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; - 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, - value_type cr, value_type cg, value_type cb, - value_type alpha, agg::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) - { - alpha = base_mask - alpha; - p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); - p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); - p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } -}; - - -template -struct fixed_blender_rgba_plain : agg::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; - enum base_scale_e { base_shift = color_type::base_shift }; - - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - value_type cr, value_type cg, value_type cb, value_type alpha, agg::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 == 0) return; - calc_type a = p[Order::A]; - calc_type r = p[Order::R] * a; - calc_type g = p[Order::G] * a; - calc_type b = p[Order::B] * a; - a = ((alpha + a) << base_shift) - alpha * a; - p[Order::A] = (value_type)(a >> base_shift); - p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); - p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); - p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); - } -}; - -#endif diff --git a/contrib/python/matplotlib/py3/src/array.h b/contrib/python/matplotlib/py3/src/array.h deleted file mode 100644 index 47d82995541..00000000000 --- a/contrib/python/matplotlib/py3/src/array.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -/* Utilities to create scalars and empty arrays that behave like the - Numpy array wrappers in numpy_cpp.h */ - -#ifndef MPL_SCALAR_H -#define MPL_SCALAR_H - -namespace array -{ - -template -class scalar -{ - public: - T m_value; - - scalar(const T value) : m_value(value) - { - } - - T &operator()(int i, int j = 0, int k = 0) - { - return m_value; - } - - const T &operator()(int i, int j = 0, int k = 0) const - { - return m_value; - } - - int dim(size_t i) - { - return 1; - } - - size_t size() - { - return 1; - } -}; - -template -class empty -{ - public: - typedef empty sub_t; - - empty() - { - } - - T &operator()(int i, int j = 0, int k = 0) - { - throw std::runtime_error("Accessed empty array"); - } - - const T &operator()(int i, int j = 0, int k = 0) const - { - throw std::runtime_error("Accessed empty array"); - } - - sub_t operator[](int i) const - { - return empty(); - } - - int dim(size_t i) const - { - return 0; - } - - size_t size() const - { - return 0; - } -}; -} - -#endif diff --git a/contrib/python/matplotlib/py3/src/checkdep_freetype2.c b/contrib/python/matplotlib/py3/src/checkdep_freetype2.c deleted file mode 100644 index 8d9d8ca24a0..00000000000 --- a/contrib/python/matplotlib/py3/src/checkdep_freetype2.c +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef __has_include - #if !__has_include() - #error "FreeType version 2.3 or higher is required. \ -You may unset the system_freetype entry in mplsetup.cfg to let Matplotlib download it." - #endif -#endif - -#include -#include FT_FREETYPE_H - -#define XSTR(x) STR(x) -#define STR(x) #x - -#pragma message("Compiling with FreeType version " \ - XSTR(FREETYPE_MAJOR) "." XSTR(FREETYPE_MINOR) "." XSTR(FREETYPE_PATCH) ".") -#if FREETYPE_MAJOR << 16 + FREETYPE_MINOR << 8 + FREETYPE_PATCH < 0x020300 - #error "FreeType version 2.3 or higher is required. \ -You may unset the system_freetype entry in mplsetup.cfg to let Matplotlib download it." -#endif diff --git a/contrib/python/matplotlib/py3/src/ft2font.cpp b/contrib/python/matplotlib/py3/src/ft2font.cpp deleted file mode 100644 index 97504137413..00000000000 --- a/contrib/python/matplotlib/py3/src/ft2font.cpp +++ /dev/null @@ -1,840 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -#define NO_IMPORT_ARRAY - -#include -#include -#include -#include -#include - -#include "ft2font.h" -#include "mplutils.h" -#include "numpy_cpp.h" -#include "py_exceptions.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846264338328 -#endif - -/** - To improve the hinting of the fonts, this code uses a hack - presented here: - - http://agg.sourceforge.net/antigrain.com/research/font_rasterization/index.html - - The idea is to limit the effect of hinting in the x-direction, while - preserving hinting in the y-direction. Since freetype does not - support this directly, the dpi in the x-direction is set higher than - in the y-direction, which affects the hinting grid. Then, a global - transform is placed on the font to shrink it back to the desired - size. While it is a bit surprising that the dpi setting affects - hinting, whereas the global transform does not, this is documented - behavior of FreeType, and therefore hopefully unlikely to change. - The FreeType 2 tutorial says: - - NOTE: The transformation is applied to every glyph that is - loaded through FT_Load_Glyph and is completely independent of - any hinting process. This means that you won't get the same - results if you load a glyph at the size of 24 pixels, or a glyph - at the size at 12 pixels scaled by 2 through a transform, - because the hints will have been computed differently (except - you have disabled hints). - */ - -FT_Library _ft2Library; - -// FreeType error codes; loaded as per fterror.h. -static char const* ft_error_string(FT_Error error) { -#undef __FTERRORS_H__ -#define FT_ERROR_START_LIST switch (error) { -#define FT_ERRORDEF( e, v, s ) case v: return s; -#define FT_ERROR_END_LIST default: return NULL; } -#include FT_ERRORS_H -} - -void throw_ft_error(std::string message, FT_Error error) { - char const* s = ft_error_string(error); - std::ostringstream os(""); - if (s) { - os << message << " (" << s << "; error code 0x" << std::hex << error << ")"; - } else { // Should not occur, but don't add another error from failed lookup. - os << message << " (error code 0x" << std::hex << error << ")"; - } - throw std::runtime_error(os.str()); -} - -FT2Image::FT2Image() : m_dirty(true), m_buffer(NULL), m_width(0), m_height(0) -{ -} - -FT2Image::FT2Image(unsigned long width, unsigned long height) - : m_dirty(true), m_buffer(NULL), m_width(0), m_height(0) -{ - resize(width, height); -} - -FT2Image::~FT2Image() -{ - delete[] m_buffer; -} - -void FT2Image::resize(long width, long height) -{ - if (width <= 0) { - width = 1; - } - if (height <= 0) { - height = 1; - } - size_t numBytes = width * height; - - if ((unsigned long)width != m_width || (unsigned long)height != m_height) { - if (numBytes > m_width * m_height) { - delete[] m_buffer; - m_buffer = NULL; - m_buffer = new unsigned char[numBytes]; - } - - m_width = (unsigned long)width; - m_height = (unsigned long)height; - } - - if (numBytes && m_buffer) { - memset(m_buffer, 0, numBytes); - } - - m_dirty = true; -} - -void FT2Image::draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y) -{ - FT_Int image_width = (FT_Int)m_width; - FT_Int image_height = (FT_Int)m_height; - FT_Int char_width = bitmap->width; - FT_Int char_height = bitmap->rows; - - FT_Int x1 = std::min(std::max(x, 0), image_width); - FT_Int y1 = std::min(std::max(y, 0), image_height); - FT_Int x2 = std::min(std::max(x + char_width, 0), image_width); - FT_Int y2 = std::min(std::max(y + char_height, 0), image_height); - - FT_Int x_start = std::max(0, -x); - FT_Int y_offset = y1 - std::max(0, -y); - - if (bitmap->pixel_mode == FT_PIXEL_MODE_GRAY) { - for (FT_Int i = y1; i < y2; ++i) { - unsigned char *dst = m_buffer + (i * image_width + x1); - unsigned char *src = bitmap->buffer + (((i - y_offset) * bitmap->pitch) + x_start); - for (FT_Int j = x1; j < x2; ++j, ++dst, ++src) - *dst |= *src; - } - } else if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO) { - for (FT_Int i = y1; i < y2; ++i) { - unsigned char *dst = m_buffer + (i * image_width + x1); - unsigned char *src = bitmap->buffer + ((i - y_offset) * bitmap->pitch); - for (FT_Int j = x1; j < x2; ++j, ++dst) { - int x = (j - x1 + x_start); - int val = *(src + (x >> 3)) & (1 << (7 - (x & 0x7))); - *dst = val ? 255 : *dst; - } - } - } else { - throw std::runtime_error("Unknown pixel mode"); - } - - m_dirty = true; -} - -void FT2Image::draw_rect(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1) -{ - if (x0 > m_width || x1 > m_width || y0 > m_height || y1 > m_height) { - throw std::runtime_error("Rect coords outside image bounds"); - } - - size_t top = y0 * m_width; - size_t bottom = y1 * m_width; - for (size_t i = x0; i < x1 + 1; ++i) { - m_buffer[i + top] = 255; - m_buffer[i + bottom] = 255; - } - - for (size_t j = y0 + 1; j < y1; ++j) { - m_buffer[x0 + j * m_width] = 255; - m_buffer[x1 + j * m_width] = 255; - } - - m_dirty = true; -} - -void -FT2Image::draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1) -{ - x0 = std::min(x0, m_width); - y0 = std::min(y0, m_height); - x1 = std::min(x1 + 1, m_width); - y1 = std::min(y1 + 1, m_height); - - for (size_t j = y0; j < y1; j++) { - for (size_t i = x0; i < x1; i++) { - m_buffer[i + j * m_width] = 255; - } - } - - m_dirty = true; -} - -static void ft_glyph_warn(FT_ULong charcode) -{ - PyObject *text_helpers = NULL, *tmp = NULL; - if (!(text_helpers = PyImport_ImportModule("matplotlib._text_helpers")) || - !(tmp = PyObject_CallMethod(text_helpers, "warn_on_missing_glyph", "k", charcode))) { - goto exit; - } -exit: - Py_XDECREF(text_helpers); - Py_XDECREF(tmp); - if (PyErr_Occurred()) { - throw py::exception(); - } -} - -static FT_UInt -ft_get_char_index_or_warn(FT_Face face, FT_ULong charcode, bool warn = true) -{ - FT_UInt glyph_index = FT_Get_Char_Index(face, charcode); - if (glyph_index) { - return glyph_index; - } - if (warn) { - ft_glyph_warn(charcode); - } - return 0; -} - -// ft_outline_decomposer should be passed to FT_Outline_Decompose. On the -// first pass, vertices and codes are set to NULL, and index is simply -// incremented for each vertex that should be inserted, so that it is set, at -// the end, to the total number of vertices. On a second pass, vertices and -// codes should point to correctly sized arrays, and index set again to zero, -// to get fill vertices and codes with the outline decomposition. -struct ft_outline_decomposer -{ - int index; - double* vertices; - unsigned char* codes; -}; - -static int -ft_outline_move_to(FT_Vector const* to, void* user) -{ - ft_outline_decomposer* d = reinterpret_cast(user); - if (d->codes) { - if (d->index) { - // Appending CLOSEPOLY is important to make patheffects work. - *(d->vertices++) = 0; - *(d->vertices++) = 0; - *(d->codes++) = CLOSEPOLY; - } - *(d->vertices++) = to->x * (1. / 64.); - *(d->vertices++) = to->y * (1. / 64.); - *(d->codes++) = MOVETO; - } - d->index += d->index ? 2 : 1; - return 0; -} - -static int -ft_outline_line_to(FT_Vector const* to, void* user) -{ - ft_outline_decomposer* d = reinterpret_cast(user); - if (d->codes) { - *(d->vertices++) = to->x * (1. / 64.); - *(d->vertices++) = to->y * (1. / 64.); - *(d->codes++) = LINETO; - } - d->index++; - return 0; -} - -static int -ft_outline_conic_to(FT_Vector const* control, FT_Vector const* to, void* user) -{ - ft_outline_decomposer* d = reinterpret_cast(user); - if (d->codes) { - *(d->vertices++) = control->x * (1. / 64.); - *(d->vertices++) = control->y * (1. / 64.); - *(d->vertices++) = to->x * (1. / 64.); - *(d->vertices++) = to->y * (1. / 64.); - *(d->codes++) = CURVE3; - *(d->codes++) = CURVE3; - } - d->index += 2; - return 0; -} - -static int -ft_outline_cubic_to( - FT_Vector const* c1, FT_Vector const* c2, FT_Vector const* to, void* user) -{ - ft_outline_decomposer* d = reinterpret_cast(user); - if (d->codes) { - *(d->vertices++) = c1->x * (1. / 64.); - *(d->vertices++) = c1->y * (1. / 64.); - *(d->vertices++) = c2->x * (1. / 64.); - *(d->vertices++) = c2->y * (1. / 64.); - *(d->vertices++) = to->x * (1. / 64.); - *(d->vertices++) = to->y * (1. / 64.); - *(d->codes++) = CURVE4; - *(d->codes++) = CURVE4; - *(d->codes++) = CURVE4; - } - d->index += 3; - return 0; -} - -static FT_Outline_Funcs ft_outline_funcs = { - ft_outline_move_to, - ft_outline_line_to, - ft_outline_conic_to, - ft_outline_cubic_to}; - -PyObject* -FT2Font::get_path() -{ - if (!face->glyph) { - PyErr_SetString(PyExc_RuntimeError, "No glyph loaded"); - return NULL; - } - ft_outline_decomposer decomposer = {}; - if (FT_Error error = - FT_Outline_Decompose( - &face->glyph->outline, &ft_outline_funcs, &decomposer)) { - PyErr_Format(PyExc_RuntimeError, - "FT_Outline_Decompose failed with error 0x%x", error); - return NULL; - } - if (!decomposer.index) { // Don't append CLOSEPOLY to null glyphs. - npy_intp vertices_dims[2] = { 0, 2 }; - numpy::array_view vertices(vertices_dims); - npy_intp codes_dims[1] = { 0 }; - numpy::array_view codes(codes_dims); - return Py_BuildValue("NN", vertices.pyobj(), codes.pyobj()); - } - npy_intp vertices_dims[2] = { decomposer.index + 1, 2 }; - numpy::array_view vertices(vertices_dims); - npy_intp codes_dims[1] = { decomposer.index + 1 }; - numpy::array_view codes(codes_dims); - decomposer.index = 0; - decomposer.vertices = vertices.data(); - decomposer.codes = codes.data(); - if (FT_Error error = - FT_Outline_Decompose( - &face->glyph->outline, &ft_outline_funcs, &decomposer)) { - PyErr_Format(PyExc_RuntimeError, - "FT_Outline_Decompose failed with error 0x%x", error); - return NULL; - } - *(decomposer.vertices++) = 0; - *(decomposer.vertices++) = 0; - *(decomposer.codes++) = CLOSEPOLY; - return Py_BuildValue("NN", vertices.pyobj(), codes.pyobj()); -} - -FT2Font::FT2Font(FT_Open_Args &open_args, - long hinting_factor_, - std::vector &fallback_list) - : image(), face(NULL) -{ - clear(); - - FT_Error error = FT_Open_Face(_ft2Library, &open_args, 0, &face); - if (error) { - throw_ft_error("Can not load face", error); - } - - // set default kerning factor to 0, i.e., no kerning manipulation - kerning_factor = 0; - - // set a default fontsize 12 pt at 72dpi - hinting_factor = hinting_factor_; - - error = FT_Set_Char_Size(face, 12 * 64, 0, 72 * (unsigned int)hinting_factor, 72); - if (error) { - FT_Done_Face(face); - throw_ft_error("Could not set the fontsize", error); - } - - if (open_args.stream != NULL) { - face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM; - } - - FT_Matrix transform = { 65536 / hinting_factor, 0, 0, 65536 }; - FT_Set_Transform(face, &transform, 0); - - // Set fallbacks - std::copy(fallback_list.begin(), fallback_list.end(), std::back_inserter(fallbacks)); -} - -FT2Font::~FT2Font() -{ - for (size_t i = 0; i < glyphs.size(); i++) { - FT_Done_Glyph(glyphs[i]); - } - - if (face) { - FT_Done_Face(face); - } -} - -void FT2Font::clear() -{ - pen.x = 0; - pen.y = 0; - - for (size_t i = 0; i < glyphs.size(); i++) { - FT_Done_Glyph(glyphs[i]); - } - - glyphs.clear(); - glyph_to_font.clear(); - char_to_font.clear(); - - for (size_t i = 0; i < fallbacks.size(); i++) { - fallbacks[i]->clear(); - } -} - -void FT2Font::set_size(double ptsize, double dpi) -{ - FT_Error error = FT_Set_Char_Size( - face, (FT_F26Dot6)(ptsize * 64), 0, (FT_UInt)(dpi * hinting_factor), (FT_UInt)dpi); - if (error) { - throw_ft_error("Could not set the fontsize", error); - } - FT_Matrix transform = { 65536 / hinting_factor, 0, 0, 65536 }; - FT_Set_Transform(face, &transform, 0); - - for (size_t i = 0; i < fallbacks.size(); i++) { - fallbacks[i]->set_size(ptsize, dpi); - } -} - -void FT2Font::set_charmap(int i) -{ - if (i >= face->num_charmaps) { - throw std::runtime_error("i exceeds the available number of char maps"); - } - FT_CharMap charmap = face->charmaps[i]; - if (FT_Error error = FT_Set_Charmap(face, charmap)) { - throw_ft_error("Could not set the charmap", error); - } -} - -void FT2Font::select_charmap(unsigned long i) -{ - if (FT_Error error = FT_Select_Charmap(face, (FT_Encoding)i)) { - throw_ft_error("Could not set the charmap", error); - } -} - -int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, bool fallback = false) -{ - if (fallback && glyph_to_font.find(left) != glyph_to_font.end() && - glyph_to_font.find(right) != glyph_to_font.end()) { - FT2Font *left_ft_object = glyph_to_font[left]; - FT2Font *right_ft_object = glyph_to_font[right]; - if (left_ft_object != right_ft_object) { - // we do not know how to do kerning between different fonts - return 0; - } - // if left_ft_object is the same as right_ft_object, - // do the exact same thing which set_text does. - return right_ft_object->get_kerning(left, right, mode, false); - } - else - { - FT_Vector delta; - return get_kerning(left, right, mode, delta); - } -} - -int FT2Font::get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, FT_Vector &delta) -{ - if (!FT_HAS_KERNING(face)) { - return 0; - } - - if (!FT_Get_Kerning(face, left, right, mode, &delta)) { - return (int)(delta.x) / (hinting_factor << kerning_factor); - } else { - return 0; - } -} - -void FT2Font::set_kerning_factor(int factor) -{ - kerning_factor = factor; - for (size_t i = 0; i < fallbacks.size(); i++) { - fallbacks[i]->set_kerning_factor(factor); - } -} - -void FT2Font::set_text( - size_t N, uint32_t *codepoints, double angle, FT_Int32 flags, std::vector &xys) -{ - FT_Matrix matrix; /* transformation matrix */ - - angle = angle * (2 * M_PI / 360.0); - - // this computes width and height in subpixels so we have to multiply by 64 - double cosangle = cos(angle) * 0x10000L; - double sinangle = sin(angle) * 0x10000L; - - matrix.xx = (FT_Fixed)cosangle; - matrix.xy = (FT_Fixed)-sinangle; - matrix.yx = (FT_Fixed)sinangle; - matrix.yy = (FT_Fixed)cosangle; - - clear(); - - bbox.xMin = bbox.yMin = 32000; - bbox.xMax = bbox.yMax = -32000; - - FT_UInt previous = 0; - FT2Font *previous_ft_object = NULL; - - for (size_t n = 0; n < N; n++) { - FT_UInt glyph_index = 0; - FT_BBox glyph_bbox; - FT_Pos last_advance; - - FT_Error charcode_error, glyph_error; - FT2Font *ft_object_with_glyph = this; - bool was_found = load_char_with_fallback(ft_object_with_glyph, glyph_index, glyphs, - char_to_font, glyph_to_font, codepoints[n], flags, - charcode_error, glyph_error, false); - if (!was_found) { - ft_glyph_warn((FT_ULong)codepoints[n]); - - // render missing glyph tofu - // come back to top-most font - ft_object_with_glyph = this; - char_to_font[codepoints[n]] = ft_object_with_glyph; - glyph_to_font[glyph_index] = ft_object_with_glyph; - ft_object_with_glyph->load_glyph(glyph_index, flags, ft_object_with_glyph, false); - } - - // retrieve kerning distance and move pen position - if ((ft_object_with_glyph == previous_ft_object) && // if both fonts are the same - ft_object_with_glyph->has_kerning() && // if the font knows how to kern - previous && glyph_index // and we really have 2 glyphs - ) { - FT_Vector delta; - pen.x += ft_object_with_glyph->get_kerning(previous, glyph_index, FT_KERNING_DEFAULT, delta); - } - - // extract glyph image and store it in our table - FT_Glyph &thisGlyph = glyphs[glyphs.size() - 1]; - - last_advance = ft_object_with_glyph->get_face()->glyph->advance.x; - FT_Glyph_Transform(thisGlyph, 0, &pen); - FT_Glyph_Transform(thisGlyph, &matrix, 0); - xys.push_back(pen.x); - xys.push_back(pen.y); - - FT_Glyph_Get_CBox(thisGlyph, FT_GLYPH_BBOX_SUBPIXELS, &glyph_bbox); - - bbox.xMin = std::min(bbox.xMin, glyph_bbox.xMin); - bbox.xMax = std::max(bbox.xMax, glyph_bbox.xMax); - bbox.yMin = std::min(bbox.yMin, glyph_bbox.yMin); - bbox.yMax = std::max(bbox.yMax, glyph_bbox.yMax); - - pen.x += last_advance; - - previous = glyph_index; - previous_ft_object = ft_object_with_glyph; - - } - - FT_Vector_Transform(&pen, &matrix); - advance = pen.x; - - if (bbox.xMin > bbox.xMax) { - bbox.xMin = bbox.yMin = bbox.xMax = bbox.yMax = 0; - } -} - -void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool fallback = false) -{ - // if this is parent FT2Font, cache will be filled in 2 ways: - // 1. set_text was previously called - // 2. set_text was not called and fallback was enabled - if (fallback && char_to_font.find(charcode) != char_to_font.end()) { - ft_object = char_to_font[charcode]; - // since it will be assigned to ft_object anyway - FT2Font *throwaway = NULL; - ft_object->load_char(charcode, flags, throwaway, false); - } else if (fallback) { - FT_UInt final_glyph_index; - FT_Error charcode_error, glyph_error; - FT2Font *ft_object_with_glyph = this; - bool was_found = load_char_with_fallback(ft_object_with_glyph, final_glyph_index, glyphs, char_to_font, - glyph_to_font, charcode, flags, charcode_error, glyph_error, true); - if (!was_found) { - ft_glyph_warn(charcode); - if (charcode_error) { - throw_ft_error("Could not load charcode", charcode_error); - } - else if (glyph_error) { - throw_ft_error("Could not load charcode", glyph_error); - } - } - ft_object = ft_object_with_glyph; - } else { - ft_object = this; - FT_UInt glyph_index = ft_get_char_index_or_warn(face, (FT_ULong)charcode); - - if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) { - throw_ft_error("Could not load charcode", error); - } - FT_Glyph thisGlyph; - if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) { - throw_ft_error("Could not get glyph", error); - } - glyphs.push_back(thisGlyph); - } -} - - -bool FT2Font::get_char_fallback_index(FT_ULong charcode, int& index) const -{ - FT_UInt glyph_index = FT_Get_Char_Index(face, charcode); - if (glyph_index) { - // -1 means the host has the char and we do not need to fallback - index = -1; - return true; - } else { - int inner_index = 0; - bool was_found; - - for (size_t i = 0; i < fallbacks.size(); ++i) { - // TODO handle recursion somehow! - was_found = fallbacks[i]->get_char_fallback_index(charcode, inner_index); - if (was_found) { - index = i; - return true; - } - } - } - return false; -} - - -bool FT2Font::load_char_with_fallback(FT2Font *&ft_object_with_glyph, - FT_UInt &final_glyph_index, - std::vector &parent_glyphs, - std::unordered_map &parent_char_to_font, - std::unordered_map &parent_glyph_to_font, - long charcode, - FT_Int32 flags, - FT_Error &charcode_error, - FT_Error &glyph_error, - bool override = false) -{ - FT_UInt glyph_index = FT_Get_Char_Index(face, charcode); - - if (glyph_index || override) { - charcode_error = FT_Load_Glyph(face, glyph_index, flags); - if (charcode_error) { - return false; - } - - FT_Glyph thisGlyph; - glyph_error = FT_Get_Glyph(face->glyph, &thisGlyph); - if (glyph_error) { - return false; - } - - final_glyph_index = glyph_index; - - // cache the result for future - // need to store this for anytime a character is loaded from a parent - // FT2Font object or to generate a mapping of individual characters to fonts - ft_object_with_glyph = this; - parent_glyph_to_font[final_glyph_index] = this; - parent_char_to_font[charcode] = this; - parent_glyphs.push_back(thisGlyph); - return true; - } - - else { - for (size_t i = 0; i < fallbacks.size(); ++i) { - bool was_found = fallbacks[i]->load_char_with_fallback( - ft_object_with_glyph, final_glyph_index, parent_glyphs, parent_char_to_font, - parent_glyph_to_font, charcode, flags, charcode_error, glyph_error, override); - if (was_found) { - return true; - } - } - return false; - } -} - -void FT2Font::load_glyph(FT_UInt glyph_index, - FT_Int32 flags, - FT2Font *&ft_object, - bool fallback = false) -{ - // cache is only for parent FT2Font - if (fallback && glyph_to_font.find(glyph_index) != glyph_to_font.end()) { - ft_object = glyph_to_font[glyph_index]; - } else { - ft_object = this; - } - - ft_object->load_glyph(glyph_index, flags); -} - -void FT2Font::load_glyph(FT_UInt glyph_index, FT_Int32 flags) -{ - if (FT_Error error = FT_Load_Glyph(face, glyph_index, flags)) { - throw_ft_error("Could not load glyph", error); - } - FT_Glyph thisGlyph; - if (FT_Error error = FT_Get_Glyph(face->glyph, &thisGlyph)) { - throw_ft_error("Could not get glyph", error); - } - glyphs.push_back(thisGlyph); -} - -FT_UInt FT2Font::get_char_index(FT_ULong charcode, bool fallback = false) -{ - FT2Font *ft_object = NULL; - if (fallback && char_to_font.find(charcode) != char_to_font.end()) { - // fallback denotes whether we want to search fallback list. - // should call set_text/load_char_with_fallback to parent FT2Font before - // wanting to use fallback list here. (since that populates the cache) - ft_object = char_to_font[charcode]; - } else { - // set as self - ft_object = this; - } - - // historically, get_char_index never raises a warning - return ft_get_char_index_or_warn(ft_object->get_face(), charcode, false); -} - -void FT2Font::get_width_height(long *width, long *height) -{ - *width = advance; - *height = bbox.yMax - bbox.yMin; -} - -long FT2Font::get_descent() -{ - return -bbox.yMin; -} - -void FT2Font::get_bitmap_offset(long *x, long *y) -{ - *x = bbox.xMin; - *y = 0; -} - -void FT2Font::draw_glyphs_to_bitmap(bool antialiased) -{ - long width = (bbox.xMax - bbox.xMin) / 64 + 2; - long height = (bbox.yMax - bbox.yMin) / 64 + 2; - - image.resize(width, height); - - for (size_t n = 0; n < glyphs.size(); n++) { - FT_Error error = FT_Glyph_To_Bitmap( - &glyphs[n], antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); - if (error) { - throw_ft_error("Could not convert glyph to bitmap", error); - } - - FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[n]; - // now, draw to our target surface (convert position) - - // bitmap left and top in pixel, string bbox in subpixel - FT_Int x = (FT_Int)(bitmap->left - (bbox.xMin * (1. / 64.))); - FT_Int y = (FT_Int)((bbox.yMax * (1. / 64.)) - bitmap->top + 1); - - image.draw_bitmap(&bitmap->bitmap, x, y); - } -} - -void FT2Font::get_xys(bool antialiased, std::vector &xys) -{ - for (size_t n = 0; n < glyphs.size(); n++) { - - FT_Error error = FT_Glyph_To_Bitmap( - &glyphs[n], antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); - if (error) { - throw_ft_error("Could not convert glyph to bitmap", error); - } - - FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[n]; - - // bitmap left and top in pixel, string bbox in subpixel - FT_Int x = (FT_Int)(bitmap->left - bbox.xMin * (1. / 64.)); - FT_Int y = (FT_Int)(bbox.yMax * (1. / 64.) - bitmap->top + 1); - // make sure the index is non-neg - x = x < 0 ? 0 : x; - y = y < 0 ? 0 : y; - xys.push_back(x); - xys.push_back(y); - } -} - -void FT2Font::draw_glyph_to_bitmap(FT2Image &im, int x, int y, size_t glyphInd, bool antialiased) -{ - FT_Vector sub_offset; - sub_offset.x = 0; // int((xd - (double)x) * 64.0); - sub_offset.y = 0; // int((yd - (double)y) * 64.0); - - if (glyphInd >= glyphs.size()) { - throw std::runtime_error("glyph num is out of range"); - } - - FT_Error error = FT_Glyph_To_Bitmap( - &glyphs[glyphInd], - antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, - &sub_offset, // additional translation - 1 // destroy image - ); - if (error) { - throw_ft_error("Could not convert glyph to bitmap", error); - } - - FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyphs[glyphInd]; - - im.draw_bitmap(&bitmap->bitmap, x + bitmap->left, y); -} - -void FT2Font::get_glyph_name(unsigned int glyph_number, char *buffer, bool fallback = false) -{ - if (fallback && glyph_to_font.find(glyph_number) != glyph_to_font.end()) { - // cache is only for parent FT2Font - FT2Font *ft_object = glyph_to_font[glyph_number]; - ft_object->get_glyph_name(glyph_number, buffer, false); - return; - } - if (!FT_HAS_GLYPH_NAMES(face)) { - /* Note that this generated name must match the name that - is generated by ttconv in ttfont_CharStrings_getname. */ - PyOS_snprintf(buffer, 128, "uni%08x", glyph_number); - } else { - if (FT_Error error = FT_Get_Glyph_Name(face, glyph_number, buffer, 128)) { - throw_ft_error("Could not get glyph names", error); - } - } -} - -long FT2Font::get_name_index(char *name) -{ - return FT_Get_Name_Index(face, (FT_String *)name); -} diff --git a/contrib/python/matplotlib/py3/src/ft2font.h b/contrib/python/matplotlib/py3/src/ft2font.h deleted file mode 100644 index d566c3f9bd9..00000000000 --- a/contrib/python/matplotlib/py3/src/ft2font.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -/* A python interface to FreeType */ -#pragma once -#ifndef MPL_FT2FONT_H -#define MPL_FT2FONT_H -#include -#include -#include - -extern "C" { -#include -#include FT_FREETYPE_H -#include FT_GLYPH_H -#include FT_OUTLINE_H -#include FT_SFNT_NAMES_H -#include FT_TYPE1_TABLES_H -#include FT_TRUETYPE_TABLES_H -} - -#define PY_SSIZE_T_CLEAN -#include - -/* - By definition, FT_FIXED as 2 16bit values stored in a single long. - */ -#define FIXED_MAJOR(val) (signed short)((val & 0xffff0000) >> 16) -#define FIXED_MINOR(val) (unsigned short)(val & 0xffff) - -// the FreeType string rendered into a width, height buffer -class FT2Image -{ - public: - FT2Image(); - FT2Image(unsigned long width, unsigned long height); - virtual ~FT2Image(); - - void resize(long width, long height); - void draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y); - void draw_rect(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1); - void draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1); - - unsigned char *get_buffer() - { - return m_buffer; - } - unsigned long get_width() - { - return m_width; - } - unsigned long get_height() - { - return m_height; - } - - private: - bool m_dirty; - unsigned char *m_buffer; - unsigned long m_width; - unsigned long m_height; - - // prevent copying - FT2Image(const FT2Image &); - FT2Image &operator=(const FT2Image &); -}; - -extern FT_Library _ft2Library; - -class FT2Font -{ - - public: - FT2Font(FT_Open_Args &open_args, long hinting_factor, std::vector &fallback_list); - virtual ~FT2Font(); - void clear(); - void set_size(double ptsize, double dpi); - void set_charmap(int i); - void select_charmap(unsigned long i); - void set_text( - size_t N, uint32_t *codepoints, double angle, FT_Int32 flags, std::vector &xys); - int get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, bool fallback); - int get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, FT_Vector &delta); - void set_kerning_factor(int factor); - void load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool fallback); - bool load_char_with_fallback(FT2Font *&ft_object_with_glyph, - FT_UInt &final_glyph_index, - std::vector &parent_glyphs, - std::unordered_map &parent_char_to_font, - std::unordered_map &parent_glyph_to_font, - long charcode, - FT_Int32 flags, - FT_Error &charcode_error, - FT_Error &glyph_error, - bool override); - void load_glyph(FT_UInt glyph_index, FT_Int32 flags, FT2Font *&ft_object, bool fallback); - void load_glyph(FT_UInt glyph_index, FT_Int32 flags); - void get_width_height(long *width, long *height); - void get_bitmap_offset(long *x, long *y); - long get_descent(); - // TODO: Since we know the size of the array upfront, we probably don't - // need to dynamically allocate like this - void get_xys(bool antialiased, std::vector &xys); - void draw_glyphs_to_bitmap(bool antialiased); - void draw_glyph_to_bitmap(FT2Image &im, int x, int y, size_t glyphInd, bool antialiased); - void get_glyph_name(unsigned int glyph_number, char *buffer, bool fallback); - long get_name_index(char *name); - FT_UInt get_char_index(FT_ULong charcode, bool fallback); - PyObject* get_path(); - bool get_char_fallback_index(FT_ULong charcode, int& index) const; - - FT_Face const &get_face() const - { - return face; - } - - FT2Image &get_image() - { - return image; - } - FT_Glyph const &get_last_glyph() const - { - return glyphs.back(); - } - size_t get_last_glyph_index() const - { - return glyphs.size() - 1; - } - size_t get_num_glyphs() const - { - return glyphs.size(); - } - long get_hinting_factor() const - { - return hinting_factor; - } - FT_Bool has_kerning() const - { - return FT_HAS_KERNING(face); - } - - private: - FT2Image image; - FT_Face face; - FT_Vector pen; /* untransformed origin */ - std::vector glyphs; - std::vector fallbacks; - std::unordered_map glyph_to_font; - std::unordered_map char_to_font; - FT_BBox bbox; - FT_Pos advance; - long hinting_factor; - int kerning_factor; - - // prevent copying - FT2Font(const FT2Font &); - FT2Font &operator=(const FT2Font &); -}; - -#endif diff --git a/contrib/python/matplotlib/py3/src/ft2font_wrapper.cpp b/contrib/python/matplotlib/py3/src/ft2font_wrapper.cpp deleted file mode 100644 index 7888a9c212a..00000000000 --- a/contrib/python/matplotlib/py3/src/ft2font_wrapper.cpp +++ /dev/null @@ -1,1578 +0,0 @@ -#include "mplutils.h" -#include "ft2font.h" -#include "py_converters.h" -#include "py_exceptions.h" -#include "numpy_cpp.h" - -// From Python -#include - -#include -#include - -#define STRINGIFY(s) XSTRINGIFY(s) -#define XSTRINGIFY(s) #s - -static PyObject *convert_xys_to_array(std::vector &xys) -{ - npy_intp dims[] = {(npy_intp)xys.size() / 2, 2 }; - if (dims[0] > 0) { - return PyArray_SimpleNewFromData(2, dims, NPY_DOUBLE, &xys[0]); - } else { - return PyArray_SimpleNew(2, dims, NPY_DOUBLE); - } -} - -/********************************************************************** - * FT2Image - * */ - -typedef struct -{ - PyObject_HEAD - FT2Image *x; - Py_ssize_t shape[2]; - Py_ssize_t strides[2]; - Py_ssize_t suboffsets[2]; -} PyFT2Image; - -static PyTypeObject PyFT2ImageType; - -static PyObject *PyFT2Image_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyFT2Image *self; - self = (PyFT2Image *)type->tp_alloc(type, 0); - self->x = NULL; - return (PyObject *)self; -} - -static int PyFT2Image_init(PyFT2Image *self, PyObject *args, PyObject *kwds) -{ - double width; - double height; - - if (!PyArg_ParseTuple(args, "dd:FT2Image", &width, &height)) { - return -1; - } - - CALL_CPP_INIT("FT2Image", (self->x = new FT2Image(width, height))); - - return 0; -} - -static void PyFT2Image_dealloc(PyFT2Image *self) -{ - delete self->x; - Py_TYPE(self)->tp_free((PyObject *)self); -} - -const char *PyFT2Image_draw_rect__doc__ = - "draw_rect(self, x0, y0, x1, y1)\n" - "--\n\n" - "Draw an empty rectangle to the image.\n" - "\n" - ".. deprecated:: 3.8\n"; -; - -static PyObject *PyFT2Image_draw_rect(PyFT2Image *self, PyObject *args) -{ - char const* msg = - "FT2Image.draw_rect is deprecated since Matplotlib 3.8 and will be removed " - "two minor releases later as it is not used in the library. If you rely on " - "it, please let us know."; - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1)) { - return NULL; - } - - double x0, y0, x1, y1; - - if (!PyArg_ParseTuple(args, "dddd:draw_rect", &x0, &y0, &x1, &y1)) { - return NULL; - } - - CALL_CPP("draw_rect", (self->x->draw_rect(x0, y0, x1, y1))); - - Py_RETURN_NONE; -} - -const char *PyFT2Image_draw_rect_filled__doc__ = - "draw_rect_filled(self, x0, y0, x1, y1)\n" - "--\n\n" - "Draw a filled rectangle to the image.\n"; - -static PyObject *PyFT2Image_draw_rect_filled(PyFT2Image *self, PyObject *args) -{ - double x0, y0, x1, y1; - - if (!PyArg_ParseTuple(args, "dddd:draw_rect_filled", &x0, &y0, &x1, &y1)) { - return NULL; - } - - CALL_CPP("draw_rect_filled", (self->x->draw_rect_filled(x0, y0, x1, y1))); - - Py_RETURN_NONE; -} - -static int PyFT2Image_get_buffer(PyFT2Image *self, Py_buffer *buf, int flags) -{ - FT2Image *im = self->x; - - Py_INCREF(self); - buf->obj = (PyObject *)self; - buf->buf = im->get_buffer(); - buf->len = im->get_width() * im->get_height(); - buf->readonly = 0; - buf->format = (char *)"B"; - buf->ndim = 2; - self->shape[0] = im->get_height(); - self->shape[1] = im->get_width(); - buf->shape = self->shape; - self->strides[0] = im->get_width(); - self->strides[1] = 1; - buf->strides = self->strides; - buf->suboffsets = NULL; - buf->itemsize = 1; - buf->internal = NULL; - - return 1; -} - -static PyTypeObject* PyFT2Image_init_type() -{ - static PyMethodDef methods[] = { - {"draw_rect", (PyCFunction)PyFT2Image_draw_rect, METH_VARARGS, PyFT2Image_draw_rect__doc__}, - {"draw_rect_filled", (PyCFunction)PyFT2Image_draw_rect_filled, METH_VARARGS, PyFT2Image_draw_rect_filled__doc__}, - {NULL} - }; - - static PyBufferProcs buffer_procs; - buffer_procs.bf_getbuffer = (getbufferproc)PyFT2Image_get_buffer; - - PyFT2ImageType.tp_name = "matplotlib.ft2font.FT2Image"; - PyFT2ImageType.tp_basicsize = sizeof(PyFT2Image); - PyFT2ImageType.tp_dealloc = (destructor)PyFT2Image_dealloc; - PyFT2ImageType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; - PyFT2ImageType.tp_methods = methods; - PyFT2ImageType.tp_new = PyFT2Image_new; - PyFT2ImageType.tp_init = (initproc)PyFT2Image_init; - PyFT2ImageType.tp_as_buffer = &buffer_procs; - - return &PyFT2ImageType; -} - -/********************************************************************** - * Glyph - * */ - -typedef struct -{ - PyObject_HEAD - size_t glyphInd; - long width; - long height; - long horiBearingX; - long horiBearingY; - long horiAdvance; - long linearHoriAdvance; - long vertBearingX; - long vertBearingY; - long vertAdvance; - FT_BBox bbox; -} PyGlyph; - -static PyTypeObject PyGlyphType; - -static PyObject *PyGlyph_from_FT2Font(const FT2Font *font) -{ - const FT_Face &face = font->get_face(); - const long hinting_factor = font->get_hinting_factor(); - const FT_Glyph &glyph = font->get_last_glyph(); - - PyGlyph *self; - self = (PyGlyph *)PyGlyphType.tp_alloc(&PyGlyphType, 0); - - self->glyphInd = font->get_last_glyph_index(); - FT_Glyph_Get_CBox(glyph, ft_glyph_bbox_subpixels, &self->bbox); - - self->width = face->glyph->metrics.width / hinting_factor; - self->height = face->glyph->metrics.height; - self->horiBearingX = face->glyph->metrics.horiBearingX / hinting_factor; - self->horiBearingY = face->glyph->metrics.horiBearingY; - self->horiAdvance = face->glyph->metrics.horiAdvance; - self->linearHoriAdvance = face->glyph->linearHoriAdvance / hinting_factor; - self->vertBearingX = face->glyph->metrics.vertBearingX; - self->vertBearingY = face->glyph->metrics.vertBearingY; - self->vertAdvance = face->glyph->metrics.vertAdvance; - - return (PyObject *)self; -} - -static void PyGlyph_dealloc(PyGlyph *self) -{ - Py_TYPE(self)->tp_free((PyObject *)self); -} - -static PyObject *PyGlyph_get_bbox(PyGlyph *self, void *closure) -{ - return Py_BuildValue( - "llll", self->bbox.xMin, self->bbox.yMin, self->bbox.xMax, self->bbox.yMax); -} - -static PyTypeObject *PyGlyph_init_type() -{ - static PyMemberDef members[] = { - {(char *)"width", T_LONG, offsetof(PyGlyph, width), READONLY, (char *)""}, - {(char *)"height", T_LONG, offsetof(PyGlyph, height), READONLY, (char *)""}, - {(char *)"horiBearingX", T_LONG, offsetof(PyGlyph, horiBearingX), READONLY, (char *)""}, - {(char *)"horiBearingY", T_LONG, offsetof(PyGlyph, horiBearingY), READONLY, (char *)""}, - {(char *)"horiAdvance", T_LONG, offsetof(PyGlyph, horiAdvance), READONLY, (char *)""}, - {(char *)"linearHoriAdvance", T_LONG, offsetof(PyGlyph, linearHoriAdvance), READONLY, (char *)""}, - {(char *)"vertBearingX", T_LONG, offsetof(PyGlyph, vertBearingX), READONLY, (char *)""}, - {(char *)"vertBearingY", T_LONG, offsetof(PyGlyph, vertBearingY), READONLY, (char *)""}, - {(char *)"vertAdvance", T_LONG, offsetof(PyGlyph, vertAdvance), READONLY, (char *)""}, - {NULL} - }; - - static PyGetSetDef getset[] = { - {(char *)"bbox", (getter)PyGlyph_get_bbox, NULL, NULL, NULL}, - {NULL} - }; - - PyGlyphType.tp_name = "matplotlib.ft2font.Glyph"; - PyGlyphType.tp_basicsize = sizeof(PyGlyph); - PyGlyphType.tp_dealloc = (destructor)PyGlyph_dealloc; - PyGlyphType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; - PyGlyphType.tp_members = members; - PyGlyphType.tp_getset = getset; - - return &PyGlyphType; -} - -/********************************************************************** - * FT2Font - * */ - -struct PyFT2Font -{ - PyObject_HEAD - FT2Font *x; - PyObject *py_file; - FT_StreamRec stream; - Py_ssize_t shape[2]; - Py_ssize_t strides[2]; - Py_ssize_t suboffsets[2]; - std::vector fallbacks; -}; - -static PyTypeObject PyFT2FontType; - -static unsigned long read_from_file_callback(FT_Stream stream, - unsigned long offset, - unsigned char *buffer, - unsigned long count) -{ - PyObject *py_file = ((PyFT2Font *)stream->descriptor.pointer)->py_file; - PyObject *seek_result = NULL, *read_result = NULL; - Py_ssize_t n_read = 0; - if (!(seek_result = PyObject_CallMethod(py_file, "seek", "k", offset)) - || !(read_result = PyObject_CallMethod(py_file, "read", "k", count))) { - goto exit; - } - char *tmpbuf; - if (PyBytes_AsStringAndSize(read_result, &tmpbuf, &n_read) == -1) { - goto exit; - } - memcpy(buffer, tmpbuf, n_read); -exit: - Py_XDECREF(seek_result); - Py_XDECREF(read_result); - if (PyErr_Occurred()) { - PyErr_WriteUnraisable(py_file); - if (!count) { - return 1; // Non-zero signals error, when count == 0. - } - } - return (unsigned long)n_read; -} - -static void close_file_callback(FT_Stream stream) -{ - PyObject *type, *value, *traceback; - PyErr_Fetch(&type, &value, &traceback); - PyFT2Font *self = (PyFT2Font *)stream->descriptor.pointer; - PyObject *close_result = NULL; - if (!(close_result = PyObject_CallMethod(self->py_file, "close", ""))) { - goto exit; - } -exit: - Py_XDECREF(close_result); - Py_CLEAR(self->py_file); - if (PyErr_Occurred()) { - PyErr_WriteUnraisable((PyObject*)self); - } - PyErr_Restore(type, value, traceback); -} - -static PyObject *PyFT2Font_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyFT2Font *self; - self = (PyFT2Font *)type->tp_alloc(type, 0); - self->x = NULL; - self->py_file = NULL; - memset(&self->stream, 0, sizeof(FT_StreamRec)); - return (PyObject *)self; -} - -const char *PyFT2Font_init__doc__ = - "FT2Font(filename, hinting_factor=8, *, _fallback_list=None, _kerning_factor=0)\n" - "--\n\n" - "Create a new FT2Font object.\n" - "\n" - "Parameters\n" - "----------\n" - "filename : str or file-like\n" - " The source of the font data in a format (ttf or ttc) that FreeType can read\n" - "\n" - "hinting_factor : int, optional\n" - " Must be positive. Used to scale the hinting in the x-direction\n" - "_fallback_list : list of FT2Font, optional\n" - " A list of FT2Font objects used to find missing glyphs.\n" - "\n" - " .. warning::\n" - " This API is both private and provisional: do not use it directly\n" - "\n" - "_kerning_factor : int, optional\n" - " Used to adjust the degree of kerning.\n" - "\n" - " .. warning::\n" - " This API is private: do not use it directly\n" - "\n" - "Attributes\n" - "----------\n" - "num_faces : int\n" - " Number of faces in file.\n" - "face_flags, style_flags : int\n" - " Face and style flags; see the ft2font constants.\n" - "num_glyphs : int\n" - " Number of glyphs in the face.\n" - "family_name, style_name : str\n" - " Face family and style name.\n" - "num_fixed_sizes : int\n" - " Number of bitmap in the face.\n" - "scalable : bool\n" - " Whether face is scalable; attributes after this one are only\n" - " defined for scalable faces.\n" - "bbox : tuple[int, int, int, int]\n" - " Face global bounding box (xmin, ymin, xmax, ymax).\n" - "units_per_EM : int\n" - " Number of font units covered by the EM.\n" - "ascender, descender : int\n" - " Ascender and descender in 26.6 units.\n" - "height : int\n" - " Height in 26.6 units; used to compute a default line spacing\n" - " (baseline-to-baseline distance).\n" - "max_advance_width, max_advance_height : int\n" - " Maximum horizontal and vertical cursor advance for all glyphs.\n" - "underline_position, underline_thickness : int\n" - " Vertical position and thickness of the underline bar.\n" - "postscript_name : str\n" - " PostScript name of the font.\n"; - -static int PyFT2Font_init(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - PyObject *filename = NULL, *open = NULL, *data = NULL, *fallback_list = NULL; - FT_Open_Args open_args; - long hinting_factor = 8; - int kerning_factor = 0; - const char *names[] = { - "filename", "hinting_factor", "_fallback_list", "_kerning_factor", NULL - }; - std::vector fallback_fonts; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "O|l$Oi:FT2Font", (char **)names, &filename, - &hinting_factor, &fallback_list, &kerning_factor)) { - return -1; - } - if (hinting_factor <= 0) { - PyErr_SetString(PyExc_ValueError, - "hinting_factor must be greater than 0"); - goto exit; - } - - self->stream.base = NULL; - self->stream.size = 0x7fffffff; // Unknown size. - self->stream.pos = 0; - self->stream.descriptor.pointer = self; - self->stream.read = &read_from_file_callback; - memset((void *)&open_args, 0, sizeof(FT_Open_Args)); - open_args.flags = FT_OPEN_STREAM; - open_args.stream = &self->stream; - - if (fallback_list) { - if (!PyList_Check(fallback_list)) { - PyErr_SetString(PyExc_TypeError, "Fallback list must be a list"); - goto exit; - } - Py_ssize_t size = PyList_Size(fallback_list); - - // go through fallbacks once to make sure the types are right - for (Py_ssize_t i = 0; i < size; ++i) { - // this returns a borrowed reference - PyObject* item = PyList_GetItem(fallback_list, i); - if (!PyObject_IsInstance(item, PyObject_Type(reinterpret_cast(self)))) { - PyErr_SetString(PyExc_TypeError, "Fallback fonts must be FT2Font objects."); - goto exit; - } - } - // go through a second time to add them to our lists - for (Py_ssize_t i = 0; i < size; ++i) { - // this returns a borrowed reference - PyObject* item = PyList_GetItem(fallback_list, i); - // Increase the ref count, we will undo this in dealloc this makes - // sure things do not get gc'd under us! - Py_INCREF(item); - self->fallbacks.push_back(item); - // Also (locally) cache the underlying FT2Font objects. As long as - // the Python objects are kept alive, these pointer are good. - FT2Font *fback = reinterpret_cast(item)->x; - fallback_fonts.push_back(fback); - } - } - - if (PyBytes_Check(filename) || PyUnicode_Check(filename)) { - if (!(open = PyDict_GetItemString(PyEval_GetBuiltins(), "open")) // Borrowed reference. - || !(self->py_file = PyObject_CallFunction(open, "Os", filename, "rb"))) { - goto exit; - } - self->stream.close = &close_file_callback; - } else if (!PyObject_HasAttrString(filename, "read") - || !(data = PyObject_CallMethod(filename, "read", "i", 0)) - || !PyBytes_Check(data)) { - PyErr_SetString(PyExc_TypeError, - "First argument must be a path to a font file or a binary-mode file object"); - Py_CLEAR(data); - goto exit; - } else { - self->py_file = filename; - self->stream.close = NULL; - Py_INCREF(filename); - } - Py_CLEAR(data); - - CALL_CPP_FULL( - "FT2Font", (self->x = new FT2Font(open_args, hinting_factor, fallback_fonts)), - Py_CLEAR(self->py_file), -1); - - CALL_CPP_INIT("FT2Font->set_kerning_factor", (self->x->set_kerning_factor(kerning_factor))); - -exit: - return PyErr_Occurred() ? -1 : 0; -} - -static void PyFT2Font_dealloc(PyFT2Font *self) -{ - delete self->x; - for (size_t i = 0; i < self->fallbacks.size(); i++) { - Py_DECREF(self->fallbacks[i]); - } - - Py_XDECREF(self->py_file); - Py_TYPE(self)->tp_free((PyObject *)self); -} - -const char *PyFT2Font_clear__doc__ = - "clear(self)\n" - "--\n\n" - "Clear all the glyphs, reset for a new call to `.set_text`.\n"; - -static PyObject *PyFT2Font_clear(PyFT2Font *self, PyObject *args) -{ - CALL_CPP("clear", (self->x->clear())); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_set_size__doc__ = - "set_size(self, ptsize, dpi)\n" - "--\n\n" - "Set the point size and dpi of the text.\n"; - -static PyObject *PyFT2Font_set_size(PyFT2Font *self, PyObject *args) -{ - double ptsize; - double dpi; - - if (!PyArg_ParseTuple(args, "dd:set_size", &ptsize, &dpi)) { - return NULL; - } - - CALL_CPP("set_size", (self->x->set_size(ptsize, dpi))); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_set_charmap__doc__ = - "set_charmap(self, i)\n" - "--\n\n" - "Make the i-th charmap current.\n"; - -static PyObject *PyFT2Font_set_charmap(PyFT2Font *self, PyObject *args) -{ - int i; - - if (!PyArg_ParseTuple(args, "i:set_charmap", &i)) { - return NULL; - } - - CALL_CPP("set_charmap", (self->x->set_charmap(i))); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_select_charmap__doc__ = - "select_charmap(self, i)\n" - "--\n\n" - "Select a charmap by its FT_Encoding number.\n"; - -static PyObject *PyFT2Font_select_charmap(PyFT2Font *self, PyObject *args) -{ - unsigned long i; - - if (!PyArg_ParseTuple(args, "k:select_charmap", &i)) { - return NULL; - } - - CALL_CPP("select_charmap", self->x->select_charmap(i)); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_get_kerning__doc__ = - "get_kerning(self, left, right, mode)\n" - "--\n\n" - "Get the kerning between *left* and *right* glyph indices.\n" - "*mode* is a kerning mode constant:\n\n" - "- KERNING_DEFAULT - Return scaled and grid-fitted kerning distances\n" - "- KERNING_UNFITTED - Return scaled but un-grid-fitted kerning distances\n" - "- KERNING_UNSCALED - Return the kerning vector in original font units\n"; - -static PyObject *PyFT2Font_get_kerning(PyFT2Font *self, PyObject *args) -{ - FT_UInt left, right, mode; - int result; - int fallback = 1; - - if (!PyArg_ParseTuple(args, "III:get_kerning", &left, &right, &mode)) { - return NULL; - } - - CALL_CPP("get_kerning", (result = self->x->get_kerning(left, right, mode, (bool)fallback))); - - return PyLong_FromLong(result); -} - -const char *PyFT2Font_get_fontmap__doc__ = - "_get_fontmap(self, string)\n" - "--\n\n" - "Get a mapping between characters and the font that includes them.\n" - "A dictionary mapping unicode characters to PyFT2Font objects."; -static PyObject *PyFT2Font_get_fontmap(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - PyObject *textobj; - const char *names[] = { "string", NULL }; - - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "O:_get_fontmap", (char **)names, &textobj)) { - return NULL; - } - - std::set codepoints; - size_t size; - - if (PyUnicode_Check(textobj)) { - size = PyUnicode_GET_LENGTH(textobj); - for (size_t i = 0; i < size; ++i) { - codepoints.insert(PyUnicode_ReadChar(textobj, i)); - } - } else { - PyErr_SetString(PyExc_TypeError, "string must be str"); - return NULL; - } - PyObject *char_to_font; - if (!(char_to_font = PyDict_New())) { - return NULL; - } - for (auto it = codepoints.begin(); it != codepoints.end(); ++it) { - auto x = *it; - PyObject* target_font; - int index; - if (self->x->get_char_fallback_index(x, index)) { - if (index >= 0) { - target_font = self->fallbacks[index]; - } else { - target_font = (PyObject *)self; - } - } else { - // TODO Handle recursion! - target_font = (PyObject *)self; - } - - PyObject *key = NULL; - bool error = (!(key = PyUnicode_FromFormat("%c", x)) - || (PyDict_SetItem(char_to_font, key, target_font) == -1)); - Py_XDECREF(key); - if (error) { - Py_DECREF(char_to_font); - PyErr_SetString(PyExc_ValueError, "Something went very wrong"); - return NULL; - } - } - return char_to_font; -} - - -const char *PyFT2Font_set_text__doc__ = - "set_text(self, string, angle=0.0, flags=32)\n" - "--\n\n" - "Set the text *string* and *angle*.\n" - "*flags* can be a bitwise-or of the LOAD_XXX constants;\n" - "the default value is LOAD_FORCE_AUTOHINT.\n" - "You must call this before `.draw_glyphs_to_bitmap`.\n" - "A sequence of x,y positions is returned.\n"; - -static PyObject *PyFT2Font_set_text(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - PyObject *textobj; - double angle = 0.0; - FT_Int32 flags = FT_LOAD_FORCE_AUTOHINT; - std::vector xys; - const char *names[] = { "string", "angle", "flags", NULL }; - - /* This makes a technically incorrect assumption that FT_Int32 is - int. In theory it can also be long, if the size of int is less - than 32 bits. This is very unlikely on modern platforms. */ - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "O|di:set_text", (char **)names, &textobj, &angle, &flags)) { - return NULL; - } - - std::vector codepoints; - size_t size; - - if (PyUnicode_Check(textobj)) { - size = PyUnicode_GET_LENGTH(textobj); - codepoints.resize(size); - for (size_t i = 0; i < size; ++i) { - codepoints[i] = PyUnicode_ReadChar(textobj, i); - } - } else { - PyErr_SetString(PyExc_TypeError, "set_text requires str-input."); - return NULL; - } - - uint32_t* codepoints_array = NULL; - if (size > 0) { - codepoints_array = &codepoints[0]; - } - CALL_CPP("set_text", self->x->set_text(size, codepoints_array, angle, flags, xys)); - - return convert_xys_to_array(xys); -} - -const char *PyFT2Font_get_num_glyphs__doc__ = - "get_num_glyphs(self)\n" - "--\n\n" - "Return the number of loaded glyphs.\n"; - -static PyObject *PyFT2Font_get_num_glyphs(PyFT2Font *self, PyObject *args) -{ - return PyLong_FromSize_t(self->x->get_num_glyphs()); -} - -const char *PyFT2Font_load_char__doc__ = - "load_char(self, charcode, flags=32)\n" - "--\n\n" - "Load character with *charcode* in current fontfile and set glyph.\n" - "*flags* can be a bitwise-or of the LOAD_XXX constants;\n" - "the default value is LOAD_FORCE_AUTOHINT.\n" - "Return value is a Glyph object, with attributes\n\n" - "- width: glyph width\n" - "- height: glyph height\n" - "- bbox: the glyph bbox (xmin, ymin, xmax, ymax)\n" - "- horiBearingX: left side bearing in horizontal layouts\n" - "- horiBearingY: top side bearing in horizontal layouts\n" - "- horiAdvance: advance width for horizontal layout\n" - "- vertBearingX: left side bearing in vertical layouts\n" - "- vertBearingY: top side bearing in vertical layouts\n" - "- vertAdvance: advance height for vertical layout\n"; - -static PyObject *PyFT2Font_load_char(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - long charcode; - int fallback = 1; - FT_Int32 flags = FT_LOAD_FORCE_AUTOHINT; - const char *names[] = { "charcode", "flags", NULL }; - - /* This makes a technically incorrect assumption that FT_Int32 is - int. In theory it can also be long, if the size of int is less - than 32 bits. This is very unlikely on modern platforms. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "l|i:load_char", (char **)names, &charcode, - &flags)) { - return NULL; - } - - FT2Font *ft_object = NULL; - CALL_CPP("load_char", (self->x->load_char(charcode, flags, ft_object, (bool)fallback))); - - return PyGlyph_from_FT2Font(ft_object); -} - -const char *PyFT2Font_load_glyph__doc__ = - "load_glyph(self, glyphindex, flags=32)\n" - "--\n\n" - "Load character with *glyphindex* in current fontfile and set glyph.\n" - "*flags* can be a bitwise-or of the LOAD_XXX constants;\n" - "the default value is LOAD_FORCE_AUTOHINT.\n" - "Return value is a Glyph object, with attributes\n\n" - "- width: glyph width\n" - "- height: glyph height\n" - "- bbox: the glyph bbox (xmin, ymin, xmax, ymax)\n" - "- horiBearingX: left side bearing in horizontal layouts\n" - "- horiBearingY: top side bearing in horizontal layouts\n" - "- horiAdvance: advance width for horizontal layout\n" - "- vertBearingX: left side bearing in vertical layouts\n" - "- vertBearingY: top side bearing in vertical layouts\n" - "- vertAdvance: advance height for vertical layout\n"; - -static PyObject *PyFT2Font_load_glyph(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - FT_UInt glyph_index; - FT_Int32 flags = FT_LOAD_FORCE_AUTOHINT; - int fallback = 1; - const char *names[] = { "glyph_index", "flags", NULL }; - - /* This makes a technically incorrect assumption that FT_Int32 is - int. In theory it can also be long, if the size of int is less - than 32 bits. This is very unlikely on modern platforms. */ - if (!PyArg_ParseTupleAndKeywords(args, kwds, "I|i:load_glyph", (char **)names, &glyph_index, - &flags)) { - return NULL; - } - - FT2Font *ft_object = NULL; - CALL_CPP("load_glyph", (self->x->load_glyph(glyph_index, flags, ft_object, (bool)fallback))); - - return PyGlyph_from_FT2Font(ft_object); -} - -const char *PyFT2Font_get_width_height__doc__ = - "get_width_height(self)\n" - "--\n\n" - "Get the width and height in 26.6 subpixels of the current string set by `.set_text`.\n" - "The rotation of the string is accounted for. To get width and height\n" - "in pixels, divide these values by 64.\n"; - -static PyObject *PyFT2Font_get_width_height(PyFT2Font *self, PyObject *args) -{ - long width, height; - - CALL_CPP("get_width_height", (self->x->get_width_height(&width, &height))); - - return Py_BuildValue("ll", width, height); -} - -const char *PyFT2Font_get_bitmap_offset__doc__ = - "get_bitmap_offset(self)\n" - "--\n\n" - "Get the (x, y) offset in 26.6 subpixels for the bitmap if ink hangs left or below (0, 0).\n" - "Since Matplotlib only supports left-to-right text, y is always 0.\n"; - -static PyObject *PyFT2Font_get_bitmap_offset(PyFT2Font *self, PyObject *args) -{ - long x, y; - - CALL_CPP("get_bitmap_offset", (self->x->get_bitmap_offset(&x, &y))); - - return Py_BuildValue("ll", x, y); -} - -const char *PyFT2Font_get_descent__doc__ = - "get_descent(self)\n" - "--\n\n" - "Get the descent in 26.6 subpixels of the current string set by `.set_text`.\n" - "The rotation of the string is accounted for. To get the descent\n" - "in pixels, divide this value by 64.\n"; - -static PyObject *PyFT2Font_get_descent(PyFT2Font *self, PyObject *args) -{ - long descent; - - CALL_CPP("get_descent", (descent = self->x->get_descent())); - - return PyLong_FromLong(descent); -} - -const char *PyFT2Font_draw_glyphs_to_bitmap__doc__ = - "draw_glyphs_to_bitmap(self, antialiased=True)\n" - "--\n\n" - "Draw the glyphs that were loaded by `.set_text` to the bitmap.\n" - "The bitmap size will be automatically set to include the glyphs.\n"; - -static PyObject *PyFT2Font_draw_glyphs_to_bitmap(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - bool antialiased = true; - const char *names[] = { "antialiased", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:draw_glyphs_to_bitmap", - (char **)names, &convert_bool, &antialiased)) { - return NULL; - } - - CALL_CPP("draw_glyphs_to_bitmap", (self->x->draw_glyphs_to_bitmap(antialiased))); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_get_xys__doc__ = - "get_xys(self, antialiased=True)\n" - "--\n\n" - "Get the xy locations of the current glyphs.\n" - "\n" - ".. deprecated:: 3.8\n"; - -static PyObject *PyFT2Font_get_xys(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - char const* msg = - "FT2Font.get_xys is deprecated since Matplotlib 3.8 and will be removed two " - "minor releases later as it is not used in the library. If you rely on it, " - "please let us know."; - if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1)) { - return NULL; - } - - bool antialiased = true; - std::vector xys; - const char *names[] = { "antialiased", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:get_xys", - (char **)names, &convert_bool, &antialiased)) { - return NULL; - } - - CALL_CPP("get_xys", (self->x->get_xys(antialiased, xys))); - - return convert_xys_to_array(xys); -} - -const char *PyFT2Font_draw_glyph_to_bitmap__doc__ = - "draw_glyph_to_bitmap(self, image, x, y, glyph, antialiased=True)\n" - "--\n\n" - "Draw a single glyph to the bitmap at pixel locations x, y\n" - "Note it is your responsibility to set up the bitmap manually\n" - "with ``set_bitmap_size(w, h)`` before this call is made.\n" - "\n" - "If you want automatic layout, use `.set_text` in combinations with\n" - "`.draw_glyphs_to_bitmap`. This function is instead intended for people\n" - "who want to render individual glyphs (e.g., returned by `.load_char`)\n" - "at precise locations.\n"; - -static PyObject *PyFT2Font_draw_glyph_to_bitmap(PyFT2Font *self, PyObject *args, PyObject *kwds) -{ - PyFT2Image *image; - double xd, yd; - PyGlyph *glyph; - bool antialiased = true; - const char *names[] = { "image", "x", "y", "glyph", "antialiased", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, - kwds, - "O!ddO!|O&:draw_glyph_to_bitmap", - (char **)names, - &PyFT2ImageType, - &image, - &xd, - &yd, - &PyGlyphType, - &glyph, - &convert_bool, - &antialiased)) { - return NULL; - } - - CALL_CPP("draw_glyph_to_bitmap", - self->x->draw_glyph_to_bitmap(*(image->x), xd, yd, glyph->glyphInd, antialiased)); - - Py_RETURN_NONE; -} - -const char *PyFT2Font_get_glyph_name__doc__ = - "get_glyph_name(self, index)\n" - "--\n\n" - "Retrieve the ASCII name of a given glyph *index* in a face.\n" - "\n" - "Due to Matplotlib's internal design, for fonts that do not contain glyph\n" - "names (per FT_FACE_FLAG_GLYPH_NAMES), this returns a made-up name which\n" - "does *not* roundtrip through `.get_name_index`.\n"; - -static PyObject *PyFT2Font_get_glyph_name(PyFT2Font *self, PyObject *args) -{ - unsigned int glyph_number; - char buffer[128]; - int fallback = 1; - - if (!PyArg_ParseTuple(args, "I:get_glyph_name", &glyph_number)) { - return NULL; - } - CALL_CPP("get_glyph_name", (self->x->get_glyph_name(glyph_number, buffer, (bool)fallback))); - return PyUnicode_FromString(buffer); -} - -const char *PyFT2Font_get_charmap__doc__ = - "get_charmap(self)\n" - "--\n\n" - "Return a dict that maps the character codes of the selected charmap\n" - "(Unicode by default) to their corresponding glyph indices.\n"; - -static PyObject *PyFT2Font_get_charmap(PyFT2Font *self, PyObject *args) -{ - PyObject *charmap; - if (!(charmap = PyDict_New())) { - return NULL; - } - FT_UInt index; - FT_ULong code = FT_Get_First_Char(self->x->get_face(), &index); - while (index != 0) { - PyObject *key = NULL, *val = NULL; - bool error = (!(key = PyLong_FromLong(code)) - || !(val = PyLong_FromLong(index)) - || (PyDict_SetItem(charmap, key, val) == -1)); - Py_XDECREF(key); - Py_XDECREF(val); - if (error) { - Py_DECREF(charmap); - return NULL; - } - code = FT_Get_Next_Char(self->x->get_face(), code, &index); - } - return charmap; -} - - -const char *PyFT2Font_get_char_index__doc__ = - "get_char_index(self, codepoint)\n" - "--\n\n" - "Return the glyph index corresponding to a character *codepoint*.\n"; - -static PyObject *PyFT2Font_get_char_index(PyFT2Font *self, PyObject *args) -{ - FT_UInt index; - FT_ULong ccode; - int fallback = 1; - - if (!PyArg_ParseTuple(args, "k:get_char_index", &ccode)) { - return NULL; - } - - CALL_CPP("get_char_index", index = self->x->get_char_index(ccode, (bool)fallback)); - - return PyLong_FromLong(index); -} - - -const char *PyFT2Font_get_sfnt__doc__ = - "get_sfnt(self)\n" - "--\n\n" - "Load the entire SFNT names table, as a dict whose keys are\n" - "(platform-ID, ISO-encoding-scheme, language-code, and description)\n" - "tuples.\n"; - -static PyObject *PyFT2Font_get_sfnt(PyFT2Font *self, PyObject *args) -{ - PyObject *names; - - if (!(self->x->get_face()->face_flags & FT_FACE_FLAG_SFNT)) { - PyErr_SetString(PyExc_ValueError, "No SFNT name table"); - return NULL; - } - - size_t count = FT_Get_Sfnt_Name_Count(self->x->get_face()); - - names = PyDict_New(); - if (names == NULL) { - return NULL; - } - - for (FT_UInt j = 0; j < count; ++j) { - FT_SfntName sfnt; - FT_Error error = FT_Get_Sfnt_Name(self->x->get_face(), j, &sfnt); - - if (error) { - Py_DECREF(names); - PyErr_SetString(PyExc_ValueError, "Could not get SFNT name"); - return NULL; - } - - PyObject *key = Py_BuildValue( - "HHHH", sfnt.platform_id, sfnt.encoding_id, sfnt.language_id, sfnt.name_id); - if (key == NULL) { - Py_DECREF(names); - return NULL; - } - - PyObject *val = PyBytes_FromStringAndSize((const char *)sfnt.string, sfnt.string_len); - if (val == NULL) { - Py_DECREF(key); - Py_DECREF(names); - return NULL; - } - - if (PyDict_SetItem(names, key, val)) { - Py_DECREF(key); - Py_DECREF(val); - Py_DECREF(names); - return NULL; - } - - Py_DECREF(key); - Py_DECREF(val); - } - - return names; -} - -const char *PyFT2Font_get_name_index__doc__ = - "get_name_index(self, name)\n" - "--\n\n" - "Return the glyph index of a given glyph *name*.\n" - "The glyph index 0 means 'undefined character code'.\n"; - -static PyObject *PyFT2Font_get_name_index(PyFT2Font *self, PyObject *args) -{ - char *glyphname; - long name_index; - if (!PyArg_ParseTuple(args, "s:get_name_index", &glyphname)) { - return NULL; - } - CALL_CPP("get_name_index", name_index = self->x->get_name_index(glyphname)); - return PyLong_FromLong(name_index); -} - -const char *PyFT2Font_get_ps_font_info__doc__ = - "get_ps_font_info(self)\n" - "--\n\n" - "Return the information in the PS Font Info structure.\n"; - -static PyObject *PyFT2Font_get_ps_font_info(PyFT2Font *self, PyObject *args) -{ - PS_FontInfoRec fontinfo; - - FT_Error error = FT_Get_PS_Font_Info(self->x->get_face(), &fontinfo); - if (error) { - PyErr_SetString(PyExc_ValueError, "Could not get PS font info"); - return NULL; - } - - return Py_BuildValue("ssssslbhH", - fontinfo.version ? fontinfo.version : "", - fontinfo.notice ? fontinfo.notice : "", - fontinfo.full_name ? fontinfo.full_name : "", - fontinfo.family_name ? fontinfo.family_name : "", - fontinfo.weight ? fontinfo.weight : "", - fontinfo.italic_angle, - fontinfo.is_fixed_pitch, - fontinfo.underline_position, - fontinfo.underline_thickness); -} - -const char *PyFT2Font_get_sfnt_table__doc__ = - "get_sfnt_table(self, name)\n" - "--\n\n" - "Return one of the following SFNT tables: head, maxp, OS/2, hhea, " - "vhea, post, or pclt.\n"; - -static PyObject *PyFT2Font_get_sfnt_table(PyFT2Font *self, PyObject *args) -{ - char *tagname; - if (!PyArg_ParseTuple(args, "s:get_sfnt_table", &tagname)) { - return NULL; - } - - int tag; - const char *tags[] = { "head", "maxp", "OS/2", "hhea", "vhea", "post", "pclt", NULL }; - - for (tag = 0; tags[tag] != NULL; tag++) { - if (strncmp(tagname, tags[tag], 5) == 0) { - break; - } - } - - void *table = FT_Get_Sfnt_Table(self->x->get_face(), (FT_Sfnt_Tag)tag); - if (!table) { - Py_RETURN_NONE; - } - - switch (tag) { - case 0: { - char head_dict[] = - "{s:(h,H), s:(h,H), s:l, s:l, s:H, s:H," - "s:(l,l), s:(l,l), s:h, s:h, s:h, s:h, s:H, s:H, s:h, s:h, s:h}"; - TT_Header *t = (TT_Header *)table; - return Py_BuildValue(head_dict, - "version", FIXED_MAJOR(t->Table_Version), FIXED_MINOR(t->Table_Version), - "fontRevision", FIXED_MAJOR(t->Font_Revision), FIXED_MINOR(t->Font_Revision), - "checkSumAdjustment", t->CheckSum_Adjust, - "magicNumber", t->Magic_Number, - "flags", t->Flags, - "unitsPerEm", t->Units_Per_EM, - "created", t->Created[0], t->Created[1], - "modified", t->Modified[0], t->Modified[1], - "xMin", t->xMin, - "yMin", t->yMin, - "xMax", t->xMax, - "yMax", t->yMax, - "macStyle", t->Mac_Style, - "lowestRecPPEM", t->Lowest_Rec_PPEM, - "fontDirectionHint", t->Font_Direction, - "indexToLocFormat", t->Index_To_Loc_Format, - "glyphDataFormat", t->Glyph_Data_Format); - } - case 1: { - char maxp_dict[] = - "{s:(h,H), s:H, s:H, s:H, s:H, s:H, s:H," - "s:H, s:H, s:H, s:H, s:H, s:H, s:H, s:H}"; - TT_MaxProfile *t = (TT_MaxProfile *)table; - return Py_BuildValue(maxp_dict, - "version", FIXED_MAJOR(t->version), FIXED_MINOR(t->version), - "numGlyphs", t->numGlyphs, - "maxPoints", t->maxPoints, - "maxContours", t->maxContours, - "maxComponentPoints", t->maxCompositePoints, - "maxComponentContours", t->maxCompositeContours, - "maxZones", t->maxZones, - "maxTwilightPoints", t->maxTwilightPoints, - "maxStorage", t->maxStorage, - "maxFunctionDefs", t->maxFunctionDefs, - "maxInstructionDefs", t->maxInstructionDefs, - "maxStackElements", t->maxStackElements, - "maxSizeOfInstructions", t->maxSizeOfInstructions, - "maxComponentElements", t->maxComponentElements, - "maxComponentDepth", t->maxComponentDepth); - } - case 2: { - char os_2_dict[] = - "{s:H, s:h, s:H, s:H, s:H, s:h, s:h, s:h," - "s:h, s:h, s:h, s:h, s:h, s:h, s:h, s:h, s:y#, s:(kkkk)," - "s:y#, s:H, s:H, s:H}"; - TT_OS2 *t = (TT_OS2 *)table; - return Py_BuildValue(os_2_dict, - "version", t->version, - "xAvgCharWidth", t->xAvgCharWidth, - "usWeightClass", t->usWeightClass, - "usWidthClass", t->usWidthClass, - "fsType", t->fsType, - "ySubscriptXSize", t->ySubscriptXSize, - "ySubscriptYSize", t->ySubscriptYSize, - "ySubscriptXOffset", t->ySubscriptXOffset, - "ySubscriptYOffset", t->ySubscriptYOffset, - "ySuperscriptXSize", t->ySuperscriptXSize, - "ySuperscriptYSize", t->ySuperscriptYSize, - "ySuperscriptXOffset", t->ySuperscriptXOffset, - "ySuperscriptYOffset", t->ySuperscriptYOffset, - "yStrikeoutSize", t->yStrikeoutSize, - "yStrikeoutPosition", t->yStrikeoutPosition, - "sFamilyClass", t->sFamilyClass, - "panose", t->panose, Py_ssize_t(10), - "ulCharRange", t->ulUnicodeRange1, t->ulUnicodeRange2, t->ulUnicodeRange3, t->ulUnicodeRange4, - "achVendID", t->achVendID, Py_ssize_t(4), - "fsSelection", t->fsSelection, - "fsFirstCharIndex", t->usFirstCharIndex, - "fsLastCharIndex", t->usLastCharIndex); - } - case 3: { - char hhea_dict[] = - "{s:(h,H), s:h, s:h, s:h, s:H, s:h, s:h, s:h," - "s:h, s:h, s:h, s:h, s:H}"; - TT_HoriHeader *t = (TT_HoriHeader *)table; - return Py_BuildValue(hhea_dict, - "version", FIXED_MAJOR(t->Version), FIXED_MINOR(t->Version), - "ascent", t->Ascender, - "descent", t->Descender, - "lineGap", t->Line_Gap, - "advanceWidthMax", t->advance_Width_Max, - "minLeftBearing", t->min_Left_Side_Bearing, - "minRightBearing", t->min_Right_Side_Bearing, - "xMaxExtent", t->xMax_Extent, - "caretSlopeRise", t->caret_Slope_Rise, - "caretSlopeRun", t->caret_Slope_Run, - "caretOffset", t->caret_Offset, - "metricDataFormat", t->metric_Data_Format, - "numOfLongHorMetrics", t->number_Of_HMetrics); - } - case 4: { - char vhea_dict[] = - "{s:(h,H), s:h, s:h, s:h, s:H, s:h, s:h, s:h," - "s:h, s:h, s:h, s:h, s:H}"; - TT_VertHeader *t = (TT_VertHeader *)table; - return Py_BuildValue(vhea_dict, - "version", FIXED_MAJOR(t->Version), FIXED_MINOR(t->Version), - "vertTypoAscender", t->Ascender, - "vertTypoDescender", t->Descender, - "vertTypoLineGap", t->Line_Gap, - "advanceHeightMax", t->advance_Height_Max, - "minTopSideBearing", t->min_Top_Side_Bearing, - "minBottomSizeBearing", t->min_Bottom_Side_Bearing, - "yMaxExtent", t->yMax_Extent, - "caretSlopeRise", t->caret_Slope_Rise, - "caretSlopeRun", t->caret_Slope_Run, - "caretOffset", t->caret_Offset, - "metricDataFormat", t->metric_Data_Format, - "numOfLongVerMetrics", t->number_Of_VMetrics); - } - case 5: { - char post_dict[] = "{s:(h,H), s:(h,H), s:h, s:h, s:k, s:k, s:k, s:k, s:k}"; - TT_Postscript *t = (TT_Postscript *)table; - return Py_BuildValue(post_dict, - "format", FIXED_MAJOR(t->FormatType), FIXED_MINOR(t->FormatType), - "italicAngle", FIXED_MAJOR(t->italicAngle), FIXED_MINOR(t->italicAngle), - "underlinePosition", t->underlinePosition, - "underlineThickness", t->underlineThickness, - "isFixedPitch", t->isFixedPitch, - "minMemType42", t->minMemType42, - "maxMemType42", t->maxMemType42, - "minMemType1", t->minMemType1, - "maxMemType1", t->maxMemType1); - } - case 6: { - char pclt_dict[] = - "{s:(h,H), s:k, s:H, s:H, s:H, s:H, s:H, s:H, s:y#, s:y#, s:b, " - "s:b, s:b}"; - TT_PCLT *t = (TT_PCLT *)table; - return Py_BuildValue(pclt_dict, - "version", FIXED_MAJOR(t->Version), FIXED_MINOR(t->Version), - "fontNumber", t->FontNumber, - "pitch", t->Pitch, - "xHeight", t->xHeight, - "style", t->Style, - "typeFamily", t->TypeFamily, - "capHeight", t->CapHeight, - "symbolSet", t->SymbolSet, - "typeFace", t->TypeFace, Py_ssize_t(16), - "characterComplement", t->CharacterComplement, Py_ssize_t(8), - "strokeWeight", t->StrokeWeight, - "widthType", t->WidthType, - "serifStyle", t->SerifStyle); - } - default: - Py_RETURN_NONE; - } -} - -const char *PyFT2Font_get_path__doc__ = - "get_path(self)\n" - "--\n\n" - "Get the path data from the currently loaded glyph as a tuple of vertices, " - "codes.\n"; - -static PyObject *PyFT2Font_get_path(PyFT2Font *self, PyObject *args) -{ - CALL_CPP("get_path", return self->x->get_path()); -} - -const char *PyFT2Font_get_image__doc__ = - "get_image(self)\n" - "--\n\n" - "Return the underlying image buffer for this font object.\n"; - -static PyObject *PyFT2Font_get_image(PyFT2Font *self, PyObject *args) -{ - FT2Image &im = self->x->get_image(); - npy_intp dims[] = {(npy_intp)im.get_height(), (npy_intp)im.get_width() }; - return PyArray_SimpleNewFromData(2, dims, NPY_UBYTE, im.get_buffer()); -} - -static PyObject *PyFT2Font_postscript_name(PyFT2Font *self, void *closure) -{ - const char *ps_name = FT_Get_Postscript_Name(self->x->get_face()); - if (ps_name == NULL) { - ps_name = "UNAVAILABLE"; - } - - return PyUnicode_FromString(ps_name); -} - -static PyObject *PyFT2Font_num_faces(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->num_faces); -} - -static PyObject *PyFT2Font_family_name(PyFT2Font *self, void *closure) -{ - const char *name = self->x->get_face()->family_name; - if (name == NULL) { - name = "UNAVAILABLE"; - } - return PyUnicode_FromString(name); -} - -static PyObject *PyFT2Font_style_name(PyFT2Font *self, void *closure) -{ - const char *name = self->x->get_face()->style_name; - if (name == NULL) { - name = "UNAVAILABLE"; - } - return PyUnicode_FromString(name); -} - -static PyObject *PyFT2Font_face_flags(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->face_flags); -} - -static PyObject *PyFT2Font_style_flags(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->style_flags); -} - -static PyObject *PyFT2Font_num_glyphs(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->num_glyphs); -} - -static PyObject *PyFT2Font_num_fixed_sizes(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->num_fixed_sizes); -} - -static PyObject *PyFT2Font_num_charmaps(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->num_charmaps); -} - -static PyObject *PyFT2Font_scalable(PyFT2Font *self, void *closure) -{ - if (FT_IS_SCALABLE(self->x->get_face())) { - Py_RETURN_TRUE; - } - Py_RETURN_FALSE; -} - -static PyObject *PyFT2Font_units_per_EM(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->units_per_EM); -} - -static PyObject *PyFT2Font_get_bbox(PyFT2Font *self, void *closure) -{ - FT_BBox *bbox = &(self->x->get_face()->bbox); - - return Py_BuildValue("llll", - bbox->xMin, bbox->yMin, bbox->xMax, bbox->yMax); -} - -static PyObject *PyFT2Font_ascender(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->ascender); -} - -static PyObject *PyFT2Font_descender(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->descender); -} - -static PyObject *PyFT2Font_height(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->height); -} - -static PyObject *PyFT2Font_max_advance_width(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->max_advance_width); -} - -static PyObject *PyFT2Font_max_advance_height(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->max_advance_height); -} - -static PyObject *PyFT2Font_underline_position(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->underline_position); -} - -static PyObject *PyFT2Font_underline_thickness(PyFT2Font *self, void *closure) -{ - return PyLong_FromLong(self->x->get_face()->underline_thickness); -} - -static PyObject *PyFT2Font_fname(PyFT2Font *self, void *closure) -{ - if (self->stream.close) { // Called passed a filename to the constructor. - return PyObject_GetAttrString(self->py_file, "name"); - } else { - Py_INCREF(self->py_file); - return self->py_file; - } -} - -static int PyFT2Font_get_buffer(PyFT2Font *self, Py_buffer *buf, int flags) -{ - FT2Image &im = self->x->get_image(); - - Py_INCREF(self); - buf->obj = (PyObject *)self; - buf->buf = im.get_buffer(); - buf->len = im.get_width() * im.get_height(); - buf->readonly = 0; - buf->format = (char *)"B"; - buf->ndim = 2; - self->shape[0] = im.get_height(); - self->shape[1] = im.get_width(); - buf->shape = self->shape; - self->strides[0] = im.get_width(); - self->strides[1] = 1; - buf->strides = self->strides; - buf->suboffsets = NULL; - buf->itemsize = 1; - buf->internal = NULL; - - return 1; -} - -static PyTypeObject *PyFT2Font_init_type() -{ - static PyGetSetDef getset[] = { - {(char *)"postscript_name", (getter)PyFT2Font_postscript_name, NULL, NULL, NULL}, - {(char *)"num_faces", (getter)PyFT2Font_num_faces, NULL, NULL, NULL}, - {(char *)"family_name", (getter)PyFT2Font_family_name, NULL, NULL, NULL}, - {(char *)"style_name", (getter)PyFT2Font_style_name, NULL, NULL, NULL}, - {(char *)"face_flags", (getter)PyFT2Font_face_flags, NULL, NULL, NULL}, - {(char *)"style_flags", (getter)PyFT2Font_style_flags, NULL, NULL, NULL}, - {(char *)"num_glyphs", (getter)PyFT2Font_num_glyphs, NULL, NULL, NULL}, - {(char *)"num_fixed_sizes", (getter)PyFT2Font_num_fixed_sizes, NULL, NULL, NULL}, - {(char *)"num_charmaps", (getter)PyFT2Font_num_charmaps, NULL, NULL, NULL}, - {(char *)"scalable", (getter)PyFT2Font_scalable, NULL, NULL, NULL}, - {(char *)"units_per_EM", (getter)PyFT2Font_units_per_EM, NULL, NULL, NULL}, - {(char *)"bbox", (getter)PyFT2Font_get_bbox, NULL, NULL, NULL}, - {(char *)"ascender", (getter)PyFT2Font_ascender, NULL, NULL, NULL}, - {(char *)"descender", (getter)PyFT2Font_descender, NULL, NULL, NULL}, - {(char *)"height", (getter)PyFT2Font_height, NULL, NULL, NULL}, - {(char *)"max_advance_width", (getter)PyFT2Font_max_advance_width, NULL, NULL, NULL}, - {(char *)"max_advance_height", (getter)PyFT2Font_max_advance_height, NULL, NULL, NULL}, - {(char *)"underline_position", (getter)PyFT2Font_underline_position, NULL, NULL, NULL}, - {(char *)"underline_thickness", (getter)PyFT2Font_underline_thickness, NULL, NULL, NULL}, - {(char *)"fname", (getter)PyFT2Font_fname, NULL, NULL, NULL}, - {NULL} - }; - - static PyMethodDef methods[] = { - {"clear", (PyCFunction)PyFT2Font_clear, METH_NOARGS, PyFT2Font_clear__doc__}, - {"set_size", (PyCFunction)PyFT2Font_set_size, METH_VARARGS, PyFT2Font_set_size__doc__}, - {"set_charmap", (PyCFunction)PyFT2Font_set_charmap, METH_VARARGS, PyFT2Font_set_charmap__doc__}, - {"select_charmap", (PyCFunction)PyFT2Font_select_charmap, METH_VARARGS, PyFT2Font_select_charmap__doc__}, - {"get_kerning", (PyCFunction)PyFT2Font_get_kerning, METH_VARARGS, PyFT2Font_get_kerning__doc__}, - {"set_text", (PyCFunction)PyFT2Font_set_text, METH_VARARGS|METH_KEYWORDS, PyFT2Font_set_text__doc__}, - {"_get_fontmap", (PyCFunction)PyFT2Font_get_fontmap, METH_VARARGS|METH_KEYWORDS, PyFT2Font_get_fontmap__doc__}, - {"get_num_glyphs", (PyCFunction)PyFT2Font_get_num_glyphs, METH_NOARGS, PyFT2Font_get_num_glyphs__doc__}, - {"load_char", (PyCFunction)PyFT2Font_load_char, METH_VARARGS|METH_KEYWORDS, PyFT2Font_load_char__doc__}, - {"load_glyph", (PyCFunction)PyFT2Font_load_glyph, METH_VARARGS|METH_KEYWORDS, PyFT2Font_load_glyph__doc__}, - {"get_width_height", (PyCFunction)PyFT2Font_get_width_height, METH_NOARGS, PyFT2Font_get_width_height__doc__}, - {"get_bitmap_offset", (PyCFunction)PyFT2Font_get_bitmap_offset, METH_NOARGS, PyFT2Font_get_bitmap_offset__doc__}, - {"get_descent", (PyCFunction)PyFT2Font_get_descent, METH_NOARGS, PyFT2Font_get_descent__doc__}, - {"draw_glyphs_to_bitmap", (PyCFunction)PyFT2Font_draw_glyphs_to_bitmap, METH_VARARGS|METH_KEYWORDS, PyFT2Font_draw_glyphs_to_bitmap__doc__}, - {"get_xys", (PyCFunction)PyFT2Font_get_xys, METH_VARARGS|METH_KEYWORDS, PyFT2Font_get_xys__doc__}, - {"draw_glyph_to_bitmap", (PyCFunction)PyFT2Font_draw_glyph_to_bitmap, METH_VARARGS|METH_KEYWORDS, PyFT2Font_draw_glyph_to_bitmap__doc__}, - {"get_glyph_name", (PyCFunction)PyFT2Font_get_glyph_name, METH_VARARGS, PyFT2Font_get_glyph_name__doc__}, - {"get_charmap", (PyCFunction)PyFT2Font_get_charmap, METH_NOARGS, PyFT2Font_get_charmap__doc__}, - {"get_char_index", (PyCFunction)PyFT2Font_get_char_index, METH_VARARGS, PyFT2Font_get_char_index__doc__}, - {"get_sfnt", (PyCFunction)PyFT2Font_get_sfnt, METH_NOARGS, PyFT2Font_get_sfnt__doc__}, - {"get_name_index", (PyCFunction)PyFT2Font_get_name_index, METH_VARARGS, PyFT2Font_get_name_index__doc__}, - {"get_ps_font_info", (PyCFunction)PyFT2Font_get_ps_font_info, METH_NOARGS, PyFT2Font_get_ps_font_info__doc__}, - {"get_sfnt_table", (PyCFunction)PyFT2Font_get_sfnt_table, METH_VARARGS, PyFT2Font_get_sfnt_table__doc__}, - {"get_path", (PyCFunction)PyFT2Font_get_path, METH_NOARGS, PyFT2Font_get_path__doc__}, - {"get_image", (PyCFunction)PyFT2Font_get_image, METH_NOARGS, PyFT2Font_get_image__doc__}, - {NULL} - }; - - static PyBufferProcs buffer_procs; - buffer_procs.bf_getbuffer = (getbufferproc)PyFT2Font_get_buffer; - - PyFT2FontType.tp_name = "matplotlib.ft2font.FT2Font"; - PyFT2FontType.tp_doc = PyFT2Font_init__doc__; - PyFT2FontType.tp_basicsize = sizeof(PyFT2Font); - PyFT2FontType.tp_dealloc = (destructor)PyFT2Font_dealloc; - PyFT2FontType.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; - PyFT2FontType.tp_methods = methods; - PyFT2FontType.tp_getset = getset; - PyFT2FontType.tp_new = PyFT2Font_new; - PyFT2FontType.tp_init = (initproc)PyFT2Font_init; - PyFT2FontType.tp_as_buffer = &buffer_procs; - - return &PyFT2FontType; -} - -static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "ft2font" }; - -PyMODINIT_FUNC PyInit_ft2font(void) -{ - import_array(); - - if (FT_Init_FreeType(&_ft2Library)) { // initialize library - return PyErr_Format( - PyExc_RuntimeError, "Could not initialize the freetype2 library"); - } - FT_Int major, minor, patch; - char version_string[64]; - FT_Library_Version(_ft2Library, &major, &minor, &patch); - snprintf(version_string, sizeof(version_string), "%d.%d.%d", major, minor, patch); - - PyObject *m; - if (!(m = PyModule_Create(&moduledef)) || - prepare_and_add_type(PyFT2Image_init_type(), m) || - prepare_and_add_type(PyFT2Font_init_type(), m) || - // Glyph is not constructible from Python, thus not added to the module. - PyType_Ready(PyGlyph_init_type()) || - PyModule_AddStringConstant(m, "__freetype_version__", version_string) || - PyModule_AddStringConstant(m, "__freetype_build_type__", STRINGIFY(FREETYPE_BUILD_TYPE)) || - PyModule_AddIntConstant(m, "SCALABLE", FT_FACE_FLAG_SCALABLE) || - PyModule_AddIntConstant(m, "FIXED_SIZES", FT_FACE_FLAG_FIXED_SIZES) || - PyModule_AddIntConstant(m, "FIXED_WIDTH", FT_FACE_FLAG_FIXED_WIDTH) || - PyModule_AddIntConstant(m, "SFNT", FT_FACE_FLAG_SFNT) || - PyModule_AddIntConstant(m, "HORIZONTAL", FT_FACE_FLAG_HORIZONTAL) || - PyModule_AddIntConstant(m, "VERTICAL", FT_FACE_FLAG_VERTICAL) || - PyModule_AddIntConstant(m, "KERNING", FT_FACE_FLAG_KERNING) || - PyModule_AddIntConstant(m, "FAST_GLYPHS", FT_FACE_FLAG_FAST_GLYPHS) || - PyModule_AddIntConstant(m, "MULTIPLE_MASTERS", FT_FACE_FLAG_MULTIPLE_MASTERS) || - PyModule_AddIntConstant(m, "GLYPH_NAMES", FT_FACE_FLAG_GLYPH_NAMES) || - PyModule_AddIntConstant(m, "EXTERNAL_STREAM", FT_FACE_FLAG_EXTERNAL_STREAM) || - PyModule_AddIntConstant(m, "ITALIC", FT_STYLE_FLAG_ITALIC) || - PyModule_AddIntConstant(m, "BOLD", FT_STYLE_FLAG_BOLD) || - PyModule_AddIntConstant(m, "KERNING_DEFAULT", FT_KERNING_DEFAULT) || - PyModule_AddIntConstant(m, "KERNING_UNFITTED", FT_KERNING_UNFITTED) || - PyModule_AddIntConstant(m, "KERNING_UNSCALED", FT_KERNING_UNSCALED) || - PyModule_AddIntConstant(m, "LOAD_DEFAULT", FT_LOAD_DEFAULT) || - PyModule_AddIntConstant(m, "LOAD_NO_SCALE", FT_LOAD_NO_SCALE) || - PyModule_AddIntConstant(m, "LOAD_NO_HINTING", FT_LOAD_NO_HINTING) || - PyModule_AddIntConstant(m, "LOAD_RENDER", FT_LOAD_RENDER) || - PyModule_AddIntConstant(m, "LOAD_NO_BITMAP", FT_LOAD_NO_BITMAP) || - PyModule_AddIntConstant(m, "LOAD_VERTICAL_LAYOUT", FT_LOAD_VERTICAL_LAYOUT) || - PyModule_AddIntConstant(m, "LOAD_FORCE_AUTOHINT", FT_LOAD_FORCE_AUTOHINT) || - PyModule_AddIntConstant(m, "LOAD_CROP_BITMAP", FT_LOAD_CROP_BITMAP) || - PyModule_AddIntConstant(m, "LOAD_PEDANTIC", FT_LOAD_PEDANTIC) || - PyModule_AddIntConstant(m, "LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH", FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH) || - PyModule_AddIntConstant(m, "LOAD_NO_RECURSE", FT_LOAD_NO_RECURSE) || - PyModule_AddIntConstant(m, "LOAD_IGNORE_TRANSFORM", FT_LOAD_IGNORE_TRANSFORM) || - PyModule_AddIntConstant(m, "LOAD_MONOCHROME", FT_LOAD_MONOCHROME) || - PyModule_AddIntConstant(m, "LOAD_LINEAR_DESIGN", FT_LOAD_LINEAR_DESIGN) || - PyModule_AddIntConstant(m, "LOAD_NO_AUTOHINT", (unsigned long)FT_LOAD_NO_AUTOHINT) || - PyModule_AddIntConstant(m, "LOAD_TARGET_NORMAL", (unsigned long)FT_LOAD_TARGET_NORMAL) || - PyModule_AddIntConstant(m, "LOAD_TARGET_LIGHT", (unsigned long)FT_LOAD_TARGET_LIGHT) || - PyModule_AddIntConstant(m, "LOAD_TARGET_MONO", (unsigned long)FT_LOAD_TARGET_MONO) || - PyModule_AddIntConstant(m, "LOAD_TARGET_LCD", (unsigned long)FT_LOAD_TARGET_LCD) || - PyModule_AddIntConstant(m, "LOAD_TARGET_LCD_V", (unsigned long)FT_LOAD_TARGET_LCD_V)) { - FT_Done_FreeType(_ft2Library); - Py_XDECREF(m); - return NULL; - } - - return m; -} diff --git a/contrib/python/matplotlib/py3/src/mplutils.h b/contrib/python/matplotlib/py3/src/mplutils.h deleted file mode 100644 index 6eb89899ca4..00000000000 --- a/contrib/python/matplotlib/py3/src/mplutils.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -/* Small utilities that are shared by most extension modules. */ - -#ifndef MPLUTILS_H -#define MPLUTILS_H -#define PY_SSIZE_T_CLEAN - -#include -#include - -#ifdef _POSIX_C_SOURCE -# undef _POSIX_C_SOURCE -#endif -#ifndef _AIX -#ifdef _XOPEN_SOURCE -# undef _XOPEN_SOURCE -#endif -#endif - -// Prevent multiple conflicting definitions of swab from stdlib.h and unistd.h -#if defined(__sun) || defined(sun) -#if defined(_XPG4) -#undef _XPG4 -#endif -#if defined(_XPG3) -#undef _XPG3 -#endif -#endif - - -inline int mpl_round_to_int(double v) -{ - return (int)(v + ((v >= 0.0) ? 0.5 : -0.5)); -} - -inline double mpl_round(double v) -{ - return (double)mpl_round_to_int(v); -} - -// 'kind' codes for paths. -enum { - STOP = 0, - MOVETO = 1, - LINETO = 2, - CURVE3 = 3, - CURVE4 = 4, - CLOSEPOLY = 0x4f -}; - -const size_t NUM_VERTICES[] = { 1, 1, 1, 2, 3, 1 }; - -inline int prepare_and_add_type(PyTypeObject *type, PyObject *module) -{ - if (PyType_Ready(type)) { - return -1; - } - char const* ptr = strrchr(type->tp_name, '.'); - if (!ptr) { - PyErr_SetString(PyExc_ValueError, "tp_name should be a qualified name"); - return -1; - } - if (PyModule_AddObject(module, ptr + 1, (PyObject *)type)) { - return -1; - } - return 0; -} - -#ifdef __cplusplus // not for macosx.m -// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs -// so that we don't need to access the NPY_INTP_FMT macro here. - -template -inline bool check_trailing_shape(T array, char const* name, long d1) -{ - if (array.dim(1) != d1) { - PyErr_Format(PyExc_ValueError, - "%s must have shape (N, %ld), got (%ld, %ld)", - name, d1, array.dim(0), array.dim(1)); - return false; - } - return true; -} - -template -inline bool check_trailing_shape(T array, char const* name, long d1, long d2) -{ - if (array.dim(1) != d1 || array.dim(2) != d2) { - PyErr_Format(PyExc_ValueError, - "%s must have shape (N, %ld, %ld), got (%ld, %ld, %ld)", - name, d1, d2, array.dim(0), array.dim(1), array.dim(2)); - return false; - } - return true; -} -#endif - -#endif diff --git a/contrib/python/matplotlib/py3/src/numpy_cpp.h b/contrib/python/matplotlib/py3/src/numpy_cpp.h deleted file mode 100644 index 36c763d1584..00000000000 --- a/contrib/python/matplotlib/py3/src/numpy_cpp.h +++ /dev/null @@ -1,578 +0,0 @@ -/* -*- mode: c++; c-basic-offset: 4 -*- */ - -#ifndef MPL_NUMPY_CPP_H -#define MPL_NUMPY_CPP_H -#define PY_SSIZE_T_CLEAN -/*************************************************************************** - * This file is based on original work by Mark Wiebe, available at: - * - * http://github.com/mwiebe/numpy-cpp - * - * However, the needs of matplotlib wrappers, such as treating an - * empty array as having the correct dimensions, have made this rather - * matplotlib-specific, so it's no longer compatible with the - * original. - */ - -#include "py_exceptions.h" - -#include - -#ifdef _POSIX_C_SOURCE -# undef _POSIX_C_SOURCE -#endif -#ifndef _AIX -#ifdef _XOPEN_SOURCE -# undef _XOPEN_SOURCE -#endif -#endif - -// Prevent multiple conflicting definitions of swab from stdlib.h and unistd.h -#if defined(__sun) || defined(sun) -#if defined(_XPG4) -#undef _XPG4 -#endif -#if defined(_XPG3) -#undef _XPG3 -#endif -#endif - -#include -#include - -namespace numpy -{ - -// Type traits for the NumPy types -template -struct type_num_of; - -/* Be careful with bool arrays as python has sizeof(npy_bool) == 1, but it is - * not always the case that sizeof(bool) == 1. Using the array_view_accessors - * is always fine regardless of sizeof(bool), so do this rather than using - * array.data() and pointer arithmetic which will not work correctly if - * sizeof(bool) != 1. */ -template <> struct type_num_of -{ - enum { - value = NPY_BOOL - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_BYTE - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_UBYTE - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_SHORT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_USHORT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_INT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_UINT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_LONG - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_ULONG - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_LONGLONG - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_ULONGLONG - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_FLOAT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_DOUBLE - }; -}; -#if NPY_LONGDOUBLE != NPY_DOUBLE -template <> -struct type_num_of -{ - enum { - value = NPY_LONGDOUBLE - }; -}; -#endif -template <> -struct type_num_of -{ - enum { - value = NPY_CFLOAT - }; -}; -template <> -struct type_num_of > -{ - enum { - value = NPY_CFLOAT - }; -}; -template <> -struct type_num_of -{ - enum { - value = NPY_CDOUBLE - }; -}; -template <> -struct type_num_of > -{ - enum { - value = NPY_CDOUBLE - }; -}; -#if NPY_CLONGDOUBLE != NPY_CDOUBLE -template <> -struct type_num_of -{ - enum { - value = NPY_CLONGDOUBLE - }; -}; -template <> -struct type_num_of > -{ - enum { - value = NPY_CLONGDOUBLE - }; -}; -#endif -template <> -struct type_num_of -{ - enum { - value = NPY_OBJECT - }; -}; -template -struct type_num_of -{ - enum { - value = type_num_of::value - }; -}; -template -struct type_num_of -{ - enum { - value = type_num_of::value - }; -}; - -template -struct is_const -{ - enum { - value = false - }; -}; -template -struct is_const -{ - enum { - value = true - }; -}; - -namespace detail -{ -template