cairo_gal.h 13.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
 * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
 *
 * CairoGal - Graphics Abstraction Layer for Cairo
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

#ifndef CAIROGAL_H_
#define CAIROGAL_H_

#include <map>
#include <iterator>

#include <cairo.h>

#include <gal/graphics_abstraction_layer.h>
36
#include <boost/smart_ptr/shared_ptr.hpp>
37
#include <wx/dcbuffer.h>
38 39 40 41 42

#if defined(__WXMSW__)
#define SCREEN_DEPTH 24
#else
#if wxCHECK_VERSION( 2, 9, 0 )
43
#define SCREEN_DEPTH    wxBITMAP_SCREEN_DEPTH
44
#else
45
#define SCREEN_DEPTH    32
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#endif
#endif

/**
 * @brief Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
 *
 * Quote from Wikipedia:
 * " Cairo is a software library used to provide a vector graphics-based, device-independent
 *   API for software developers. It is designed to provide primitives for 2-dimensional
 *   drawing across a number of different backends. "
 * <br>
 * Cairo offers also backends for Postscript and PDF surfaces. So it can be used for printing
 * of KiCad graphics surfaces as well.
 *
 */
61
namespace KIGFX
62
{
63 64
class CAIRO_COMPOSITOR;

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
class CAIRO_GAL : public GAL, public wxWindow
{
public:
    /**
     * Constructor CAIRO_GAL
     *
     * @param aParent is the wxWidgets immediate wxWindow parent of this object.
     *
     * @param aMouseListener is the wxEvtHandler that should receive the mouse events,
     *  this can be can be any wxWindow, but is often a wxFrame container.
     *
     * @param aPaintListener is the wxEvtHandler that should receive the paint
     *  event.  This can be any wxWindow, but is often a derived instance
     *  of this class or a containing wxFrame.  The "paint event" here is
     *  a wxCommandEvent holding EVT_GAL_REDRAW, as sent by PostPaint().
     *
     * @param aName is the name of this window for use by wxWindow::FindWindowByName()
     */
    CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener = NULL,
84
               wxEvtHandler* aPaintListener = NULL, const wxString& aName = wxT( "CairoCanvas" ) );
85 86 87 88 89 90 91 92

    virtual ~CAIRO_GAL();

    // ---------------
    // Drawing methods
    // ---------------

    /// @copydoc GAL::BeginDrawing()
Maciej Suminski's avatar
Maciej Suminski committed
93
    virtual void BeginDrawing();
94 95 96 97 98

    /// @copydoc GAL::EndDrawing()
    virtual void EndDrawing();

    /// @copydoc GAL::DrawLine()
99
    virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
100

101 102 103
    /// @copydoc GAL::DrawSegment()
    virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );

104
    /// @copydoc GAL::DrawCircle()
105
    virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius );
106 107

    /// @copydoc GAL::DrawArc()
Maciej Suminski's avatar
Maciej Suminski committed
108 109
    virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
                          double aStartAngle, double aEndAngle );
110 111

    /// @copydoc GAL::DrawRectangle()
112
    virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
113

Maciej Suminski's avatar
Maciej Suminski committed
114 115 116
    /// @copydoc GAL::DrawPolyline()
    virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );

117 118 119 120
    /// @copydoc GAL::DrawPolygon()
    virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList );

    /// @copydoc GAL::DrawCurve()
121 122
    virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
                            const VECTOR2D& controlPointB, const VECTOR2D& endPoint );
123 124 125 126 127 128

    // --------------
    // Screen methods
    // --------------

    /// @brief Resizes the canvas.
129
    virtual void ResizeScreen( int aWidth, int aHeight );
130 131 132 133 134 135 136 137

    /// @brief Shows/hides the GAL canvas
    virtual bool Show( bool aShow );

    /// @copydoc GAL::Flush()
    virtual void Flush();

    /// @copydoc GAL::ClearScreen()
138
    virtual void ClearScreen( const COLOR4D& aColor );
139 140 141 142 143 144 145 146 147 148 149 150

    // -----------------
    // Attribute setting
    // -----------------

    /// @copydoc GAL::SetIsFill()
    virtual void SetIsFill( bool aIsFillEnabled );

    /// @copydoc GAL::SetIsStroke()
    virtual void SetIsStroke( bool aIsStrokeEnabled );

    /// @copydoc GAL::SetStrokeColor()
151
    virtual void SetStrokeColor( const COLOR4D& aColor );
152

Maciej Suminski's avatar
Maciej Suminski committed
153 154
    /// @copydoc GAL::SetFillColor()
    virtual void SetFillColor( const COLOR4D& aColor );
155 156 157 158 159

    /// @copydoc GAL::SetLineWidth()
    virtual void SetLineWidth( double aLineWidth );

    /// @copydoc GAL::SetLayerDepth()
160
    virtual void SetLayerDepth( double aLayerDepth );
