]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/dc.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[wxWidgets.git] / src / gtk / dc.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/gtk/dc.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
6f65e337 5// RCS-ID: $Id$
6c9a19aa 6// Copyright: (c) 1998 Robert Roebling
65571936 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
14f355c2
VS
10// For compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
c801d85f 12
9dc44eff
PC
13#ifdef __WXGTK3__
14
15#include "wx/window.h"
16#include "wx/dcclient.h"
17#include "wx/dcmemory.h"
18#include "wx/dcscreen.h"
19#include "wx/icon.h"
20#include "wx/gtk/dc.h"
21
22#include <gtk/gtk.h>
23
24wxGTKCairoDCImpl::wxGTKCairoDCImpl(wxDC* owner)
25 : base_type(owner)
26{
27 m_width = 0;
28 m_height = 0;
29}
30
f30b9eed
PC
31wxGTKCairoDCImpl::wxGTKCairoDCImpl(wxDC* owner, int)
32 : base_type(owner, 0)
33{
34 m_width = 0;
35 m_height = 0;
36}
37
9dc44eff 38wxGTKCairoDCImpl::wxGTKCairoDCImpl(wxDC* owner, wxWindow* window)
f30b9eed 39 : base_type(owner, 0)
9dc44eff
PC
40{
41 m_window = window;
42 m_font = window->GetFont();
43 m_textForegroundColour = window->GetForegroundColour();
44 m_textBackgroundColour = window->GetBackgroundColour();
45 m_width = 0;
46 m_height = 0;
47}
48
49void wxGTKCairoDCImpl::DoDrawBitmap(const wxBitmap& bitmap, int x, int y, bool useMask)
50{
51 wxCHECK_RET(IsOk(), "invalid DC");
52
53 cairo_t* cr = NULL;
54 if (m_graphicContext)
55 cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext());
56 if (cr)
57 {
58 cairo_save(cr);
59 bitmap.Draw(cr, x, y, useMask, &m_textForegroundColour, &m_textBackgroundColour);
60 cairo_restore(cr);
61 }
62}
63
64void wxGTKCairoDCImpl::DoDrawIcon(const wxIcon& icon, int x, int y)
65{
66 DoDrawBitmap(icon, x, y, true);
67}
68
69#if wxUSE_IMAGE
70bool wxDoFloodFill(wxDC* dc, int x, int y, const wxColour& col, wxFloodFillStyle style);
71
72bool wxGTKCairoDCImpl::DoFloodFill(int x, int y, const wxColour& col, wxFloodFillStyle style)
73{
74 return wxDoFloodFill(GetOwner(), x, y, col, style);
75}
76#endif
77
78wxBitmap wxGTKCairoDCImpl::DoGetAsBitmap(const wxRect* /*subrect*/) const
79{
80 wxFAIL_MSG("DoGetAsBitmap not implemented");
81 return wxBitmap();
82}
83
84bool wxGTKCairoDCImpl::DoGetPixel(int x, int y, wxColour* col) const
85{
86 if (col)
87 {
88 cairo_t* cr = NULL;
89 if (m_graphicContext)
90 cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext());
91 if (cr)
92 {
93 cairo_surface_t* surface = cairo_get_target(cr);
94 x = LogicalToDeviceX(x);
95 y = LogicalToDeviceY(y);
96 GdkPixbuf* pixbuf = gdk_pixbuf_get_from_surface(surface, x, y, 1, 1);
97 if (pixbuf)
98 {
99 const guchar* src = gdk_pixbuf_get_pixels(pixbuf);
100 col->Set(src[0], src[1], src[2]);
101 g_object_unref(pixbuf);
102 return true;
103 }
104 *col = wxColour();
105 }
106 }
107 return false;
108}
109
110void wxGTKCairoDCImpl::DoGetSize(int* width, int* height) const
111{
112 if (width)
113 *width = m_width;
114 if (height)
115 *height = m_height;
116}
117
118bool wxGTKCairoDCImpl::DoStretchBlit(int xdest, int ydest, int dstWidth, int dstHeight, wxDC* source, int xsrc, int ysrc, int srcWidth, int srcHeight, wxRasterOperationMode rop, bool useMask, int xsrcMask, int ysrcMask)
119{
120 wxCHECK_MSG(IsOk(), false, "invalid DC");
121 wxCHECK_MSG(source && source->IsOk(), false, "invalid source DC");
122
123 cairo_t* cr = NULL;
124 if (m_graphicContext)
125 cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext());
126 cairo_t* cr_src = NULL;
127 wxGraphicsContext* gc_src = source->GetGraphicsContext();
128 if (gc_src)
129 cr_src = static_cast<cairo_t*>(gc_src->GetNativeContext());
130
131 if (cr == NULL || cr_src == NULL)
132 return false;
133
134 const int xsrc_dev = source->LogicalToDeviceX(xsrc);
135 const int ysrc_dev = source->LogicalToDeviceY(ysrc);
136
137 cairo_surface_t* surface = cairo_get_target(cr_src);
138 cairo_surface_flush(surface);
139 cairo_save(cr);
140 cairo_translate(cr, xdest, ydest);
141 cairo_rectangle(cr, 0, 0, dstWidth, dstHeight);
142 double sx, sy;
143 source->GetUserScale(&sx, &sy);
144 cairo_scale(cr, dstWidth / (sx * srcWidth), dstHeight / (sy * srcHeight));
145 cairo_set_source_surface(cr, surface, -xsrc_dev, -ysrc_dev);
146 const wxRasterOperationMode rop_save = m_logicalFunction;
147 SetLogicalFunction(rop);
148 cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
149 cairo_surface_t* maskSurf = NULL;
150 if (useMask)
151 {
152 const wxBitmap& bitmap = source->GetImpl()->GetSelectedBitmap();
153 if (bitmap.IsOk())
154 {
155 wxMask* mask = bitmap.GetMask();
156 if (mask)
157 maskSurf = mask->GetBitmap();
158 }
159 }
160 if (maskSurf)
161 {
162 int xsrcMask_dev = xsrc_dev;
163 int ysrcMask_dev = ysrc_dev;
164 if (xsrcMask != -1)
165 xsrcMask_dev = source->LogicalToDeviceX(xsrcMask);
166 if (ysrcMask != -1)
167 ysrcMask_dev = source->LogicalToDeviceY(ysrcMask);
168 cairo_clip(cr);
169 cairo_mask_surface(cr, maskSurf, -xsrcMask_dev, -ysrcMask_dev);
170 }
171 else
172 {
173 cairo_fill(cr);
174 }
175 cairo_restore(cr);
176 m_logicalFunction = rop_save;
177 return true;
178}
179
180void* wxGTKCairoDCImpl::GetCairoContext() const
181{
182 cairo_t* cr = NULL;
183 if (m_graphicContext)
184 cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext());
185 if (cr)
186 cairo_reference(cr);
187 return cr;
188}
189//-----------------------------------------------------------------------------
190
191wxWindowDCImpl::wxWindowDCImpl(wxWindowDC* owner, wxWindow* window)
192 : base_type(owner, window)
193{
194 GtkWidget* widget = window->m_wxwindow;
195 if (widget == NULL)
196 widget = window->m_widget;
197 GdkWindow* gdkWindow = NULL;
198 if (widget)
199 {
200 gdkWindow = gtk_widget_get_window(widget);
201 m_ok = true;
202 }
203 if (gdkWindow)
204 {
205 cairo_t* cr = gdk_cairo_create(gdkWindow);
206 SetGraphicsContext(wxGraphicsContext::CreateFromNative(cr));
207 GtkAllocation a;
208 gtk_widget_get_allocation(widget, &a);
209 int x, y;
210 if (gtk_widget_get_has_window(widget))
211 {
212 m_width = gdk_window_get_width(gdkWindow);
213 m_height = gdk_window_get_height(gdkWindow);
214 x = m_width - a.width;
215 y = m_height - a.height;
216 }
217 else
218 {
219 m_width = a.width;
220 m_height = a.height;
221 x = a.x;
222 y = a.y;
223 cairo_rectangle(cr, a.x, a.y, a.width, a.height);
224 cairo_clip(cr);
225 }
226 if (x || y)
227 SetDeviceLocalOrigin(x, y);
228 }
f30b9eed
PC
229 else
230 SetGraphicsContext(wxGraphicsContext::Create());
9dc44eff
PC
231}
232//-----------------------------------------------------------------------------
233
234wxClientDCImpl::wxClientDCImpl(wxClientDC* owner, wxWindow* window)
235 : base_type(owner, window)
236{
237 GtkWidget* widget = window->m_wxwindow;
238 if (widget == NULL)
239 widget = window->m_widget;
240 GdkWindow* gdkWindow = NULL;
241 if (widget)
242 {
243 gdkWindow = gtk_widget_get_window(widget);
244 m_ok = true;
245 }
246 if (gdkWindow)
247 {
248 cairo_t* cr = gdk_cairo_create(gdkWindow);
249 SetGraphicsContext(wxGraphicsContext::CreateFromNative(cr));
250 if (gtk_widget_get_has_window(widget))
251 {
252 m_width = gdk_window_get_width(gdkWindow);
253 m_height = gdk_window_get_height(gdkWindow);
254 }
255 else
256 {
257 GtkAllocation a;
258 gtk_widget_get_allocation(widget, &a);
259 m_width = a.width;
260 m_height = a.height;
261 cairo_rectangle(cr, a.x, a.y, a.width, a.height);
262 cairo_clip(cr);
263 SetDeviceLocalOrigin(a.x, a.y);
264 }
265 }
266 else
f30b9eed 267 SetGraphicsContext(wxGraphicsContext::Create());
9dc44eff
PC
268}
269//-----------------------------------------------------------------------------
270
271wxPaintDCImpl::wxPaintDCImpl(wxPaintDC* owner, wxWindow* window)
272 : base_type(owner, window)
273{
274 cairo_t* cr = window->GTKPaintContext();
275 wxCHECK_RET(cr, "using wxPaintDC without being in a native paint event");
276 GdkWindow* gdkWindow = gtk_widget_get_window(window->m_wxwindow);
277 m_width = gdk_window_get_width(gdkWindow);
278 m_height = gdk_window_get_height(gdkWindow);
279 cairo_reference(cr);
280 SetGraphicsContext(wxGraphicsContext::CreateFromNative(cr));
281}
282//-----------------------------------------------------------------------------
283
284wxScreenDCImpl::wxScreenDCImpl(wxScreenDC* owner)
f30b9eed 285 : base_type(owner, 0)
9dc44eff
PC
286{
287 GdkWindow* window = gdk_get_default_root_window();
288 m_width = gdk_window_get_width(window);
289 m_height = gdk_window_get_height(window);
290 cairo_t* cr = gdk_cairo_create(window);
291 SetGraphicsContext(wxGraphicsContext::CreateFromNative(cr));
292}
293//-----------------------------------------------------------------------------
294
295wxMemoryDCImpl::wxMemoryDCImpl(wxMemoryDC* owner)
296 : base_type(owner)
297{
298 m_ok = false;
299}
300
301wxMemoryDCImpl::wxMemoryDCImpl(wxMemoryDC* owner, wxBitmap& bitmap)
f30b9eed 302 : base_type(owner, 0)
9dc44eff
PC
303 , m_bitmap(bitmap)
304{
305 Setup();
306}
307
308wxMemoryDCImpl::wxMemoryDCImpl(wxMemoryDC* owner, wxDC*)
309 : base_type(owner)
310{
311 m_ok = false;
312}
313
314wxBitmap wxMemoryDCImpl::DoGetAsBitmap(const wxRect* subrect) const
315{
316 return subrect ? m_bitmap.GetSubBitmap(*subrect) : m_bitmap;
317}
318
319void wxMemoryDCImpl::DoSelect(const wxBitmap& bitmap)
320{
321 m_bitmap = bitmap;
322 Setup();
323}
324
325const wxBitmap& wxMemoryDCImpl::GetSelectedBitmap() const
326{
327 return m_bitmap;
328}
329
330wxBitmap& wxMemoryDCImpl::GetSelectedBitmap()
331{
332 return m_bitmap;
333}
334
335void wxMemoryDCImpl::Setup()
336{
337 wxGraphicsContext* gc = NULL;
338 m_ok = m_bitmap.IsOk();
339 if (m_ok)
340 {
341 m_width = m_bitmap.GetWidth();
342 m_height = m_bitmap.GetHeight();
343 cairo_t* cr = m_bitmap.CairoCreate();
344 gc = wxGraphicsContext::CreateFromNative(cr);
345 }
346 SetGraphicsContext(gc);
347}
348//-----------------------------------------------------------------------------
349
350wxGTKCairoDC::wxGTKCairoDC(cairo_t* cr)
f30b9eed 351 : base_type(new wxGTKCairoDCImpl(this, 0))
9dc44eff
PC
352{
353 cairo_reference(cr);
354 SetGraphicsContext(wxGraphicsContext::CreateFromNative(cr));
355}
356
357#else
358
18591d70 359#include "wx/gtk/dc.h"
d296fd8f 360
d296fd8f 361//-----------------------------------------------------------------------------
888dde65 362// wxGTKDCImpl
d296fd8f
RR
363//-----------------------------------------------------------------------------
364
888dde65 365IMPLEMENT_ABSTRACT_CLASS(wxGTKDCImpl, wxDCImpl)
c801d85f 366
03647350 367wxGTKDCImpl::wxGTKDCImpl( wxDC *owner )
888dde65 368 : wxDCImpl( owner )
c801d85f 369{
4bc67cc5 370 m_ok = FALSE;
a23fd0e1 371
4bc67cc5
RR
372 m_pen = *wxBLACK_PEN;
373 m_font = *wxNORMAL_FONT;
41bf0eb3 374 m_brush = *wxWHITE_BRUSH;
ff7b1510 375}
c801d85f 376
888dde65 377wxGTKDCImpl::~wxGTKDCImpl()
ab171e95
RR
378{
379}
380
888dde65 381void wxGTKDCImpl::DoSetClippingRegion( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 382{
4bc67cc5
RR
383 m_clipping = TRUE;
384 m_clipX1 = x;
385 m_clipY1 = y;
386 m_clipX2 = x + width;
387 m_clipY2 = y + height;
ff7b1510 388}
c801d85f 389
a23fd0e1
VZ
390// ---------------------------------------------------------------------------
391// get DC capabilities
392// ---------------------------------------------------------------------------
c801d85f 393
888dde65 394void wxGTKDCImpl::DoGetSizeMM( int* width, int* height ) const
c801d85f 395{
4bc67cc5
RR
396 int w = 0;
397 int h = 0;
ab171e95 398 GetOwner()->GetSize( &w, &h );
ce83033f
VZ
399 if (width) *width = int( double(w) / (m_userScaleX*m_mm_to_pix_x) );
400 if (height) *height = int( double(h) / (m_userScaleY*m_mm_to_pix_y) );
7bcb11d3
JS
401}
402
403// Resolution in pixels per logical inch
888dde65 404wxSize wxGTKDCImpl::GetPPI() const
7bcb11d3
JS
405{
406 // TODO (should probably be pure virtual)
407 return wxSize(0, 0);
ff7b1510 408}
9dc44eff 409#endif