1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/dc.cpp
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2006 REA Elektronik GmbH
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
28 #include "wx/dcmemory.h"
32 #include "wx/dfb/private.h"
34 // these values are used to initialize newly created DC
35 #define DEFAULT_FONT (*wxNORMAL_FONT)
36 #define DEFAULT_PEN (*wxBLACK_PEN)
37 #define DEFAULT_BRUSH (*wxWHITE_BRUSH)
39 // ===========================================================================
41 // ===========================================================================
43 //-----------------------------------------------------------------------------
45 //-----------------------------------------------------------------------------
47 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxDCBase
)
49 // Default constructor
55 wxDC::wxDC(const wxIDirectFBSurfacePtr
& surface
)
60 void wxDC::DFBInit(const wxIDirectFBSurfacePtr
& surface
)
62 m_ok
= (surface
!= NULL
);
63 wxCHECK_RET( surface
!= NULL
, _T("invalid surface") );
67 m_mm_to_pix_x
= (double)wxGetDisplaySize().GetWidth() /
68 (double)wxGetDisplaySizeMM().GetWidth();
69 m_mm_to_pix_y
= (double)wxGetDisplaySize().GetHeight() /
70 (double)wxGetDisplaySizeMM().GetHeight();
72 SetFont(DEFAULT_FONT
);
74 SetBrush(DEFAULT_BRUSH
);
78 // ---------------------------------------------------------------------------
80 // ---------------------------------------------------------------------------
82 void wxDC::DoSetClippingRegion(wxCoord cx
, wxCoord cy
, wxCoord cw
, wxCoord ch
)
84 wxCHECK_RET( Ok(), wxT("invalid dc") );
86 wxSize
size(GetSize());
88 wxASSERT_MSG( !m_clipping
,
89 _T("narrowing clipping region not implemented yet") );
91 // NB: We intersect the clipping rectangle with surface's area here because
92 // DirectFB will return an error if you try to set clipping rectangle
93 // that is partially outside of the surface.
95 r
.x1
= wxMax(0, XLOG2DEV(cx
));
96 r
.y1
= wxMax(0, YLOG2DEV(cy
));
97 r
.x2
= wxMin(r
.x1
+ XLOG2DEVREL(cw
), size
.x
) - 1;
98 r
.y2
= wxMin(r
.y1
+ YLOG2DEVREL(ch
), size
.y
) - 1;
100 if ( !m_surface
->SetClip(&r
) )
105 m_clipX2
= cx
+ cw
- 1;
106 m_clipY2
= cy
+ ch
-1;
110 void wxDC::DoSetClippingRegionAsRegion(const wxRegion
& region
)
112 // NB: this can be done because wxDFB only supports rectangular regions
113 SetClippingRegion(region
.AsRect());
116 void wxDC::DestroyClippingRegion()
118 wxCHECK_RET( Ok(), wxT("invalid dc") );
120 m_surface
->SetClip(NULL
);
125 // ---------------------------------------------------------------------------
126 // query capabilities
127 // ---------------------------------------------------------------------------
129 int wxDC::GetDepth() const
131 return m_surface
->GetDepth();
134 // ---------------------------------------------------------------------------
136 // ---------------------------------------------------------------------------
140 wxCHECK_RET( Ok(), wxT("invalid dc") );
142 if ( m_backgroundBrush
.GetStyle() == wxTRANSPARENT
)
145 wxColour clr
= m_backgroundBrush
.GetColour();
146 m_surface
->Clear(clr
.Red(), clr
.Green(), clr
.Blue(), clr
.Alpha());
148 wxSize
size(GetSize());
149 CalcBoundingBox(XDEV2LOG(0), YDEV2LOG(0));
150 CalcBoundingBox(XDEV2LOG(size
.x
), YDEV2LOG(size
.y
));
153 extern bool wxDoFloodFill(wxDC
*dc
, wxCoord x
, wxCoord y
,
154 const wxColour
& col
, int style
);
156 bool wxDC::DoFloodFill(wxCoord x
, wxCoord y
,
157 const wxColour
& col
, int style
)
159 return wxDoFloodFill(this, x
, y
, col
, style
);
162 bool wxDC::DoGetPixel(wxCoord x
, wxCoord y
, wxColour
*col
) const
164 wxCHECK_MSG( col
, false, _T("NULL colour parameter in wxDC::GetPixel"));
166 wxFAIL_MSG( _T("GetPixel not implemented") );
170 void wxDC::DoCrossHair(wxCoord x
, wxCoord y
)
172 wxCHECK_RET( Ok(), wxT("invalid dc") );
174 wxFAIL_MSG( _T("CrossHair not implemented") );
177 void wxDC::DoDrawLine(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
179 wxCHECK_RET( Ok(), wxT("invalid dc") );
181 if ( m_pen
.GetStyle() == wxTRANSPARENT
)
184 wxCoord xx1
= XLOG2DEV(x1
);
185 wxCoord yy1
= YLOG2DEV(y1
);
186 wxCoord xx2
= XLOG2DEV(x2
);
187 wxCoord yy2
= YLOG2DEV(y2
);
189 // FIXME: DrawLine() shouldn't draw the last pixel, but DFB's DrawLine()
190 // does draw it. We should undo any change to the last pixel by
191 // using GetPixel() and PutPixel(), but until they are implemented,
192 // handle at least the special case of vertical and horizontal
198 else if ( yy1
> yy2
)
205 else if ( xx1
> xx2
)
209 m_surface
->DrawLine(xx1
, yy1
, xx2
, yy2
);
211 CalcBoundingBox(x1
, y1
);
212 CalcBoundingBox(x2
, y2
);
215 // Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
216 // and ending at (x2, y2)
217 void wxDC::DoDrawArc(wxCoord x1
, wxCoord y1
,
218 wxCoord x2
, wxCoord y2
,
219 wxCoord xc
, wxCoord yc
)
221 wxCHECK_RET( Ok(), wxT("invalid dc") );
223 wxFAIL_MSG( _T("DrawArc not implemented") );
226 void wxDC::DoDrawPoint(wxCoord x
, wxCoord y
)
228 wxCHECK_RET( Ok(), wxT("invalid dc") );
230 // NB: DirectFB API doesn't provide a function for drawing points, so
231 // implement it as 1px long line. This is inefficient, but then, so is
232 // using DrawPoint() for drawing more than a few points.
233 DoDrawLine(x
, y
, x
, y
);
235 // FIXME_DFB: implement special cases for common formats (RGB24,RGBA/RGB32)
238 void wxDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int WXUNUSED(fillStyle
))
240 wxCHECK_RET( Ok(), wxT("invalid dc") );
242 wxFAIL_MSG( _T("DrawPolygon not implemented") );
245 void wxDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
247 wxCHECK_RET( Ok(), wxT("invalid dc") );
249 // TODO: impl. using DirectDB's DrawLines
250 wxFAIL_MSG( _T("DrawLines not implemented") );
253 void wxDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
255 wxCHECK_RET( Ok(), wxT("invalid dc") );
257 wxCoord xx
= XLOG2DEV(x
);
258 wxCoord yy
= YLOG2DEV(y
);
259 wxCoord ww
= m_signX
* XLOG2DEVREL(width
);
260 wxCoord hh
= m_signY
* YLOG2DEVREL(height
);
262 if ( ww
== 0 || hh
== 0 ) return;
275 if ( m_brush
.GetStyle() != wxTRANSPARENT
)
277 SelectColour(m_brush
.GetColour());
278 m_surface
->FillRectangle(xx
, yy
, ww
, hh
);
279 // restore pen's colour, because other drawing functions expect the
280 // colour to be set to the pen:
281 SelectColour(m_pen
.GetColour());
284 if ( m_pen
.GetStyle() != wxTRANSPARENT
)
286 m_surface
->DrawRectangle(xx
, yy
, ww
, hh
);
289 CalcBoundingBox(x
, y
);
290 CalcBoundingBox(x
+ width
, y
+ height
);
293 void wxDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
295 wxCHECK_RET( Ok(), wxT("invalid dc") );
297 wxFAIL_MSG( _T("DrawRoundedRectangle not implemented") );
300 void wxDC::DoDrawEllipse(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
302 wxCHECK_RET( Ok(), wxT("invalid dc") );
304 wxFAIL_MSG( _T("DrawElipse not implemented") );
307 void wxDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
309 wxCHECK_RET( Ok(), wxT("invalid dc") );
311 wxFAIL_MSG( _T("DrawElipticArc not implemented") );
314 void wxDC::DoDrawText(const wxString
& text
, wxCoord x
, wxCoord y
)
316 wxCHECK_RET( Ok(), wxT("invalid dc") );
318 wxCoord xx
= XLOG2DEV(x
);
319 wxCoord yy
= YLOG2DEV(y
);
321 // update the bounding box
323 CalcBoundingBox(x
, y
);
324 GetTextExtent(text
, &w
, &h
);
325 CalcBoundingBox(x
+ w
, y
+ h
);
327 // if background mode is solid, DrawText must paint text's background:
328 if ( m_backgroundMode
== wxSOLID
)
330 wxCHECK_RET( m_textBackgroundColour
.Ok(),
331 wxT("invalid background color") );
333 SelectColour(m_textBackgroundColour
);
334 m_surface
->FillRectangle(xx
, yy
, XLOG2DEVREL(w
), YLOG2DEVREL(h
));
337 // finally draw the text itself:
338 wxCHECK_RET( m_textForegroundColour
.Ok(),
339 wxT("invalid foreground color") );
340 SelectColour(m_textForegroundColour
);
341 m_surface
->DrawString(text
.utf8_str(), -1, xx
, yy
, DSTF_LEFT
| DSTF_TOP
);
343 // restore pen's colour, because other drawing functions expect the colour
344 // to be set to the pen:
345 SelectColour(m_pen
.GetColour());
348 void wxDC::DoDrawRotatedText(const wxString
& text
,
349 wxCoord x
, wxCoord y
,
352 wxCHECK_RET( Ok(), wxT("invalid dc") );
354 wxFAIL_MSG( _T("DrawRotatedText not implemented") );
357 // ---------------------------------------------------------------------------
359 // ---------------------------------------------------------------------------
361 void wxDC::SetPen(const wxPen
& pen
)
363 m_pen
= pen
.Ok() ? pen
: DEFAULT_PEN
;
365 SelectColour(m_pen
.GetColour());
368 void wxDC::SetBrush(const wxBrush
& brush
)
370 m_brush
= brush
.Ok() ? brush
: DEFAULT_BRUSH
;
373 void wxDC::SelectColour(const wxColour
& clr
)
375 m_surface
->SetColor(clr
.Red(), clr
.Green(), clr
.Blue(), clr
.Alpha());
376 #warning "use SetColorIndex?"
380 void wxDC::SetPalette(const wxPalette
& WXUNUSED(palette
))
382 wxCHECK_RET( Ok(), wxT("invalid dc") );
384 wxFAIL_MSG( _T("SetPalette not implemented") );
386 #endif // wxUSE_PALETTE
388 void wxDC::SetFont(const wxFont
& font
)
390 wxCHECK_RET( Ok(), wxT("invalid dc") );
392 wxFont
f(font
.Ok() ? font
: DEFAULT_FONT
);
394 wxFont
oldfont(m_font
);
398 if ( !m_surface
->SetFont(GetCurrentFont()) )
405 wxIDirectFBFontPtr
wxDC::GetCurrentFont() const
407 bool aa
= (GetDepth() > 8);
408 return m_font
.GetDirectFBFont(aa
);
411 void wxDC::SetBackground(const wxBrush
& brush
)
413 wxCHECK_RET( Ok(), wxT("invalid dc") );
415 if (!brush
.Ok()) return;
417 m_backgroundBrush
= brush
;
420 void wxDC::SetBackgroundMode(int mode
)
422 m_backgroundMode
= mode
;
425 void wxDC::SetLogicalFunction(int function
)
427 wxCHECK_RET( Ok(), wxT("invalid dc") );
429 // NB: we could also support XOR, but for blitting only (via DSBLIT_XOR);
430 // and possibly others via SetSrc/DstBlendFunction()
431 wxASSERT_MSG( function
== wxCOPY
,
432 _T("only wxCOPY logical function supported") );
434 m_logicalFunction
= function
;
437 bool wxDC::StartDoc(const wxString
& WXUNUSED(message
))
439 // We might be previewing, so return true to let it continue.
447 void wxDC::StartPage()
455 // ---------------------------------------------------------------------------
457 // ---------------------------------------------------------------------------
459 wxCoord
wxDC::GetCharHeight() const
461 wxCHECK_MSG( Ok(), -1, wxT("invalid dc") );
462 wxCHECK_MSG( m_font
.Ok(), -1, wxT("no font selected") );
465 GetCurrentFont()->GetHeight(&h
);
466 return YDEV2LOGREL(h
);
469 wxCoord
wxDC::GetCharWidth() const
471 wxCHECK_MSG( Ok(), -1, wxT("invalid dc") );
472 wxCHECK_MSG( m_font
.Ok(), -1, wxT("no font selected") );
475 GetCurrentFont()->GetStringWidth("H", 1, &w
);
476 // VS: YDEV is corrent, it should *not* be XDEV, because font's are only
477 // scaled according to m_scaleY
478 return YDEV2LOGREL(w
);
481 void wxDC::DoGetTextExtent(const wxString
& string
, wxCoord
*x
, wxCoord
*y
,
482 wxCoord
*descent
, wxCoord
*externalLeading
,
483 const wxFont
*theFont
) const
485 wxCHECK_RET( Ok(), wxT("invalid dc") );
486 wxCHECK_RET( m_font
.Ok(), wxT("no font selected") );
487 wxCHECK_RET( !theFont
|| theFont
->Ok(), wxT("invalid font") );
490 if ( theFont
!= NULL
)
493 wxConstCast(this, wxDC
)->SetFont(*theFont
);
496 wxCoord xx
= 0, yy
= 0;
498 wxIDirectFBFontPtr f
= GetCurrentFont();
500 if ( f
->GetStringExtents(string
.utf8_str(), -1, &rect
, NULL
) )
502 // VS: YDEV is corrent, it should *not* be XDEV, because font's are
503 // only scaled according to m_scaleY
504 xx
= YDEV2LOGREL(rect
.w
);
505 yy
= YDEV2LOGREL(rect
.h
);
510 if ( f
->GetDescender(&d
) )
511 *descent
= YDEV2LOGREL(-d
);
519 if ( externalLeading
) *externalLeading
= 0;
521 if ( theFont
!= NULL
)
522 wxConstCast(this, wxDC
)->SetFont(oldFont
);
527 // ---------------------------------------------------------------------------
529 // ---------------------------------------------------------------------------
531 // FIXME_DFB: scaling affects pixel size of font, pens, brushes, which
532 // is not currently implemented here; probably makes sense to
533 // switch to Cairo instead of implementing everything for DFB
535 void wxDC::DoGetSize(int *w
, int *h
) const
537 wxCHECK_RET( Ok(), wxT("invalid dc") );
539 m_surface
->GetSize(w
, h
);
542 void wxDC::DoGetSizeMM(int *width
, int *height
) const
544 #warning "move this to common code?"
548 if ( width
) *width
= int(double(w
) / (m_userScaleX
*m_mm_to_pix_x
));
549 if ( height
) *height
= int(double(h
) / (m_userScaleY
*m_mm_to_pix_y
));
552 wxSize
wxDC::GetPPI() const
554 #warning "move this to common code?"
555 return wxSize(int(double(m_mm_to_pix_x
) * inches2mm
),
556 int(double(m_mm_to_pix_y
) * inches2mm
));
560 // ---------------------------------------------------------------------------
562 // ---------------------------------------------------------------------------
564 bool wxDC::DoBlit(wxCoord xdest
, wxCoord ydest
,
565 wxCoord width
, wxCoord height
,
566 wxDC
*source
, wxCoord xsrc
, wxCoord ysrc
,
567 int rop
, bool useMask
,
568 wxCoord xsrcMask
, wxCoord ysrcMask
)
570 wxCHECK_MSG( Ok(), false, _T("invalid dc") );
571 wxCHECK_MSG( source
, false, _T("invalid source dc") );
573 // NB: we could also support XOR here (via DSBLIT_XOR)
574 // and possibly others via SetSrc/DstBlendFunction()
575 wxCHECK_MSG( rop
== wxCOPY
, false, _T("only wxCOPY function supported") );
577 // transform the source DC coords to the device ones
578 xsrc
= source
->LogicalToDeviceX(xsrc
);
579 ysrc
= source
->LogicalToDeviceY(ysrc
);
581 // FIXME_DFB: use the mask origin when drawing transparently
582 wxASSERT_MSG( xsrcMask
== -1 && ysrcMask
== -1,
583 _T("non-default source mask offset not implemented") );
585 if (xsrcMask
== -1 && ysrcMask
== -1)
587 xsrcMask
= xsrc
; ysrcMask
= ysrc
;
591 xsrcMask
= source
->LogicalToDeviceX(xsrcMask
);
592 ysrcMask
= source
->LogicalToDeviceY(ysrcMask
);
596 wxMemoryDC
*sourceAsMemDC
= wxDynamicCast(source
, wxMemoryDC
);
599 DoDrawSubBitmap(sourceAsMemDC
->GetSelectedObject(),
608 return DoBlitFromSurface(source
->GetDirectFBSurface(),
617 void wxDC::DoDrawBitmap(const wxBitmap
&bmp
, wxCoord x
, wxCoord y
, bool useMask
)
619 wxCHECK_RET( Ok(), wxT("invalid dc") );
620 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
623 0, 0, bmp
.GetWidth(), bmp
.GetHeight(),
625 m_logicalFunction
, useMask
);
628 void wxDC::DoDrawIcon(const wxIcon
& icon
, wxCoord x
, wxCoord y
)
630 // VZ: egcs 1.0.3 refuses to compile this without cast, no idea why
631 DoDrawBitmap((const wxBitmap
&)icon
, x
, y
, true);
634 void wxDC::DoDrawSubBitmap(const wxBitmap
&bmp
,
635 wxCoord x
, wxCoord y
, wxCoord w
, wxCoord h
,
636 wxCoord destx
, wxCoord desty
, int rop
, bool useMask
)
638 wxCHECK_RET( Ok(), wxT("invalid dc") );
639 wxCHECK_RET( bmp
.Ok(), wxT("invalid bitmap") );
641 // NB: we could also support XOR here (via DSBLIT_XOR)
642 // and possibly others via SetSrc/DstBlendFunction()
643 wxCHECK_RET( rop
== wxCOPY
, _T("only wxCOPY function supported") );
645 if ( bmp
.GetDepth() == 1 )
647 // Mono bitmaps are handled in special way -- all 1s are drawn in
648 // foreground colours, all 0s in background colour.
649 wxFAIL_MSG( _T("drawing mono bitmaps not implemented") );
653 if ( useMask
&& bmp
.GetMask() )
655 // FIXME_DFB: see MGL sources for a way to do it, but it's not directly
656 // applicable because DirectFB doesn't implement ROPs; OTOH,
657 // it has blitting modes that can be useful; finally, see
658 // DFB's SetSrcBlendFunction() and SetSrcColorKey()
659 wxFAIL_MSG( _T("drawing bitmaps with masks not implemented") );
663 DoBlitFromSurface(bmp
.GetDirectFBSurface(),
669 bool wxDC::DoBlitFromSurface(const wxIDirectFBSurfacePtr
& src
,
670 wxCoord srcx
, wxCoord srcy
,
671 wxCoord w
, wxCoord h
,
672 wxCoord dstx
, wxCoord dsty
)
674 // don't do anything if the source rectangle is outside of source surface,
675 // DirectFB would assert in that case:
677 src
->GetSize(&srcsize
.x
, &srcsize
.y
);
678 if ( !wxRect(srcx
, srcy
, w
, h
).Intersects(wxRect(srcsize
)) )
680 wxLogDebug(_T("Blitting from area outside of the source surface, caller code needs fixing."));
684 CalcBoundingBox(dstx
, dsty
);
685 CalcBoundingBox(dstx
+ w
, dsty
+ h
);
687 DFBRectangle srcRect
= { srcx
, srcy
, w
, h
};
688 DFBRectangle dstRect
= { XLOG2DEV(dstx
), YLOG2DEV(dsty
),
689 XLOG2DEVREL(w
), YLOG2DEVREL(h
) };
691 wxIDirectFBSurfacePtr
dst(m_surface
);
693 // FIXME: this will have to be different in useMask case, see above
694 DFBSurfaceBlittingFlags blitFlag
= (src
->GetPixelFormat() == DSPF_ARGB
)
695 ? DSBLIT_BLEND_ALPHACHANNEL
697 if ( !dst
->SetBlittingFlags(blitFlag
) )
700 if ( srcRect
.w
!= dstRect
.w
|| srcRect
.h
!= dstRect
.h
)
702 // the bitmap is drawn stretched:
703 dst
->StretchBlit(src
, &srcRect
, &dstRect
);
707 // no stretching, size is preserved:
708 dst
->Blit(src
, &srcRect
, dstRect
.x
, dstRect
.y
);