161 162 163 164 165 166

    // --------------
    // Transformation
    // --------------

    /// @copydoc GAL::Transform()
167
    virtual void Transform( const MATRIX3x3D& aTransformation );
168 169 170 171 172

    /// @copydoc GAL::Rotate()
    virtual void Rotate( double aAngle );

    /// @copydoc GAL::Translate()
173
    virtual void Translate( const VECTOR2D& aTranslation );
174 175

    /// @copydoc GAL::Scale()
176
    virtual void Scale( const VECTOR2D& aScale );
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196

    /// @copydoc GAL::Save()
    virtual void Save();

    /// @copydoc GAL::Restore()
    virtual void Restore();

    // --------------------------------------------
    // Group methods
    // ---------------------------------------------

    /// @copydoc GAL::BeginGroup()
    virtual int BeginGroup();

    /// @copydoc GAL::EndGroup()
    virtual void EndGroup();

    /// @copydoc GAL::DrawGroup()
    virtual void DrawGroup( int aGroupNumber );

197 198 199
    /// @copydoc GAL::ChangeGroupColor()
    virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor );

200 201 202
    /// @copydoc GAL::ChangeGroupDepth()
    virtual void ChangeGroupDepth( int aGroupNumber, int aDepth );

203 204 205
    /// @copydoc GAL::DeleteGroup()
    virtual void DeleteGroup( int aGroupNumber );

206 207 208
    /// @copydoc GAL::ClearCache()
    virtual void ClearCache();

209 210 211 212 213 214 215 216 217 218
    // --------------------------------------------------------
    // Handling the world <-> screen transformation
    // --------------------------------------------------------

    /// @copydoc GAL::SaveScreen()
    virtual void SaveScreen();

    /// @copydoc GAL::RestoreScreen()
    virtual void RestoreScreen();

219
    /// @copydoc GAL::SetTarget()
Maciej Suminski's avatar
Maciej Suminski committed
220
    virtual void SetTarget( RENDER_TARGET aTarget );
221

222
    /// @copydoc GAL::GetTarget()
Maciej Suminski's avatar
Maciej Suminski committed
223
    virtual RENDER_TARGET GetTarget() const;
224

225
    /// @copydoc GAL::ClearTarget()
Maciej Suminski's avatar
Maciej Suminski committed
226
    virtual void ClearTarget( RENDER_TARGET aTarget );
227

228 229 230 231
    // -------
    // Cursor
    // -------

232 233 234
    /// @copydoc GAL::SetCursorSize()
    virtual void SetCursorSize( unsigned int aCursorSize );

235
    /// @copydoc GAL::DrawCursor()
236
    virtual void DrawCursor( const VECTOR2D& aCursorPosition );
237 238 239 240 241 242 243 244 245 246

    /**
     * Function PostPaint
     * posts an event to m_paint_listener.  A post is used so that the actual drawing
     * function can use a device context type that is not specific to the wxEVT_PAINT event.
     */
    void PostPaint()
    {
        if( paintListener )
        {
247
            wxPaintEvent redrawEvent;
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
            wxPostEvent( paintListener, redrawEvent );
        }
    }

    void SetMouseListener( wxEvtHandler* aMouseListener )
    {
        mouseListener = aMouseListener;
    }

    void SetPaintListener( wxEvtHandler* aPaintListener )
    {
        paintListener = aPaintListener;
    }

protected:
Maciej Suminski's avatar
Maciej Suminski committed
263
    virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
264 265 266 267 268

private:
    /// Super class definition
    typedef GAL super;

269 270
    // Compositing variables
    boost::shared_ptr<CAIRO_COMPOSITOR> compositor; ///< Object for layers compositing
Maciej Suminski's avatar
Maciej Suminski committed
271 272
    unsigned int            mainBuffer;             ///< Handle to the main buffer
    unsigned int            overlayBuffer;          ///< Handle to the overlay buffer
Maciej Suminski's avatar
Maciej Suminski committed
273
    RENDER_TARGET           currentTarget;          ///< Current rendering target
274
    bool                    validCompositor;        ///< Compositor initialization flag
275

276
    // Variables related to wxWidgets
Maciej Suminski's avatar
Maciej Suminski committed
277 278 279 280 281
    wxWindow*               parentWindow;           ///< Parent window
    wxEvtHandler*           mouseListener;          ///< Mouse listener
    wxEvtHandler*           paintListener;          ///< Paint listener
    unsigned int            bufferSize;             ///< Size of buffers cairoOutput, bitmapBuffers
    unsigned char*          wxOutput;               ///< wxImage comaptible buffer
282 283

    // Cursor variables
Maciej Suminski's avatar
Maciej Suminski committed
284 285 286 287 288
    std::deque<wxColour>    savedCursorPixels;      ///< Saved pixels of the cursor
    bool                    isDeleteSavedPixels;    ///< True, if the saved pixels can be discarded
    wxPoint                 savedCursorPosition;    ///< The last cursor position
    wxBitmap*               cursorPixels;           ///< Cursor pixels
    wxBitmap*               cursorPixelsSaved;      ///< Saved cursor pixels
