1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/dfb/dc.cpp
3 // Purpose:     wxDFBDCImpl class
4 // Author:      Vaclav Slavik
5 // Created:     2006-08-07
6 // Copyright:   (c) 2006 REA Elektronik GmbH
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 // ===========================================================================
11 // declarations
12 // ===========================================================================
13 
14 // ---------------------------------------------------------------------------
15 // headers
16 // ---------------------------------------------------------------------------
17 
18 // For compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20 
21 
22 #ifndef WX_PRECOMP
23     #include "wx/dcmemory.h"
24     #include "wx/log.h"
25 #endif
26 
27 #include "wx/dfb/dc.h"
28 #include "wx/dfb/private.h"
29 
30 // these values are used to initialize newly created DC
31 #define DEFAULT_FONT      (*wxNORMAL_FONT)
32 #define DEFAULT_PEN       (*wxBLACK_PEN)
33 #define DEFAULT_BRUSH     (*wxWHITE_BRUSH)
34 
35 // ===========================================================================
36 // implementation
37 // ===========================================================================
38 
39 //-----------------------------------------------------------------------------
40 // wxDFBDCImpl
41 //-----------------------------------------------------------------------------
42 
43 wxIMPLEMENT_ABSTRACT_CLASS(wxDFBDCImpl, wxDCImpl);
44 
DFBInit(const wxIDirectFBSurfacePtr & surface)45 void wxDFBDCImpl::DFBInit(const wxIDirectFBSurfacePtr& surface)
46 {
47     m_surface = surface;
48 
49     wxCHECK_RET( surface != NULL, "invalid surface" );
50 
51     SetFont(DEFAULT_FONT);
52     SetPen(DEFAULT_PEN);
53     SetBrush(DEFAULT_BRUSH);
54 }
55 
56 
57 // ---------------------------------------------------------------------------
58 // clipping
59 // ---------------------------------------------------------------------------
60 
DoSetClippingRegion(wxCoord cx,wxCoord cy,wxCoord cw,wxCoord ch)61 void wxDFBDCImpl::DoSetClippingRegion(wxCoord cx, wxCoord cy, wxCoord cw, wxCoord ch)
62 {
63     wxCHECK_RET( IsOk(), wxT("invalid dc") );
64 
65     wxSize size(GetSize());
66 
67     wxASSERT_MSG( !m_clipping,
68                   "narrowing clipping region not implemented yet" );
69 
70     // NB: We intersect the clipping rectangle with surface's area here because
71     //     DirectFB will return an error if you try to set clipping rectangle
72     //     that is partially outside of the surface.
73     DFBRegion r;
74     r.x1 = wxMax(0, XLOG2DEV(cx));
75     r.y1 = wxMax(0, YLOG2DEV(cy));
76     r.x2 = wxMin(r.x1 + XLOG2DEVREL(cw), size.x) - 1;
77     r.y2 = wxMin(r.y1 + YLOG2DEVREL(ch), size.y) - 1;
78 
79     if ( !m_surface->SetClip(&r) )
80         return;
81 
82     m_clipX1 = cx;
83     m_clipY1 = cy;
84     m_clipX2 = cx + cw - 1;
85     m_clipY2 = cy + ch -1;
86     m_clipping = true;
87 }
88 
DoSetDeviceClippingRegion(const wxRegion & region)89 void wxDFBDCImpl::DoSetDeviceClippingRegion(const wxRegion& region)
90 {
91     // NB: this can be done because wxDFB only supports rectangular regions
92     wxRect rect = region.AsRect();
93 
94     // our parameter is in physical coordinates while DoSetClippingRegion()
95     // takes logical ones
96     rect.x = XDEV2LOG(rect.x);
97     rect.y = YDEV2LOG(rect.y);
98     rect.width = XDEV2LOG(rect.width);
99     rect.height = YDEV2LOG(rect.height);
100 
101     DoSetClippingRegion(rect.x, rect.y, rect.width, rect.height);
102 }
103 
DestroyClippingRegion()104 void wxDFBDCImpl::DestroyClippingRegion()
105 {
106     wxCHECK_RET( IsOk(), wxT("invalid dc") );
107 
108     m_surface->SetClip(NULL);
109 
110     wxDCImpl::DestroyClippingRegion();
111 }
112 
113 // ---------------------------------------------------------------------------
114 // query capabilities
115 // ---------------------------------------------------------------------------
116 
GetDepth() const117 int wxDFBDCImpl::GetDepth() const
118 {
119     return m_surface->GetDepth();
120 }
121 
122 // ---------------------------------------------------------------------------
123 // drawing
124 // ---------------------------------------------------------------------------
125 
Clear()126 void wxDFBDCImpl::Clear()
127 {
128     wxCHECK_RET( IsOk(), wxT("invalid dc") );
129 
130     if ( m_backgroundBrush.GetStyle() == wxBRUSHSTYLE_TRANSPARENT )
131         return;
132 
133     wxColour clr = m_backgroundBrush.GetColour();
134     m_surface->Clear(clr.Red(), clr.Green(), clr.Blue(), clr.Alpha());
135 
136     wxSize size(GetSize());
137     CalcBoundingBox(XDEV2LOG(0), YDEV2LOG(0));
138     CalcBoundingBox(XDEV2LOG(size.x), YDEV2LOG(size.y));
139 }
140 
141 extern bool wxDoFloodFill(wxDC *dc, wxCoord x, wxCoord y,
142                           const wxColour & col, wxFloodFillStyle style);
143 
DoFloodFill(wxCoord x,wxCoord y,const wxColour & col,wxFloodFillStyle style)144 bool wxDFBDCImpl::DoFloodFill(wxCoord x, wxCoord y,
145                        const wxColour& col, wxFloodFillStyle style)
146 {
147     return wxDoFloodFill(GetOwner(), x, y, col, style);
148 }
149 
DoGetPixel(wxCoord x,wxCoord y,wxColour * col) const150 bool wxDFBDCImpl::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
151 {
152     wxCHECK_MSG( col, false, "NULL colour parameter in wxDFBDCImpl::GetPixel");
153 
154     wxFAIL_MSG( "GetPixel not implemented" );
155 
156     wxUnusedVar(x);
157     wxUnusedVar(y);
158 
159     return false;
160 }
161 
DoCrossHair(wxCoord x,wxCoord y)162 void wxDFBDCImpl::DoCrossHair(wxCoord x, wxCoord y)
163 {
164     wxCHECK_RET( IsOk(), wxT("invalid dc") );
165 
166     wxFAIL_MSG( "CrossHair not implemented" );
167 
168     wxUnusedVar(x);
169     wxUnusedVar(y);
170 }
171 
DoDrawLine(wxCoord x1,wxCoord y1,wxCoord x2,wxCoord y2)172 void wxDFBDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
173 {
174     wxCHECK_RET( IsOk(), wxT("invalid dc") );
175 
176     if ( m_pen.GetStyle() == wxPENSTYLE_TRANSPARENT )
177         return;
178 
179     wxCoord xx1 = XLOG2DEV(x1);
180     wxCoord yy1 = YLOG2DEV(y1);
181     wxCoord xx2 = XLOG2DEV(x2);
182     wxCoord yy2 = YLOG2DEV(y2);
183 
184     // FIXME: DrawLine() shouldn't draw the last pixel, but DFB's DrawLine()
185     //        does draw it. We should undo any change to the last pixel by
186     //        using GetPixel() and PutPixel(), but until they are implemented,
187     //        handle at least the special case of vertical and horizontal
188     //        lines correctly:
189     if ( xx1 == xx2 )
190     {
191         if ( yy1 < yy2 )
192             yy2--;
193         else if ( yy1 > yy2 )
194             yy2++;
195     }
196     if ( yy1 == yy2 )
197     {
198         if ( xx1 < xx2 )
199             xx2--;
200         else if ( xx1 > xx2 )
201             xx2++;
202     }
203 
204     m_surface->DrawLine(xx1, yy1, xx2, yy2);
205 
206     CalcBoundingBox(x1, y1);
207     CalcBoundingBox(x2, y2);
208 }
209 
210 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
211 // and ending at (x2, y2)
DoDrawArc(wxCoord WXUNUSED (x1),wxCoord WXUNUSED (y1),wxCoord WXUNUSED (x2),wxCoord WXUNUSED (y2),wxCoord WXUNUSED (xc),wxCoord WXUNUSED (yc))212 void wxDFBDCImpl::DoDrawArc(wxCoord WXUNUSED(x1), wxCoord WXUNUSED(y1),
213                             wxCoord WXUNUSED(x2), wxCoord WXUNUSED(y2),
214                             wxCoord WXUNUSED(xc), wxCoord WXUNUSED(yc))
215 {
216     wxCHECK_RET( IsOk(), wxT("invalid dc") );
217 
218     wxFAIL_MSG( "DrawArc not implemented" );
219 }
220 
DoDrawPoint(wxCoord x,wxCoord y)221 void wxDFBDCImpl::DoDrawPoint(wxCoord x, wxCoord y)
222 {
223     wxCHECK_RET( IsOk(), wxT("invalid dc") );
224 
225     // NB: DirectFB API doesn't provide a function for drawing points, so
226     //     implement it as 1px long line. This is inefficient, but then, so is
227     //     using DrawPoint() for drawing more than a few points.
228     DoDrawLine(x, y, x, y);
229 
230     // FIXME_DFB: implement special cases for common formats (RGB24,RGBA/RGB32)
231 }
232 
DoDrawPolygon(int WXUNUSED (n),const wxPoint WXUNUSED (points)[],wxCoord WXUNUSED (xoffset),wxCoord WXUNUSED (yoffset),wxPolygonFillMode WXUNUSED (fillStyle))233 void wxDFBDCImpl::DoDrawPolygon(int WXUNUSED(n), const wxPoint WXUNUSED(points)[],
234                                 wxCoord WXUNUSED(xoffset), wxCoord WXUNUSED(yoffset),
235                                 wxPolygonFillMode WXUNUSED(fillStyle))
236 {
237     wxCHECK_RET( IsOk(), wxT("invalid dc") );
238 
239     wxFAIL_MSG( "DrawPolygon not implemented" );
240 }
241 
DoDrawLines(int WXUNUSED (n),const wxPoint WXUNUSED (points)[],wxCoord WXUNUSED (xoffset),wxCoord WXUNUSED (yoffset))242 void wxDFBDCImpl::DoDrawLines(int WXUNUSED(n), const wxPoint WXUNUSED(points)[],
243                               wxCoord WXUNUSED(xoffset), wxCoord WXUNUSED(yoffset))
244 {
245     wxCHECK_RET( IsOk(), wxT("invalid dc") );
246 
247     // TODO: impl. using DirectDB's DrawLines
248     wxFAIL_MSG( "DrawLines not implemented" );
249 }
250 
DoDrawRectangle(wxCoord x,wxCoord y,wxCoord width,wxCoord height)251 void wxDFBDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
252 {
253     wxCHECK_RET( IsOk(), wxT("invalid dc") );
254 
255     wxCoord xx = XLOG2DEV(x);
256     wxCoord yy = YLOG2DEV(y);
257     wxCoord ww = m_signX * XLOG2DEVREL(width);
258     wxCoord hh = m_signY * YLOG2DEVREL(height);
259 
260     if ( ww == 0 || hh == 0 ) return;
261 
262     if ( ww < 0 )
263     {
264         ww = -ww;
265         xx = xx - ww;
266     }
267     if ( hh < 0 )
268     {
269         hh = -hh;
270         yy = yy - hh;
271     }
272 
273     if ( m_brush.GetStyle() != wxBRUSHSTYLE_TRANSPARENT )
274     {
275         SelectColour(m_brush.GetColour());
276         m_surface->FillRectangle(xx, yy, ww, hh);
277         // restore pen's colour, because other drawing functions expect the
278         // colour to be set to the pen:
279         SelectColour(m_pen.GetColour());
280     }
281 
282     if ( m_pen.GetStyle() != wxPENSTYLE_TRANSPARENT )
283     {
284         m_surface->DrawRectangle(xx, yy, ww, hh);
285     }
286 
287     CalcBoundingBox(x, y);
288     CalcBoundingBox(x + width, y + height);
289 }
290 
DoDrawRoundedRectangle(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),wxCoord WXUNUSED (width),wxCoord WXUNUSED (height),double WXUNUSED (radius))291 void wxDFBDCImpl::DoDrawRoundedRectangle(wxCoord WXUNUSED(x),
292                                          wxCoord WXUNUSED(y),
293                                          wxCoord WXUNUSED(width),
294                                          wxCoord WXUNUSED(height),
295                                          double WXUNUSED(radius))
296 {
297     wxCHECK_RET( IsOk(), wxT("invalid dc") );
298 
299     wxFAIL_MSG( "DrawRoundedRectangle not implemented" );
300 }
301 
DoDrawEllipse(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),wxCoord WXUNUSED (width),wxCoord WXUNUSED (height))302 void wxDFBDCImpl::DoDrawEllipse(wxCoord WXUNUSED(x),
303                                 wxCoord WXUNUSED(y),
304                                 wxCoord WXUNUSED(width),
305                                 wxCoord WXUNUSED(height))
306 {
307     wxCHECK_RET( IsOk(), wxT("invalid dc") );
308 
309     wxFAIL_MSG( "DrawElipse not implemented" );
310 }
311 
DoDrawEllipticArc(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),wxCoord WXUNUSED (w),wxCoord WXUNUSED (h),double WXUNUSED (sa),double WXUNUSED (ea))312 void wxDFBDCImpl::DoDrawEllipticArc(wxCoord WXUNUSED(x),
313                                     wxCoord WXUNUSED(y),
314                                     wxCoord WXUNUSED(w),
315                                     wxCoord WXUNUSED(h),
316                                     double WXUNUSED(sa),
317                                     double WXUNUSED(ea))
318 {
319     wxCHECK_RET( IsOk(), wxT("invalid dc") );
320 
321     wxFAIL_MSG( "DrawElipticArc not implemented" );
322 }
323 
DoDrawText(const wxString & text,wxCoord x,wxCoord y)324 void wxDFBDCImpl::DoDrawText(const wxString& text, wxCoord x, wxCoord y)
325 {
326     wxCHECK_RET( IsOk(), wxT("invalid dc") );
327 
328     wxCoord xx = XLOG2DEV(x);
329     wxCoord yy = YLOG2DEV(y);
330 
331     // update the bounding box
332     wxCoord w, h;
333     CalcBoundingBox(x, y);
334     DoGetTextExtent(text, &w, &h);
335     CalcBoundingBox(x + w, y + h);
336 
337     // if background mode is solid, DrawText must paint text's background:
338     if ( m_backgroundMode == wxBRUSHSTYLE_SOLID )
339     {
340         wxCHECK_RET( m_textBackgroundColour.IsOk(),
341                      wxT("invalid background color") );
342 
343         SelectColour(m_textBackgroundColour);
344         m_surface->FillRectangle(xx, yy, XLOG2DEVREL(w), YLOG2DEVREL(h));
345     }
346 
347     // finally draw the text itself:
348     wxCHECK_RET( m_textForegroundColour.IsOk(),
349                  wxT("invalid foreground color") );
350     SelectColour(m_textForegroundColour);
351     m_surface->DrawString(text.utf8_str(), -1, xx, yy, DSTF_LEFT | DSTF_TOP);
352 
353     // restore pen's colour, because other drawing functions expect the colour
354     // to be set to the pen:
355     SelectColour(m_pen.GetColour());
356 }
357 
DoDrawRotatedText(const wxString & WXUNUSED (text),wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),double WXUNUSED (angle))358 void wxDFBDCImpl::DoDrawRotatedText(const wxString& WXUNUSED(text),
359                                     wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
360                                     double WXUNUSED(angle))
361 {
362     wxCHECK_RET( IsOk(), wxT("invalid dc") );
363 
364     wxFAIL_MSG( "DrawRotatedText not implemented" );
365 }
366 
367 // ---------------------------------------------------------------------------
368 // set GDI objects
369 // ---------------------------------------------------------------------------
370 
SetPen(const wxPen & pen)371 void wxDFBDCImpl::SetPen(const wxPen& pen)
372 {
373     m_pen = pen.IsOk() ? pen : DEFAULT_PEN;
374 
375     SelectColour(m_pen.GetColour());
376 }
377 
SetBrush(const wxBrush & brush)378 void wxDFBDCImpl::SetBrush(const wxBrush& brush)
379 {
380     m_brush = brush.IsOk() ? brush : DEFAULT_BRUSH;
381 }
382 
SelectColour(const wxColour & clr)383 void wxDFBDCImpl::SelectColour(const wxColour& clr)
384 {
385     m_surface->SetColor(clr.Red(), clr.Green(), clr.Blue(), clr.Alpha());
386     #warning "use SetColorIndex?"
387 }
388 
389 #if wxUSE_PALETTE
SetPalette(const wxPalette & WXUNUSED (palette))390 void wxDFBDCImpl::SetPalette(const wxPalette& WXUNUSED(palette))
391 {
392     wxCHECK_RET( IsOk(), wxT("invalid dc") );
393 
394     wxFAIL_MSG( "SetPalette not implemented" );
395 }
396 #endif // wxUSE_PALETTE
397 
SetFont(const wxFont & font)398 void wxDFBDCImpl::SetFont(const wxFont& font)
399 {
400     wxCHECK_RET( IsOk(), wxT("invalid dc") );
401 
402     wxFont f(font.IsOk() ? font : DEFAULT_FONT);
403 
404     wxFont oldfont(m_font);
405 
406     m_font = f;
407 
408     if ( !m_surface->SetFont(GetCurrentFont()) )
409     {
410         m_font = oldfont;
411         return;
412     }
413 }
414 
GetCurrentFont() const415 wxIDirectFBFontPtr wxDFBDCImpl::GetCurrentFont() const
416 {
417     bool aa = (GetDepth() > 8);
418     return m_font.GetDirectFBFont(aa);
419 }
420 
SetBackground(const wxBrush & brush)421 void wxDFBDCImpl::SetBackground(const wxBrush& brush)
422 {
423     wxCHECK_RET( IsOk(), wxT("invalid dc") );
424 
425     if (!brush.IsOk()) return;
426 
427     m_backgroundBrush = brush;
428 }
429 
SetBackgroundMode(int mode)430 void wxDFBDCImpl::SetBackgroundMode(int mode)
431 {
432     m_backgroundMode = mode;
433 }
434 
SetLogicalFunction(wxRasterOperationMode function)435 void wxDFBDCImpl::SetLogicalFunction(wxRasterOperationMode function)
436 {
437     wxCHECK_RET( IsOk(), wxT("invalid dc") );
438 
439     // NB: we could also support XOR, but for blitting only (via DSBLIT_XOR);
440     //     and possibly others via SetSrc/DstBlendFunction()
441     wxASSERT_MSG( function == wxCOPY,
442                   "only wxCOPY logical function supported" );
443 
444     m_logicalFunction = function;
445 }
446 
StartDoc(const wxString & WXUNUSED (message))447 bool wxDFBDCImpl::StartDoc(const wxString& WXUNUSED(message))
448 {
449     // We might be previewing, so return true to let it continue.
450     return true;
451 }
452 
EndDoc()453 void wxDFBDCImpl::EndDoc()
454 {
455 }
456 
StartPage()457 void wxDFBDCImpl::StartPage()
458 {
459 }
460 
EndPage()461 void wxDFBDCImpl::EndPage()
462 {
463 }
464 
465 // ---------------------------------------------------------------------------
466 // text metrics
467 // ---------------------------------------------------------------------------
468 
GetCharHeight() const469 wxCoord wxDFBDCImpl::GetCharHeight() const
470 {
471     wxCHECK_MSG( IsOk(), -1, wxT("invalid dc") );
472     wxCHECK_MSG( m_font.IsOk(), -1, wxT("no font selected") );
473 
474     int h = -1;
475     GetCurrentFont()->GetHeight(&h);
476     return YDEV2LOGREL(h);
477 }
478 
GetCharWidth() const479 wxCoord wxDFBDCImpl::GetCharWidth() const
480 {
481     wxCHECK_MSG( IsOk(), -1, wxT("invalid dc") );
482     wxCHECK_MSG( m_font.IsOk(), -1, wxT("no font selected") );
483 
484     int w = -1;
485     GetCurrentFont()->GetStringWidth("H", 1, &w);
486     // VS: YDEV is corrent, it should *not* be XDEV, because font's are only
487     //     scaled according to m_scaleY
488     return YDEV2LOGREL(w);
489 }
490 
DoGetTextExtent(const wxString & string,wxCoord * x,wxCoord * y,wxCoord * descent,wxCoord * externalLeading,const wxFont * theFont) const491 void wxDFBDCImpl::DoGetTextExtent(const wxString& string, wxCoord *x, wxCoord *y,
492                            wxCoord *descent, wxCoord *externalLeading,
493                            const wxFont *theFont) const
494 {
495     wxCHECK_RET( IsOk(), wxT("invalid dc") );
496     wxCHECK_RET( m_font.IsOk(), wxT("no font selected") );
497     wxCHECK_RET( !theFont || theFont->IsOk(), wxT("invalid font") );
498 
499     wxFont oldFont;
500     if ( theFont != NULL )
501     {
502         oldFont = m_font;
503         wxConstCast(this, wxDFBDCImpl)->SetFont(*theFont);
504     }
505 
506     wxCoord xx = 0, yy = 0;
507     DFBRectangle rect;
508     wxIDirectFBFontPtr f = GetCurrentFont();
509 
510     if ( f->GetStringExtents(string.utf8_str(), -1, &rect, NULL) )
511     {
512         // VS: YDEV is corrent, it should *not* be XDEV, because font's are
513         //     only scaled according to m_scaleY
514         xx = YDEV2LOGREL(rect.w);
515         yy = YDEV2LOGREL(rect.h);
516 
517         if ( descent )
518         {
519             int d;
520             if ( f->GetDescender(&d) )
521                 *descent = YDEV2LOGREL(-d);
522             else
523                 *descent = 0;
524         }
525     }
526 
527     if ( x ) *x = xx;
528     if ( y ) *y = yy;
529     if ( externalLeading ) *externalLeading = 0;
530 
531     if ( theFont != NULL )
532         wxConstCast(this, wxDFBDCImpl)->SetFont(oldFont);
533 }
534 
535 
536 
537 // ---------------------------------------------------------------------------
538 // mapping modes
539 // ---------------------------------------------------------------------------
540 
541 // FIXME_DFB: scaling affects pixel size of font, pens, brushes, which
542 //            is not currently implemented here; probably makes sense to
543 //            switch to Cairo instead of implementing everything for DFB
544 
DoGetSize(int * w,int * h) const545 void wxDFBDCImpl::DoGetSize(int *w, int *h) const
546 {
547     wxCHECK_RET( IsOk(), wxT("invalid dc") );
548 
549     m_surface->GetSize(w, h);
550 }
551 
DoGetSizeMM(int * width,int * height) const552 void wxDFBDCImpl::DoGetSizeMM(int *width, int *height) const
553 {
554     #warning "move this to common code?"
555     int w = 0;
556     int h = 0;
557     GetSize(&w, &h);
558     if ( width ) *width = int(double(w) / (m_userScaleX*GetMMToPXx()));
559     if ( height ) *height = int(double(h) / (m_userScaleY*GetMMToPXy()));
560 }
561 
GetPPI() const562 wxSize wxDFBDCImpl::GetPPI() const
563 {
564     #warning "move this to common code?"
565     return wxSize(int(double(GetMMToPXx()) * inches2mm),
566                   int(double(GetMMToPXy()) * inches2mm));
567 }
568 
569 
570 // ---------------------------------------------------------------------------
571 // Blitting
572 // ---------------------------------------------------------------------------
573 
DoBlit(wxCoord xdest,wxCoord ydest,wxCoord width,wxCoord height,wxDC * source,wxCoord xsrc,wxCoord ysrc,wxRasterOperationMode rop,bool useMask,wxCoord xsrcMask,wxCoord ysrcMask)574 bool wxDFBDCImpl::DoBlit(wxCoord xdest, wxCoord ydest,
575                          wxCoord width, wxCoord height,
576                          wxDC *source, wxCoord xsrc, wxCoord ysrc,
577                          wxRasterOperationMode rop, bool useMask,
578                          wxCoord xsrcMask, wxCoord ysrcMask)
579 {
580     wxCHECK_MSG( IsOk(), false, "invalid dc" );
581     wxCHECK_MSG( source, false, "invalid source dc" );
582 
583     // NB: we could also support XOR here (via DSBLIT_XOR)
584     //     and possibly others via SetSrc/DstBlendFunction()
585     wxCHECK_MSG( rop == wxCOPY, false, "only wxCOPY function supported" );
586 
587     // transform the source DC coords to the device ones
588     xsrc = source->LogicalToDeviceX(xsrc);
589     ysrc = source->LogicalToDeviceY(ysrc);
590 
591     // FIXME_DFB: use the mask origin when drawing transparently
592     wxASSERT_MSG( xsrcMask == -1 && ysrcMask == -1,
593                   "non-default source mask offset not implemented" );
594 #if 0
595     if (xsrcMask == -1 && ysrcMask == -1)
596     {
597         xsrcMask = xsrc; ysrcMask = ysrc;
598     }
599     else
600     {
601         xsrcMask = source->LogicalToDeviceX(xsrcMask);
602         ysrcMask = source->LogicalToDeviceY(ysrcMask);
603     }
604 #endif
605 
606     wxMemoryDC *sourceAsMemDC = wxDynamicCast(source, wxMemoryDC);
607     if ( sourceAsMemDC )
608     {
609         DoDrawSubBitmap(sourceAsMemDC->GetSelectedBitmap(),
610                         xsrc, ysrc,
611                         width, height,
612                         xdest, ydest,
613                         rop,
614                         useMask);
615     }
616     else
617     {
618         return DoBlitFromSurface
619                (
620                  static_cast<wxDFBDCImpl *>(source->GetImpl())
621                     ->GetDirectFBSurface(),
622                  xsrc, ysrc,
623                  width, height,
624                  xdest, ydest
625                );
626     }
627 
628     return true;
629 }
630 
DoDrawBitmap(const wxBitmap & bmp,wxCoord x,wxCoord y,bool useMask)631 void wxDFBDCImpl::DoDrawBitmap(const wxBitmap &bmp, wxCoord x, wxCoord y, bool useMask)
632 {
633     wxCHECK_RET( IsOk(), wxT("invalid dc") );
634     wxCHECK_RET( bmp.IsOk(), wxT("invalid bitmap") );
635 
636     DoDrawSubBitmap(bmp,
637                     0, 0, bmp.GetWidth(), bmp.GetHeight(),
638                     x, y,
639                     m_logicalFunction, useMask);
640 }
641 
DoDrawIcon(const wxIcon & icon,wxCoord x,wxCoord y)642 void wxDFBDCImpl::DoDrawIcon(const wxIcon& icon, wxCoord x, wxCoord y)
643 {
644     // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
645     DoDrawBitmap((const wxBitmap&)icon, x, y, true);
646 }
647 
DoDrawSubBitmap(const wxBitmap & bmp,wxCoord x,wxCoord y,wxCoord w,wxCoord h,wxCoord destx,wxCoord desty,int rop,bool useMask)648 void wxDFBDCImpl::DoDrawSubBitmap(const wxBitmap &bmp,
649                            wxCoord x, wxCoord y, wxCoord w, wxCoord h,
650                            wxCoord destx, wxCoord desty, int rop, bool useMask)
651 {
652     wxCHECK_RET( IsOk(), wxT("invalid dc") );
653     wxCHECK_RET( bmp.IsOk(), wxT("invalid bitmap") );
654 
655     // NB: we could also support XOR here (via DSBLIT_XOR)
656     //     and possibly others via SetSrc/DstBlendFunction()
657     wxCHECK_RET( rop == wxCOPY, "only wxCOPY function supported" );
658 
659     if ( bmp.GetDepth() == 1 )
660     {
661         // Mono bitmaps are handled in special way -- all 1s are drawn in
662         // foreground colours, all 0s in background colour.
663         wxFAIL_MSG( "drawing mono bitmaps not implemented" );
664         return;
665     }
666 
667     if ( useMask && bmp.GetMask() )
668     {
669         // FIXME_DFB: Could use blitting modes for this; also see
670         //            DFB's SetSrcBlendFunction() and SetSrcColorKey()
671         wxFAIL_MSG( "drawing bitmaps with masks not implemented" );
672         return;
673     }
674 
675     DoBlitFromSurface(bmp.GetDirectFBSurface(),
676                       x, y,
677                       w, h,
678                       destx, desty);
679 }
680 
DoBlitFromSurface(const wxIDirectFBSurfacePtr & src,wxCoord srcx,wxCoord srcy,wxCoord w,wxCoord h,wxCoord dstx,wxCoord dsty)681 bool wxDFBDCImpl::DoBlitFromSurface(const wxIDirectFBSurfacePtr& src,
682                                     wxCoord srcx, wxCoord srcy,
683                                     wxCoord w, wxCoord h,
684                                     wxCoord dstx, wxCoord dsty)
685 {
686     // don't do anything if the source rectangle is outside of source surface,
687     // DirectFB would assert in that case:
688     wxSize srcsize;
689     src->GetSize(&srcsize.x, &srcsize.y);
690     if ( !wxRect(srcx, srcy, w, h).Intersects(wxRect(srcsize)) )
691     {
692         wxLogDebug("Blitting from area outside of the source surface, caller code needs fixing.");
693         return false;
694     }
695 
696     CalcBoundingBox(dstx, dsty);
697     CalcBoundingBox(dstx + w, dsty + h);
698 
699     DFBRectangle srcRect = { srcx, srcy, w, h };
700     DFBRectangle dstRect = { XLOG2DEV(dstx), YLOG2DEV(dsty),
701                              XLOG2DEVREL(w), YLOG2DEVREL(h) };
702 
703     wxIDirectFBSurfacePtr dst(m_surface);
704 
705     // FIXME: this will have to be different in useMask case, see above
706     DFBSurfaceBlittingFlags blitFlag = (src->GetPixelFormat() == DSPF_ARGB)
707                                        ? DSBLIT_BLEND_ALPHACHANNEL
708                                        : DSBLIT_NOFX;
709     if ( !dst->SetBlittingFlags(blitFlag) )
710         return false;
711 
712     if ( srcRect.w != dstRect.w || srcRect.h != dstRect.h )
713     {
714         // the bitmap is drawn stretched:
715         dst->StretchBlit(src, &srcRect, &dstRect);
716     }
717     else
718     {
719         // no stretching, size is preserved:
720         dst->Blit(src, &srcRect, dstRect.x, dstRect.y);
721     }
722 
723     return true;
724 }
725