summaryrefslogtreecommitdiff
path: root/plugins/Clist_ng/INCLUDE/gfx.h
diff options
context:
space:
mode:
authorTobias Weimer <wishmaster51@googlemail.com>2015-07-12 14:10:16 +0000
committerTobias Weimer <wishmaster51@googlemail.com>2015-07-12 14:10:16 +0000
commitf4ce2b5c214cce406dbd7a73dc7f35ae409546ad (patch)
tree533cc821ffc9c5664c075930be6a40fde9593aba /plugins/Clist_ng/INCLUDE/gfx.h
parent71a88c6d8c4578ca24e02a5c6f4860c206e7c6da (diff)
Clist NG:
Commit of CList NG by silvercircle from https://github.com/silvercircle/miranda-ng This is based on clist_nicer and Anti-Grain Geometry: http://www.antigrain.com/ This is the first version that actually compiles. Do NOT use it in production environment! git-svn-id: http://svn.miranda-ng.org/main/trunk@14543 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/Clist_ng/INCLUDE/gfx.h')
-rw-r--r--plugins/Clist_ng/INCLUDE/gfx.h501
1 files changed, 501 insertions, 0 deletions
diff --git a/plugins/Clist_ng/INCLUDE/gfx.h b/plugins/Clist_ng/INCLUDE/gfx.h
new file mode 100644
index 0000000000..10b4da7e19
--- /dev/null
+++ b/plugins/Clist_ng/INCLUDE/gfx.h
@@ -0,0 +1,501 @@
+/*
+* astyle --force-indent=tab=4 --brackets=linux --indent-switches
+* --pad=oper --one-line=keep-blocks --unpad=paren
+*
+* Miranda IM: the free IM client for Microsoft* Windows*
+*
+* Copyright 2000-2010 Miranda ICQ/IM project,
+* all portions of this codebase are copyrighted to the people
+* listed in contributors.txt.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* you should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* part of clist_ng plugin for Miranda.
+*
+* (C) 2005-2010 by silvercircle _at_ gmail _dot_ com and contributors
+*
+* $Id: gfx.h 137 2010-10-16 21:03:23Z silvercircle $
+*
+* low level painting functions - manage DCs, render skin image glyphs,
+* text and backbuffer drawing.
+*
+* provide wrappers for AGG render pipelines
+*
+*/
+
+#ifndef __GFX_H_
+#define __GFX_H_
+
+#define M_PI 3.14159265358979323846
+
+BYTE __forceinline percent_to_byte(UINT32 percent)
+{
+ return(BYTE) ((FLOAT) (((FLOAT) percent) / 100) * 255);
+}
+
+class AGGBaseContext
+{
+public:
+ /**
+ * CTOR - construct AGGBaseContext and attach it to a bitmap
+ * @param hdc device context (not really needed)
+ * @param hbm bitmap handle
+ * @return
+ */
+ AGGBaseContext(HDC hdc, HBITMAP hbm)
+ {
+ m_hdc= hdc;
+ attach(hbm);
+ }
+
+ /**
+ * construct AGGBaseContext and attach it to a in-memory bitmap used
+ * by a BufferedPaint operation
+ * @param hdc device context (not really required)
+ * @param rgbq RGBQUAD* memory buffer with bitmap bits in BGRA32 format
+ * @param width bitmap width (can be larger than the actual painting rectangle)
+ * @param height bitmap height
+ * @return
+ */
+ AGGBaseContext(HDC hdc, RGBQUAD* rgbq, LONG width, LONG height)
+ {
+ m_hdc = hdc;
+ attach(rgbq, width, height);
+ }
+
+ /**
+ * construct an empty AGGBase context and assign the optional HDC
+ * must be attached to a memory bitmap later by using one of the
+ * attach() methods.
+ * @param hdc device context
+ * @return
+ */
+ AGGBaseContext(HDC hdc) { m_hdc = hdc; }
+
+ /**
+ * attach the AGG rendering buffer to a memory bitmap, selected into a HDC for
+ * off-screen drawing.
+ * @param hbm bitmap to use for rendering.
+ */
+ void attach(HBITMAP hbm)
+ {
+ BITMAP bm;
+ ::GetObject(hbm, sizeof(bm), &bm);
+
+ m_rbuf.attach((unsigned char*)bm.bmBits, bm.bmWidth, bm.bmHeight, bm.bmWidthBytes);
+ }
+
+ /**
+ * attach the AGG rendering buffer to a RGBQUAD array (as returned by
+ * GetBufferedPaintBits() API
+ *
+ * @param rgbq pointer to memory buffer holding the bitmap bits
+ * @param width width (in pixels, always properly aligned)
+ * @param height height (in pixels)
+ */
+ void attach(RGBQUAD* rgbq, LONG width, LONG height)
+ {
+ m_rbuf.attach((unsigned char *)rgbq, width, height, width * 4);
+ }
+
+ HDC m_hdc;
+ agg::rendering_buffer m_rbuf;
+
+ ~AGGBaseContext() {}
+};
+
+class AGGContext
+{
+public:
+ AGGContext(HBITMAP hbm)
+ {
+ BITMAP bm;
+ ::GetObject(hbm, sizeof(bm), &bm);
+
+ m_rbuf.attach((unsigned char*)bm.bmBits, bm.bmWidth, bm.bmHeight, bm.bmWidthBytes);
+ initPipeline();
+ };
+
+ AGGContext(RGBQUAD* rgbq, LONG width, LONG height)
+ {
+ m_rbuf.attach((unsigned char *)rgbq, width, height, width * 4);
+ initPipeline();
+ }
+
+ AGGContext() {}
+
+ void initPipeline()
+ {
+ m_pixfmt.attach(m_rbuf);
+ m_rbase.attach(m_pixfmt);
+ m_solid_renderer.attach(m_rbase);
+ m_span_interpolator = agg::span_interpolator_linear<>(m_gradient_trans);
+ m_span_gradient = span_gradient_t(m_span_interpolator, m_gradient_func, m_color_array, 0, 200);
+ m_gradient_renderer.attach(m_rbase, m_span_allocator, m_span_gradient);
+ }
+
+ void attach(HBITMAP hbm)
+ {
+ BITMAP bm;
+ ::GetObject(hbm, sizeof(bm), &bm);
+
+ m_rbuf.attach((unsigned char*)bm.bmBits, bm.bmWidth, bm.bmHeight, bm.bmWidthBytes);
+ initPipeline();
+ }
+
+ void attach(RGBQUAD* rgbq, LONG width, LONG height, LONG stride)
+ {
+ m_rbuf.attach((unsigned char *)rgbq, width, height, stride);
+ initPipeline();
+ }
+
+ /*
+ * fill the color array we need for the gradient with
+ */
+ template<class Array> static void fill_color_array(Array& arr, agg::rgba8& begin, agg::rgba8& end)
+ {
+ unsigned size = arr.size();
+
+ for(unsigned i = 0; i < size; ++i)
+ arr[i] = begin.gradient(end, i / double(size));
+ }
+
+public:
+ agg::rendering_buffer m_rbuf;
+ agg::pixfmt_bgra32 m_pixfmt;
+ agg::renderer_base<agg::pixfmt_bgra32> m_rbase;
+
+ agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_bgra32> > m_solid_renderer;
+ typedef agg::span_gradient<agg::rgba8, agg::span_interpolator_linear<>, agg::gradient_x, agg::pod_auto_array<agg::rgba8, 256> > span_gradient_t;
+ typedef agg::span_allocator<agg::rgba8> span_allocator_t;
+
+ agg::renderer_scanline_aa<agg::renderer_base<agg::pixfmt_bgra32>, span_allocator_t, span_gradient_t> m_gradient_renderer;
+
+ span_allocator_t m_span_allocator;
+ span_gradient_t m_span_gradient;
+ agg::span_interpolator_linear<> m_span_interpolator;
+ agg::gradient_x m_gradient_func;
+ agg::pod_auto_array<agg::rgba8, 256> m_color_array;
+ agg::trans_affine m_gradient_trans;
+};
+
+class AGGPaintHelper
+{
+public:
+ AGGPaintHelper(HDC hdc)
+ {
+ hdcMem = hdc;
+ aggctx = new AGGBaseContext(hdcMem);
+ }
+
+ ~AGGPaintHelper()
+ {
+ delete aggctx;
+ };
+
+public:
+ agg::rounded_rect* current_shape;
+ AGGBaseContext* aggctx;
+ HDC hdcMem;
+};
+
+class CLCPaintHelper : public AGGPaintHelper
+{
+public:
+ CLCPaintHelper(const HWND hwndCLC, ClcData* clcdat, DWORD windowstyle, RECT* rc, int yFirst, int fontShift, int idx) : AGGPaintHelper(0)
+ {
+ hwnd = hwndCLC;
+ indent = 0;
+ dat = clcdat;
+ style = windowstyle;
+ clRect = rc;
+ y = yFirst;
+ index = idx;
+ bFirstNGdrawn = false;
+ groupCountsFontTopShift = fontShift;
+ isContactFloater = false;
+ }
+
+ void setHDC(const HDC hdc)
+ {
+ hdcMem = hdc;
+ }
+
+ virtual ~CLCPaintHelper() {};
+
+ void setFloater () { isContactFloater = true; }
+ void Paint (ClcGroup* group, ClcContact* contact, int rowHeight);
+ int drawAvatar (RECT *rc, ClcContact *contact, int y, WORD cstatus, int rowHeight);
+ HFONT changeToFont (const unsigned int id);
+ void setHotTrackColour ();
+
+ int indent;
+ int y;
+ int index;
+ int fSelected;
+ HANDLE hTheme, hbp;
+ bool fAvatar, fSecondLine;
+ TDspOverride* dsp;
+
+ HWND hwnd;
+ ClcData* dat;
+ DWORD style;
+ RECT* clRect;
+ bool bFirstNGdrawn;
+ int groupCountsFontTopShift;
+ bool isContactFloater;
+
+ TStatusItem *sevencontact_pos, *soddcontact_pos, *sfirstitem,
+ *ssingleitem, *slastitem, *sfirstitem_NG, *ssingleitem_NG, *slastitem_NG;
+
+private:
+ int m_fontHeight;
+};
+
+class Gfx
+{
+public:
+#ifdef _USE_D2D
+ static ID2D1Factory* pD2DFactory;
+#endif
+ static COLORREF txtColor;
+ //static ULONG_PTR gdiPlusToken;
+ //static Gdiplus::GdiplusStartupInput gdiPlusStartupInput;
+
+public:
+ static inline HANDLE initiateBufferedPaint (const HDC hdcSrc, RECT& rc, HDC& hdcOut);
+ static inline void finalizeBufferedPaint (HANDLE hbp, RECT *rc, BYTE alpha = 0);
+ static HBITMAP createRGBABitmap (const LONG cx, const LONG cy);
+ static inline void drawBGFromSurface (const HWND hwnd, const RECT& rc, HDC hdc);
+ static inline void renderSkinItem (HDC hdc, RECT* rc, TImageItem* item);
+ static inline void renderSkinItem (AGGPaintHelper *ph, TStatusItem *item, RECT* rc);
+
+ static void setBitmapAlpha (HBITMAP hBitmap, BYTE bAlpha);
+ static void deSaturate (HBITMAP hBitmap, bool fReduceContrast = false);
+ static void preMultiply (HBITMAP hBitmap, int mode);
+ static void __fastcall renderImageItem (HDC hdc, TImageItem *item, RECT *rc);
+ static void colorizeGlyph (TImageItem *item, const COLORREF clr, float H, float S, float V);
+
+ static inline void hsvTransformPixel (BYTE *p, float value, float vsu, float vsw, BYTE alpha);
+ static inline void rgbTransformPixel (BYTE *p, float r, float g, float b, BYTE alpha);
+
+ static void D2D_Init ();
+ static void D2D_Release ();
+
+ static inline void setTextColor (const COLORREF clr);
+ static inline COLORREF getTextColor ();
+ static int renderText (HDC hdc, HANDLE hTheme, const TCHAR *szText, RECT *rc, DWORD dtFlags, const int iGlowSize = 0, int length = -1, bool fForceAero = false);
+ static void shutDown() { if (m_p) free(m_p); }
+
+ /**
+ * load a png image using miranda image load service.
+ *
+ * @param szFilename full path and filename of the image
+ *
+ * @return HBITMAP of the image loaded
+ */
+ template<class T> static HBITMAP loadPNG(const T* szFilename)
+ {
+ HBITMAP hBitmap = 0;
+ DWORD dwFlags = 0;
+
+ if(sizeof(T) > 1)
+ dwFlags = IMGL_WCHAR;
+
+ hBitmap = (HBITMAP)CallService(MS_IMG_LOAD, (WPARAM)szFilename, dwFlags);
+ if(CALLSERVICE_NOTFOUND == (INT_PTR)hBitmap) {
+ hBitmap = 0;
+ throw(CRTException("Critical error while loading a skin", L"The image service plugin is not available"));
+ }
+ return(hBitmap);
+ }
+
+ /*
+ * a generic buffer used by various things in the class Will only be realloc'd and grow when
+ * needed. Free'd on shutdown. It's primarily used by bitmap operations as temporary buffer
+ */
+ static BYTE* m_p;
+ static size_t m_sAllocated;
+};
+
+/*
+ * some inlined functions
+ */
+
+/**
+ * Initiate a buffered paint operation
+ *
+ * @param hdcSrc The source device context (usually obtained by BeginPaint())
+ * @param rc RECT&: the target rectangle that receives the painting
+ * @param hdcOut HDC& (out) receives the buffered device context handle
+ *
+ * @return (HANDLE) buffered paint handle
+ */
+inline HANDLE Gfx::initiateBufferedPaint(const HDC hdcSrc, RECT& rc, HDC& hdcOut)
+{
+ HANDLE hbp = Api::pfnBeginBufferedPaint(hdcSrc, &rc, BPBF_TOPDOWNDIB, NULL, &hdcOut);
+ return(hbp);
+}
+
+/**
+ * finalize buffered paint cycle and apply (if applicable) the global alpha value
+ *
+ * @param hbp HANDLE: handle of the buffered paint context
+ * @param rc RECT*: target rectangly where alpha value should be applied
+ */
+inline void Gfx::finalizeBufferedPaint(HANDLE hbp, RECT *rc, BYTE alpha)
+{
+ if(alpha > 0)
+ Api::pfnBufferedPaintSetAlpha(hbp, rc, alpha);
+ Api::pfnEndBufferedPaint(hbp, TRUE);
+}
+
+/**
+ * blit the background from the back buffer surface (cfg::dat.hdcBg) to the
+ * client area of the child frame.
+ * @param hwnd child window handle
+ * @param rcCl child window client area
+ * @param hdc painting DC
+ */
+inline void Gfx::drawBGFromSurface(const HWND hwnd, const RECT& rcCl, HDC hdc)
+{
+ RECT rcMapped = rcCl;
+
+ MapWindowPoints(hwnd, pcli->hwndContactList, (POINT *)&rcMapped, 2);
+ BitBlt(hdc, rcCl.left, rcCl.top, rcCl.right - rcCl.left, rcCl.bottom - rcCl.top, cfg::dat.hdcBg,
+ rcMapped.left, rcMapped.top, SRCCOPY);
+}
+
+/**
+ * render a simply skin item (image item only, do not render the underlays)
+ * @param hdc device context
+ * @param rc target rectangle
+ * @param imageItem image item to render
+ */
+inline void Gfx::renderSkinItem(HDC hdc, RECT* rc, TImageItem *imageItem)
+{
+ if(imageItem)
+ renderImageItem(hdc, imageItem, rc);
+}
+
+/**
+ * render a skin item with a possible underlay (gradient and corner
+ * shape)
+ * @param ph CLCPaintHelper* (clc painting context with AGG base context)
+ * @param item TStatusItem* (item to render)
+ * @param rc target rectangle
+ */
+inline void Gfx::renderSkinItem(AGGPaintHelper *ph, TStatusItem *item, RECT* rc)
+{
+ TImageItem *imageItem = item->imageItem;
+
+ if (CLC::fInPaint && CLC::iHottrackItem) {
+ item = &Skin::statusItems[ID_EXTBKHOTTRACK];
+ if (item->IGNORED == 0)
+ imageItem = item->imageItem;
+ CLC::fHottrackDone = true;
+ }
+
+ if(!(item->dwFlags & S_ITEM_SKIP_UNDERLAY)) {
+ /*
+ * attach the item rendering pipeline to the AGG context rendering buffer
+ */
+ item->pixfmt->attach(ph->aggctx->m_rbuf);
+ item->rbase->attach(*(item->pixfmt));
+ if(item->dwFlags & AGG_USE_GRADIENT_X_RENDERER) {
+ item->span_gradient_x->d1(rc->left);
+ item->span_gradient_x->d2(rc->right);
+ }
+ else {
+ item->span_gradient_y->d1(rc->top);
+ item->span_gradient_y->d2(rc->bottom);
+ }
+
+ /*
+ * for each rendering cycle, the first shape defines the final shape for this item
+ * this allows items like "first item of a group" or "last item of a group" define
+ * their own shapes - overlays like a selection or hottrack item will use the
+ * original shape and only render their own color(s).
+ */
+ if(0 == ph->current_shape)
+ ph->current_shape = item->rect;
+
+ ph->current_shape->rect(rc->left, rc->top, rc->right, rc->bottom);
+
+ agg::rasterizer_scanline_aa<> r;
+ r.add_path(*(ph->current_shape));
+ agg::scanline_p8 sl;
+
+ if(item->dwFlags & AGG_USE_GRADIENT_X_RENDERER)
+ agg::render_scanlines(r, sl, *(item->gradient_renderer_x));
+ else if(item->dwFlags & AGG_USE_GRADIENT_Y_RENDERER)
+ agg::render_scanlines(r, sl, *(item->gradient_renderer_y));
+ else
+ agg::render_scanlines(r, sl, *(item->solid_renderer));
+ }
+ if(imageItem && !(item->dwFlags & S_ITEM_SKIP_IMAGE))
+ renderImageItem(ph->hdcMem, imageItem, rc);
+}
+
+/**
+ * set our text color for Gfx::RenderText() - replaces GDI SetTextColor() for all
+ * cases where we are using DrawThemeTextEx() for full 32bit text rendering.
+ * @param clr new text color to use
+ */
+inline void Gfx::setTextColor(const COLORREF clr)
+{
+ txtColor = clr;
+}
+
+inline COLORREF Gfx::getTextColor()
+{
+ return(txtColor);
+}
+
+inline void Gfx::hsvTransformPixel(BYTE *p, float value, float v_s_u, float v_s_w, BYTE alpha)
+{
+ // ain't matrices beautiful? :)
+
+ float r = (.299 * value +.701 * v_s_u +.168 * v_s_w) * p[2] + (.587 * value -.587 * v_s_u +.330 * v_s_w) * p[1] + (.114 * value -.114 * v_s_u -.497 * v_s_w) * p[0];
+ float g = (.299 * value -.299 * v_s_u -.328 * v_s_w) * p[2] + (.587 * value +.413 * v_s_u +.035 * v_s_w) * p[1] + (.114 * value -.114 * v_s_u +.292 * v_s_w) * p[0];
+ float b = (.299 * value -.3 * v_s_u +1.25 * v_s_w) * p[2]+ (.587* value -.588 * v_s_u -1.05 * v_s_w) * p[1] + (.114 * value +.886 * v_s_u -.203 * v_s_w) * p[0];
+
+ /*
+ * premultiply
+ */
+ p[0] = (int)b * alpha/255;
+ p[1] = (int)g * alpha/255;
+ p[2] = (int)r * alpha/255;
+}
+
+inline void Gfx::rgbTransformPixel(BYTE *p, float r, float g, float b, BYTE alpha)
+{
+ p[0] = (int)(p[0] + b) > 255 ? 255 : p[0] + b;
+ p[1] = (int)(p[1] + g) > 255 ? 255 : p[1] + g;
+ p[2] = (int)(p[2] + r) > 255 ? 255 : p[2] + r;
+
+ p[0] = p[0] * alpha/255;
+ p[1] = p[1] * alpha/255;
+ p[2] = p[2] * alpha/255;
+}
+
+#ifndef _XP_SUPPORT
+#define INIT_PAINT(a, b, c) (hbp = Gfx::initiateBufferedPaint((a), (b), (c)))
+#define FINALIZE_PAINT(a, b, c) Gfx::finalizeBufferedPaint((a), (b), (c))
+#else
+#endif
+
+#endif /*__GFX_H_*/
+