/*************************************************************************** qsdrv.h ------------------- begin : 01-January-2000 copyright : (C) 2000 by Kamil Dobkowski email : kamildobk@poczta.onet.pl ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef QSGDRIVER_H #define QSGDRIVER_H #ifdef HAVE_CONFIG_H #include #endif #include "qscoord.h" #include "qsgattr.h" #include "qsprojection.h" //------------------------------------------------------------------------------------------------// /** * \brief Abstract graphics driver. * * Most functions need to be reimplemented. Font, point, arrow sizes are * in points, so 'dpi' must be used to convert it to pixels, line width is an exception. Despite all * coordinates are float, they are pixel coordinates. Function startDrawing() is used to initialize the graphics driver, * and function stopDrawing() is called when drawing is finished. */ class QSCanvasDrv : public Qt { public: double dpi; /** * Converts points to pixels - "pixels = points*dpi/72.0". */ inline double toPixels( double points ) { return QSCoord::pointsToPixels(points,dpi); } /** * Converts pixels to points */ inline double toPoints( double pixels ) { return QSCoord::pixelsToPoints(pixels,dpi); } /** * Constructor */ QSCanvasDrv(); /** * Destructor */ virtual ~QSCanvasDrv(); /** * Returns a copy of this object. */ virtual QSCanvasDrv *copy() = 0; /** * This method is called to activate the graphics context * when drawing starts. */ virtual void startDrawing(); /** * This function is called when drawing ends. */ virtual void stopDrawing(); /** * Draw a line. */ virtual void drawLine( const QSPt2f &one, const QSPt2f &two ) = 0; /** * Draw a rectangle. */ virtual void drawRect( const QSPt2f &p1, const QSPt2f &p2 ) = 0; /** * Draw a polygon defined by 'npoints' points in 'pts'. * Can change the current line ( if edgeAuto color != 0 ) */ virtual void drawPoly( const QSPt2f pts[], int npoints, const bool edges[] = NULL, int edgesAutoColor = 0 ) = 0; /** * Draws a circle. */ virtual void drawEllipse( const QSPt2f& p1, const QSPt2f& p2 ) = 0; /** * Draw a text. */ virtual void drawText( const QSPt2f &pos, const QString& text, int align = AlignLeft | AlignBottom ) = 0; /** * Return the size of the text that will be printed by the corresponding * @ref QSDrv::drawText function. */ virtual QSPt2f textSize( const QString& text ) = 0; /** * Draw a rotated text. This must be reimplemented. */ virtual void drawRText( const QSPt2f &pos, int angle, const QString& text, int align = AlignLeft | AlignBottom ) = 0; /** * Draw a rotated text. Aligns the bounding rectangle, not the bounding poly. No need to be reimplemented */ virtual void drawRTextBox( const QSPt2f &pos, int angle, const QString& text, int align = AlignLeft | AlignBottom ); /** * Return size of a rotated text. This must be reimplemented. */ virtual void getRTextBoundingPoly( QSPt2f outPts[4], const QSPt2f &pos, int angle, const QString& text, int align = AlignLeft | AlignBottom ) = 0; /** * Returns the size of a roated text. Default implementation is provided using 'getRTextBoundingPoly' */ virtual QSPt2f rTextSize( int angle, const QString& text ); /** * Draws a point. Because point contains its own color attr. it can change * current fill and line settings * It has a default implementation already. */ virtual void drawPoint( const QSPt2f& pos, const QSGPoint& style ); /** * Draws a line end. It can change current fill settings. * It has a default implementation already. */ virtual void drawDart( const QSPt2f& pos, double angle, const QSGArrow& style ); /** * Draws an arrow. It can change current fill and line settings. * It has a default implementation already. */ virtual void drawArrow( const QSPt2f& p1, const QSPt2f& p2, const QSGArrow& p1style, const QSGArrow& p2style ); /** * Set the current fill . */ virtual void setFill( const QSGFill &f ) = 0; /** * Set the current font. */ virtual void setFont( const QSGFont &f ) = 0; /** * Set the current line style. */ virtual void setLine( const QSGLine &l ) = 0; /** * This function should return the current font. */ virtual QSGFont currentFont() { return QSGFont(); } /** * This function should return the current fill. */ virtual QSGFill currentFill() { return QSGFill(); } /** * This function should return the current line. */ virtual QSGLine currentLine() { return QSGLine(); } //----------------------------------------------------------------------// // 2D DRIVER /** * Starts to draw a polyline. */ virtual void beginPolyline( const QSPt2f& pos ) = 0; /** * Draw the next line segment. Wach out for setLine() call during drawPolyline2() */ virtual void drawPolylineTo( const QSPt2f& pos ) = 0; /** * Ends polyline. */ virtual void endPolyline() {} /** * Returns the current pen position. */ virtual QSPt2f currPolylinePos() { return QSPt2f(); } /** * Pixmap buffer for the 2d graphics driver. */ struct PixmapBuffer { /** * Pointer to the memory buffer, which will be filled with * pixel values. Pixel at the position (x,y) has his position * in memory calculated as below: * char *ppos = ptr+y*lo+x*po * or if it is RGB : * char *rpos = ppos; * char *gpos = rpos+co; * char *bpos = gpos+co; * Notice that all values: 'lo', 'po', 'co' may be lower * than zero. Currently only RGB mode is supported. */ unsigned char *ptr; /** * Byte ofseet between two succesive lines in memory. * ( scanline length in bytes ). */ int lo; /** * Byte offset between two succesive pixels in memory. */ int po; /** * Byte offset between two succesive channels (Red, Green, Blue) */ int co; /** * Buffer capacity in lines. It means that buffer length is * at last: len=lines*lo. */ int lines; }; /** * This method is always called before @ref QSDrv::drawPixmap. * The struct 'PixmapBuffer' must be filled with correct values. * Pixmap width is requested to be equal to 'pwidth', pixmap height * must be lower or equal to pheight ( see field 'lines' in 'PixmapBuffer' ). */ virtual void getPixmapBuffer( PixmapBuffer *buff, int pwidth, int pheight ); /** * Draw a pixmap. Notice that the pixmap buffer will be always * the last requested one.'getPixmapBuffer' / 'drawPixmap' pair * is always called together. */ virtual void drawPixmap( const QSPt2f& pos, PixmapBuffer *data ); }; //------------------------------------------------------------------------------------------------// /** * \brief Abstract extedned graphic driver. * * Abstract base class for graphics drivers with 3D functions and logical cordinates. It expects all coordinates to be * world coordinates - it means that all values between 0.0 and 1.0 are inside * an axis cube/box, while others are outside of it. Generally those functions * don't need to be reimplemented. Default implementation simply maps all coordinates * to the screen ( using providen projection object ) and calls functions from QSCanvasDrv. * This driver should additionaly do clipping as provided by QSProjection object. * @author Kamil Dobkowski */ class QSDrv : public QSCanvasDrv { public: /** * Normal mode. See @ref #drawPoly3 . */ enum CNormals { VertexNormals, MeshNormal, NoNormals }; /** * Color mode. See @ref #drawPoly3 . */ enum CColors { VertexColors, MeshColor }; /** * Ordering. See @ref #drawPoly3 . */ enum COrdering { FurtherFirst, NearerFirst, NoOrdering }; /** * Constructor. See also setProjection() */ QSDrv(); /** * Destructor */ virtual ~QSDrv(); /** * Returns a copy of this object. */ virtual QSDrv *copy() = 0; /** * Copies a pointer to a projection object */ void copySettingsFrom( const QSDrv *drv ); /** * Sets a projection object used by this driver. None method of this interface can be called * if projection is not set. Projection is not owned by this object, it only holds a pointer. */ virtual void setProjection( const QSProjection *t ); /** * Returns a projection object used by this driver. */ const QSProjection *projection() const { return m_t; } /** * Reimplemented */ virtual void startDrawing(); /** * Reimplemented */ virtual void stopDrawing(); /** * Turns on clipping when drawing ( ..2(), *3() methods ). Must be called after startDrawing() * Always clips polygons,lines,points using clipPoly2,clipLine2,clipPoint2,clipPoint3, clipPoly3. */ virtual void setClipping( bool enabled ); /** * Returns the current clipping setting. */ bool clipping() const { return m_clipping ; } /** * Sets a currently drawn element. It has no meaning for this objects - just a pair of ints. * It is called by a graphic object, which uses this driver. * It can be used for example in QSHitDrv to see what part of an object was exacly hit * by mouse. It can be read, but further interpretation must be done in an other place. * It is reset to -1, -1 in stopDrawing(). See QSAxes::ElementCategory */ virtual void setCurrentElement( int category, int element ); /** * Returns a currently drawn element See QSAxes::ElementCategory */ int currentElement() const { return m_element; } /** * Returns a category of the currently drawn element. See QSAxes::ElementCategory */ int currentCategory() const { return m_category; } /** * Turns on top/bottom detection for drawPoly3 */ virtual void setTopBottom( bool enabled ); /** * Is top/bottom detection turned on ? */ bool topBottom() const { return m_top_bottom; } /** * Sets a bottom fill */ virtual void setBottomFill( const QSGFill& fill ); /** * Returns the current bottom fill */ QSGFill bottomFill() const { return m_bottom_fill; } /** * Return a normals mode required by this driver. */ virtual CNormals cNormals() const { return MeshNormal; } /** * Returns a color mode required by this driver. */ virtual CColors cColors() const { return MeshColor; } /** * Returns an ordering required by this driver. */ virtual COrdering cOrdering() const { return FurtherFirst; } //----------------------------------------------------------------------// // 2D DRIVER /** * Clear the canvas. */ virtual void clearCanvas( const QSGFill& f, const QSPt2f& pos, const QSPt2f& size ); /** * The same as QS */ virtual void drawLine2( const QSPt2f &one, const QSPt2f &two ); /** * Draw a rectangle. */ virtual void drawRect2( const QSPt2f &p1, const QSPt2f &p2 ); /** * Draw a polygon defined by 'npoints' points in 'pts'. * Can change the current line ( if edgeAuto color != 0 ) */ virtual void drawPoly2( const QSPt2f pts[], int npoints, const bool edges[] = NULL, int edgeAutoColor = 0 ); /** * Draws a circle. */ virtual void drawEllipse2( const QSPt2f& p1, const QSPt2f& p2 ); /** * Draw a text. */ virtual void drawText2( const QSPt2f &pos, const QString& text, int align = AlignLeft | AlignBottom ); /** * Draw a rotated text. This must be reimplemented. */ virtual void drawRText2( const QSPt2f &pos, int angle, const QString& text, int align = AlignLeft | AlignBottom ); /** * Draw a rotated text. Aligns the bounding rectangle, not the bounding poly. No need to be reimplemented */ virtual void drawRTextBox2( const QSPt2f &pos, int angle, const QString& text, int align = AlignLeft | AlignBottom ); /** * Draws a point. Because point contains its own color attr. it can change * current fill and line settings * It has a default implementation already. */ virtual void drawPoint2( const QSPt2f& pos, const QSGPoint& style ); /** * Draws a line end. It can change current fill settings. * It has a default implementation already. */ virtual void drawDart2( const QSPt2f& pos, double angle, const QSGArrow& style ); /** * Draws an arrow. It can change current fill and line settings. * It has a default implementation already. */ virtual void drawArrow2( const QSPt2f& p1, const QSPt2f& p2, const QSGArrow& p1style, const QSGArrow& p2style ); /** * Starts to draw a polyline. */ virtual void beginPolyline2( const QSPt2f& pos ); /** * Ups ! a little hack. Leave place for the label in the current polyline */ virtual void setPolylineLabelPlace2( const QString& label, const QSPt2f& label_place, int label_angle ); /** * Draw the next line segment. */ virtual void drawPolylineTo2( const QSPt2f& pos ); /** * Ends polyline. */ virtual void endPolyline2(); /** * Returns the current pen position. */ virtual QSPt2f currPolylinePos2(); //----------------------------------------------------------------------// // 3D DRIVER /** * Draws a 3d polygon with 'npoints' vertices in 'pts' table. * Each vertex has its color in 'colors' table. If 'VertexColors' * is set, then color for each vertex is calculated separately, * otherwise only colors[0] is set to the color of the whole polygon. * Each vertex has its normal vector in 'norm', but the first position in * this table is always occupied by a normal to the whole polygon. * If 'MeshNormals' is set, the normal to the polygon, norm[0], is calculated. * If 'VertexNormals' is set, a normal for each vertex is calculated separately * but the normal to the polygon is also calculated and set as 'norm[0]'. * If none of this two flags is set, contents of the table is undefined * Default implementation maps 3d points on 2d plane and draws 2d polygon. * Can change the current fill and the current line ( if edgeAuto color != 0 ) */ virtual void drawPoly3( const QSPt3f pts[], int npoints, const QSPt3f *norm, const QSGFill *colors, const bool edges[] = NULL, int edgeAutoColor = 0 ); /** * Draws a line. * Default implementation maps 3d points on 2d plane and draws 2d line. */ virtual void drawLine3( const QSPt3f& begin, const QSPt3f& end, const QSPt3f norm[2] ); /** * Draws a text at the given position. * Defaul implementation maps 3d point on 2d plane and draws text.. */ virtual void drawText3( const QSPt3f& pos, const QString& text, int align = AlignLeft | AlignBottom ); /** * Draw a point mark. */ virtual void drawPoint3( const QSPt3f& pos, const QSGPoint& point ); protected: int m_element; int m_category; bool m_top_bottom; QSGFill m_bottom_fill; const QSProjection *m_t; bool m_clipping; QSPt2f m_curr_polyline_pos; // clipped 2d coordinates QSPt2f *m_cpts2; int m_ncpts2; int m_max_cpts2; QSProjection::ClipResult clip_poly( const QSPt2f *pts, int npoints, const bool edges[] ); // clipped 3d coordinated QSPt3f *m_cpts3; int m_ncpts3; int m_max_cpts3; QSProjection::ClipResult clip_poly( const QSPt3f *pts, int npoints, const bool edges[] ); // buffer for screen coordinates QSPt2f *m_pts; int m_max_pts; void map_to_screen( const QSPt2f *pts, int npoints ); void map_to_screen( const QSPt3f *pts, int npoints ); // clipped edges bool *m_cedges; int m_max_cedges; QSPt2f m_polyline_label_pos; QSPt2f m_polyline_label_size; }; #endif