You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

530 lines
17 KiB

/***************************************************************************
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 <config.h>
#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