/* * Copyright (c) 2007, ai-chan * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the ASSDraw3 Team nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY AI-CHAN ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL AI-CHAN BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /////////////////////////////////////////////////////////////////////////////// // Name: engine.hpp // Purpose: header file for ASSDraw drawing engine // Author: ai-chan // Created: 08/26/06 // Copyright: (c) ai-chan // Licence: 3-clause BSD /////////////////////////////////////////////////////////////////////////////// #pragma once #include "_common.hpp" // we use these 2 standard libraries #include #include #include #include // agg support #include "wxAGG/AGGWindow.h" #include "agg_color_rgba.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_scanline_p.h" #include "agg_renderer_base.h" #include "agg_renderer_primitives.h" #include "agg_renderer_scanline.h" #include "agg_path_storage.h" #include "agg_curves.h" #include "agg_conv_curve.h" #include "agg_conv_contour.h" #include "agg_conv_stroke.h" #include "agg_conv_bcspline.h" #include "agg_math.h" #define DEFAULT_SCALE 10 // this header file declare the following classes class DrawEngine; class Point; class PointSystem; class DrawCmd; typedef std::list DrawCmdList; typedef std::list PointList; typedef std::set PointSet; // Command type enum CMDTYPE { M = 0, N = 1, L = 2, B = 3, S = 4, P = 5, C = 6 }; // Point type enum POINTTYPE { MP, // main point CP // control point }; // A PointSystem is a centralized entity holding the parameters: // scale, originx and originy, all of which are needed by Point class PointSystem { public: double scale, originx, originy; PointSystem ( double sc = 1.0, double origx = 0.0, double origy = 0.0 ) { Set( sc, origx, origy ); } // set scale, originx and originy; void Set( double sc, double origx, double origy ) { scale = sc, originx = origx, originy = origy; } wxRealPoint ToWxRealPoint ( double x, double y ) { return wxRealPoint( originx + x * scale, originy + y * scale ); } // given drawing command coordinates returns the wxPoint on the GUI wxPoint ToWxPoint ( double x, double y ) { return wxPoint( (int) (originx + x * scale), (int) (originy + y * scale) ); } // given wxPoint on the GUI returns the nearest drawing command coords void FromWxPoint ( int wxpx, int wxpy, int &x, int &y ) { x = int( floor( ((double) wxpx - originx) / scale + 0.5 ) ); y = int( floor( ((double) wxpy - originy) / scale + 0.5 ) ); } // given wxPoint on the GUI returns the nearest drawing command coords void FromWxPoint ( wxPoint wxp, int &x, int &y ) { FromWxPoint( wxp.x, wxp.y, x, y ); } }; // The point class // note: this actually refers to the x,y-coordinate in drawing commands, // not the coordinate in the GUI class Point { public: POINTTYPE type; PointSystem *pointsys; // drawing commands that depend on this point DrawCmd* cmd_main; DrawCmd* cmd_next; bool isselected; unsigned num; // constructor //Point ( ) { cmd_main = NULL; cmd_next = NULL; } // constructor Point ( int _x, int _y, PointSystem* ps, POINTTYPE t, DrawCmd* cmd, unsigned n = 0 ); // getters int x() { return x_; } int y() { return y_; } //set x and y void setXY( int _x, int _y); // simply returns true if px and py are the coordinate values bool IsAt( int px, int py ); // convert this point to wxPoint using scale and originx, originy wxPoint ToWxPoint () { return ToWxPoint(true); } // convert this point to wxPoint using scale; // also use originx and originy if useorigin = true wxPoint ToWxPoint (bool useorigin); // check if wxpoint is nearby this point bool CheckWxPoint ( wxPoint wxpoint ); private: int x_, y_; }; // The base class for all draw commands class DrawCmd { public: CMDTYPE type; // main point (almost every command has one) // for B and S it's the last (destination) point Point* m_point; // other points than the main point // subclasses must populate this list even if they define // new variables for other points PointList controlpoints; // Linked list feature DrawCmd *prev; // Must set to true if the next command should NOT utilize this command // for the drawing bool dobreak; // Set to true if invisible m_point (not drawn) bool invisible; // true if this DrawCmd has been initialized with Init(), false otherwise // (initialized means that the control points have been generated) bool initialized; // ----------------------------------------------------------- // Constructor(s) DrawCmd ( int x, int y, PointSystem *ps, DrawCmd *pv ); // Destructor virtual ~DrawCmd (); // Init the draw command (for example to generate the control points) virtual void Init(unsigned n = 0) { initialized = true; } virtual wxString ToString() { return wxT(""); } }; class ASSDrawEngine: public GUI::AGGWindow { public: ASSDrawEngine( wxWindow *parent, int extraflags = 0 ); // destructor ~ASSDrawEngine(); virtual void SetDrawCmdSet(wxString set) { drawcmdset = set; } virtual void ResetEngine(); virtual void ResetEngine(bool addM); virtual void RefreshDisplay(); void FitToViewPoint(int hmargin, int vmargin); void SetFitToViewPointOnNextPaint(int hmargin = -1, int vmargin = -1); PointSystem* _PointSystem() { return pointsys; } // ASS draw commands; returns the number of parsed commands virtual int ParseASS ( wxString str ); // generate ASS draw commands virtual wxString GenerateASS ( ); // drawing virtual void OnPaint(wxPaintEvent &event); // -------------------- adding new commands ---------------------------- // create draw command of type 'type' and m_point (x, y), append to the // list and return it virtual DrawCmd* AppendCmd ( CMDTYPE type, int x, int y ); // append draw command virtual DrawCmd* AppendCmd ( DrawCmd* cmd ); // create draw command of type 'type' and m_point (x, y), insert to the // list after the _cmd and return it virtual DrawCmd* InsertCmd ( CMDTYPE type, int x, int y, DrawCmd* _cmd ); // insert draw command cmd after _cmd virtual void InsertCmd ( DrawCmd* cmd, DrawCmd* _cmd ); // Create new DrawCmd DrawCmd* NewCmd ( CMDTYPE type, int x, int y ); // -------------------- read/modify commands --------------------------- // returns the iterator for the list virtual DrawCmdList::iterator Iterator ( ); // returns the 'end' iterator for the list virtual DrawCmdList::iterator IteratorEnd ( ); // returns the last command in the list virtual DrawCmd* LastCmd (); // returns the total number of commands in the list //virtual int CmdCount () { return cmds.size(); } // move all points by relative amount of x, y coordinates virtual void MovePoints ( int x, int y ); // transform all points using the calculation: // | (m11) (m12) | x | (x - mx) | + | nx | // | (m21) (m22) | | (y - my) | | ny | virtual void Transform( float m11, float m12, float m21, float m22, float mx, float my, float nx, float ny ); // returns some DrawCmd if its m_point = (x, y) virtual DrawCmd* PointAt ( int x, int y ); // returns some DrawCmd if one of its control point = (x, y) // also set &point to refer to that control point virtual DrawCmd* ControlAt ( int x, int y, Point* &point ); // attempts to delete a commmand, returns true|false if successful|fail virtual bool DeleteCommand ( DrawCmd* cmd ); agg::rgba rgba_shape; PixelFormat::AGGType::color_type color_bg; protected: /// The AGG base renderer typedef agg::renderer_base RendererBase; /// The AGG primitives renderer typedef agg::renderer_primitives RendererPrimitives; /// The AGG solid renderer typedef agg::renderer_scanline_aa_solid RendererSolid; enum DRAWCMDMODE { NORMAL, CTRL_LN, HILITE }; DrawCmdList cmds; wxString drawcmdset; PointSystem* pointsys; // for FitToViewPoint feature bool setfitviewpoint; int fitviewpoint_vmargin, fitviewpoint_hmargin; // AGG agg::rasterizer_scanline_aa<> rasterizer; ///< Scanline rasterizer agg::scanline_p8 scanline; ///< Scanline container void render_scanlines_aa_solid(RendererBase& rbase, agg::rgba rbga, bool affectboundaries = true); void render_scanlines(RendererSolid& rsolid, bool affectboundaries = true); int rendered_min_x, rendered_min_y, rendered_max_x, rendered_max_y; //bounding coord of rendered shapes void update_rendered_bound_coords(bool rendered_fresh = false); typedef agg::conv_transform trans_path; agg::path_storage m_path, b_path; trans_path *rm_path, *rb_path; agg::conv_curve *rm_curve; void draw(); virtual void ConstructPathsAndCurves(agg::trans_affine& mtx, trans_path*& _rm_path, trans_path*& _rb_path, agg::conv_curve*& _rm_curve); virtual void DoDraw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx ); virtual void Draw_Clear( RendererBase& rbase ); virtual void Draw_Draw( RendererBase& rbase, RendererPrimitives& rprim, RendererSolid& rsolid, agg::trans_affine& mtx, agg::rgba color ); bool refresh_called; // set stuff to connect two drawing commands cmd1 and cmd2 such that // cmd1 comes right before cmd2 virtual void ConnectSubsequentCmds (DrawCmd* cmd1, DrawCmd* cmd2); virtual void AddDrawCmdToAGGPathStorage(DrawCmd* cmd, agg::path_storage& path, DRAWCMDMODE mode = NORMAL); virtual std::vector< bool > PrepareC1ContData(); DECLARE_EVENT_TABLE() }; namespace agg { class simple_polygon_vertex_source { public: simple_polygon_vertex_source(const double* polygon, unsigned np, bool roundoff = false, bool close = true) : m_polygon(polygon), m_num_points(np), m_vertex(0), m_roundoff(roundoff), m_close(close) { } void close(bool f) { m_close = f; } bool close() const { return m_close; } void rewind(unsigned) { m_vertex = 0; } unsigned vertex(double* x, double* y) { if(m_vertex > m_num_points) return path_cmd_stop; if(m_vertex == m_num_points) { ++m_vertex; return path_cmd_end_poly | (m_close ? path_flags_close : 0); } *x = m_polygon[m_vertex * 2]; *y = m_polygon[m_vertex * 2 + 1]; if(m_roundoff) { *x = floor(*x) + 0.5; *y = floor(*y) + 0.5; } ++m_vertex; return (m_vertex == 1) ? path_cmd_move_to : path_cmd_line_to; } private: const double* m_polygon; unsigned m_num_points; unsigned m_vertex; bool m_roundoff; bool m_close; }; }; typedef agg::simple_polygon_vertex_source aggpolygon;