#pragma once #include #include #include #include #include namespace cadabra { /// \ingroup frontend /// /// TeXEngine is used to convert LaTeX strings into PNG images. This is /// a two-stage process: you first 'check in' a string into the system, /// in exchange for a pointer to a TeXRequest object. When you are /// ready to retrieve the image, call 'get_pixbuf'. /// /// If you need to generate images for more than one string, simply /// check them all in and then call 'convert_all' before retrieving the /// pixbufs. This requires only one round-trip through latex/dvipng. class TeXEngine { public: class TeXException : public std::logic_error { public: TeXException(const std::string&); }; class TeXRequest { public: TeXRequest(); friend class TeXEngine; unsigned width() const; unsigned height() const; const std::vector& image() const; /// Get the original LaTeX string. std::string latex() const; private: std::string latex_string; std::string start_wrap, end_wrap; bool needs_generating; bool has_error; // currently set, but never re-set, and unused. std::vector image_; unsigned width_, height_; }; TeXEngine(); ~TeXEngine(); // Set the width and font size for all images to be generated. void set_geometry(int horizontal_pixels); // Get the width. int get_geometry() const; // Set the scale factor for generating bitmaps. The total scale is // the product of HiDPI scale and any text-scaling factor on top of // that, so that it represents the total scale at which text renders. // The device_scale is just the HiDPI factor; we need to generate // bitmaps at the width times this size. void set_scale(double total_scale, double device_scale); double get_scale() const; double get_device_scale() const; void set_font_size(int font_size); int get_font_size() const; std::vector latex_packages; // All checkin/checkout conversion routines. TeXEngine keeps // track of all TeXRequests in order to be able to convert // all of them in one shot (with one LaTeX run), which you can // do with 'convert_all'. // You can share the result in a TeXRequest in multiple // widgets, but you need to call checkout if a widget no // longer needs it. TeXEngine will then run a cleanup on all // TeXRequests that are no longer referenced except by // itself. std::shared_ptr checkin(const std::string&, const std::string& startwrap, const std::string& endwrap); std::shared_ptr modify(std::shared_ptr, const std::string&); /// Generate images for all TeXRequests which are labelled as needing conversion. void convert_all(); /// Mark all TeXRequests as needing re-generating. Use this e.g. when changing font /// size for the entire notebook: first invalidate_all, then convert_all. void invalidate_all(); /// Mark a TeXRequest as no longer being needed. void checkout(std::shared_ptr); void checkout_all(); private: std::string convert_unicode_to_tex(const std::string&) const; static double millimeter_per_inch; std::set > requests; std::string preamble_string; int horizontal_pixels_; int font_size_; double total_scale_, device_scale_; void erase_file(const std::string&) const; void convert_one(std::shared_ptr); void convert_set(std::set >&); std::string handle_latex_errors(const std::string&, int exit_code) const; }; }