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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
|
#ifndef __canvas_h__
#define __canvas_h__
#include <cstdlib>
#include "../DasherCore/DasherScreen.h"
#include "../DasherCore/DasherTypes.h"
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <pango/pango.h>
#include <map>
#include <iostream>
#if WITH_CAIRO
#define BEGIN_DRAWING_BACKEND \
cairo_save(cr)
#define END_DRAWING_BACKEND \
cairo_restore(cr)
#define SET_COLOR_BACKEND(c) \
cairo_set_source(cr, cairo_colours[(c)])
#else /* WITHOUT_CAIRO */
#define BEGIN_DRAWING_BACKEND \
GdkGCValues origvalues; \
gdk_gc_get_values(graphics_context,&origvalues)
#define END_DRAWING_BACKEND \
gdk_gc_set_values(graphics_context,&origvalues,GDK_GC_FOREGROUND)
#define SET_COLOR_BACKEND(c) \
do { \
GdkColor _c = colours[(c)]; \
gdk_colormap_alloc_color(colormap, &_c, FALSE, TRUE); \
gdk_gc_set_foreground (graphics_context, &_c); \
} while (0)
#endif /* WITH_CAIRO */
// Some other useful macros (for all backends)
#define BEGIN_DRAWING \
BEGIN_DRAWING_BACKEND
#define END_DRAWING \
END_DRAWING_BACKEND
#define SET_COLOR(c) \
SET_COLOR_BACKEND(c)
/// CCanvas
///
/// Method definitions for CCanvas, implementing the CDasherScreen
/// interface. Please think very carefully before implementing new
/// functionality in this class. Anything which isn't a 'drawing
/// primitive' should really not be here - higher level drawing
/// functions belong in CDasherView.
class CCanvas:public Dasher::CLabelListScreen {
public:
typedef Dasher::screenint screenint;
/// Creates a new canvas - initially of zero size, so drawing
/// operations won't do anything until a call to resize() is made.
/// \param pCanvas The GTK drawing area used by the canvas
///
CCanvas(GtkWidget *pCanvas);
~CCanvas();
///
/// GTK signal handler for exposure of the canvas - cause a redraw to the screen from the buffer.
///
bool ExposeEvent( GtkWidget *pWidget, GdkEventExpose *pEvent);
// CDasherScreen methods
///
/// Set the font used to render the Dasher display
/// \param Name The name of the font.
/// \todo This needs to be reimplemented for 4.0
/// \deprecated In Linux - now handled by the pango cache, but need to think how this fits in with Windows
///
void SetFont(const std::string &strName);
///Make a label for use with this screen; caches Pango layout information inside it.
CDasherScreen::Label *MakeLabel(const std::string &strText, unsigned int iWrapSize=0) override;
///
/// Return the physical extent of a given string being rendered at a given size.
/// \param String The string to be rendered
/// \param Width Pointer to a variable to be filled with the width
/// \param Height Pointer to a variable to be filled with the height
/// \param Size Size at which the string will be rendered (units?)
///
std::pair<screenint,screenint> TextSize(CDasherScreen::Label *label, unsigned int Size) override;
///
/// Draw a text string
/// \param String The string to be rendered
/// \param x1 The x coordinate at which to draw the text (be more precise)
/// \param y1 The y coordinate at which to draw the text (be more precise)
/// \param Size The size at which to render the rectangle (units?)
///
void DrawString(CDasherScreen::Label *label, screenint x1, screenint y1, unsigned int Size, int iColor) override;
///
/// Draw a rectangle
/// \param x1 x coordiate of the top left corner
/// \param y1 y coordiate of the top left corner
/// \param x2 x coordiate of the bottom right corner
/// \param y2 y coordiate of the bottom right corner
/// \param Color Colour to fill the rectangle (-1 = don't fill)
/// \param iOutlineColour Colour to draw the outline (-1 = use default)
/// \param iThickness line width of outline (<=0 = don't outline)
///
void DrawRectangle(screenint x1, screenint y1, screenint x2, screenint y2, int Color, int iOutlineColour, int iThickness) override;
void DrawCircle(screenint iCX, screenint iCY, screenint iR, int iFillColour, int iLineColour, int iThickness) override;
///
/// Send a marker to indicate phases of the redraw process. This is
/// done so that we can do tripple buffering to minimise the amount
/// of costly font rendering which needs to be done. Marker 1
/// indicates that start of a new frame. Marker 2 indicates that we
/// are now drawing decoration (such as mouse cursors etc.) rather
/// than tne background. Only marker 2 will be send while Dasher is
/// paused.
/// \param iMarker ID of the marker being sent.
///
void SendMarker(int iMarker) override;
///
/// Draw a coloured polyline
/// \param Points Array of vertices
/// \param Number Size of 'Points' array
/// \param Colour Colour with which to draw the line
///
void Polyline(point * Points, int Number, int iWidth, int Colour) override;
///
/// Draw a closed polygon (linking last vertex back to first)
/// @param fillColour colour to fill; -1 => don't fill
/// @param outlineColour colour to draw outline...
/// @param iWidth ...and line thickness; -1 => don't draw outline
///
void Polygon(point *Points, int Number, int fillColour, int outlineColour, int iWidth) override;
///
/// Marks the end of the display process - at this point the offscreen buffer is copied onscreen.
///
void Display() override;
///
/// Update the colour definitions
/// \param Colours New colours to use
///
void SetColourScheme(const Dasher::CColourIO::ColourInfo *pColourScheme) override;
///
/// Gets the location and size of our canvas.
/// Returns true on success, false otherwise.
bool GetCanvasSize(GdkRectangle *pRectangle);
// Redeclare to make public and adjust cairo/gdk surface sizes
void resize(screenint w,screenint h);
// Returns true if cursor is over visible part of this window.
bool IsWindowUnderCursor() override;
private:
///
/// The GTK drawing area for the canvas
///
GtkWidget *m_pCanvas;
void InitSurfaces();
void DestroySurfaces();
#if WITH_CAIRO
cairo_surface_t *m_pDisplaySurface;
cairo_surface_t *m_pDecorationSurface;
//cairo_surface_t *m_pOnscreenSurface;
cairo_surface_t *m_pOffscreenbuffer;
#else
///
/// The offscreen buffer containing the 'background'
///
GdkPixmap *m_pDisplayBuffer;
///
/// The offscreen buffer containing the full display. This is
/// constructed by first copying the display buffer across and then
/// drawing decorations such as the mouse cursor on top.
///
GdkPixmap *m_pDecorationBuffer;
///
/// The onscreen buffer - copied onscreen whenever an expose event occurs.
///
//GdkPixmap *m_pOnscreenBuffer;
///
/// Pointer to which of the offscreen buffers is currently active.
///
GdkPixmap *m_pOffscreenBuffer;
//GdkPixmap *m_pDummyBuffer;
#endif
std::string m_strFontName;
std::map<unsigned int,PangoFontDescription *> m_mFonts;
class CPangoLabel : public CLabelListScreen::Label {
public:
CPangoLabel(CCanvas *pCanvas, const std::string &strText, unsigned int iWrapFontSize)
: CLabelListScreen::Label(pCanvas, strText, iWrapFontSize) {
}
std::map<unsigned int,PangoLayout *> m_mLayouts;
};
PangoLayout *GetLayout(CPangoLabel *label, unsigned int iFontSize);
#if WITH_CAIRO
cairo_t *display_cr;
cairo_t *decoration_cr;
cairo_t *cr; // offscreen
cairo_pattern_t **cairo_colours;
#else
GdkColor *colours;
#endif
};
#endif
|