289 290 291 292 293

    /// Maximum number of arguments for one command
    static const int MAX_CAIRO_ARGUMENTS = 6;

    /// Definitions for the command recorder
Maciej Suminski's avatar
Maciej Suminski committed
294 295
    enum GRAPHICS_COMMAND
    {
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
        CMD_SET_FILL,                               ///< Enable/disable filling
        CMD_SET_STROKE,                             ///< Enable/disable stroking
        CMD_SET_FILLCOLOR,                          ///< Set the fill color
        CMD_SET_STROKECOLOR,                        ///< Set the stroke color
        CMD_SET_LINE_WIDTH,                         ///< Set the line width
        CMD_STROKE_PATH,                            ///< Set the stroke path
        CMD_FILL_PATH,                              ///< Set the fill path
        CMD_TRANSFORM,                              ///< Transform the actual context
        CMD_ROTATE,                                 ///< Rotate the context
        CMD_TRANSLATE,                              ///< Translate the context
        CMD_SCALE,                                  ///< Scale the context
        CMD_SAVE,                                   ///< Save the transformation matrix
        CMD_RESTORE,                                ///< Restore the transformation matrix
        CMD_CALL_GROUP                              ///< Call a group
    };

    /// Type definition for an graphics group element
    typedef struct
    {
315
        GRAPHICS_COMMAND command;                   ///< Command to execute
316 317 318 319
        double arguments[MAX_CAIRO_ARGUMENTS];      ///< Arguments for Cairo commands
        bool boolArgument;                          ///< A bool argument
        int intArgument;                            ///< An int argument
        cairo_path_t* cairoPath;                    ///< Pointer to a Cairo path
Maciej Suminski's avatar
Maciej Suminski committed
320
    } GROUP_ELEMENT;
321

322 323 324
    // Variables for the grouping function
    bool                        isGrouping;         ///< Is grouping enabled ?
    bool                        isElementAdded;     ///< Was an graphic element added ?
Maciej Suminski's avatar
Maciej Suminski committed
325 326
    typedef std::deque<GROUP_ELEMENT> GROUP;        ///< A graphic group type definition
    std::map<int, GROUP>        groups;             ///< List of graphic groups
327
    unsigned int                groupCounter;       ///< Counter used for generating keys for groups
Maciej Suminski's avatar
Maciej Suminski committed
328
    GROUP*                      currentGroup;       ///< Currently used group
329 330 331

    // Variables related to Cairo <-> wxWidgets
    cairo_matrix_t      cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix
332 333 334
    cairo_t*            currentContext;         ///< Currently used Cairo context for drawing
    cairo_t*            context;                ///< Cairo image
    cairo_surface_t*    surface;                ///< Cairo surface
335 336 337
    unsigned int*       bitmapBuffer;           ///< Storage of the cairo image
    unsigned int*       bitmapBufferBackup;     ///< Backup storage of the cairo image
    int                 stride;                 ///< Stride value for Cairo
338
    bool                isInitialized;          ///< Are Cairo image & surface ready to use
339
    COLOR4D             backgroundColor;        ///< Background color
340 341

    // Methods
342
    void storePath();                           ///< Store the actual path
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

    // Event handlers
    /**
     * @brief Paint event handler.
     *
     * @param aEvent is the paint event.
     */
    void onPaint( wxPaintEvent& aEvent );

    /**
     * @brief Mouse event handler, forwards the event to the child.
     *
     * @param aEvent is the mouse event to be forwarded.
     */
    void skipMouseEvent( wxMouseEvent& aEvent );

359 360 361 362
    /**
     * @brief Prepares cursor bitmap.
     */
    virtual void initCursor();
363

364
    /**
365
     * @brief Blits cursor into the current screen.
366 367 368
     */
    virtual void blitCursor( wxBufferedDC& clientDC );

369 370 371
    /// Prepare Cairo surfaces for drawing
    void initSurface();

372
    /// Destroy Cairo surfaces when are not needed anymore
373
    void deinitSurface();
374

Maciej Suminski's avatar
Maciej Suminski committed
375 376 377 378 379 380
    /// Allocate the bitmaps for drawing
    void allocateBitmaps();

    /// Allocate the bitmaps for drawing
    void deleteBitmaps();

381 382 383
    /// Prepare the compositor
    void setCompositor();

384
    /**
385
     * @brief Returns a valid key that can be used as a new group number.
386 387 388
     *
     * @return An unique group number that is not used by any other group.
     */
389
    unsigned int getNewGroupNumber();
390 391 392

    /// Format used to store pixels
    static const cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
393 394

    ///> Opacity of a single layer
395
    static const float LAYER_ALPHA;
396
};
397
} // namespace KIGFX
398

399
#endif  // CAIROGAL_H_