#ifndef _plugin_cairo_CairoCtrl_h_ #define _plugin_cairo_CairoCtrl_h_ #include #include "Cairo.h" #include "CairoDraw.h" NAMESPACE_UPP #ifdef PLATFORM_WIN32 #include "lib/cairo-win32.h" class CairoCtrl : public DHCtrl { private: Drawing const *_drawing; Color const *_backgroundColor; HDC _hDC; Cairo _cairo; bool _doubleBuffering; void DoPaint() { if (!_cairo.HasContext()) return; CairoDraw draw(_cairo); if (_drawing == NULL) { if (_backgroundColor != NULL) _cairo.Clear(*_backgroundColor); CairoPaint(_cairo); UppPaint(draw); } else { _cairo.Clear(_backgroundColor == NULL ? White() : *_backgroundColor); Size drawingSize = _drawing->GetSize(); Size size = GetSize(); Size drawSize = size; int dx = 0, dy = 0; if(drawingSize.cy * size.cx < size.cy * drawingSize.cx) { drawSize.cy = drawingSize.cy * size.cx / drawingSize.cx; dy = (size.cy - drawSize.cy) / 2; } else { drawSize.cx = drawingSize.cx * size.cy / drawingSize.cy; dx = (size.cx - drawSize.cx) / 2; } draw.Clipoff(dx, dy, drawSize.cx, drawSize.cy); draw.DrawDrawing(drawSize, *_drawing); draw.End(); } if (_doubleBuffering) BitBlt(_hDC, Point(0, 0), cairo_win32_surface_get_dc(_cairo.GetSurface()), GetSize()); } protected: // Called on paint events virtual void CairoPaint(Cairo &cairo) { WhenCairoPaint(cairo); } virtual void UppPaint(Draw &draw) { WhenPaint(draw); } public: Callback1 WhenCairoPaint; Callback1 WhenPaint; CairoCtrl() : _drawing(NULL), _hDC(NULL), _doubleBuffering(true), _backgroundColor(NULL) {} ~CairoCtrl() { if (_hDC != NULL) ReleaseDC(GetHWND(), _hDC); if (_backgroundColor != NULL) delete _backgroundColor; } void Set(Drawing const * const drawing) { _drawing = drawing; Refresh(); } void Background(Color const &color) { if (_backgroundColor != NULL) delete _backgroundColor; _backgroundColor = new Color(color); } void SetDoubleBuffering(bool buffer = true) { _doubleBuffering = buffer; State(LAYOUTPOS); } virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_PAINT) { PAINTSTRUCT ps; BeginPaint(GetHWND(), &ps); DoPaint(); EndPaint(GetHWND(), &ps); return 0; } else if(message == WM_ERASEBKGND) return 1; return DHCtrl::WindowProc(message, wParam, lParam); } virtual void State(int reason) { DHCtrl::State(reason); if (reason == OPEN || reason == LAYOUTPOS) { HWND hwnd = GetHWND(); if (hwnd != NULL) _hDC = ::GetDC(hwnd); if (_hDC != NULL) { if (_doubleBuffering) _cairo.SetSurface(cairo_win32_surface_create_with_ddb(_hDC, CAIRO_FORMAT_RGB24, GetSize().cx, GetSize().cy), GetSize().cx, GetSize().cy); else _cairo.SetSurface(cairo_win32_surface_create(_hDC), GetSize().cx, GetSize().cy); } } else if (reason == CLOSE && _hDC != NULL) { ReleaseDC(GetHWND(), _hDC); _hDC = NULL; } } }; #else class CairoCtrl : public Ctrl { private: Drawing const *_drawing; Color const *_backgroundColor; Cairo _cairo; ImageBuffer _buffer; void DoPaint() { if (!_cairo.HasContext()) return; CairoDraw draw(_cairo); if (_drawing == NULL) { if (_backgroundColor != NULL) _cairo.Clear(*_backgroundColor); CairoPaint(_cairo); UppPaint(draw); } else { _cairo.Clear(_backgroundColor == NULL ? White() : *_backgroundColor); Size drawingSize = _drawing->GetSize(); Size size = GetSize(); Size drawSize = size; int dx = 0, dy = 0; if(drawingSize.cy * size.cx < size.cy * drawingSize.cx) { drawSize.cy = drawingSize.cy * size.cx / drawingSize.cx; dy = (size.cy - drawSize.cy) / 2; } else { drawSize.cx = drawingSize.cx * size.cy / drawingSize.cy; dx = (size.cx - drawSize.cx) / 2; } draw.Clipoff(dx, dy, drawSize.cx, drawSize.cy); draw.DrawDrawing(drawSize, *_drawing); draw.End(); } } virtual void Paint(Draw& draw) { if (GetSize() != _buffer.GetSize()) { _buffer.Create(GetSize()); _cairo.SetSurface(_buffer); } if (_buffer.IsEmpty()) return; DoPaint(); Image i = _buffer; draw.DrawImage(0, 0, i); _buffer = i; } protected: // Called on paint events virtual void CairoPaint(Cairo &cairo) { WhenCairoPaint(cairo); } virtual void UppPaint(Draw &draw) { WhenPaint(draw); } public: Callback1 WhenCairoPaint; Callback1 WhenPaint; CairoCtrl() : _drawing(NULL), _backgroundColor(NULL) {} ~CairoCtrl() { if (_backgroundColor != NULL) delete _backgroundColor; } void Set(Drawing const * const drawing) { _drawing = drawing; Refresh(); } void Background(Color const &color) { if (_backgroundColor != NULL) delete _backgroundColor; _backgroundColor = new Color(color); } void SetDoubleBuffering(bool buffer = true) {} }; #endif END_UPP_NAMESPACE #endif